This commit is contained in:
wcq 2023-04-18 15:02:51 +08:00
parent d0ac46db5c
commit 195df32f78
8 changed files with 360 additions and 44 deletions

View File

@ -2,13 +2,15 @@
<div>
<div class="m-2">
<el-button size="small" type="success" @click="runModel">运行</el-button>
<el-switch class="ml-2" v-model="fillingMode" active-text="填报模式" />
<el-switch class="ml-2" v-model="simpleMode" @change="onSimpleModeChange" active-text="精简模式" />
<el-switch class="ml-2" v-model="treeColorShow" active-text="树颜色" />
<el-switch class="ml-2" v-model="options.fillingMode" active-text="填报模式" />
<el-switch class="ml-2" v-model="options.simpleMode" @change="onSimpleModeChange" active-text="精简模式" />
<el-switch class="ml-2" v-model="options.treeColorShow" active-text="树颜色" />
<el-select class="ml-2" v-model="options.defaultLang" placeholder="语言选择" style="width: 6rem;">
<el-option v-for="lang in ['js', 'python']" :label="lang" :value="lang" :key="lang"></el-option>
</el-select>
</div>
<el-table height="100%" :cell-style="tableCellStyle" ref="table" :data="[tableIdTree]"
style="width: 100%; margin-bottom: 20px" :max-height="props.maxHeight" row-key="id" align="center" border
default-expand-all>
style="width: 100%; margin-bottom: 20px" row-key="id" align="center" border default-expand-all>
<el-table-column prop="name" label="指标名称" />
<!-- <el-table-column prop="key" label="键值" align="center" /> -->
<el-table-column prop="calValue" label="计算结果" align="center" />
@ -16,7 +18,7 @@
<template #default="scope">
<!-- v-if="(() => findParent(scope.row, calModel.data) && ([null, undefined, ''].indexOf(findParent(scope.row, calModel.data).inputValue) == -1))()" -->
<div
v-if="!(indexDic[scope.row.id].children && indexDic[scope.row.id].children.length && simpleMode && !(indexDic[scope.row.id].packUp && scope.row.id !== calModel.id))">
v-if="!(indexDic[scope.row.id].children && indexDic[scope.row.id].children.length && options.simpleMode && !(indexDic[scope.row.id].packUp && scope.row.id !== calModel.id))">
<div v-if="indexDic[scope.row.id].ignore === true" style="text-decoration: line-through;color: red;">
{{ " " + indexDic[scope.row.id].inputValue + " " }}
</div>
@ -33,14 +35,14 @@
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" width="120" align="center" />
<el-table-column label="计算" width="60" align="center" v-if="!simpleMode">
<el-table-column label="计算" width="60" align="center" v-if="!options.simpleMode">
<template #default="scope">
<el-button type="success"
:disabled="!(indexDic[scope.row.id].children && indexDic[scope.row.id].children.length > 0)" size="small"
:icon="CaretRight" circle @click="run(indexDic[scope.row.id])" />
</template>
</el-table-column>
<el-table-column v-if="!fillingMode && !simpleMode" label="操作" :width="180" align="center">
<el-table-column v-if="!options.fillingMode && !options.simpleMode" label="操作" :width="180" align="center">
<template #default="scope">
<el-button type="primary" size="small" :icon="Edit" circle @click="showRowEdit(indexDic[scope.row.id])" />
<el-button type="success" size="small" :icon="Plus" circle @click="showRowAdd(indexDic[scope.row.id])" />
@ -51,7 +53,7 @@
</el-button>
</template>
</el-table-column>
<el-table-column label="收纳" width="60" align="center" v-if="!simpleMode && !fillingMode">
<el-table-column label="收纳" width="60" align="center" v-if="!options.simpleMode && !options.fillingMode">
<template #default="scope">
<el-switch
:disabled="!(scope.row.id !== props.calModel.id && (indexDic[scope.row.id].children && indexDic[scope.row.id].children.length))"
@ -114,7 +116,7 @@
</el-dialog>
<el-dialog :title="'公式编辑-' + editRowTemp.name" class="funcEditerDialog"
style="width: 90%;margin-top: 1rem;margin-bottom: 0;" v-model="codeEditVisible">
<FuncEditer :lang="props.defaultLang" :key="funcEditerKey" style="max-height: 100%;" :index="editRowTemp">
<FuncEditer :lang="props.options.defaultLang" :key="funcEditerKey" style="max-height: 100%;" :index="editRowTemp">
</FuncEditer>
<template #footer>
<el-button type="info" @click="codeEditVisible = false">取消</el-button>
@ -123,14 +125,13 @@
</el-dialog>
<el-dialog class="childTableDialog" :title="childTableData ? childTableData.name : ''" v-model="childTableShow"
style="width: 98%">
<index-cal-model-edit-plus :key="childTableKey" :filling-mode="fillingMode" :simple-mode="simpleMode"
:tree-color-show="treeColorShow" :cal-model="childTableData" default-lang="js"></index-cal-model-edit-plus>
<index-cal-model-edit-plus :key="childTableKey" :options="options" :cal-model="childTableData" />
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ElMessageBox, ElMessage, ElTable, ColumnStyle } from "element-plus";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, ref, watch } from "vue";
import { useDebounceFn } from "@vueuse/core";
import { Index, Lang } from "@/components/IndexCal/types";
import FuncEditer from "../IndexFuncEditer/components/FuncEditer.vue";
@ -147,19 +148,16 @@ defineOptions({
});
const props = defineProps<{
calModel: Index,
defaultLang: Lang,
maxHeight?: null | number,
fillingMode?: boolean,
treeColorShow?: boolean,
simpleMode?: boolean
options?: { defaultLang?: Lang, fillingMode?: boolean, treeColorShow?: boolean, simpleMode?: boolean },
}>();
const options = ref<{ defaultLang?: Lang, fillingMode?: boolean, treeColorShow?: boolean, simpleMode?: boolean }>({
defaultLang: 'js', fillingMode: false, simpleMode: false, treeColorShow: false
})
watch(props.options, (newVal) => options.value = newVal)
const table = ref<InstanceType<typeof ElTable> | null>(null);
const rowAddVisible = ref(false);
const rowEditVisible = ref(false);
const codeEditVisible = ref(false);
const fillingMode = ref(false);
const simpleMode = ref(false);
const treeColorShow = ref(false);
const childTableShow = ref(false);
const childTableData = ref<Index>(null);
const childTableKey = ref(String(new Date()) + "_childTableKey");
@ -257,7 +255,7 @@ function tableCellStyle({ row, column, rowIndex, columnIndex }: {
if (index !== -1) {
mgrStyle = highlightCellList.value[index].style || { background: "red" };
}
if (treeColorShow.value && columnIndex == 0 && row.dep != undefined) {
if (options.value.treeColorShow && columnIndex == 0 && row.dep != undefined) {
mgrStyle = { ...mgrStyle, color: depColorList.value[row.dep % depColorList.value.length] }
}
return mgrStyle;
@ -435,7 +433,7 @@ function run(data: Index) {
// return
// }
try {
runner.run(data, { lang: props.defaultLang });
runner.run(data, { lang: options.value.defaultLang });
highlightRowIdList.value = [];
highlightCellList.value = [];
// ElMessage.success('')
@ -461,9 +459,17 @@ function run(data: Index) {
}
onMounted(() => {
fillingMode.value = props.fillingMode;
simpleMode.value = props.simpleMode;
treeColorShow.value = props.treeColorShow;
if (props.options) {
if (props.options.defaultLang != null)
options.value.defaultLang = props.options.defaultLang
if (props.options.fillingMode != null)
options.value.fillingMode = props.options.fillingMode
if (props.options.simpleMode != null)
options.value.simpleMode = props.options.simpleMode
if (props.options.treeColorShow != null)
options.value.treeColorShow = props.options.treeColorShow
}
});
</script>
<style lang="css">

View File

@ -1,3 +1,4 @@
import { api } from "@/api/api";
import type { Index, Lang } from "@/components/IndexCal/types";
type IndexCalErrorType =
@ -137,18 +138,33 @@ class IndexCalRunner {
}
) {
clearCalValue(data);
const depDic = getDepDicExincludeHasInput(data);
let maxDep = Math.max(...Object.keys(depDic).map(item => Number(item)));
for (let i = maxDep; i > 0; i--) {
let parents = depDic[i];
parents.forEach(item => {
if (item.children && item.children.length) {
const calValue = calIndex(item, config.lang);
item.calValue = calValue;
}
if (config.lang == "js") {
const depDic = getDepDicExincludeHasInput(data);
let maxDep = Math.max(...Object.keys(depDic).map(item => Number(item)));
for (let i = maxDep; i > 0; i--) {
let parents = depDic[i];
parents.forEach(item => {
if (item.children && item.children.length) {
const calValue = calIndex(item, config.lang);
item.calValue = calValue;
}
});
}
}
if (config.lang == "python") {
api.post("/index_cal/cal_index", { index: data }).then(res => {
let calValueDic = {};
let resIndex = res.data.index;
treeMapCore(resIndex, c => {
calValueDic[c.id] = c.calValue;
});
treeMapCore(data, c => {
c.calValue = calValueDic[c.id];
});
});
}
return data;
// return data;
}
}

View File

@ -50,9 +50,12 @@
import { nextTick, onMounted, ref, watch, defineProps, computed } from "vue";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import python from "highlight.js/lib/languages/python";
import type { Index, Lang } from "../../types";
import IndexCalParamInput from "../../IndexCalParam/IndexCalParamInput.vue";
import { api } from "@/api/api";
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("python", python);
const props = defineProps<{ index: Index, lang: Lang }>();
const codeEditerId = ref("codeEditerId");
const codeEditerCardWidth = ref(220);
@ -80,13 +83,17 @@ const preConst = `function sum(arr) {
});
}`;
const funcTest = () => {
if (props.lang == 'python') {
funcTestPython(testParams, code.value)
return
}
const constInParams = props.index.children
.map(item => `let ${item.key} = ${JSON.stringify(testParams.value[item.key])};`)
.join("\n");
const evalCode =
constInParams +
"\n" +
code +
code.value +
"\n"
let error = "";
try {
@ -98,7 +105,7 @@ const funcTest = () => {
"参数定义:\n" +
constInParams +
"\n\n执行代码:\n" +
code +
code.value +
"\n\n输出结果:\n" +
JSON.stringify(
outValue
@ -122,6 +129,15 @@ const funcTest = () => {
return;
}
};
const funcTestPython = (params: {}, code: string) => {
api.post("/index_cal/func_test", { params, code }).then(res => {
if (res.data.state == 1) {
let value = res.data.value
}
let msg = res.data.msg
})
}
</script>
<style scoped>
.max-all {

View File

@ -55,4 +55,13 @@ interface CalModel {
data: Index;
defaultLang: Lang;
}
export type { Index, ValueConfig, Lang, CalModel };
interface FuncTemplace {
id: number;
name: string;
code: string;
lang: Lang;
key: string;
}
export type { Index, ValueConfig, Lang, CalModel, FuncTemplace };

267
src/mock/data (5).json Normal file
View File

@ -0,0 +1,267 @@
{
"id": 1,
"name": "黄土坡GEP",
"inputValue": null,
"calValue": 1706.91,
"codeConfig": {
"python": "",
"js": "let v=双流GDP+武侯GDP+龙泉驿GDP+金牛GDP+青羊GDP+郫都GDP+新都GDP\nreturn Number(v.toFixed(4))"
},
"unit": "万元",
"valueConfig": { "type": "number" },
"key": "黄土坡GEP",
"children": [
{
"id": 2,
"name": "物质供给",
"key": "物质供给",
"calValue": 330,
"packUp": false,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=农产品+林产品+牧产品+渔产品\nreturn v"
},
"unit": "万元",
"children": [
{
"id": 3,
"name": "农产品",
"key": "农产品",
"calValue": null,
"inputValue": 100,
"valueConfig": { "type": "number" },
"unit": "万元"
},
{
"id": 4,
"name": "林产品",
"key": "林产品",
"calValue": null,
"inputValue": 80,
"valueConfig": { "type": "number" },
"unit": "万元"
},
{
"id": 5,
"name": "牧产品",
"key": "牧产品",
"calValue": null,
"inputValue": 60,
"valueConfig": { "type": "number" },
"unit": "万元"
},
{
"id": 6,
"name": "渔产品",
"key": "渔产品",
"calValue": null,
"inputValue": 90,
"valueConfig": { "type": "number" },
"unit": "万元"
}
]
},
{
"id": 7,
"name": "调节服务",
"key": "调节服务",
"calValue": null,
"inputValue": null,
"valueConfig": { "type": "number" },
"unit": "万元",
"children": [
{
"id": 8,
"name": "水源涵养",
"key": "水源涵养",
"calValue": 2127.4464,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=实物量*单价/10000\nreturn v"
},
"unit": "万元",
"children": [
{
"id": 9,
"name": "实物量",
"key": "实物量",
"calValue": 4246400,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=森林生态系统+草地生态系统+农田生态系统\nreturn v"
},
"unit": "立方米",
"children": [
{
"id": 10,
"name": "森林生态系统",
"key": "森林生态系统",
"calValue": 3866400,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=面积*(降雨量-地表径流量-蒸散发量)*1000\nreturn Number(v.toFixed(2))"
},
"unit": "立方米",
"children": [
{
"id": 11,
"name": "面积",
"key": "面积",
"calValue": null,
"inputValue": 40,
"valueConfig": { "type": "number" },
"unit": "平方公里"
},
{
"id": 12,
"name": "降雨量",
"key": "降雨量",
"calValue": null,
"inputValue": 100,
"valueConfig": { "type": "number" },
"unit": "mm"
},
{
"id": 13,
"name": "地表径流量",
"key": "地表径流量",
"calValue": null,
"inputValue": 2.67,
"valueConfig": { "type": "number" },
"unit": "mm"
},
{
"id": 14,
"name": "蒸散发量",
"key": "蒸散发量",
"calValue": null,
"inputValue": 0.67,
"valueConfig": { "type": "number" },
"unit": "mm"
}
]
},
{
"id": 15,
"name": "草地生态系统",
"key": "草地生态系统",
"calValue": null,
"inputValue": 200000,
"valueConfig": { "type": "number" },
"unit": "立方米"
},
{
"id": 16,
"name": "农田生态系统",
"key": "农田生态系统",
"calValue": null,
"inputValue": 180000,
"valueConfig": { "type": "number" },
"unit": "立方米"
}
]
},
{
"id": 17,
"name": "单价",
"key": "单价",
"calValue": 5.01,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=单位库容年运营成本+单位库容工程造价*(水库折旧率/100)\nreturn parseFloat((v).toFixed(2))"
},
"unit": "元",
"children": [
{
"id": 18,
"name": "单位库容年运营成本",
"key": "单位库容年运营成本",
"calValue": 5,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=年度水库运营成本*10000/水库容量\nreturn v"
},
"unit": "元",
"children": [
{
"id": 19,
"name": "水库容量",
"key": "水库容量",
"calValue": null,
"inputValue": 10000,
"valueConfig": { "type": "number" },
"unit": "立方米"
},
{
"id": 20,
"name": "年度水库运营成本",
"key": "年度水库运营成本",
"calValue": null,
"inputValue": 5,
"valueConfig": { "type": "number" },
"unit": "万元"
}
]
},
{
"id": 21,
"name": "单位库容工程造价",
"key": "单位库容工程造价",
"calValue": 2,
"inputValue": null,
"valueConfig": { "type": "number" },
"codeConfig": {
"python": "",
"js": "let v=水库工程造价*10000/水库容量\nreturn v"
},
"unit": "元",
"children": [
{
"id": 22,
"name": "水库工程造价",
"key": "水库工程造价",
"calValue": null,
"inputValue": 2,
"valueConfig": { "type": "number" },
"unit": "万元"
},
{
"id": 23,
"name": "水库容量",
"key": "水库容量",
"calValue": null,
"inputValue": 10000,
"valueConfig": { "type": "number" },
"unit": "立方米"
}
]
},
{
"id": 24,
"name": "水库折旧率",
"key": "水库折旧率",
"calValue": null,
"inputValue": 0.3,
"valueConfig": { "type": "number" },
"unit": "%"
}
]
}
]
}
]
}
]
}

View File

@ -1,11 +1,13 @@
<template>
<div>
<el-table>
</el-table>
</div>
</template>
<script lang="ts" setup>
</script>
<style scoped>
</style>
<style scoped></style>

View File

@ -1,6 +1,6 @@
<template>
<div>
<IndexCalModelEditPlus :cal-model="model" :default-lang="'js'"></IndexCalModelEditPlus>
<IndexCalModelEditPlus :cal-model="model"></IndexCalModelEditPlus>
<div>
<el-button size="small" type="primary" class="ml-2" @click="saveToCache">保存到缓存</el-button>
<el-button size="small" type="primary" class="ml-2" @click="saveToFile">保存到文件</el-button>
@ -8,7 +8,7 @@
</div>
</template>
<script lang="ts" setup>
import { Index } from '@/components/IndexCal/types';
import { Index, Lang } from '@/components/IndexCal/types';
import htpGEP from "@/mock/htpGEP.json"
import { onMounted, ref } from 'vue';
import IndexCalModelEditPlus from "@/components/IndexCal/IndexCalModelEdit/indexCalModelEditPlus.vue";