在 JavaScript 计算过程中,因为计算机底层二进制存储的原因导致结果出现精度问题,而 number-precision 第三库就是解决这个精度问题的。
安装依赖如下:
npm install number-precision --save
使用 JavaScript 中的 reduce() 方法,对数组中每个元素执行一个 reduce 函数后,将其结果汇总返回值,比如:数值求和、数值中元素出现的次数、数组去重等等。
export const handleTableTotal = function (key, data = [], sum = 0) {
if (!data.length) return sum
return data.reduce((prev, next) => {
return NP.plus(prev, (key ? next[key] : next) || 0)
}, sum)
}
reduce() 方法还可以将数组转换为对象。代码如下:
// optionsSource 为原数组
const getEnumMap = function (optionsSource, key = 'dictCode', value = 'dictValue') {
return optionsSource.reduce((obj, item) => {
obj[item[key]] = item[value]
return obj
}, {})
}
// 相当于
const arrayToObject = function (optionsSource, key = 'dictCode', value = 'dictValue') {
let obj = {}
if (!key || !optionsSource.length) return {}
for (let i = 0; i < optionsSource.length; i++) {
const { [key]: k, [value]: v } = optionsSource[i]
obj[k] = v
}
return obj
}
使用如下:
handleCheckData () {
// 付款金额合计值不能小于 0
if (handleTableTotal('amount', this.selectedRows) < 0) {
this.$antdMessage.warning('请选择 [付款金额] 合计值不能小于 0 的数据')
return
}
return true
},
针对汇总数据,使用函数返回数组格式。
export const handleDetailsData = function (data = []) {
return [
{ title: '收款金额', value: handleTableTotal('amount', data) },
{ title: '总数量', value: handleTableTotal('qty', data), isConvert: false },
{ title: '未申请金额', value: handleTableTotal('waitApplyAmount', data) },
{ title: '本次申请金额', value: handleTableTotal('applyAmount', data) },
]
}
<table-total dataSource={config.handleRefundDetailsData.call(this, this.selectedRows)} selectedRows={this.selectedRows}/>
针对汇总数据,统一使用 TableTotal 组件中的样式显示。
import { thousandMark } from '@/utils/util'
import { isDef } from '@/utils/business/definetion.js'
export default {
name: 'TableTotal',
props: {
// 数据源
dataSource: {
type: Function | Array,
required: true,
},
optionModel: {
type: Object,
default: () => ({
name: 'title',
value: 'value',
isConvert: true,
}),
},
},
render () {
const data = (typeof this.dataSource === 'function') ? this.dataSource() : this.dataSource
return <div>
{data.length !== 0 && <a-alert type="info">
<template slot="message">
<span class="sum-info">
{data.map(item => {
const value = (isDef(item.isConvert)
? item.isConvert : this.optionModel.isConvert)
? thousandMark(item[this.optionModel.value]) : item[this.optionModel.value]
return <span>{item[this.optionModel.name]} : {value}</span>
})}
</span>
</template>
</a-alert>}
</div>
},
}
上述汇总数据数组是名称都是固定好的,根据 columns 上的名称来动态统计信息的名称处理如下:
export default {
name: 'TableTotal',
props: {
......
columns: {
type: Array,
default: () => ([]),
},
},
render () {
const data = (typeof this.dataSource === 'function') ? this.dataSource() : this.dataSource
return <div>
{data.length !== 0 && <a-alert type="info">
<template slot="message">
<span class="sum-info">
{data.map(item => {
function getName (row) {
if (row[this.optionModel.name] || !this.columns.length) return row[this.optionModel.name]
return (this.columns.find(item => item.dataIndex === row.key) || {}).title
}
......
return <span>{getName.call(this, item)} : {value}</span>
})}
</span>
</template>
</a-alert>}
</div>
},
}