今天接到需求,要开发一个二维表格的统计功能,统计项是嵌套的,看来还是得思考下
具体需求如下
- 统计a.1项的值是由a.1.1, a.1.2,a.1.3的值求和得到
- a.1.2 的值由 a.1.2.1, a.1.2.2, a.1.2.3 求和得到
- 统计项的值只读,被统计项可输入,统计项随被统计项联动展示
效果如下
;
有的同学说你这个循环就搞定了,求个值搞个类,每个计算格子的地方来个函数,此时的我:
由于后面还有四个类似的表格,肯定不能硬编码到实现里了,后面表格变了代码也会废掉; 其实这个东西有点像浏览器里事件的冒泡,输入变了后,一次将变动向上传递给依赖,传递的过程中再去累加,但是考虑到样式和布局以及渲染的方便,这个实现方式没有继续深入;最终定的数据格式如下,渲染中去查找依赖并设置total
// 一个list 直接循环渲染出来,list 成员结构
{
"label": "金额1",
"code": "1",
"dependency": ['1.1','1.2', '1.3', '1.4', '1.5'], // 求和依赖
"attr": 0,
"value": [
{
"type": 1,
"dictCode": "1110001",
"doubleValue": "", // 每一列的值
},
{
"type": 1,
"dictCode": "1110002",
"doubleValue": ""
},
{
"type": 1,
"dictCode": "1110003",
"doubleValue": ""
},
{
"type": 1,
"dictCode": "1110004",
"doubleValue": ""
}
]
}
list 渲染组件
<template>
<div class="line">
<div class="label min middle-center padding-h">
{{desc.label}}
</div>
<div class="value">
<div class="line" v-for="(line) in desc.list" :key="line.label">
<div class="label reset padding-h">{{desc.label}}</div>
<template v-if="!line.dependency.length">
<div class="value" v-for="col in line.value" :key="col.dictCode">
<el-input v-model.number="col.doubleValue"></el-input>
</div>
</template>
<render-cell :origin-data="desc.list" :desc="line" v-else></render-cell>
</div>
</div>
</div>
</template>
render-cell 组件
<template>
export default {
name: 'renderCell',
props: {
originData: {
type: Array,
default () {
return []
}
},
desc: {
type: Object,
default () {
return {}
}
}
},
render (h) {
let getValue = (desc, originData) => {
let dependency = desc.dependency;
let dependencyObj = this.originData.filter(item => {
return dependency.some(dependencyId => item.code === dependencyId)
});
let initValue = JSON.parse(JSON.stringify(desc.value)).map(item => {
item.doubleValue = 0;
return item;
});
let value = dependencyObj.reduce((asum, item, idx) => {
let Ivalue = item.value;
if (item.dependency.length) {
Ivalue = getValue(item) // DFS
}
asum.forEach((elem, idx) => {
elem.doubleValue += Number(Ivalue[idx].doubleValue);
});
return asum;
}, initValue)
return value;
}
const value = getValue(this.desc);
return (
<fragment>
{
value.map(item => {
return (
<div class="value bg">
<el-input value={item.doubleValue} readonly={true}/>
</div>
)
})
}
</fragment>
)
}
}
</template>
为啥要用DFS呢?其实是因为金额 = 金额1 + 金额2 + 金额3的时候,这些的值可能是旧的;大家有好的方法希望可以在底下评论;抱拳。