gm-printer 10.41.0 → 10.41.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 +9 -9
- package/package.json +1 -1
- package/src/common/data_key_util.js +35 -0
- package/src/common/editor_edit_field.js +206 -168
- package/src/common/editor_store.js +16 -12
- package/src/editor_purchase/editor.js +2 -1
- package/src/editor_purchase/editor_special_table.js +16 -13
- package/src/editor_purchase/editor_sum_table.js +5 -1
- package/src/editor_purchase/store.js +47 -47
- package/src/printer/long_print_table/index.js +4 -2
- package/src/printer/printer.js +2 -5
- package/src/printer/store.js +113 -56
- package/src/printer/table.js +2 -1
- package/src/util.js +11 -3
|
@@ -16,10 +16,14 @@ class TableDetailEditor extends Component {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
render() {
|
|
19
|
-
const { editStore } = this.props
|
|
20
19
|
const {
|
|
21
20
|
addFields: { sumTableConfig }
|
|
22
21
|
} = this.props
|
|
22
|
+
// 业务侧可传 sumTableConfig.hide=true 隐藏「汇总表」开关;默认展示
|
|
23
|
+
if (sumTableConfig?.hide) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
const { editStore } = this.props
|
|
23
27
|
if (editStore.computedRegionIsTable) {
|
|
24
28
|
const arr = editStore.selectedRegion.split('.')
|
|
25
29
|
const tableConfig = editStore.config.contents[arr[2]]
|
|
@@ -1,58 +1,71 @@
|
|
|
1
1
|
import EditorStore from '../common/editor_store'
|
|
2
2
|
import { action, observable } from 'mobx'
|
|
3
3
|
import i18next from '../../locales'
|
|
4
|
+
import { getDataKeySuffix, isLastColDataKey } from '../common/data_key_util'
|
|
5
|
+
|
|
6
|
+
const getPurchaseDefaultDetailText = () =>
|
|
7
|
+
i18next.t('{{采购数量_采购单位}}{{采购单位}}*{{商户名}}*{{商品备注}}')
|
|
8
|
+
|
|
9
|
+
/** 创建/切换「单列-最后一列」时,明细列 text 应与 template_text 一致 */
|
|
10
|
+
const resolveDetailTemplateText = (tableConfig, specialTableConfig) => {
|
|
11
|
+
const existing = tableConfig.specialConfig?.template_text
|
|
12
|
+
if (existing) return existing
|
|
13
|
+
if (specialTableConfig && specialTableConfig.defaultDetailText !== undefined) {
|
|
14
|
+
return specialTableConfig.defaultDetailText
|
|
15
|
+
}
|
|
16
|
+
return getPurchaseDefaultDetailText()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const syncLastColColumnText = (tableConfig) => {
|
|
20
|
+
if (!isLastColDataKey(tableConfig.dataKey)) return
|
|
21
|
+
const templateText = tableConfig.specialConfig?.template_text
|
|
22
|
+
if (!templateText) return
|
|
23
|
+
const specialCol = tableConfig.columns?.find((o) => o.isSpecialColumn)
|
|
24
|
+
if (specialCol) specialCol.text = templateText
|
|
25
|
+
}
|
|
4
26
|
|
|
5
27
|
class Store extends EditorStore {
|
|
6
28
|
constructor({ defaultTableDataKey }) {
|
|
7
29
|
super()
|
|
8
|
-
this.defaultTableDataKey = defaultTableDataKey
|
|
30
|
+
this.defaultTableDataKey = defaultTableDataKey
|
|
9
31
|
}
|
|
10
32
|
|
|
11
33
|
@observable
|
|
12
34
|
customerTag = false
|
|
13
35
|
|
|
14
|
-
|
|
36
|
+
@action.bound
|
|
37
|
+
init(config, data) {
|
|
38
|
+
super.init(config, data)
|
|
39
|
+
config?.contents?.forEach((tableConfig) => {
|
|
40
|
+
if (tableConfig?.type === 'table') syncLastColColumnText(tableConfig)
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
15
44
|
@action.bound
|
|
16
45
|
setPurchaseTableKey(dataKey, specialTableConfig) {
|
|
17
|
-
// 先移除选中项,安全第一
|
|
18
46
|
this.selected = null
|
|
19
47
|
this.setTableDataKey(dataKey)
|
|
20
48
|
|
|
21
49
|
const arr = this.selectedRegion.split('.')
|
|
22
50
|
const tableConfig = this.config.contents[arr[2]]
|
|
23
51
|
|
|
24
|
-
|
|
25
|
-
const newCols = tableConfig.columns.filter(o => !o.isSpecialColumn)
|
|
52
|
+
const newCols = tableConfig.columns.filter((o) => !o.isSpecialColumn)
|
|
26
53
|
tableConfig.columns.replace(newCols)
|
|
27
54
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
dataKey === 'purchase_last_col' ||
|
|
31
|
-
dataKey === 'purchase_last_col_noLineBreak'
|
|
32
|
-
) {
|
|
55
|
+
if (isLastColDataKey(dataKey)) {
|
|
56
|
+
const templateText = resolveDetailTemplateText(tableConfig, specialTableConfig)
|
|
33
57
|
tableConfig.columns.push({
|
|
34
58
|
head: i18next.t('明细'),
|
|
35
59
|
headStyle: { textAlign: 'center' },
|
|
36
60
|
style: { textAlign: 'left' },
|
|
37
61
|
isSpecialColumn: true,
|
|
38
62
|
separator: '+',
|
|
39
|
-
// detailsType: 'purchase_last_col',
|
|
40
63
|
specialDetailsKey: '__details',
|
|
41
|
-
text:
|
|
42
|
-
specialTableConfig && specialTableConfig.defaultDetailText !== undefined
|
|
43
|
-
? specialTableConfig.defaultDetailText
|
|
44
|
-
: i18next.t(
|
|
45
|
-
'{{采购数量_采购单位}}{{采购单位}}*{{商户名}}*{{商品备注}}'
|
|
46
|
-
)
|
|
64
|
+
text: templateText,
|
|
47
65
|
})
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
?
|
|
51
|
-
tableConfig.columns.length - 1
|
|
52
|
-
].detailLastColType = 'purchase_last_col')
|
|
53
|
-
: (tableConfig.columns[
|
|
54
|
-
tableConfig.columns.length - 1
|
|
55
|
-
].detailLastColType = 'purchase_last_col_noLineBreak')
|
|
66
|
+
const suffix = getDataKeySuffix(dataKey)
|
|
67
|
+
tableConfig.columns[tableConfig.columns.length - 1].detailLastColType =
|
|
68
|
+
suffix === 'last_col' ? 'purchase_last_col' : 'purchase_last_col_noLineBreak'
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
71
|
|
|
@@ -62,13 +75,9 @@ class Store extends EditorStore {
|
|
|
62
75
|
const tableConfig = this.config.contents[arr[2]]
|
|
63
76
|
|
|
64
77
|
tableConfig.specialConfig.template_text = value
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
tableConfig.dataKey === 'purchase_last_col_noLineBreak'
|
|
69
|
-
) {
|
|
70
|
-
const specialCol = tableConfig.columns.find(o => o.isSpecialColumn)
|
|
71
|
-
specialCol.text = value
|
|
78
|
+
if (isLastColDataKey(tableConfig.dataKey)) {
|
|
79
|
+
const specialCol = tableConfig.columns.find((o) => o.isSpecialColumn)
|
|
80
|
+
if (specialCol) specialCol.text = value
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
83
|
|
|
@@ -78,13 +87,9 @@ class Store extends EditorStore {
|
|
|
78
87
|
const tableConfig = this.config.contents[arr[2]]
|
|
79
88
|
|
|
80
89
|
tableConfig.specialConfig.style = value
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
tableConfig.dataKey === 'purchase_last_col_noLineBreak'
|
|
85
|
-
) {
|
|
86
|
-
const specialCol = tableConfig.columns.find(o => o.isSpecialColumn)
|
|
87
|
-
specialCol.style = value
|
|
90
|
+
if (isLastColDataKey(tableConfig.dataKey)) {
|
|
91
|
+
const specialCol = tableConfig.columns.find((o) => o.isSpecialColumn)
|
|
92
|
+
if (specialCol) specialCol.style = value
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
|
|
@@ -94,17 +99,12 @@ class Store extends EditorStore {
|
|
|
94
99
|
const tableConfig = this.config.contents[arr[2]]
|
|
95
100
|
|
|
96
101
|
tableConfig.specialConfig.template_text += fieldText
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
tableConfig.dataKey === 'purchase_last_col_noLineBreak'
|
|
101
|
-
) {
|
|
102
|
-
const specialCol = tableConfig.columns.find(o => o.isSpecialColumn)
|
|
103
|
-
specialCol.text += fieldText
|
|
102
|
+
if (isLastColDataKey(tableConfig.dataKey)) {
|
|
103
|
+
const specialCol = tableConfig.columns.find((o) => o.isSpecialColumn)
|
|
104
|
+
if (specialCol) specialCol.text += fieldText
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
/* end---------设置采购明细相关--------- */
|
|
108
108
|
@action.bound
|
|
109
109
|
switchCustomerTag(val) {
|
|
110
110
|
const arr = this.selectedRegion.split('.')
|
|
@@ -203,7 +203,8 @@ class Table extends React.Component {
|
|
|
203
203
|
? printerStore.templateSpecialDetails(
|
|
204
204
|
col,
|
|
205
205
|
dataKey,
|
|
206
|
-
i
|
|
206
|
+
i,
|
|
207
|
+
config.specialConfig?.template_text
|
|
207
208
|
)
|
|
208
209
|
: printerStore
|
|
209
210
|
.templateTable(
|
|
@@ -309,7 +310,8 @@ class Table extends React.Component {
|
|
|
309
310
|
? printerStore.templateSpecialDetails(
|
|
310
311
|
col,
|
|
311
312
|
dataKey,
|
|
312
|
-
i
|
|
313
|
+
i,
|
|
314
|
+
config.specialConfig?.template_text
|
|
313
315
|
)
|
|
314
316
|
: printerStore
|
|
315
317
|
.templateTable(col.text, dataKey, i, pageIndex)
|
package/src/printer/printer.js
CHANGED
|
@@ -117,9 +117,7 @@ class Printer extends React.Component {
|
|
|
117
117
|
componentDidMount() {
|
|
118
118
|
const { printerStore, config, getremainpageHeight } = this.props
|
|
119
119
|
const batchPrintConfig = config.batchPrintConfig
|
|
120
|
-
// didMount
|
|
121
|
-
printerStore.setReady(true)
|
|
122
|
-
// 连续打印不需要分页计算
|
|
120
|
+
// didMount 代表第一次渲染完成,先分页再 ready,避免空 pages 触发 renderPage
|
|
123
121
|
if (batchPrintConfig !== 2) {
|
|
124
122
|
printerStore.computedPages()
|
|
125
123
|
if (config.autoFillConfig?.checked) {
|
|
@@ -131,11 +129,10 @@ class Printer extends React.Component {
|
|
|
131
129
|
)
|
|
132
130
|
printerStore.changeTableData()
|
|
133
131
|
}
|
|
134
|
-
// 开始计算,获取各种数据
|
|
135
|
-
// 如果是自适应要先计算高度,在算出行数 不是自适应就先计算行数 在计算高度
|
|
136
132
|
// 获取剩余空白高度,传到editor
|
|
137
133
|
getremainpageHeight && getremainpageHeight(printerStore.remainPageHeight)
|
|
138
134
|
}
|
|
135
|
+
printerStore.setReady(true)
|
|
139
136
|
|
|
140
137
|
// Printer 不是立马就呈现出最终样式,有个过程。这个过程需要时间,什么 ready,不太清楚,估借 setState 来获取过程结束时刻
|
|
141
138
|
this.setState({}, () => {
|
package/src/printer/store.js
CHANGED
|
@@ -7,11 +7,24 @@ import {
|
|
|
7
7
|
getArrayMid,
|
|
8
8
|
getOverallOrderTrHeight
|
|
9
9
|
} from '../util'
|
|
10
|
+
import { isIndependentRolDataKey } from '../common/data_key_util'
|
|
10
11
|
import _ from 'lodash'
|
|
11
12
|
import Big from 'big.js'
|
|
12
13
|
import { Tip } from '../components'
|
|
13
14
|
|
|
14
15
|
export const TR_BASE_HEIGHT = 23
|
|
16
|
+
|
|
17
|
+
/** 分页高度运算:像素精度足够,避免热路径中 Big.js 开销 */
|
|
18
|
+
const roundHeight = n => Math.round(n * 100) / 100
|
|
19
|
+
|
|
20
|
+
/** 判断行是否含可拆分的采购明细(普通长文本列不可拆分) */
|
|
21
|
+
const canSplitRowDetails = (dataKey, row) => {
|
|
22
|
+
if (!row || dataKey.includes('noLineBreak')) return false
|
|
23
|
+
const details = row.__details
|
|
24
|
+
const detailsMulti = row.__details_MULTI_SUFFIX
|
|
25
|
+
return !!(details?.length || detailsMulti?.length)
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
const price = (n, f = 2) => {
|
|
16
29
|
if (isNaN(n)) return null
|
|
17
30
|
return Big(n || 0).toFixed(f)
|
|
@@ -262,17 +275,26 @@ class PrinterStore {
|
|
|
262
275
|
|
|
263
276
|
@action
|
|
264
277
|
computedPages() {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.
|
|
278
|
+
// 快照 observable,避免热路径反复触发 MobX依赖追踪
|
|
279
|
+
const pageHeight = this.pageHeight
|
|
280
|
+
const heightMap = { ...this.height }
|
|
281
|
+
const contents = this.config.contents
|
|
282
|
+
const contentsLength = contents.length
|
|
283
|
+
const tablesInfo = this.tablesInfo
|
|
284
|
+
const tableDataMap = this.data._table
|
|
285
|
+
|
|
286
|
+
// 使用本地数组累积分页结果,避免循环中反复触发 observable 更新
|
|
287
|
+
const pages = []
|
|
268
288
|
// 每页必有 页眉header, 页脚footer , 签名
|
|
269
|
-
const allPagesHaveThisHeight =
|
|
289
|
+
const allPagesHaveThisHeight = heightMap.header + heightMap.footer
|
|
270
290
|
// 退出计算! 因为页眉 + 页脚 > currentPageHeight,页面装不下其他东西
|
|
271
|
-
if (allPagesHaveThisHeight >
|
|
291
|
+
if (allPagesHaveThisHeight > pageHeight) {
|
|
292
|
+
this.pages = []
|
|
293
|
+
this.isSave = true
|
|
294
|
+
this.config.isSave = true
|
|
272
295
|
Tip.warning(
|
|
273
296
|
i18next.t('检测到当前页面高度不足,无法完整渲染,请重新设置页面高度!')
|
|
274
297
|
)
|
|
275
|
-
this.setIsSave(true)
|
|
276
298
|
return
|
|
277
299
|
}
|
|
278
300
|
|
|
@@ -285,15 +307,19 @@ class PrinterStore {
|
|
|
285
307
|
/** 处理配送单有多个表格的情况 */
|
|
286
308
|
let tableCount = 0
|
|
287
309
|
/* --- 遍历 contents,将内容动态分配到page --- */
|
|
288
|
-
while (index <
|
|
289
|
-
const content =
|
|
310
|
+
while (index < contentsLength) {
|
|
311
|
+
const content = contents[index]
|
|
290
312
|
|
|
291
313
|
/* 表格内容处理 */
|
|
292
314
|
if (content.type === 'table') {
|
|
293
315
|
// 是表格就++
|
|
294
316
|
tableCount++
|
|
295
317
|
// 表格原始的高度和宽度信息
|
|
296
|
-
const table =
|
|
318
|
+
const table = tablesInfo[`contents.table.${index}`]
|
|
319
|
+
if (!table?.body?.heights) {
|
|
320
|
+
index++
|
|
321
|
+
continue
|
|
322
|
+
}
|
|
297
323
|
const {
|
|
298
324
|
subtotal,
|
|
299
325
|
dataKey,
|
|
@@ -330,13 +356,14 @@ class PrinterStore {
|
|
|
330
356
|
const currentPageMinimumHeight =
|
|
331
357
|
allPagesHaveThisHeight + allTableHaveThisHeight
|
|
332
358
|
/** 当前page可容纳的table高度 */
|
|
333
|
-
let pageAccomodateTableHeight =
|
|
334
|
-
|
|
335
|
-
.toFixed(2)
|
|
336
|
-
const heights = this.getNormalTableBodyHeights(
|
|
337
|
-
table.body.heights,
|
|
338
|
-
dataKey
|
|
359
|
+
let pageAccomodateTableHeight = roundHeight(
|
|
360
|
+
pageHeight - currentPageHeight
|
|
339
361
|
)
|
|
362
|
+
// 拷贝一份行高数组,避免 splice 触发 observable 副作用
|
|
363
|
+
const heights = [
|
|
364
|
+
...this.getNormalTableBodyHeights(table.body.heights, dataKey)
|
|
365
|
+
]
|
|
366
|
+
const tableData = tableDataMap[dataKey] || []
|
|
340
367
|
// 表格行的索引,用于table.slice(begin, end), 分割到不同页面中
|
|
341
368
|
let begin = 0
|
|
342
369
|
let end = 0
|
|
@@ -352,27 +379,41 @@ class PrinterStore {
|
|
|
352
379
|
let currentRemainTableHeight = 0
|
|
353
380
|
/** 去最小的tr高度,用于下面的计算compare,(避免特殊情况:一般来说最小tr——height = 23, 比23还小的不考虑计算) */
|
|
354
381
|
const minHeight = Math.max(getArrayMid(heights), 23)
|
|
382
|
+
// 安全阈值:防止极端情况下内层 while 迭代失控
|
|
383
|
+
const maxIterations = heights.length * 10 + 100
|
|
384
|
+
let loopCount = 0
|
|
355
385
|
/* 遍历表格每一行,填充表格内容 */
|
|
356
386
|
while (end < heights.length) {
|
|
357
|
-
|
|
387
|
+
if (++loopCount > maxIterations) {
|
|
388
|
+
console.warn(
|
|
389
|
+
'[gm-printer] computedPages: iteration limit exceeded, force break'
|
|
390
|
+
)
|
|
391
|
+
break
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const rowHeight = heights[end]
|
|
395
|
+
currentTableHeight += rowHeight
|
|
358
396
|
// 用于计算最后一页有footer情况的高度
|
|
359
|
-
currentPageHeight +=
|
|
397
|
+
currentPageHeight += rowHeight
|
|
360
398
|
// 当前页没有多余空间
|
|
361
399
|
if (currentTableHeight > pageAccomodateTableHeight) {
|
|
362
|
-
currentRemainTableHeight =
|
|
363
|
-
|
|
364
|
-
|
|
400
|
+
currentRemainTableHeight = roundHeight(
|
|
401
|
+
pageAccomodateTableHeight - currentTableHeight + rowHeight
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
const row = tableData[end]
|
|
405
|
+
const isRowOversized = rowHeight > pageAccomodateTableHeight
|
|
406
|
+
const shouldTrySplitDetails =
|
|
407
|
+
canSplitRowDetails(dataKey, row) &&
|
|
408
|
+
((currentRemainTableHeight / minHeight > 1.5 &&
|
|
409
|
+
rowHeight / currentRemainTableHeight > 1) ||
|
|
410
|
+
isRowOversized)
|
|
365
411
|
|
|
366
412
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* 3. heights[end] 高度超过了 pageAccomodateTableHeight
|
|
413
|
+
* 仅对含 __details 的采购明细行尝试拆分;
|
|
414
|
+
* 普通长文本列(如规格)超高时直接整行换页,避免无效 computedData 调用
|
|
370
415
|
*/
|
|
371
|
-
if (
|
|
372
|
-
(currentRemainTableHeight / minHeight > 1.5 &&
|
|
373
|
-
heights[end] / currentRemainTableHeight > 1) ||
|
|
374
|
-
heights[end] > pageAccomodateTableHeight
|
|
375
|
-
) {
|
|
416
|
+
if (shouldTrySplitDetails) {
|
|
376
417
|
const detailsPageHeight = this.computedData(
|
|
377
418
|
dataKey,
|
|
378
419
|
table,
|
|
@@ -380,7 +421,7 @@ class PrinterStore {
|
|
|
380
421
|
currentRemainTableHeight
|
|
381
422
|
)
|
|
382
423
|
|
|
383
|
-
// 拆分明细后,同时也要更新
|
|
424
|
+
// 拆分明细后,同时也要更新 heights 不能影响后续计算
|
|
384
425
|
if (detailsPageHeight.length > 0) {
|
|
385
426
|
// 比较剩余高度和minHeight的大小,取最大(防止剩余一条明细时,第二页撑开的高度远大于一条明细的高度)
|
|
386
427
|
detailsPageHeight[1] = Math.max(
|
|
@@ -395,7 +436,8 @@ class PrinterStore {
|
|
|
395
436
|
if (begin === 0 && end === 0 && index === 0) {
|
|
396
437
|
index++
|
|
397
438
|
this.pages = []
|
|
398
|
-
this.
|
|
439
|
+
this.isSave = true
|
|
440
|
+
this.config.isSave = true
|
|
399
441
|
Tip.warning(
|
|
400
442
|
i18next.t(
|
|
401
443
|
'检测到当前页面高度不足,无法完整渲染,请重新设置页面高度!'
|
|
@@ -403,7 +445,7 @@ class PrinterStore {
|
|
|
403
445
|
)
|
|
404
446
|
break
|
|
405
447
|
}
|
|
406
|
-
//
|
|
448
|
+
// 行无法拆分(普通长文本列)或拆分失败时,强制推进 end 防止死循环
|
|
407
449
|
if (end === begin) {
|
|
408
450
|
end = end + 1
|
|
409
451
|
}
|
|
@@ -416,27 +458,27 @@ class PrinterStore {
|
|
|
416
458
|
end
|
|
417
459
|
})
|
|
418
460
|
// 此页完成任务
|
|
419
|
-
|
|
461
|
+
pages.push(page)
|
|
420
462
|
page = []
|
|
421
463
|
}
|
|
422
464
|
// 页面有多个表格时,当同一页的第二个表格的第一行高度加上第一个表格的高度大于页面的高度,需要生成新的一页
|
|
423
465
|
// 因为是第二个表格,重新走了遍历,end重置0,没有进入到上面的判断(end !== 0),不会生成新的一页
|
|
424
466
|
if (tableCount > 1 && end === 0) {
|
|
425
|
-
|
|
467
|
+
pages.push(page)
|
|
426
468
|
page = []
|
|
427
469
|
}
|
|
428
470
|
|
|
429
471
|
begin = end
|
|
430
472
|
// 开启新一页,重置页面高度
|
|
431
|
-
pageAccomodateTableHeight =
|
|
432
|
-
allPagesHaveThisHeight
|
|
473
|
+
pageAccomodateTableHeight = roundHeight(
|
|
474
|
+
pageHeight - allPagesHaveThisHeight
|
|
433
475
|
)
|
|
434
476
|
currentTableHeight = allTableHaveThisHeight
|
|
435
477
|
currentPageHeight = currentPageMinimumHeight
|
|
436
478
|
} else {
|
|
437
479
|
// 有空间,继续做下行
|
|
438
480
|
end++
|
|
439
|
-
// 最后一行,把信息加入 page
|
|
481
|
+
// 最后一行,把信息加入 page
|
|
440
482
|
if (end === heights.length) {
|
|
441
483
|
page.push({
|
|
442
484
|
type: 'table',
|
|
@@ -444,27 +486,35 @@ class PrinterStore {
|
|
|
444
486
|
begin,
|
|
445
487
|
end
|
|
446
488
|
})
|
|
447
|
-
index++
|
|
448
489
|
}
|
|
449
490
|
}
|
|
450
491
|
}
|
|
492
|
+
// 最后一行换页时走 if 分支,内层不会 index++,此处统一推进
|
|
493
|
+
if (end >= heights.length) {
|
|
494
|
+
index++
|
|
495
|
+
} else {
|
|
496
|
+
console.warn(
|
|
497
|
+
'[gm-printer] computedPages: table pagination incomplete, force advance'
|
|
498
|
+
)
|
|
499
|
+
index++
|
|
500
|
+
}
|
|
451
501
|
}
|
|
452
502
|
/* 非表格内容处理 */
|
|
453
503
|
} else {
|
|
454
|
-
const panelHeight =
|
|
504
|
+
const panelHeight = heightMap[`contents.panel.${index}`]
|
|
455
505
|
currentPageHeight += panelHeight
|
|
456
506
|
|
|
457
507
|
// 当 panel + allPagesHaveThisHeight > 页高度, 停止. 避免死循环
|
|
458
|
-
if (panelHeight + allPagesHaveThisHeight >
|
|
508
|
+
if (panelHeight + allPagesHaveThisHeight > pageHeight) {
|
|
459
509
|
break
|
|
460
510
|
}
|
|
461
511
|
|
|
462
512
|
// 如果是最后一页,必须要加上sign的高度,否则会重叠
|
|
463
|
-
if (index ===
|
|
464
|
-
currentPageHeight +=
|
|
513
|
+
if (index === contentsLength - 1) {
|
|
514
|
+
currentPageHeight += heightMap?.sign || 0
|
|
465
515
|
}
|
|
466
516
|
|
|
467
|
-
if (currentPageHeight <=
|
|
517
|
+
if (currentPageHeight <= pageHeight) {
|
|
468
518
|
// 空间充足,把信息加入 page,并轮下一个contents
|
|
469
519
|
page.push({
|
|
470
520
|
type: 'panel',
|
|
@@ -474,7 +524,7 @@ class PrinterStore {
|
|
|
474
524
|
index++
|
|
475
525
|
} else {
|
|
476
526
|
// 此页空间不足,此页完成任务
|
|
477
|
-
|
|
527
|
+
pages.push(page)
|
|
478
528
|
|
|
479
529
|
// 为下一页做准备
|
|
480
530
|
page = []
|
|
@@ -482,8 +532,11 @@ class PrinterStore {
|
|
|
482
532
|
}
|
|
483
533
|
}
|
|
484
534
|
}
|
|
485
|
-
|
|
486
|
-
this.
|
|
535
|
+
pages.push(page)
|
|
536
|
+
this.pages = pages
|
|
537
|
+
this.remainPageHeight = Math.round(pageHeight - currentPageHeight)
|
|
538
|
+
this.isSave = false
|
|
539
|
+
this.config.isSave = false
|
|
487
540
|
}
|
|
488
541
|
|
|
489
542
|
@action
|
|
@@ -552,13 +605,14 @@ class PrinterStore {
|
|
|
552
605
|
*/
|
|
553
606
|
templateTableRowSpan(text, dataKey, index, begin) {
|
|
554
607
|
try {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
dataKey
|
|
558
|
-
dataKey
|
|
559
|
-
dataKey
|
|
560
|
-
dataKey
|
|
561
|
-
|
|
608
|
+
// 采购 / 分拣「按明细单行」展开后才做合并单元格(后缀 independent_rol_*)
|
|
609
|
+
const canMerge =
|
|
610
|
+
isIndependentRolDataKey(dataKey) ||
|
|
611
|
+
dataKey === 'taxRateSales' ||
|
|
612
|
+
dataKey === 'ordinary' ||
|
|
613
|
+
dataKey === 'purchase_detail_one_row' ||
|
|
614
|
+
dataKey === 'sorting_detail_detail_one_row'
|
|
615
|
+
if (!canMerge) {
|
|
562
616
|
return null
|
|
563
617
|
}
|
|
564
618
|
const list = this.data._table[dataKey] || this.data._table.orders
|
|
@@ -644,12 +698,15 @@ class PrinterStore {
|
|
|
644
698
|
}
|
|
645
699
|
}
|
|
646
700
|
|
|
647
|
-
templateSpecialDetails(col, dataKey, index) {
|
|
648
|
-
// 做好保护,出错就返回 text
|
|
701
|
+
templateSpecialDetails(col, dataKey, index, fallbackText = '') {
|
|
649
702
|
const { specialDetailsKey, text, detailLastColType, separator } = col
|
|
703
|
+
const templateText = text || fallbackText
|
|
704
|
+
if (!templateText) return ''
|
|
650
705
|
try {
|
|
651
706
|
const row = this.data._table[dataKey][index]
|
|
652
|
-
const compiled = _.template(
|
|
707
|
+
const compiled = _.template(templateText, {
|
|
708
|
+
interpolate: /{{([\s\S]+?)}}/g,
|
|
709
|
+
})
|
|
653
710
|
let detailsList = row[specialDetailsKey] || []
|
|
654
711
|
|
|
655
712
|
/** 简单处理下数据 */
|
|
@@ -672,7 +729,7 @@ class PrinterStore {
|
|
|
672
729
|
|
|
673
730
|
return detailsList
|
|
674
731
|
} catch (err) {
|
|
675
|
-
return
|
|
732
|
+
return templateText
|
|
676
733
|
}
|
|
677
734
|
}
|
|
678
735
|
|
package/src/printer/table.js
CHANGED
package/src/util.js
CHANGED
|
@@ -233,16 +233,24 @@ const caclSingleDetailsPageHeight = (detailsHeights, curRemainPageHeight) => {
|
|
|
233
233
|
* @param {*} arr
|
|
234
234
|
*/
|
|
235
235
|
const getArrayMid = arr => {
|
|
236
|
+
let majority = 23
|
|
237
|
+
|
|
238
|
+
if (arr.length === 0) return majority
|
|
239
|
+
|
|
240
|
+
// 行数少时直接取最小行高,跳过多轮 Map 统计
|
|
241
|
+
if (arr.length <= 30) {
|
|
242
|
+
const min = Math.min(...arr)
|
|
243
|
+
if (min / 23 > 10) return 23
|
|
244
|
+
return min
|
|
245
|
+
}
|
|
246
|
+
|
|
236
247
|
/** 数组元素出现次数的集合 */
|
|
237
248
|
const mapArr = []
|
|
238
249
|
const map = new Map()
|
|
239
|
-
let majority = 23
|
|
240
250
|
/** 次数相同的元素集合 */
|
|
241
251
|
const majorityArr = []
|
|
242
252
|
const min = Math.min(...arr)
|
|
243
253
|
|
|
244
|
-
if (arr.length === 0) return majority
|
|
245
|
-
|
|
246
254
|
_.forEach(arr, (val, key) => {
|
|
247
255
|
if (map.has(val)) {
|
|
248
256
|
map.set(val, map.get(val) + 1)
|