index.vue
2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<template>
<el-input v-model="innerValue" readonly placeholder="用于展示计算结果" />
</template>
<script>
import { mergeNumberOfExps, validExp, toRPN, calcRPN, debounce } from '../../utils'
export default {
model: {
prop: 'value',
event: 'input'
},
props: [
"value",
"formData",
"expression",
"rowIndex" // 计算公式放在表格中时, 需要获取在表格中的行位置
],
name: 'calculate',
data() {
return {
innerValue: this.value,
RPN_EXP: toRPN(mergeNumberOfExps(this.expression))
}
},
computed: {
rootFormData() {
return this.formData || this.getFormData()
},
},
methods: {
getFormData() {
var root = this.$parent
while (root) {
if ('vmFormData' in root) {
return root.vmFormData
}
root = root.$parent
}
},
/**
* 获取指定组件的值
*/
getFormVal(vModel) {
try {
if (vModel.indexOf('.') > -1) {
let [tabelVModel, cmpVModel] = vModel.split('.')
if (typeof this.rowIndex === 'number') {
return this.rootFormData[tabelVModel][this.rowIndex][cmpVModel] || 0
} else {
return this.rootFormData[tabelVModel].reduce((sum, c) => (c[cmpVModel] ? Number(c[cmpVModel]) : 0) + sum, 0)
}
}
return this.rootFormData[vModel] || 0
} catch (error) {
console.warn('计算公式出错, 可能包含无效的组件值', error)
return 0
}
},
/**
* 计算表达式
*/
execRPN() {
const temp = this.RPN_EXP.map(t => typeof t === 'object' ? this.getFormVal(t.__vModel__) : t)
this.innerValue = calcRPN(temp)
if (isNaN(this.innerValue)) this.innerValue = 0
this.$emit('input', this.innerValue)
}
},
watch: {
formData: {
handler: function (val) {
if (!val) return
if (!this.computeExps) { // formData更新可能比较频繁
this.computeExps = debounce(this.execRPN, 500)
}
this.computeExps()
},
deep: true,
immediate: true
}
}
}
</script>