bug
This commit is contained in:
parent
4093e21047
commit
e80e6ac44f
|
@ -18,4 +18,5 @@ tests/**/coverage/
|
|||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
tsconfig.tsbuildinfo
|
||||
tsconfig.tsbuildinfo
|
||||
dist01
|
|
@ -68,8 +68,7 @@ export default defineComponent({
|
|||
}
|
||||
arrayData && (this.value = arrayData)
|
||||
this.arrayEditVisible = false
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -30,8 +30,8 @@
|
|||
:style="{
|
||||
width: codeEditerCardWidth + 'px',
|
||||
height: codeEditerCardHeight - 10 + 'px'
|
||||
}" :code="props.index.code" language="js" />
|
||||
<textarea v-model="props.index.code" :style="{
|
||||
}" :code="code" :language="props.lang" />
|
||||
<textarea v-model="code" :style="{
|
||||
width: codeEditerCardWidth + 'px',
|
||||
height: codeEditerCardHeight - 10 + 'px'
|
||||
}" class="flex-1 focus:outline-none resize-none absolute code-editer-text p-2"></textarea>
|
||||
|
@ -50,13 +50,13 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, ref, watch, defineProps } from "vue";
|
||||
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 type { Index } from "../../types";
|
||||
import type { Index, Lang } from "../../types";
|
||||
import IndexCalParamInput from "../../IndexCalParam/IndexCalParamInput.vue";
|
||||
hljs.registerLanguage("javascript", javascript);
|
||||
const props = defineProps<{ index: Index }>();
|
||||
const props = defineProps<{ index: Index,lang: Lang }>();
|
||||
const codeEditerId = ref("codeEditerId");
|
||||
const codeEditerCardWidth = ref(220);
|
||||
const codeEditerCardHeight = ref(220);
|
||||
|
@ -71,7 +71,7 @@ onMounted(() => {
|
|||
});
|
||||
window.addEventListener("resize", setSize);
|
||||
});
|
||||
|
||||
const code = computed({ set(val: string) { props.index.codeConfig[props.lang] = val }, get() { return props.index&&props.index.codeConfig[props.lang] } })
|
||||
const setSize = () => {
|
||||
const el = document.getElementById(codeEditerId.value);
|
||||
codeEditerCardHeight.value = el.offsetHeight;
|
||||
|
@ -89,7 +89,7 @@ const funcTest = () => {
|
|||
const evalCode =
|
||||
constInParams +
|
||||
"\n" +
|
||||
props.index.code +
|
||||
code +
|
||||
"\n"
|
||||
let error = "";
|
||||
try {
|
||||
|
@ -101,7 +101,7 @@ const funcTest = () => {
|
|||
"参数定义:\n" +
|
||||
constInParams +
|
||||
"\n\n执行代码:\n" +
|
||||
props.index.code +
|
||||
code +
|
||||
"\n\n输出结果:\n" +
|
||||
JSON.stringify(
|
||||
outValue
|
||||
|
@ -116,7 +116,7 @@ const funcTest = () => {
|
|||
"参数定义:\n" +
|
||||
constInParams +
|
||||
"\n\n执行代码:\n" +
|
||||
props.index.code +
|
||||
code +
|
||||
"\n\n执行错误:\n" +
|
||||
error.message;
|
||||
});
|
||||
|
|
|
@ -27,6 +27,12 @@ type ValueConfig =
|
|||
| ValueNumber
|
||||
| ValueFile
|
||||
| ValueNumberArray;
|
||||
|
||||
interface CodeConfig {
|
||||
python: string;
|
||||
js: string;
|
||||
}
|
||||
type Lang = "python" | "js";
|
||||
interface Index {
|
||||
id: number;
|
||||
name: string;
|
||||
|
@ -34,9 +40,16 @@ interface Index {
|
|||
inputValue: any;
|
||||
calValue: any;
|
||||
valueConfig: ValueConfig;
|
||||
code: string;
|
||||
codeConfig?: CodeConfig;
|
||||
unit?: string;
|
||||
description?: string;
|
||||
children?: Index[];
|
||||
}
|
||||
export type { Index, ValueConfig };
|
||||
|
||||
interface CalModel {
|
||||
id: number;
|
||||
name: string;
|
||||
data: Index;
|
||||
defaultLang: Lang;
|
||||
}
|
||||
export type { Index, ValueConfig, Lang, CalModel };
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
"name": "黄土坡GEP",
|
||||
"inputValue": null,
|
||||
"calValue": 1706.91,
|
||||
"code": "let v=双流GDP+武侯GDP+龙泉驿GDP+金牛GDP+青羊GDP+郫都GDP+新都GDP\nreturn Number(v.toFixed(4))",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=双流GDP+武侯GDP+龙泉驿GDP+金牛GDP+青羊GDP+郫都GDP+新都GDP\nreturn Number(v.toFixed(4))"
|
||||
},
|
||||
"unit": "万元",
|
||||
"valueConfig": { "type": "number" },
|
||||
"key": "黄土坡GEP",
|
||||
|
@ -16,7 +19,10 @@
|
|||
"calValue": 330,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=农产品+林产品+牧产品+渔产品\nreturn v",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=农产品+林产品+牧产品+渔产品\nreturn v"
|
||||
},
|
||||
"unit": "万元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -26,7 +32,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 100,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
},
|
||||
{
|
||||
|
@ -36,7 +41,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 80,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
},
|
||||
{
|
||||
|
@ -46,7 +50,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 60,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
},
|
||||
{
|
||||
|
@ -56,7 +59,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 90,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
}
|
||||
]
|
||||
|
@ -68,7 +70,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -78,7 +79,10 @@
|
|||
"calValue": 2127.4464,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=实物量*单价/10000\nreturn v",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=实物量*单价/10000\nreturn v"
|
||||
},
|
||||
"unit": "万元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -88,7 +92,10 @@
|
|||
"calValue": 4246400,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=森林生态系统+草地生态系统+农田生态系统\nreturn v",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=森林生态系统+草地生态系统+农田生态系统\nreturn v"
|
||||
},
|
||||
"unit": "立方米",
|
||||
"children": [
|
||||
{
|
||||
|
@ -98,7 +105,10 @@
|
|||
"calValue": 3866400,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=面积*(降雨量-地表径流量-蒸散发量)*1000\nreturn Number(v.toFixed(2))",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=面积*(降雨量-地表径流量-蒸散发量)*1000\nreturn Number(v.toFixed(2))"
|
||||
},
|
||||
"unit": "立方米",
|
||||
"children": [
|
||||
{
|
||||
|
@ -108,7 +118,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 40,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "平方公里"
|
||||
},
|
||||
{
|
||||
|
@ -118,7 +127,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 100,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "mm"
|
||||
},
|
||||
{
|
||||
|
@ -128,7 +136,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 2.67,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "mm"
|
||||
},
|
||||
{
|
||||
|
@ -138,7 +145,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 0.67,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "mm"
|
||||
}
|
||||
]
|
||||
|
@ -150,7 +156,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 200000,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "立方米"
|
||||
},
|
||||
{
|
||||
|
@ -160,7 +165,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 180000,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "立方米"
|
||||
}
|
||||
]
|
||||
|
@ -172,7 +176,10 @@
|
|||
"calValue": 5.01,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=单位库容年运营成本+单位库容工程造价*(水库折旧率/100)\nreturn parseFloat((v).toFixed(2))",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=单位库容年运营成本+单位库容工程造价*(水库折旧率/100)\nreturn parseFloat((v).toFixed(2))"
|
||||
},
|
||||
"unit": "元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -182,7 +189,10 @@
|
|||
"calValue": 5,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=年度水库运营成本*10000/水库容量\nreturn v",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=年度水库运营成本*10000/水库容量\nreturn v"
|
||||
},
|
||||
"unit": "元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -192,7 +202,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 10000,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "立方米"
|
||||
},
|
||||
{
|
||||
|
@ -202,7 +211,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 5,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
}
|
||||
]
|
||||
|
@ -214,7 +222,10 @@
|
|||
"calValue": 2,
|
||||
"inputValue": null,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "let v=水库工程造价*10000/水库容量\nreturn v",
|
||||
"codeConfig": {
|
||||
"python": "",
|
||||
"js": "let v=水库工程造价*10000/水库容量\nreturn v"
|
||||
},
|
||||
"unit": "元",
|
||||
"children": [
|
||||
{
|
||||
|
@ -224,7 +235,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 2,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "万元"
|
||||
},
|
||||
{
|
||||
|
@ -234,7 +244,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 10000,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "立方米"
|
||||
}
|
||||
]
|
||||
|
@ -246,7 +255,6 @@
|
|||
"calValue": null,
|
||||
"inputValue": 0.3,
|
||||
"valueConfig": { "type": "number" },
|
||||
"code": "",
|
||||
"unit": "%"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
<div class="m-2">
|
||||
<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>
|
||||
<el-button size="small" type="success" class="ml-2" @click="() => run(tableData[0])">运行</el-button>
|
||||
<el-button size="small" type="success" class="ml-2" @click="() => run(calModel.data)">运行</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" style="width: 100%; margin-bottom: 20px" row-key="id" align="center" border
|
||||
default-expand-all>
|
||||
<el-table highlight-current-row ref="table" :data="[calModel.data]" 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" />
|
||||
<el-table-column prop="inputValue" label="输入值" align="center">
|
||||
<template #default="scope">
|
||||
<div
|
||||
v-if="(() => findParent(scope.row, tableData) && ([null, undefined, ''].indexOf(findParent(scope.row, tableData).inputValue) == -1))()"
|
||||
v-if="(() => findParent(scope.row, calModel.data) && ([null, undefined, ''].indexOf(findParent(scope.row, calModel.data).inputValue) == -1))()"
|
||||
style="text-decoration: line-through;color: red;">
|
||||
{{ scope.row.inputValue }}
|
||||
</div>
|
||||
|
@ -21,10 +21,8 @@
|
|||
<IndexCalParamInput v-model="scope.row.inputValue" :value-config="scope.row.valueConfig">
|
||||
</IndexCalParamInput>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="unit" label="单位" width="120" align="center" />
|
||||
<el-table-column label="操作" width="230" align="center">
|
||||
<template #default="scope">
|
||||
|
@ -96,7 +94,8 @@
|
|||
</el-dialog>
|
||||
<el-dialog :title="'公式编辑-' + editRowTemp.name" class="funcEditerDialog"
|
||||
style="width: 90%;margin-top: 1rem;margin-bottom: 0;" v-model="codeEditVisible">
|
||||
<FuncEditer :key="funcEditerKey" style="max-height: 100%;" :index="editRowTemp"></FuncEditer>
|
||||
<FuncEditer :lang="calModel.defaultLang" :key="funcEditerKey" style="max-height: 100%;" :index="editRowTemp">
|
||||
</FuncEditer>
|
||||
<template #footer>
|
||||
<el-button type="info" @click="codeEditVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveCodeEdit">保存</el-button>
|
||||
|
@ -105,10 +104,10 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox, ElMessage } from "element-plus";
|
||||
import { ElMessageBox, ElMessage, ElTable } from "element-plus";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useDebounceFn } from "@vueuse/core";
|
||||
import { Index } from "@/components/IndexCal/types";
|
||||
import { CalModel, Index } from "@/components/IndexCal/types";
|
||||
import FuncEditer from "@/components/IndexCal/IndexFuncEditer/components/FuncEditer.vue";
|
||||
import 黄土坡GEP from "@/mock/黄土坡GEP.json"
|
||||
import {
|
||||
|
@ -117,8 +116,8 @@ import {
|
|||
Edit,
|
||||
Plus,
|
||||
} from '@element-plus/icons-vue'
|
||||
import { IndexCalRunner, treeMap } from "./indexCalRunner";
|
||||
|
||||
import { IndexCalError, IndexCalRunner, treeMapCore } from "./indexCalRunner";
|
||||
const table = ref<InstanceType<typeof ElTable> | null>(null)
|
||||
const rowAddVisible = ref(false);
|
||||
const rowEditVisible = ref(false);
|
||||
const codeEditVisible = ref(false);
|
||||
|
@ -127,7 +126,6 @@ const addRowTemp = ref<Index>(null);
|
|||
const editRowTemp = ref<Index>({
|
||||
id: 0, name: '', inputValue: 1,
|
||||
calValue: 1,
|
||||
code: "",
|
||||
valueConfig: { type: 'int' },
|
||||
key: "",
|
||||
});
|
||||
|
@ -137,8 +135,9 @@ defineOptions({
|
|||
name: "index_cal_model_edit"
|
||||
});
|
||||
//@ts-ignore
|
||||
const tableData = ref<Index[]>(黄土坡GEP)
|
||||
|
||||
// const tableData = ref<Index[]>(黄土坡GEP)
|
||||
//@ts-ignore
|
||||
const calModel = ref<CalModel>({ id: 1, name: "黄土坡GEP", data: 黄土坡GEP[0], defaultLang: 'js' })
|
||||
function copy(obj) {
|
||||
if (obj) {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
|
@ -151,9 +150,8 @@ function showRowAdd(row: Index) {
|
|||
// console.log("rrr", rs);
|
||||
selectRow.value = row;
|
||||
let idSet = new Set<number>()
|
||||
treeMap(tableData.value[0], (p, c) => {
|
||||
idSet.add(p.id)
|
||||
idSet.add(c.id)
|
||||
treeMapCore(calModel.value.data, (node) => {
|
||||
idSet.add(node.id)
|
||||
})
|
||||
|
||||
const newId = Math.max(...idSet) + 1;
|
||||
|
@ -164,7 +162,10 @@ function showRowAdd(row: Index) {
|
|||
calValue: null,
|
||||
inputValue: null,
|
||||
valueConfig: { type: "number" },
|
||||
code: ""
|
||||
codeConfig: {
|
||||
python: "",
|
||||
js: ""
|
||||
}
|
||||
};
|
||||
rowAddVisible.value = true;
|
||||
}
|
||||
|
@ -198,7 +199,7 @@ function saveRowEdit() {
|
|||
ElMessage.warning("键值不能为空");
|
||||
return;
|
||||
}
|
||||
const parent = findParent(editRowTemp.value, tableData.value)
|
||||
const parent = findParent(editRowTemp.value, calModel.value.data)
|
||||
if ((editRowTemp.value.key != selectRow.value.key) && parent && parent.children && parent.children.filter(item => (item.key == addRowTemp.value.key)).length > 1) {
|
||||
ElMessage.warning("键值不能重复");
|
||||
return;
|
||||
|
@ -210,7 +211,7 @@ function saveRowEdit() {
|
|||
}
|
||||
|
||||
function saveCodeEdit() {
|
||||
selectRow.value.code = editRowTemp.value.code
|
||||
selectRow.value.codeConfig = copy(editRowTemp.value.codeConfig)
|
||||
codeEditVisible.value = false;
|
||||
}
|
||||
const addRowUseDebounceFn = useDebounceFn(addRow, 200)
|
||||
|
@ -221,14 +222,17 @@ function showRowEdit(row: Index) {
|
|||
}
|
||||
function showCodeEdit(row: Index, scope: any) {
|
||||
editRowTemp.value = copy(row)
|
||||
if (!editRowTemp.value.codeConfig) {
|
||||
editRowTemp.value.codeConfig = { js: "", python: "" }
|
||||
}
|
||||
selectRow.value = row
|
||||
funcEditerKey.value = String(new Date())
|
||||
codeEditVisible.value = true;
|
||||
}
|
||||
|
||||
// 查找父节点
|
||||
function findParent(findItem, tree = [] as Index[]) {
|
||||
let parens = tree;
|
||||
function findParent(findItem, tree: Index) {
|
||||
let parens = [tree];
|
||||
let maxTime = 3000;
|
||||
let times = 0;
|
||||
while (parens.length) {
|
||||
|
@ -266,7 +270,7 @@ function showRowDelete(row: Index) {
|
|||
}
|
||||
|
||||
function rowDelete(row: Index) {
|
||||
const parent = findParent(row, tableData.value);
|
||||
const parent = findParent(row, calModel.value.data);
|
||||
if (!parent) {
|
||||
ElMessage.warning("无法删除");
|
||||
} else {
|
||||
|
@ -282,22 +286,31 @@ function createAndDownloadFile(fileName, content) {
|
|||
URL.revokeObjectURL(blob.toString());
|
||||
}
|
||||
function saveToFile() {
|
||||
createAndDownloadFile('data.json', JSON.stringify(tableData.value))
|
||||
createAndDownloadFile('data.json', JSON.stringify(calModel.value))
|
||||
}
|
||||
|
||||
function saveToCache() {
|
||||
localStorage.setItem('indexCalModelCache', JSON.stringify(tableData.value))
|
||||
localStorage.setItem('indexCalModelCache', JSON.stringify(calModel.value))
|
||||
}
|
||||
|
||||
|
||||
function loadFromCache() {
|
||||
let item = localStorage.getItem('indexCalModelCache')
|
||||
item && (tableData.value = JSON.parse(item))
|
||||
item && (calModel.value = JSON.parse(item))
|
||||
}
|
||||
|
||||
function run(data: Index) {
|
||||
const runner = new IndexCalRunner(data)
|
||||
runner.run(data)
|
||||
try {
|
||||
runner.run(data, calModel.value.defaultLang)
|
||||
} catch (e) {
|
||||
if (e instanceof IndexCalError) {
|
||||
console.error(e)
|
||||
ElMessage.warning(e.message)
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
@ -1,67 +1,74 @@
|
|||
import { Index } from "@/components/IndexCal/types";
|
||||
import type { Index, Lang } from "@/components/IndexCal/types";
|
||||
type IndexCalErrorType = "codeConfigNotConfig" | "paramValueNotInput";
|
||||
interface errorStore {
|
||||
index?: Index;
|
||||
}
|
||||
class IndexCalError extends Error {
|
||||
store: errorStore;
|
||||
type: IndexCalErrorType;
|
||||
constructor(
|
||||
type: IndexCalErrorType = "",
|
||||
message = "计算出错",
|
||||
store: {} = {}
|
||||
) {
|
||||
super(message);
|
||||
this.name = "IndexCalError";
|
||||
this.type = type;
|
||||
this.store = store;
|
||||
}
|
||||
}
|
||||
|
||||
function treeMap(
|
||||
function treeMapCore(
|
||||
tree: Index,
|
||||
func: (parent: Index, child: Index, dep: number) => any,
|
||||
dep = 1
|
||||
func: (child: Index, parent: Index, dep: number) => boolean | any,
|
||||
dep = 1,
|
||||
parent: Index = null
|
||||
) {
|
||||
if (func(tree, parent, dep) === false) {
|
||||
return;
|
||||
}
|
||||
const children = tree.children;
|
||||
if (children) {
|
||||
const len = children.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const child = children[i];
|
||||
func(tree, child, dep);
|
||||
treeMap(child, func, dep + 1);
|
||||
treeMapCore(child, func, dep + 1, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// //获取所有叶节点
|
||||
// function getLeafNodes(index: Index) {
|
||||
// const leafNodes = [];
|
||||
// treeMap(index, (p, c) => {
|
||||
// if (!(c.children && c.children.length > 0)) {
|
||||
// leafNodes.push(c);
|
||||
// }
|
||||
// });
|
||||
// return leafNodes;
|
||||
// }
|
||||
// //获取所有叶节点的父节点
|
||||
// function getLeafParentNodes(index: Index) {
|
||||
// const parentNodes = [];
|
||||
// treeMap(index, (p, c) => {
|
||||
// if (!(c.children && c.children.length > 0)) {
|
||||
// if (parentNodes.indexOf(p) == -1) {
|
||||
// parentNodes.push(p);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// return parentNodes;
|
||||
// }
|
||||
// //获取节点列表的父节点列表
|
||||
// function getNodesParent(index: Index, nodes: Index[]) {
|
||||
// const parentNodes = [];
|
||||
// treeMap(index, (p, c) => {
|
||||
// if (nodes.indexOf(c) != -1 && parentNodes.indexOf(p) != -1) {
|
||||
// parentNodes.push(p);
|
||||
// }
|
||||
// });
|
||||
// return parentNodes;
|
||||
// }
|
||||
//获取树的深度字典
|
||||
function getDepDic(index: Index) {
|
||||
let depDic = {};
|
||||
treeMap(index, (p, c, dep) => {
|
||||
treeMapCore(index, (node, parent, dep) => {
|
||||
if (!depDic[dep]) {
|
||||
depDic[dep] = [];
|
||||
}
|
||||
depDic[dep].push(p);
|
||||
depDic[dep].push(node);
|
||||
});
|
||||
return depDic;
|
||||
}
|
||||
// //获取树的深度字典(不保留有输入值节点的子节点)
|
||||
function getDepDicExincludeHasInput(index: Index) {
|
||||
let depDic = {};
|
||||
treeMapCore(index, (node, parent, dep) => {
|
||||
if (!depDic[dep]) {
|
||||
depDic[dep] = [];
|
||||
}
|
||||
depDic[dep].push(node);
|
||||
if ([undefined, null, ""].indexOf(node.inputValue) == -1) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return depDic;
|
||||
}
|
||||
//清除保留的计算值
|
||||
function clearCalValue(index: Index) {
|
||||
treeMapCore(index, node => (node.calValue = null));
|
||||
}
|
||||
|
||||
//对节点进行计算
|
||||
function calIndex(index: Index) {
|
||||
function calIndex(index: Index, lang: Lang = "js") {
|
||||
const paramDic = {};
|
||||
index.children.forEach(
|
||||
//计算值与输入值优先取输入值
|
||||
|
@ -70,12 +77,27 @@ function calIndex(index: Index) {
|
|||
[undefined, null, ""].indexOf(item.inputValue) == -1
|
||||
? item.inputValue
|
||||
: item.calValue;
|
||||
if (paramDic[item.key] === null) {
|
||||
throw new IndexCalError(
|
||||
"paramValueNotInput",
|
||||
`${index.name}-${item.name}值未配置`,
|
||||
{
|
||||
index
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (!index.codeConfig) {
|
||||
throw new IndexCalError("codeConfigNotConfig", index.name + "公式未配置", {
|
||||
index
|
||||
});
|
||||
}
|
||||
let code = index.codeConfig[lang];
|
||||
const defineValueCode = `let {${Object.keys(paramDic).join(
|
||||
","
|
||||
)}}=${JSON.stringify(paramDic)}`;
|
||||
let evalCode = `()=>{${defineValueCode + "\n" + index.code}}`;
|
||||
let evalCode = `()=>{${defineValueCode + "\n" + code}}`;
|
||||
let res = eval(evalCode)();
|
||||
return res;
|
||||
}
|
||||
|
@ -87,30 +109,21 @@ class IndexCalRunner {
|
|||
this.data = JSON.parse(JSON.stringify(sourecData));
|
||||
this.sourecData = sourecData;
|
||||
}
|
||||
run(data: Index) {
|
||||
// let data = JSON.parse(JSON.stringify(this.data));
|
||||
const depDic = getDepDic(data);
|
||||
run(data: Index, lang: Lang = "js") {
|
||||
clearCalValue(data);
|
||||
const depDic = getDepDicExincludeHasInput(data);
|
||||
let maxDep = Math.max(...Object.keys(depDic).map(item => Number(item)));
|
||||
// let parents = getLeafParentNodes(data);
|
||||
for (let i = maxDep; i > 0; i--) {
|
||||
let parents = depDic[i];
|
||||
parents.forEach(item => {
|
||||
const calValue = calIndex(item);
|
||||
item.calValue = calValue;
|
||||
if (item.children && item.children.length) {
|
||||
const calValue = calIndex(item, lang);
|
||||
item.calValue = calValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
// while (true) {
|
||||
// if (!(parents && parents.length > 0)) {
|
||||
// break;
|
||||
// }
|
||||
// parents.forEach(item => {
|
||||
// const calValue = calIndex(item);
|
||||
// item.calValue = calValue;
|
||||
// });
|
||||
// parents = getNodesParent(data, parents);
|
||||
// }
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export { IndexCalRunner, treeMap };
|
||||
export { IndexCalRunner, IndexCalError, treeMapCore };
|
||||
|
|
Loading…
Reference in New Issue