gm-printer 10.39.4-beta.2 → 10.39.4-beta.21
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/locales/en.json +3 -0
- package/locales/th.json +3 -0
- package/locales/zh-HK.json +3 -0
- package/package.json +1 -1
- package/src/common/common_context_menu.js +6 -4
- package/src/common/component.js +64 -8
- package/src/common/data_key_util.js +35 -0
- package/src/common/editor_edit_field.js +288 -167
- package/src/common/editor_store.js +230 -42
- package/src/common/hoc_with_store.js +9 -0
- package/src/common/style.lesss +43 -0
- package/src/common/util.js +58 -4
- package/src/editor/context_menu.js +17 -0
- package/src/editor/store.js +13 -0
- package/src/editor_purchase/editor.js +2 -1
- package/src/editor_purchase/editor_special_table.js +39 -17
- package/src/editor_purchase/editor_sum_table.js +5 -1
- package/src/editor_purchase/store.js +48 -45
- package/src/finance_voucher/components/table_subtotal_tr.js +12 -18
- package/src/index.js +6 -2
- package/src/printer/block.js +154 -4
- package/src/printer/compute_pages.js +122 -0
- package/src/printer/index.js +3 -1
- package/src/printer/long_print_table/index.js +14 -4
- package/src/printer/multi_column.js +1 -0
- package/src/printer/page_summary.js +3 -1
- package/src/printer/printer.js +23 -3
- package/src/printer/store.js +141 -91
- package/src/printer/table.js +11 -3
- package/src/printer/table_diy_overallOrder_tr.js +8 -15
- package/src/printer/table_diy_summary_tr.js +18 -35
- package/src/printer/table_overallOrder_tr.js +49 -37
- package/src/printer/table_special_tr.js +17 -2
- package/src/printer/table_subtotal_tr.js +100 -16
- package/src/util.js +34 -8
- package/yarn-error.log +372 -152
package/src/printer/store.js
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
getDataKey,
|
|
8
8
|
caclSingleDetailsPageHeight,
|
|
9
9
|
getArrayMid,
|
|
10
|
-
getOverallOrderTrHeight
|
|
10
|
+
getOverallOrderTrHeight,
|
|
11
|
+
isMaskedValue
|
|
11
12
|
} from '../util'
|
|
13
|
+
import { isIndependentRolDataKey } from '../common/data_key_util'
|
|
12
14
|
import _ from 'lodash'
|
|
13
15
|
import Big from 'big.js'
|
|
14
16
|
import { Tip } from '../components'
|
|
@@ -28,7 +30,21 @@ import {
|
|
|
28
30
|
} from './multi_column'
|
|
29
31
|
|
|
30
32
|
export const TR_BASE_HEIGHT = 23
|
|
33
|
+
|
|
34
|
+
/** 分页高度运算:像素精度足够,避免热路径中 Big.js 开销 */
|
|
35
|
+
const roundHeight = n => Math.round(n * 100) / 100
|
|
36
|
+
|
|
37
|
+
/** 判断行是否含可拆分的采购明细(普通长文本列不可拆分) */
|
|
38
|
+
const canSplitRowDetails = (dataKey, row) => {
|
|
39
|
+
if (!row || dataKey.includes('noLineBreak')) return false
|
|
40
|
+
const details = row.__details
|
|
41
|
+
const detailsMulti = row.__details_MULTI_SUFFIX
|
|
42
|
+
return !!(details?.length || detailsMulti?.length)
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
const price = (n, f = 2) => {
|
|
46
|
+
// 脱敏值 '***' 原样返回(不能走 isNaN 判空,空单元格仍需显空)
|
|
47
|
+
if (isMaskedValue(n)) return n
|
|
32
48
|
if (isNaN(n)) return null
|
|
33
49
|
return Big(n || 0).toFixed(f)
|
|
34
50
|
}
|
|
@@ -250,10 +266,10 @@ class PrinterStore {
|
|
|
250
266
|
count = details.length + detailsMulti.length + count
|
|
251
267
|
})
|
|
252
268
|
|
|
253
|
-
/** 明细data */
|
|
254
|
-
const detailsData = tableData[end]?.__details
|
|
255
|
-
// 双栏明细data
|
|
256
|
-
const detailsDataMulti = tableData[end]?.__details_MULTI_SUFFIX
|
|
269
|
+
/** 明细data(左栏),兜底空数组避免另一侧缺省时切片报错 */
|
|
270
|
+
const detailsData = tableData[end]?.__details || []
|
|
271
|
+
// 双栏明细data(右栏)
|
|
272
|
+
const detailsDataMulti = tableData[end]?.__details_MULTI_SUFFIX || []
|
|
257
273
|
// 采购单如果使用双栏,取明细最多的那个数据
|
|
258
274
|
const data =
|
|
259
275
|
detailsData?.length > (detailsDataMulti?.length || 0)
|
|
@@ -276,10 +292,12 @@ class PrinterStore {
|
|
|
276
292
|
_.filter(ranges, i => i[0] !== i[1] || (!i[0] && !i[1])), // 过滤掉 {[0,3],[3,3]}这周情况
|
|
277
293
|
range => {
|
|
278
294
|
const _tableData = Object.assign({}, tableData[end])
|
|
279
|
-
|
|
295
|
+
// 左右两栏各用各的明细切片(slice 超出长度自动截断,明细少的一侧在第一片即展示完),
|
|
296
|
+
// 修复:此前两栏都塞明细多的一侧数据,导致明细少的一侧(如双栏右栏)明细被替换、自身明细丢失
|
|
297
|
+
_tableData.__details = detailsData.slice(...range)
|
|
280
298
|
// 双栏中的数据也要做处理
|
|
281
299
|
if (isMultiTable(dataKey)) {
|
|
282
|
-
_tableData.__details_MULTI_SUFFIX =
|
|
300
|
+
_tableData.__details_MULTI_SUFFIX = detailsDataMulti.slice(...range)
|
|
283
301
|
}
|
|
284
302
|
|
|
285
303
|
return _tableData
|
|
@@ -293,17 +311,26 @@ class PrinterStore {
|
|
|
293
311
|
|
|
294
312
|
@action
|
|
295
313
|
computedPages() {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
this.
|
|
314
|
+
// 快照 observable,避免热路径反复触发 MobX依赖追踪
|
|
315
|
+
const pageHeight = this.pageHeight
|
|
316
|
+
const heightMap = { ...this.height }
|
|
317
|
+
const contents = this.config.contents
|
|
318
|
+
const contentsLength = contents.length
|
|
319
|
+
const tablesInfo = this.tablesInfo
|
|
320
|
+
const tableDataMap = this.data._table
|
|
321
|
+
|
|
322
|
+
// 使用本地数组累积分页结果,避免循环中反复触发 observable 更新
|
|
323
|
+
const pages = []
|
|
299
324
|
// 每页必有 页眉header, 页脚footer , 签名
|
|
300
|
-
const allPagesHaveThisHeight =
|
|
325
|
+
const allPagesHaveThisHeight = heightMap.header + heightMap.footer
|
|
301
326
|
// 退出计算! 因为页眉 + 页脚 > currentPageHeight,页面装不下其他东西
|
|
302
|
-
if (allPagesHaveThisHeight >
|
|
327
|
+
if (allPagesHaveThisHeight > pageHeight) {
|
|
328
|
+
this.pages = []
|
|
329
|
+
this.isSave = true
|
|
330
|
+
this.config.isSave = true
|
|
303
331
|
Tip.warning(
|
|
304
332
|
i18next.t('检测到当前页面高度不足,无法完整渲染,请重新设置页面高度!')
|
|
305
333
|
)
|
|
306
|
-
this.setIsSave(true)
|
|
307
334
|
return
|
|
308
335
|
}
|
|
309
336
|
|
|
@@ -316,15 +343,19 @@ class PrinterStore {
|
|
|
316
343
|
/** 处理配送单有多个表格的情况 */
|
|
317
344
|
let tableCount = 0
|
|
318
345
|
/* --- 遍历 contents,将内容动态分配到page --- */
|
|
319
|
-
while (index <
|
|
320
|
-
const content =
|
|
346
|
+
while (index < contentsLength) {
|
|
347
|
+
const content = contents[index]
|
|
321
348
|
|
|
322
349
|
/* 表格内容处理 */
|
|
323
350
|
if (content.type === 'table') {
|
|
324
351
|
// 是表格就++
|
|
325
352
|
tableCount++
|
|
326
353
|
// 表格原始的高度和宽度信息
|
|
327
|
-
const table =
|
|
354
|
+
const table = tablesInfo[`contents.table.${index}`]
|
|
355
|
+
if (!table?.body?.heights) {
|
|
356
|
+
index++
|
|
357
|
+
continue
|
|
358
|
+
}
|
|
328
359
|
const {
|
|
329
360
|
subtotal,
|
|
330
361
|
dataKey,
|
|
@@ -361,17 +392,17 @@ class PrinterStore {
|
|
|
361
392
|
const currentPageMinimumHeight =
|
|
362
393
|
allPagesHaveThisHeight + allTableHaveThisHeight
|
|
363
394
|
// 最后一项是表格时,末页仍要渲染签名:装行可用高度预留签名,避免空行顶进签名区
|
|
364
|
-
const isLastContent = index ===
|
|
395
|
+
const isLastContent = index === contentsLength - 1
|
|
365
396
|
const signReserve = isLastContent ? this.getSignHeight() : 0
|
|
366
397
|
/** 当前page可容纳的table高度 */
|
|
367
|
-
let pageAccomodateTableHeight =
|
|
368
|
-
|
|
369
|
-
.minus(signReserve)
|
|
370
|
-
.toFixed(2)
|
|
371
|
-
const heights = this.getNormalTableBodyHeights(
|
|
372
|
-
table.body.heights,
|
|
373
|
-
dataKey
|
|
398
|
+
let pageAccomodateTableHeight = roundHeight(
|
|
399
|
+
pageHeight - currentPageHeight - signReserve
|
|
374
400
|
)
|
|
401
|
+
// 拷贝一份行高数组,避免 splice 触发 observable 副作用
|
|
402
|
+
const heights = [
|
|
403
|
+
...this.getNormalTableBodyHeights(table.body.heights, dataKey)
|
|
404
|
+
]
|
|
405
|
+
const tableData = tableDataMap[dataKey] || []
|
|
375
406
|
// 表格行的索引,用于table.slice(begin, end), 分割到不同页面中
|
|
376
407
|
let begin = 0
|
|
377
408
|
let end = 0
|
|
@@ -387,27 +418,41 @@ class PrinterStore {
|
|
|
387
418
|
let currentRemainTableHeight = 0
|
|
388
419
|
/** 去最小的tr高度,用于下面的计算compare,(避免特殊情况:一般来说最小tr——height = 23, 比23还小的不考虑计算) */
|
|
389
420
|
const minHeight = Math.max(getArrayMid(heights), 23)
|
|
421
|
+
// 安全阈值:防止极端情况下内层 while 迭代失控
|
|
422
|
+
const maxIterations = heights.length * 10 + 100
|
|
423
|
+
let loopCount = 0
|
|
390
424
|
/* 遍历表格每一行,填充表格内容 */
|
|
391
425
|
while (end < heights.length) {
|
|
392
|
-
|
|
426
|
+
if (++loopCount > maxIterations) {
|
|
427
|
+
console.warn(
|
|
428
|
+
'[gm-printer] computedPages: iteration limit exceeded, force break'
|
|
429
|
+
)
|
|
430
|
+
break
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const rowHeight = heights[end]
|
|
434
|
+
currentTableHeight += rowHeight
|
|
393
435
|
// 用于计算最后一页有footer情况的高度
|
|
394
|
-
currentPageHeight +=
|
|
436
|
+
currentPageHeight += rowHeight
|
|
395
437
|
// 当前页没有多余空间
|
|
396
438
|
if (currentTableHeight > pageAccomodateTableHeight) {
|
|
397
|
-
currentRemainTableHeight =
|
|
398
|
-
|
|
399
|
-
|
|
439
|
+
currentRemainTableHeight = roundHeight(
|
|
440
|
+
pageAccomodateTableHeight - currentTableHeight + rowHeight
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
const row = tableData[end]
|
|
444
|
+
const isRowOversized = rowHeight > pageAccomodateTableHeight
|
|
445
|
+
const shouldTrySplitDetails =
|
|
446
|
+
canSplitRowDetails(dataKey, row) &&
|
|
447
|
+
((currentRemainTableHeight / minHeight > 1.5 &&
|
|
448
|
+
rowHeight / currentRemainTableHeight > 1) ||
|
|
449
|
+
isRowOversized)
|
|
400
450
|
|
|
401
451
|
/**
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
* 3. heights[end] 高度超过了 pageAccomodateTableHeight
|
|
452
|
+
* 仅对含 __details 的采购明细行尝试拆分;
|
|
453
|
+
* 普通长文本列(如规格)超高时直接整行换页,避免无效 computedData 调用
|
|
405
454
|
*/
|
|
406
|
-
if (
|
|
407
|
-
(currentRemainTableHeight / minHeight > 1.5 &&
|
|
408
|
-
heights[end] / currentRemainTableHeight > 1) ||
|
|
409
|
-
heights[end] > pageAccomodateTableHeight
|
|
410
|
-
) {
|
|
455
|
+
if (shouldTrySplitDetails) {
|
|
411
456
|
const detailsPageHeight = this.computedData(
|
|
412
457
|
dataKey,
|
|
413
458
|
table,
|
|
@@ -415,7 +460,7 @@ class PrinterStore {
|
|
|
415
460
|
currentRemainTableHeight
|
|
416
461
|
)
|
|
417
462
|
|
|
418
|
-
// 拆分明细后,同时也要更新
|
|
463
|
+
// 拆分明细后,同时也要更新 heights 不能影响后续计算
|
|
419
464
|
if (detailsPageHeight.length > 0) {
|
|
420
465
|
// 比较剩余高度和minHeight的大小,取最大(防止剩余一条明细时,第二页撑开的高度远大于一条明细的高度)
|
|
421
466
|
detailsPageHeight[1] = Math.max(
|
|
@@ -430,7 +475,8 @@ class PrinterStore {
|
|
|
430
475
|
if (begin === 0 && end === 0 && index === 0) {
|
|
431
476
|
index++
|
|
432
477
|
this.pages = []
|
|
433
|
-
this.
|
|
478
|
+
this.isSave = true
|
|
479
|
+
this.config.isSave = true
|
|
434
480
|
Tip.warning(
|
|
435
481
|
i18next.t(
|
|
436
482
|
'检测到当前页面高度不足,无法完整渲染,请重新设置页面高度!'
|
|
@@ -438,7 +484,7 @@ class PrinterStore {
|
|
|
438
484
|
)
|
|
439
485
|
break
|
|
440
486
|
}
|
|
441
|
-
//
|
|
487
|
+
// 行无法拆分(普通长文本列)或拆分失败时,强制推进 end 防止死循环
|
|
442
488
|
if (end === begin) {
|
|
443
489
|
end = end + 1
|
|
444
490
|
}
|
|
@@ -451,28 +497,27 @@ class PrinterStore {
|
|
|
451
497
|
end
|
|
452
498
|
})
|
|
453
499
|
// 此页完成任务
|
|
454
|
-
|
|
500
|
+
pages.push(page)
|
|
455
501
|
page = []
|
|
456
502
|
}
|
|
457
503
|
// 页面有多个表格时,当同一页的第二个表格的第一行高度加上第一个表格的高度大于页面的高度,需要生成新的一页
|
|
458
504
|
// 因为是第二个表格,重新走了遍历,end重置0,没有进入到上面的判断(end !== 0),不会生成新的一页
|
|
459
505
|
if (tableCount > 1 && end === 0) {
|
|
460
|
-
|
|
506
|
+
pages.push(page)
|
|
461
507
|
page = []
|
|
462
508
|
}
|
|
463
509
|
|
|
464
510
|
begin = end
|
|
465
511
|
// 开启新一页,重置页面高度(末项表格仍预留签名)
|
|
466
|
-
pageAccomodateTableHeight =
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
.toFixed(2)
|
|
512
|
+
pageAccomodateTableHeight = roundHeight(
|
|
513
|
+
pageHeight - allPagesHaveThisHeight - signReserve
|
|
514
|
+
)
|
|
470
515
|
currentTableHeight = allTableHaveThisHeight
|
|
471
516
|
currentPageHeight = currentPageMinimumHeight
|
|
472
517
|
} else {
|
|
473
518
|
// 有空间,继续做下行
|
|
474
519
|
end++
|
|
475
|
-
// 最后一行,把信息加入 page
|
|
520
|
+
// 最后一行,把信息加入 page
|
|
476
521
|
if (end === heights.length) {
|
|
477
522
|
page.push({
|
|
478
523
|
type: 'table',
|
|
@@ -480,27 +525,35 @@ class PrinterStore {
|
|
|
480
525
|
begin,
|
|
481
526
|
end
|
|
482
527
|
})
|
|
483
|
-
index++
|
|
484
528
|
}
|
|
485
529
|
}
|
|
486
530
|
}
|
|
531
|
+
// 最后一行换页时走 if 分支,内层不会 index++,此处统一推进
|
|
532
|
+
if (end >= heights.length) {
|
|
533
|
+
index++
|
|
534
|
+
} else {
|
|
535
|
+
console.warn(
|
|
536
|
+
'[gm-printer] computedPages: table pagination incomplete, force advance'
|
|
537
|
+
)
|
|
538
|
+
index++
|
|
539
|
+
}
|
|
487
540
|
}
|
|
488
541
|
/* 非表格内容处理 */
|
|
489
542
|
} else {
|
|
490
|
-
const panelHeight =
|
|
543
|
+
const panelHeight = heightMap[`contents.panel.${index}`]
|
|
491
544
|
currentPageHeight += panelHeight
|
|
492
545
|
|
|
493
546
|
// 当 panel + allPagesHaveThisHeight > 页高度, 停止. 避免死循环
|
|
494
|
-
if (panelHeight + allPagesHaveThisHeight >
|
|
547
|
+
if (panelHeight + allPagesHaveThisHeight > pageHeight) {
|
|
495
548
|
break
|
|
496
549
|
}
|
|
497
550
|
|
|
498
551
|
// 如果是最后一页,必须要加上sign的高度,否则会重叠
|
|
499
|
-
if (index ===
|
|
552
|
+
if (index === contentsLength - 1) {
|
|
500
553
|
currentPageHeight += this.getSignHeight()
|
|
501
554
|
}
|
|
502
555
|
|
|
503
|
-
if (currentPageHeight <=
|
|
556
|
+
if (currentPageHeight <= pageHeight) {
|
|
504
557
|
// 空间充足,把信息加入 page,并轮下一个contents
|
|
505
558
|
page.push({
|
|
506
559
|
type: 'panel',
|
|
@@ -510,7 +563,7 @@ class PrinterStore {
|
|
|
510
563
|
index++
|
|
511
564
|
} else {
|
|
512
565
|
// 此页空间不足,此页完成任务
|
|
513
|
-
|
|
566
|
+
pages.push(page)
|
|
514
567
|
|
|
515
568
|
// 为下一页做准备
|
|
516
569
|
page = []
|
|
@@ -518,19 +571,21 @@ class PrinterStore {
|
|
|
518
571
|
}
|
|
519
572
|
}
|
|
520
573
|
}
|
|
521
|
-
|
|
574
|
+
pages.push(page)
|
|
575
|
+
this.pages = pages
|
|
522
576
|
|
|
523
577
|
// 末页签名:panel 分支会在「最后一项是 panel」时扣 sign;
|
|
524
578
|
// 最后一项是 table 时上面不会扣,导致 remain 偏大、空行多填溢页
|
|
525
|
-
|
|
526
|
-
const lastContent = this.config.contents[this.config.contents.length - 1]
|
|
579
|
+
const lastContent = contents[contentsLength - 1]
|
|
527
580
|
if (lastContent?.type === 'table') {
|
|
528
581
|
currentPageHeight += this.getSignHeight()
|
|
529
582
|
}
|
|
530
583
|
|
|
531
|
-
this.remainPageHeight =
|
|
532
|
-
Math.max(0,
|
|
533
|
-
)
|
|
584
|
+
this.remainPageHeight = Math.round(
|
|
585
|
+
Math.max(0, pageHeight - currentPageHeight)
|
|
586
|
+
)
|
|
587
|
+
this.isSave = false
|
|
588
|
+
this.config.isSave = false
|
|
534
589
|
this.repackVerticalMultiByPages()
|
|
535
590
|
}
|
|
536
591
|
|
|
@@ -579,8 +634,8 @@ class PrinterStore {
|
|
|
579
634
|
const sourceColNumber = isMultiTable(singleKey)
|
|
580
635
|
? getMultiNumber(singleKey)
|
|
581
636
|
: isMultiTable(sourceKey)
|
|
582
|
-
|
|
583
|
-
|
|
637
|
+
? colNumber
|
|
638
|
+
: 1
|
|
584
639
|
const sourceItems = flattenHorizontalPackedRows(
|
|
585
640
|
sourceRows,
|
|
586
641
|
sourceColNumber
|
|
@@ -666,13 +721,14 @@ class PrinterStore {
|
|
|
666
721
|
*/
|
|
667
722
|
templateTableRowSpan(text, dataKey, index, begin) {
|
|
668
723
|
try {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
dataKey
|
|
672
|
-
dataKey
|
|
673
|
-
dataKey
|
|
674
|
-
dataKey
|
|
675
|
-
|
|
724
|
+
// 采购 / 分拣「按明细单行」展开后才做合并单元格(后缀 independent_rol_*)
|
|
725
|
+
const canMerge =
|
|
726
|
+
isIndependentRolDataKey(dataKey) ||
|
|
727
|
+
dataKey === 'taxRateSales' ||
|
|
728
|
+
dataKey === 'ordinary' ||
|
|
729
|
+
dataKey === 'purchase_detail_one_row' ||
|
|
730
|
+
dataKey === 'sorting_detail_detail_one_row'
|
|
731
|
+
if (!canMerge) {
|
|
676
732
|
return null
|
|
677
733
|
}
|
|
678
734
|
const list = this.data._table[dataKey] || this.data._table.orders
|
|
@@ -729,13 +785,8 @@ class PrinterStore {
|
|
|
729
785
|
row = list[index]
|
|
730
786
|
}
|
|
731
787
|
row =
|
|
732
|
-
ensureRowSerialKeys(
|
|
733
|
-
|
|
734
|
-
index,
|
|
735
|
-
colNumber,
|
|
736
|
-
this.fillIndex,
|
|
737
|
-
dataKey
|
|
738
|
-
) || row
|
|
788
|
+
ensureRowSerialKeys(list, index, colNumber, this.fillIndex, dataKey) ||
|
|
789
|
+
row
|
|
739
790
|
|
|
740
791
|
return _.template(text, {
|
|
741
792
|
interpolate: /{{([\s\S]+?)}}/g
|
|
@@ -779,12 +830,15 @@ class PrinterStore {
|
|
|
779
830
|
}
|
|
780
831
|
}
|
|
781
832
|
|
|
782
|
-
templateSpecialDetails(col, dataKey, index) {
|
|
783
|
-
// 做好保护,出错就返回 text
|
|
833
|
+
templateSpecialDetails(col, dataKey, index, fallbackText = '') {
|
|
784
834
|
const { specialDetailsKey, text, detailLastColType, separator } = col
|
|
835
|
+
const templateText = text || fallbackText
|
|
836
|
+
if (!templateText) return ''
|
|
785
837
|
try {
|
|
786
838
|
const row = this.data._table[dataKey][index]
|
|
787
|
-
const compiled = _.template(
|
|
839
|
+
const compiled = _.template(templateText, {
|
|
840
|
+
interpolate: /{{([\s\S]+?)}}/g
|
|
841
|
+
})
|
|
788
842
|
let detailsList = row[specialDetailsKey] || []
|
|
789
843
|
|
|
790
844
|
/** 简单处理下数据 */
|
|
@@ -807,7 +861,7 @@ class PrinterStore {
|
|
|
807
861
|
|
|
808
862
|
return detailsList
|
|
809
863
|
} catch (err) {
|
|
810
|
-
return
|
|
864
|
+
return templateText
|
|
811
865
|
}
|
|
812
866
|
}
|
|
813
867
|
|
|
@@ -841,8 +895,7 @@ class PrinterStore {
|
|
|
841
895
|
const info = this.tablesInfo[name]
|
|
842
896
|
if (!info?.body?.heights) return
|
|
843
897
|
|
|
844
|
-
const rows =
|
|
845
|
-
this.data._table[resolved] || this.data._table[dataKey] || []
|
|
898
|
+
const rows = this.data._table[resolved] || this.data._table[dataKey] || []
|
|
846
899
|
const realCount = rows.filter(row => row && !row._isEmptyData).length
|
|
847
900
|
if (info.body.heights.length > realCount) {
|
|
848
901
|
info.body.heights = info.body.heights.slice(0, realCount)
|
|
@@ -877,18 +930,15 @@ class PrinterStore {
|
|
|
877
930
|
return []
|
|
878
931
|
}
|
|
879
932
|
|
|
880
|
-
const sourceItems = flattenHorizontalPackedRows(
|
|
881
|
-
sourceRows,
|
|
882
|
-
sourceColNumber
|
|
883
|
-
)
|
|
933
|
+
const sourceItems = flattenHorizontalPackedRows(sourceRows, sourceColNumber)
|
|
884
934
|
const baseRowCount = sourceItems.length
|
|
885
935
|
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
886
936
|
: 0
|
|
887
937
|
const packed = !baseRowCount
|
|
888
938
|
? []
|
|
889
939
|
: isVertical
|
|
890
|
-
|
|
891
|
-
|
|
940
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
941
|
+
: packHorizontalRowMajor(sourceItems, colNumber)
|
|
892
942
|
this.data._table[dataKey] = packed
|
|
893
943
|
return packed
|
|
894
944
|
}
|
|
@@ -920,8 +970,8 @@ class PrinterStore {
|
|
|
920
970
|
const sourceColNumber = isMultiTable(singleKey)
|
|
921
971
|
? getMultiNumber(singleKey)
|
|
922
972
|
: isMultiTable(sourceKey)
|
|
923
|
-
|
|
924
|
-
|
|
973
|
+
? colNumber
|
|
974
|
+
: 1
|
|
925
975
|
const sourceItems = flattenHorizontalPackedRows(
|
|
926
976
|
sourceRows,
|
|
927
977
|
sourceColNumber
|
|
@@ -952,8 +1002,8 @@ class PrinterStore {
|
|
|
952
1002
|
emptyCount === 0
|
|
953
1003
|
? []
|
|
954
1004
|
: emptyTable.length > 0
|
|
955
|
-
|
|
956
|
-
|
|
1005
|
+
? emptyTable
|
|
1006
|
+
: this.getFilledTableData(table)
|
|
957
1007
|
const withPartial = fillPartialLastRow(table, colNumber, this.fillIndex)
|
|
958
1008
|
const lastKey = getMaxSerial(withPartial, colNumber) + 1
|
|
959
1009
|
const sample = table[0]
|
package/src/printer/table.js
CHANGED
|
@@ -169,7 +169,8 @@ class Table extends React.Component {
|
|
|
169
169
|
range,
|
|
170
170
|
pageIndex,
|
|
171
171
|
printerStore,
|
|
172
|
-
isSomeSubtotalTr
|
|
172
|
+
isSomeSubtotalTr,
|
|
173
|
+
isLastTablePage
|
|
173
174
|
} = this.props
|
|
174
175
|
// 数据
|
|
175
176
|
dataKey = getDataKey(dataKey, arrange)
|
|
@@ -407,7 +408,8 @@ class Table extends React.Component {
|
|
|
407
408
|
? printerStore.templateSpecialDetails(
|
|
408
409
|
col,
|
|
409
410
|
dataKey,
|
|
410
|
-
i
|
|
411
|
+
i,
|
|
412
|
+
config.specialConfig?.template_text
|
|
411
413
|
)
|
|
412
414
|
: printerStore
|
|
413
415
|
.templateTable(col.text, dataKey, i, pageIndex)
|
|
@@ -441,6 +443,7 @@ class Table extends React.Component {
|
|
|
441
443
|
range={range}
|
|
442
444
|
config={config}
|
|
443
445
|
printerStore={printerStore}
|
|
446
|
+
isLastTablePage={isLastTablePage}
|
|
444
447
|
/>
|
|
445
448
|
<DiyOverallOrder
|
|
446
449
|
range={range}
|
|
@@ -499,7 +502,12 @@ Table.propTypes = {
|
|
|
499
502
|
pageIndex: PropTypes.number.isRequired,
|
|
500
503
|
placeholder: PropTypes.string,
|
|
501
504
|
printerStore: PropTypes.object,
|
|
502
|
-
isSomeSubtotalTr: PropTypes.bool
|
|
505
|
+
isSomeSubtotalTr: PropTypes.bool,
|
|
506
|
+
isLastTablePage: PropTypes.bool
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
Table.defaultProps = {
|
|
510
|
+
isLastTablePage: true
|
|
503
511
|
}
|
|
504
512
|
|
|
505
513
|
export default Table
|
|
@@ -2,10 +2,9 @@ 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 { coverDigit2Uppercase, getDataKey } from '../util'
|
|
5
|
+
import { coverDigit2Uppercase, getDataKey, maskedSum } from '../util'
|
|
6
6
|
import { observer } from 'mobx-react'
|
|
7
7
|
import classNames from 'classnames'
|
|
8
|
-
import Big from 'big.js'
|
|
9
8
|
|
|
10
9
|
const DiyOverallOrder = props => {
|
|
11
10
|
const {
|
|
@@ -15,20 +14,14 @@ const DiyOverallOrder = props => {
|
|
|
15
14
|
} = props
|
|
16
15
|
const tableData = printerStore.data._table[getDataKey(dataKey)] || []
|
|
17
16
|
|
|
18
|
-
//
|
|
17
|
+
// 计算合计:任一渲染结果脱敏 '***' 则合计显 '***'(整格判定假设同 table_diy_summary_tr)
|
|
19
18
|
const sumData = field => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.replace(/\(\)/g, '')
|
|
27
|
-
result = a.plus(+bRes || 0)
|
|
28
|
-
return result
|
|
29
|
-
},
|
|
30
|
-
Big(0)
|
|
31
|
-
).toFixed(2)
|
|
19
|
+
const values = _.map(tableData, (b, i) =>
|
|
20
|
+
printerStore
|
|
21
|
+
.templateTable(field, dataKey, i, pageIndex)
|
|
22
|
+
.replace(/\(\)/g, '')
|
|
23
|
+
)
|
|
24
|
+
return maskedSum(values)
|
|
32
25
|
}
|
|
33
26
|
|
|
34
27
|
if (!diyOverallOrder?.show || !printerStore?.ready) {
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import _ from 'lodash'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
coverDigit2Uppercase,
|
|
6
|
+
getDataKey,
|
|
7
|
+
isMultiTable,
|
|
8
|
+
maskedSum
|
|
9
|
+
} from '../util'
|
|
5
10
|
import { MULTI_SUFFIX, MULTI_SUFFIX3 } from '../config'
|
|
6
11
|
import { observer } from 'mobx-react'
|
|
7
12
|
import classNames from 'classnames'
|
|
8
|
-
import Big from 'big.js'
|
|
9
13
|
|
|
10
14
|
function buildTemplateField(fieldStr, suffix) {
|
|
11
15
|
// 如果 field 是 "{{列.下单数}}",提取出 "下单数"
|
|
@@ -45,39 +49,18 @@ const DiySummary = props => {
|
|
|
45
49
|
|
|
46
50
|
// 计算合计
|
|
47
51
|
const sumData = field => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// 三栏
|
|
62
|
-
const multiField3 = buildTemplateField(field, MULTI_SUFFIX3)
|
|
63
|
-
result = result.plus(+getRes(multiField3, i) || 0)
|
|
64
|
-
|
|
65
|
-
return result
|
|
66
|
-
},
|
|
67
|
-
Big(0)
|
|
68
|
-
).toFixed(2)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return _.reduce(
|
|
72
|
-
tableData,
|
|
73
|
-
(a, b, i) => {
|
|
74
|
-
let result = a
|
|
75
|
-
const bRes = getRes(field, i)
|
|
76
|
-
result = a.plus(+bRes || 0)
|
|
77
|
-
return result
|
|
78
|
-
},
|
|
79
|
-
Big(0)
|
|
80
|
-
).toFixed(2)
|
|
52
|
+
// 收集本列渲染结果(含多栏后缀列),任一脱敏 '***' 则合计显 '***'
|
|
53
|
+
// 注意:基于渲染后字符串判定,假设模板整格就是脱敏值;带前后缀的模板(如 '{{列.金额}}元')无法识别
|
|
54
|
+
const values = []
|
|
55
|
+
_.each(tableData, (b, i) => {
|
|
56
|
+
values.push(getRes(field, i))
|
|
57
|
+
if (isMulti) {
|
|
58
|
+
// 双栏/三栏取后缀字段
|
|
59
|
+
values.push(getRes(buildTemplateField(field, MULTI_SUFFIX), i))
|
|
60
|
+
values.push(getRes(buildTemplateField(field, MULTI_SUFFIX3), i))
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
return maskedSum(values)
|
|
81
64
|
|
|
82
65
|
function getRes(field, i) {
|
|
83
66
|
return printerStore
|