gm-printer 11.1.0-beta.0 → 11.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/demo.js +7 -7
- package/package.json +1 -1
- package/src/printer/long_print_table/index.js +2 -0
- package/src/printer/store.js +6 -3
- package/src/printer/table.js +2 -0
- package/src/printer/table_diy_overallOrder_tr.js +6 -157
- package/src/printer/table_diy_summary_tr.js +42 -57
- package/src/printer/table_overallOrder_tr.js +36 -6
- package/src/printer/table_subtotal_tr.js +29 -2
- package/src/util.js +109 -1
package/package.json
CHANGED
|
@@ -125,6 +125,7 @@ class Table extends React.Component {
|
|
|
125
125
|
<>
|
|
126
126
|
<SubtotalTr
|
|
127
127
|
range={range}
|
|
128
|
+
pageIndex={pageIndex}
|
|
128
129
|
config={config}
|
|
129
130
|
printerStore={printerStore}
|
|
130
131
|
isSomeSubtotalTr={isSomeSubtotalTr}
|
|
@@ -140,6 +141,7 @@ class Table extends React.Component {
|
|
|
140
141
|
<PageSummary {...this.props} />
|
|
141
142
|
<SubtotalTr
|
|
142
143
|
range={range}
|
|
144
|
+
pageIndex={pageIndex}
|
|
143
145
|
config={config}
|
|
144
146
|
printerStore={printerStore}
|
|
145
147
|
isSomeSubtotalTr={isSomeSubtotalTr}
|
package/src/printer/store.js
CHANGED
|
@@ -584,7 +584,7 @@ class PrinterStore {
|
|
|
584
584
|
}
|
|
585
585
|
}
|
|
586
586
|
|
|
587
|
-
templateTable(text, dataKey, index, pageIndex) {
|
|
587
|
+
templateTable(text, dataKey, index, pageIndex, options = {}) {
|
|
588
588
|
// 做好保护,出错就返回 text
|
|
589
589
|
try {
|
|
590
590
|
let list = this.data._table[dataKey] || this.data._table.orders
|
|
@@ -594,15 +594,18 @@ class PrinterStore {
|
|
|
594
594
|
list = _.uniqBy(list, '序号')
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
const { rowTransform, priceFn = price } = options
|
|
598
|
+
const sourceRow = list[index]
|
|
599
|
+
const row = rowTransform ? rowTransform(sourceRow) : sourceRow
|
|
597
600
|
return _.template(text, {
|
|
598
601
|
interpolate: /{{([\s\S]+?)}}/g
|
|
599
602
|
})({
|
|
600
603
|
...this.data.common,
|
|
601
604
|
|
|
602
|
-
[i18next.t('列')]:
|
|
605
|
+
[i18next.t('列')]: row,
|
|
603
606
|
[i18next.t('当前页码')]: pageIndex + 1,
|
|
604
607
|
[i18next.t('页码总数')]: this.pages.length,
|
|
605
|
-
price:
|
|
608
|
+
price: priceFn // 提供一个价格处理函数
|
|
606
609
|
})
|
|
607
610
|
} catch (err) {
|
|
608
611
|
return text
|
package/src/printer/table.js
CHANGED
|
@@ -185,6 +185,7 @@ class Table extends React.Component {
|
|
|
185
185
|
<>
|
|
186
186
|
<SubtotalTr
|
|
187
187
|
range={range}
|
|
188
|
+
pageIndex={pageIndex}
|
|
188
189
|
config={config}
|
|
189
190
|
printerStore={printerStore}
|
|
190
191
|
isSomeSubtotalTr={isSomeSubtotalTr}
|
|
@@ -200,6 +201,7 @@ class Table extends React.Component {
|
|
|
200
201
|
<PageSummary {...this.props} />
|
|
201
202
|
<SubtotalTr
|
|
202
203
|
range={range}
|
|
204
|
+
pageIndex={pageIndex}
|
|
203
205
|
config={config}
|
|
204
206
|
printerStore={printerStore}
|
|
205
207
|
isSomeSubtotalTr={isSomeSubtotalTr}
|
|
@@ -1,168 +1,17 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import
|
|
4
|
-
// import Big from 'big.js'
|
|
5
|
-
import {
|
|
6
|
-
coverDigit2Uppercase,
|
|
7
|
-
getDataKey,
|
|
8
|
-
formatSumWithPrecision
|
|
9
|
-
} from '../util'
|
|
10
|
-
import { observer } from 'mobx-react'
|
|
11
|
-
import classNames from 'classnames'
|
|
12
|
-
import Big from 'big.js'
|
|
3
|
+
import DiySummary from './table_diy_summary_tr'
|
|
13
4
|
|
|
5
|
+
// 自定义整单合计复用通用自定义合计组件
|
|
14
6
|
const DiyOverallOrder = props => {
|
|
15
|
-
|
|
16
|
-
config: { diyOverallOrder, dataKey },
|
|
17
|
-
printerStore,
|
|
18
|
-
pageIndex
|
|
19
|
-
} = props
|
|
20
|
-
const tableData = printerStore.data._table[getDataKey(dataKey)] || []
|
|
21
|
-
|
|
22
|
-
const formatter = printerStore.config?.payAmountFormatter
|
|
23
|
-
const highPrecisionMapping = printerStore.config?.highPrecisionFieldMapping
|
|
24
|
-
|
|
25
|
-
// 计算合计
|
|
26
|
-
const sumData = field => {
|
|
27
|
-
// 查找高精度字段,有则直接从原始数据取值,避免 templateTable 的精度损失
|
|
28
|
-
const hpField = highPrecisionMapping?.[field]
|
|
29
|
-
const sum = _.reduce(
|
|
30
|
-
tableData,
|
|
31
|
-
(a, b, i) => {
|
|
32
|
-
let result = a
|
|
33
|
-
if (hpField) {
|
|
34
|
-
result = a.plus(b._origin?.[hpField] ?? b[hpField] ?? 0)
|
|
35
|
-
} else {
|
|
36
|
-
const bRes = printerStore
|
|
37
|
-
.templateTable(field, dataKey, i, pageIndex)
|
|
38
|
-
.replace(/\(\)/g, '')
|
|
39
|
-
result = a.plus(+bRes || 0)
|
|
40
|
-
}
|
|
41
|
-
return result
|
|
42
|
-
},
|
|
43
|
-
Big(0)
|
|
44
|
-
)
|
|
45
|
-
return formatSumWithPrecision(sum, formatter)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!diyOverallOrder?.show || !printerStore?.ready) {
|
|
49
|
-
return null
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const leftField = diyOverallOrder.fields?.[0]
|
|
53
|
-
if (!leftField) return null
|
|
54
|
-
const rightName = leftField.rightName || ''
|
|
55
|
-
|
|
56
|
-
// 左右显示分离
|
|
57
|
-
const isUpperLowerCaseSeparate = diyOverallOrder?.isUpperLowerCaseSeparate
|
|
58
|
-
// 大写金额在前
|
|
59
|
-
const isUpperCaseBefore = diyOverallOrder?.isUpperCaseBefore
|
|
60
|
-
// 大写金额
|
|
61
|
-
const needUpperCase = diyOverallOrder?.needUpperCase
|
|
62
|
-
// 小写金额
|
|
63
|
-
const numericValue = sumData(leftField.valueField)
|
|
64
|
-
// 大写金额
|
|
65
|
-
const upperCaseValue = needUpperCase ? coverDigit2Uppercase(numericValue) : ''
|
|
66
|
-
|
|
67
|
-
const leftText = () => {
|
|
68
|
-
if (isUpperLowerCaseSeparate) {
|
|
69
|
-
// 大写金额在前
|
|
70
|
-
if (isUpperCaseBefore) {
|
|
71
|
-
return upperCaseValue
|
|
72
|
-
}
|
|
73
|
-
// 小写金额在前
|
|
74
|
-
return numericValue
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 大写金额在前且需要大写金额
|
|
78
|
-
if (isUpperCaseBefore) {
|
|
79
|
-
return `${upperCaseValue} ${numericValue}`
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (needUpperCase) {
|
|
83
|
-
return `${numericValue} ${upperCaseValue}`
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return numericValue
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const rightText = () => {
|
|
90
|
-
if (isUpperLowerCaseSeparate) {
|
|
91
|
-
if (isUpperCaseBefore) {
|
|
92
|
-
return `${rightName} ${numericValue}`
|
|
93
|
-
}
|
|
94
|
-
return `${rightName} ${upperCaseValue}`
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return ''
|
|
98
|
-
}
|
|
99
|
-
return (
|
|
100
|
-
<tr>
|
|
101
|
-
<td colSpan={99}>
|
|
102
|
-
<div style={{ ...leftField.style }} className='gm-flex-page'>
|
|
103
|
-
{leftField.name}
|
|
104
|
-
<div
|
|
105
|
-
className={classNames('gm-flex-page', {
|
|
106
|
-
'gm-flex-justify-between-page': isUpperLowerCaseSeparate,
|
|
107
|
-
'gm-flex-grow-page': isUpperLowerCaseSeparate
|
|
108
|
-
})}
|
|
109
|
-
>
|
|
110
|
-
{/* 左侧金额 */}
|
|
111
|
-
<span>{leftText()}</span>
|
|
112
|
-
|
|
113
|
-
<span>{rightText()}</span>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
</td>
|
|
117
|
-
</tr>
|
|
118
|
-
)
|
|
119
|
-
// return (
|
|
120
|
-
// diyOverallOrder?.show &&
|
|
121
|
-
// printerStore?.ready && (
|
|
122
|
-
// <tr>
|
|
123
|
-
// {_.map(diyOverallOrder.fields, (item, index) => {
|
|
124
|
-
// return (
|
|
125
|
-
// <td colSpan={item.colSpan ?? 99} key={index}>
|
|
126
|
-
// <div style={{ ...item.style }} className='gm-flex-page'>
|
|
127
|
-
// {item.name}
|
|
128
|
-
// <div
|
|
129
|
-
// className={classNames('gm-flex-page', {
|
|
130
|
-
// 'gm-flex-justify-between-page':
|
|
131
|
-
// diyOverallOrder?.isUpperLowerCaseSeparate,
|
|
132
|
-
// 'gm-flex-grow-page':
|
|
133
|
-
// diyOverallOrder?.isUpperLowerCaseSeparate
|
|
134
|
-
// })}
|
|
135
|
-
// >
|
|
136
|
-
// <span
|
|
137
|
-
// className={
|
|
138
|
-
// diyOverallOrder?.isUpperCaseBefore
|
|
139
|
-
// ? 'gm-printer-subtotal-isUpperCaseBefore-inter'
|
|
140
|
-
// : ''
|
|
141
|
-
// }
|
|
142
|
-
// >
|
|
143
|
-
// {sumData(item.valueField)}
|
|
144
|
-
// </span>
|
|
145
|
-
// {diyOverallOrder?.needUpperCase && (
|
|
146
|
-
// <span>
|
|
147
|
-
// {coverDigit2Uppercase(sumData(item.valueField))
|
|
148
|
-
// ? coverDigit2Uppercase(sumData(item.valueField))
|
|
149
|
-
// : ''}
|
|
150
|
-
// </span>
|
|
151
|
-
// )}
|
|
152
|
-
// </div>
|
|
153
|
-
// </div>
|
|
154
|
-
// </td>
|
|
155
|
-
// )
|
|
156
|
-
// })}
|
|
157
|
-
// </tr>
|
|
158
|
-
// )
|
|
159
|
-
// )
|
|
7
|
+
return <DiySummary {...props} configKey='diyOverallOrder' />
|
|
160
8
|
}
|
|
9
|
+
|
|
161
10
|
DiyOverallOrder.propTypes = {
|
|
162
11
|
config: PropTypes.object.isRequired,
|
|
163
|
-
range: PropTypes.object
|
|
12
|
+
range: PropTypes.object,
|
|
164
13
|
printerStore: PropTypes.object,
|
|
165
14
|
pageIndex: PropTypes.number
|
|
166
15
|
}
|
|
167
16
|
|
|
168
|
-
export default
|
|
17
|
+
export default DiyOverallOrder
|
|
@@ -2,6 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import _ from 'lodash'
|
|
4
4
|
import {
|
|
5
|
+
calculateDiySummary,
|
|
5
6
|
coverDigit2Uppercase,
|
|
6
7
|
getDataKey,
|
|
7
8
|
isMultiTable,
|
|
@@ -53,67 +54,52 @@ const DiySummary = props => {
|
|
|
53
54
|
|
|
54
55
|
const formatter = printerStore.config?.payAmountFormatter
|
|
55
56
|
const highPrecisionMapping = printerStore.config?.highPrecisionFieldMapping
|
|
57
|
+
const isRoundFirst =
|
|
58
|
+
printerStore.data._origin?.precision_control?.is_round_first === true
|
|
56
59
|
|
|
57
|
-
//
|
|
60
|
+
// 单栏使用统一计算器;多栏保留原有后缀字段累加逻辑
|
|
58
61
|
const sumData = field => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const fieldKey = extractSumField(field)
|
|
62
|
-
const hpField =
|
|
63
|
-
highPrecisionMapping?.[field] || highPrecisionMapping?.[fieldKey]
|
|
64
|
-
|
|
65
|
-
if (isMulti) {
|
|
66
|
-
// 多栏表格暂不使用高精度字段,保持原有 templateTable 逻辑
|
|
67
|
-
const sum = _.reduce(
|
|
62
|
+
if (!isMulti) {
|
|
63
|
+
return calculateDiySummary({
|
|
68
64
|
tableData,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Big(0)
|
|
85
|
-
)
|
|
86
|
-
return formatSumWithPrecision(sum, formatter)
|
|
65
|
+
valueField: field,
|
|
66
|
+
formatter,
|
|
67
|
+
highPrecisionMapping,
|
|
68
|
+
isRoundFirst,
|
|
69
|
+
renderTemplate: (template, index, options) =>
|
|
70
|
+
printerStore
|
|
71
|
+
.templateTable(
|
|
72
|
+
template,
|
|
73
|
+
dataKey,
|
|
74
|
+
range ? range.begin + index : index,
|
|
75
|
+
pageIndex,
|
|
76
|
+
options
|
|
77
|
+
)
|
|
78
|
+
.replace(/\(\)/g, '')
|
|
79
|
+
})
|
|
87
80
|
}
|
|
88
81
|
|
|
89
|
-
// 单栏:有高精度字段则直接从原始数据取值
|
|
90
|
-
if (hpField) {
|
|
91
|
-
const sum = _.reduce(
|
|
92
|
-
tableData,
|
|
93
|
-
(a, b) => {
|
|
94
|
-
return a.plus(b._origin?.[hpField] ?? b[hpField] ?? 0)
|
|
95
|
-
},
|
|
96
|
-
Big(0)
|
|
97
|
-
)
|
|
98
|
-
return formatSumWithPrecision(sum, formatter)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 兜底:无高精度字段,使用 templateTable
|
|
102
82
|
const sum = _.reduce(
|
|
103
83
|
tableData,
|
|
104
|
-
(
|
|
105
|
-
let result =
|
|
106
|
-
const
|
|
107
|
-
result =
|
|
108
|
-
|
|
84
|
+
(total, row, index) => {
|
|
85
|
+
let result = total.plus(+getRes(field, index) || 0)
|
|
86
|
+
const multiField = buildTemplateField(field, MULTI_SUFFIX)
|
|
87
|
+
result = result.plus(+getRes(multiField, index) || 0)
|
|
88
|
+
const multiField3 = buildTemplateField(field, MULTI_SUFFIX3)
|
|
89
|
+
return result.plus(+getRes(multiField3, index) || 0)
|
|
109
90
|
},
|
|
110
91
|
Big(0)
|
|
111
92
|
)
|
|
112
93
|
return formatSumWithPrecision(sum, formatter)
|
|
113
94
|
|
|
114
|
-
function getRes(
|
|
95
|
+
function getRes(template, index) {
|
|
115
96
|
return printerStore
|
|
116
|
-
.templateTable(
|
|
97
|
+
.templateTable(
|
|
98
|
+
template,
|
|
99
|
+
dataKey,
|
|
100
|
+
range ? range.begin + index : index,
|
|
101
|
+
pageIndex
|
|
102
|
+
)
|
|
117
103
|
.replace(/\(\)/g, '')
|
|
118
104
|
}
|
|
119
105
|
}
|
|
@@ -131,15 +117,14 @@ const DiySummary = props => {
|
|
|
131
117
|
const isUpperLowerCaseSeparate = diyConfig?.isUpperLowerCaseSeparate
|
|
132
118
|
const isUpperCaseBefore = diyConfig?.isUpperCaseBefore
|
|
133
119
|
const needUpperCase = diyConfig?.needUpperCase
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
)
|
|
120
|
+
// 单栏完整遵循统一舍入顺序;多栏保持原有求和后执行模板逻辑
|
|
121
|
+
const displayValue = isMulti
|
|
122
|
+
? templateSumResult(
|
|
123
|
+
leftField.valueField,
|
|
124
|
+
sumData(toSumColTemplate(leftField.valueField)),
|
|
125
|
+
extractSumField(leftField.valueField)
|
|
126
|
+
)
|
|
127
|
+
: sumData(leftField.valueField)
|
|
143
128
|
const upperCaseValue = needUpperCase ? coverDigit2Uppercase(displayValue) : ''
|
|
144
129
|
|
|
145
130
|
const leftText = () => {
|
|
@@ -2,24 +2,56 @@ import React from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import _ from 'lodash'
|
|
4
4
|
// import Big from 'big.js'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
calculateDiySummary,
|
|
7
|
+
coverDigit2Uppercase,
|
|
8
|
+
extractSumField,
|
|
9
|
+
getDataKey,
|
|
10
|
+
hasDiySummaryExpression
|
|
11
|
+
} from '../util'
|
|
6
12
|
import { observer } from 'mobx-react'
|
|
7
13
|
import classNames from 'classnames'
|
|
8
14
|
|
|
9
15
|
const OverallOrder = props => {
|
|
10
16
|
const {
|
|
11
|
-
config: { overallOrder },
|
|
17
|
+
config: { overallOrder, dataKey, arrange },
|
|
12
18
|
printerStore,
|
|
13
19
|
printerStore: {
|
|
14
20
|
data: { common }
|
|
15
21
|
}
|
|
16
22
|
} = props
|
|
23
|
+
const tableDataKey = getDataKey(dataKey, arrange)
|
|
24
|
+
const tableData = printerStore.data._table[tableDataKey] || []
|
|
25
|
+
const formatter = printerStore.config?.payAmountFormatter
|
|
26
|
+
const highPrecisionMapping = printerStore.config?.highPrecisionFieldMapping
|
|
27
|
+
const isRoundFirst =
|
|
28
|
+
printerStore.data._origin?.precision_control?.is_round_first === true
|
|
29
|
+
|
|
30
|
+
// 普通字段沿用服务端整单值,表达式使用统一明细计算器
|
|
31
|
+
const getOverallValue = valueField => {
|
|
32
|
+
const fieldKey = extractSumField(valueField)
|
|
33
|
+
if (!hasDiySummaryExpression(valueField)) {
|
|
34
|
+
return common?.[fieldKey] ?? ''
|
|
35
|
+
}
|
|
36
|
+
return calculateDiySummary({
|
|
37
|
+
tableData,
|
|
38
|
+
valueField,
|
|
39
|
+
formatter,
|
|
40
|
+
highPrecisionMapping,
|
|
41
|
+
isRoundFirst,
|
|
42
|
+
renderTemplate: (template, index, options) =>
|
|
43
|
+
printerStore
|
|
44
|
+
.templateTable(template, tableDataKey, index, undefined, options)
|
|
45
|
+
.replace(/\(\)/g, '')
|
|
46
|
+
})
|
|
47
|
+
}
|
|
17
48
|
|
|
18
49
|
return (
|
|
19
50
|
overallOrder?.show &&
|
|
20
51
|
printerStore?.ready && (
|
|
21
52
|
<tr>
|
|
22
53
|
{_.map(overallOrder.fields, (item, index) => {
|
|
54
|
+
const displayValue = getOverallValue(item.valueField)
|
|
23
55
|
return (
|
|
24
56
|
<td colSpan={item.colSpan} key={index}>
|
|
25
57
|
<div style={{ ...item.style }} className='gm-flex-page'>
|
|
@@ -38,13 +70,11 @@ const OverallOrder = props => {
|
|
|
38
70
|
: ''
|
|
39
71
|
}
|
|
40
72
|
>
|
|
41
|
-
{
|
|
73
|
+
{displayValue}
|
|
42
74
|
</span>
|
|
43
75
|
{overallOrder?.needUpperCase && (
|
|
44
76
|
<span>
|
|
45
|
-
{
|
|
46
|
-
? coverDigit2Uppercase(common[item.valueField])
|
|
47
|
-
: ''}
|
|
77
|
+
{displayValue ? coverDigit2Uppercase(displayValue) : ''}
|
|
48
78
|
</span>
|
|
49
79
|
)}
|
|
50
80
|
</div>
|
|
@@ -5,10 +5,12 @@ import _ from 'lodash'
|
|
|
5
5
|
import { MULTI_SUFFIX, MULTI_SUFFIX3 } from '../config'
|
|
6
6
|
import Big from 'big.js'
|
|
7
7
|
import {
|
|
8
|
+
calculateDiySummary,
|
|
8
9
|
coverDigit2Uppercase,
|
|
9
10
|
getDataKey,
|
|
10
11
|
formatSumWithPrecision,
|
|
11
12
|
extractSumField,
|
|
13
|
+
isMultiTable,
|
|
12
14
|
templateSumResult
|
|
13
15
|
} from '../util'
|
|
14
16
|
import { observer } from 'mobx-react'
|
|
@@ -47,10 +49,14 @@ const SubtotalTr = props => {
|
|
|
47
49
|
}
|
|
48
50
|
},
|
|
49
51
|
range,
|
|
52
|
+
pageIndex,
|
|
50
53
|
printerStore,
|
|
51
54
|
isSomeSubtotalTr
|
|
52
55
|
} = props
|
|
53
56
|
const tableData = printerStore.data._table[getDataKey(dataKey, arrange)] || []
|
|
57
|
+
const isMulti = isMultiTable(dataKey)
|
|
58
|
+
const isRoundFirst =
|
|
59
|
+
printerStore.data._origin?.precision_control?.is_round_first === true
|
|
54
60
|
|
|
55
61
|
// 计算合计
|
|
56
62
|
const sumData2 = (list, field, formatter, highPrecisionMapping) => {
|
|
@@ -97,8 +103,28 @@ const SubtotalTr = props => {
|
|
|
97
103
|
if (show && printerStore.ready) {
|
|
98
104
|
const list = tableData.slice(range.begin, range.end)
|
|
99
105
|
|
|
100
|
-
//
|
|
106
|
+
// 单栏使用统一舍入逻辑,多栏保留原有后缀字段累加
|
|
101
107
|
const formatSumValue = valueField => {
|
|
108
|
+
if (!isMulti) {
|
|
109
|
+
return calculateDiySummary({
|
|
110
|
+
tableData: list,
|
|
111
|
+
valueField,
|
|
112
|
+
formatter,
|
|
113
|
+
highPrecisionMapping,
|
|
114
|
+
isRoundFirst,
|
|
115
|
+
renderTemplate: (template, index, options) =>
|
|
116
|
+
printerStore
|
|
117
|
+
.templateTable(
|
|
118
|
+
template,
|
|
119
|
+
dataKey,
|
|
120
|
+
range.begin + index,
|
|
121
|
+
pageIndex,
|
|
122
|
+
options
|
|
123
|
+
)
|
|
124
|
+
.replace(/\(\)/g, '')
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
102
128
|
const fieldKey = extractSumField(valueField)
|
|
103
129
|
const sum = sumData2(list, fieldKey, formatter, highPrecisionMapping)
|
|
104
130
|
return templateSumResult(valueField, sum, fieldKey)
|
|
@@ -201,7 +227,8 @@ const SubtotalTr = props => {
|
|
|
201
227
|
SubtotalTr.propTypes = {
|
|
202
228
|
config: PropTypes.object.isRequired,
|
|
203
229
|
range: PropTypes.object.isRequired,
|
|
204
|
-
printStore: PropTypes.object
|
|
230
|
+
printStore: PropTypes.object,
|
|
231
|
+
pageIndex: PropTypes.number
|
|
205
232
|
}
|
|
206
233
|
|
|
207
234
|
export default observer(SubtotalTr)
|
package/src/util.js
CHANGED
|
@@ -450,6 +450,112 @@ const toSumColTemplate = text => {
|
|
|
450
450
|
return `{{列.${key}}}`
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
/**
|
|
454
|
+
* 判断自定义合计配置是否包含函数或运算表达式
|
|
455
|
+
* @param {string} valueField
|
|
456
|
+
* @returns {boolean}
|
|
457
|
+
*/
|
|
458
|
+
const hasDiySummaryExpression = valueField => {
|
|
459
|
+
const expression =
|
|
460
|
+
typeof valueField === 'string'
|
|
461
|
+
? valueField.match(/{{([\s\S]+?)}}/)?.[1]?.trim()
|
|
462
|
+
: ''
|
|
463
|
+
return expression ? !/^(?:列\.)?[\w㐀-鿿()]+$/.test(expression) : false
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* 按字段/表达式和舍入顺序计算自定义合计
|
|
468
|
+
* @param {Object} options
|
|
469
|
+
* @returns {string}
|
|
470
|
+
*/
|
|
471
|
+
const calculateDiySummary = options => {
|
|
472
|
+
const {
|
|
473
|
+
tableData,
|
|
474
|
+
valueField,
|
|
475
|
+
formatter,
|
|
476
|
+
highPrecisionMapping,
|
|
477
|
+
isRoundFirst,
|
|
478
|
+
renderTemplate
|
|
479
|
+
} = options
|
|
480
|
+
const hasExpression = hasDiySummaryExpression(valueField)
|
|
481
|
+
|
|
482
|
+
// 用高精度字段构造公式上下文,不修改实际打印行
|
|
483
|
+
const getHighPrecisionRow = row => {
|
|
484
|
+
const formulaRow = { ...row }
|
|
485
|
+
_.forEach(highPrecisionMapping, (hpField, field) => {
|
|
486
|
+
const value = row._origin?.[hpField] ?? row[hpField]
|
|
487
|
+
if (value !== undefined && value !== null) {
|
|
488
|
+
formulaRow[field] = value
|
|
489
|
+
}
|
|
490
|
+
})
|
|
491
|
+
return formulaRow
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (!hasExpression) {
|
|
495
|
+
const fieldKey = extractSumField(valueField)
|
|
496
|
+
const mappedField = getHighPrecisionField(fieldKey, highPrecisionMapping)
|
|
497
|
+
const hpField = highPrecisionMapping?.[valueField] || mappedField
|
|
498
|
+
const hasHighPrecisionField = hpField !== fieldKey
|
|
499
|
+
const columnTemplate = valueField.includes('{{')
|
|
500
|
+
? valueField
|
|
501
|
+
: toSumColTemplate(valueField)
|
|
502
|
+
const sum = _.reduce(
|
|
503
|
+
tableData,
|
|
504
|
+
(total, row, index) => {
|
|
505
|
+
const rawValue = hasHighPrecisionField
|
|
506
|
+
? row._origin?.[hpField] ?? row[hpField] ?? 0
|
|
507
|
+
: renderTemplate(columnTemplate, index)
|
|
508
|
+
const value =
|
|
509
|
+
isRoundFirst && formatter ? formatter(rawValue).toFixed() : rawValue
|
|
510
|
+
const numericValue = value === '' || isNaN(Number(value)) ? 0 : value
|
|
511
|
+
return total.plus(numericValue)
|
|
512
|
+
},
|
|
513
|
+
Big(0)
|
|
514
|
+
)
|
|
515
|
+
return formatSumWithPrecision(sum, formatter)
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// 表达式最多包含一个 price;后舍入模式下将 price 延迟到合计结果
|
|
519
|
+
const usesPrice = /\bprice\s*\(/.test(valueField)
|
|
520
|
+
let formulaPrecision = 2
|
|
521
|
+
let decimalPlaces = 0
|
|
522
|
+
const deferredPrice = (value, precision = 2) => {
|
|
523
|
+
formulaPrecision = precision
|
|
524
|
+
return value
|
|
525
|
+
}
|
|
526
|
+
const sum = _.reduce(
|
|
527
|
+
tableData,
|
|
528
|
+
(total, row, index) => {
|
|
529
|
+
const renderOptions = isRoundFirst
|
|
530
|
+
? undefined
|
|
531
|
+
: {
|
|
532
|
+
rowTransform: getHighPrecisionRow,
|
|
533
|
+
priceFn: usesPrice ? deferredPrice : undefined
|
|
534
|
+
}
|
|
535
|
+
const result = String(
|
|
536
|
+
renderTemplate(valueField, index, renderOptions)
|
|
537
|
+
).trim()
|
|
538
|
+
if (result === '' || isNaN(Number(result))) return total
|
|
539
|
+
|
|
540
|
+
const value =
|
|
541
|
+
isRoundFirst && !usesPrice && formatter
|
|
542
|
+
? formatter(result).toFixed()
|
|
543
|
+
: result
|
|
544
|
+
const decimalPart = String(value).split('.')[1]
|
|
545
|
+
decimalPlaces = Math.max(decimalPlaces, decimalPart?.length || 0)
|
|
546
|
+
return total.plus(value)
|
|
547
|
+
},
|
|
548
|
+
Big(0)
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
if (!isRoundFirst && usesPrice) {
|
|
552
|
+
return price(sum, formulaPrecision)
|
|
553
|
+
}
|
|
554
|
+
return usesPrice
|
|
555
|
+
? sum.toFixed(decimalPlaces)
|
|
556
|
+
: formatSumWithPrecision(sum, formatter)
|
|
557
|
+
}
|
|
558
|
+
|
|
453
559
|
export {
|
|
454
560
|
collectGroups,
|
|
455
561
|
getHeight,
|
|
@@ -476,5 +582,7 @@ export {
|
|
|
476
582
|
price,
|
|
477
583
|
extractSumField,
|
|
478
584
|
templateSumResult,
|
|
479
|
-
toSumColTemplate
|
|
585
|
+
toSumColTemplate,
|
|
586
|
+
hasDiySummaryExpression,
|
|
587
|
+
calculateDiySummary
|
|
480
588
|
}
|