gm-printer 10.41.9 → 10.42.1
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 +22 -3
- package/src/common/editor_customize_config.js +3 -0
- package/src/common/editor_store.js +229 -28
- package/src/editor_purchase/editor_special_table.js +12 -6
- package/src/index.js +4 -2
- package/src/printer/compute_pages.js +122 -0
- package/src/printer/index.js +3 -1
- package/src/printer/multi_column.js +461 -0
- package/src/printer/printer.js +34 -15
- package/src/printer/store.js +304 -38
- package/src/printer/table.js +3 -7
- package/src/util.js +13 -10
package/src/printer/store.js
CHANGED
|
@@ -3,14 +3,33 @@ import { action, observable, computed } from 'mobx'
|
|
|
3
3
|
import {
|
|
4
4
|
getSumTrHeight,
|
|
5
5
|
isMultiTable,
|
|
6
|
+
getMultiNumber,
|
|
7
|
+
getDataKey,
|
|
6
8
|
caclSingleDetailsPageHeight,
|
|
7
9
|
getArrayMid,
|
|
8
10
|
getOverallOrderTrHeight
|
|
9
11
|
} from '../util'
|
|
10
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
isDetailOneRowSelectKey,
|
|
14
|
+
isIndependentRolDataKey
|
|
15
|
+
} from '../common/data_key_util'
|
|
11
16
|
import _ from 'lodash'
|
|
12
17
|
import Big from 'big.js'
|
|
13
18
|
import { Tip } from '../components'
|
|
19
|
+
import {
|
|
20
|
+
fillEmptyRowIndex,
|
|
21
|
+
fillPartialLastRow,
|
|
22
|
+
getMaxSerial,
|
|
23
|
+
detectColNumber,
|
|
24
|
+
ensureRowSerialKeys,
|
|
25
|
+
flattenHorizontalPackedRows,
|
|
26
|
+
repackVerticalTableByPageRanges,
|
|
27
|
+
packVerticalNewspaper,
|
|
28
|
+
packHorizontalRowMajor,
|
|
29
|
+
createEmptyRows,
|
|
30
|
+
createEmptyRowSkeleton,
|
|
31
|
+
resolveVerticalEmptyCount
|
|
32
|
+
} from './multi_column'
|
|
14
33
|
|
|
15
34
|
export const TR_BASE_HEIGHT = 23
|
|
16
35
|
|
|
@@ -48,6 +67,8 @@ class PrinterStore {
|
|
|
48
67
|
/** 当前页剩余空白高度 */
|
|
49
68
|
@observable remainPageHeight = 0
|
|
50
69
|
@observable isSave = false
|
|
70
|
+
/** data._table 非 observable,变更后递增以驱动预览重渲 */
|
|
71
|
+
@observable dataRevision = 0
|
|
51
72
|
|
|
52
73
|
data = {}
|
|
53
74
|
|
|
@@ -217,6 +238,19 @@ class PrinterStore {
|
|
|
217
238
|
this.config = config || {}
|
|
218
239
|
}
|
|
219
240
|
|
|
241
|
+
/**
|
|
242
|
+
* 签名区高度:优先 DOM 测高,否则用配置 style.height。
|
|
243
|
+
* 打印在 iframe 内时测高常为 0,若只用 this.height.sign 会导致末页不扣签名、空行多填。
|
|
244
|
+
*/
|
|
245
|
+
getSignHeight() {
|
|
246
|
+
const measured = this.height?.sign
|
|
247
|
+
if (measured && measured > 0) return measured
|
|
248
|
+
const raw = this.config?.sign?.style?.height
|
|
249
|
+
if (raw == null || raw === '') return 0
|
|
250
|
+
const parsed = parseFloat(raw)
|
|
251
|
+
return Number.isFinite(parsed) ? parsed : 0
|
|
252
|
+
}
|
|
253
|
+
|
|
220
254
|
/** 处理采购单的明细
|
|
221
255
|
一行有多个明细, 并且采购明细是换行展示, 明细数据超多的情况则需要分割到不同页面中
|
|
222
256
|
比如: 一行有20行明细,当前页只能放下17行明细 ,剩下的3行明细需要放到下一页进行展示 */
|
|
@@ -357,9 +391,12 @@ class PrinterStore {
|
|
|
357
391
|
/** 当前page页面的最小高度 */
|
|
358
392
|
const currentPageMinimumHeight =
|
|
359
393
|
allPagesHaveThisHeight + allTableHaveThisHeight
|
|
394
|
+
// 最后一项是表格时,末页仍要渲染签名:装行可用高度预留签名,避免空行顶进签名区
|
|
395
|
+
const isLastContent = index === this.config.contents.length - 1
|
|
396
|
+
const signReserve = isLastContent ? this.getSignHeight() : 0
|
|
360
397
|
/** 当前page可容纳的table高度 */
|
|
361
398
|
let pageAccomodateTableHeight = roundHeight(
|
|
362
|
-
pageHeight - currentPageHeight
|
|
399
|
+
pageHeight - currentPageHeight - signReserve
|
|
363
400
|
)
|
|
364
401
|
// 拷贝一份行高数组,避免 splice 触发 observable 副作用
|
|
365
402
|
const heights = [
|
|
@@ -492,9 +529,9 @@ class PrinterStore {
|
|
|
492
529
|
}
|
|
493
530
|
|
|
494
531
|
begin = end
|
|
495
|
-
//
|
|
532
|
+
// 开启新一页,重置页面高度(末项表格仍预留签名)
|
|
496
533
|
pageAccomodateTableHeight = roundHeight(
|
|
497
|
-
pageHeight - allPagesHaveThisHeight
|
|
534
|
+
pageHeight - allPagesHaveThisHeight - signReserve
|
|
498
535
|
)
|
|
499
536
|
currentTableHeight = allTableHaveThisHeight
|
|
500
537
|
currentPageHeight = currentPageMinimumHeight
|
|
@@ -534,7 +571,7 @@ class PrinterStore {
|
|
|
534
571
|
|
|
535
572
|
// 如果是最后一页,必须要加上sign的高度,否则会重叠
|
|
536
573
|
if (index === contentsLength - 1) {
|
|
537
|
-
currentPageHeight +=
|
|
574
|
+
currentPageHeight += this.getSignHeight()
|
|
538
575
|
}
|
|
539
576
|
|
|
540
577
|
if (currentPageHeight <= pageHeight) {
|
|
@@ -557,9 +594,88 @@ class PrinterStore {
|
|
|
557
594
|
}
|
|
558
595
|
pages.push(page)
|
|
559
596
|
this.pages = pages
|
|
560
|
-
|
|
597
|
+
|
|
598
|
+
// 末页签名:panel 分支会在「最后一项是 panel」时扣 sign;
|
|
599
|
+
// 最后一项是 table 时上面不会扣,导致 remain 偏大、空行多填溢页
|
|
600
|
+
// 打印 iframe 内 height.sign 可能为 0,必须用 getSignHeight(含配置兜底)
|
|
601
|
+
const lastContent = contents[contentsLength - 1]
|
|
602
|
+
if (lastContent?.type === 'table') {
|
|
603
|
+
currentPageHeight += this.getSignHeight()
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
this.remainPageHeight = Math.max(
|
|
607
|
+
0,
|
|
608
|
+
Math.round(pageHeight - currentPageHeight)
|
|
609
|
+
)
|
|
561
610
|
this.isSave = false
|
|
562
611
|
this.config.isSave = false
|
|
612
|
+
this.repackVerticalMultiByPages()
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
getTablePageRanges(contentIndex, rows) {
|
|
616
|
+
const ranges = []
|
|
617
|
+
this.pages.forEach(page => {
|
|
618
|
+
page.forEach(panel => {
|
|
619
|
+
if (panel.type === 'table' && panel.index === contentIndex) {
|
|
620
|
+
ranges.push({ begin: panel.begin, end: panel.end })
|
|
621
|
+
}
|
|
622
|
+
})
|
|
623
|
+
})
|
|
624
|
+
if (!ranges.length || !rows?.length) return ranges
|
|
625
|
+
const last = ranges[ranges.length - 1]
|
|
626
|
+
let end = last.end
|
|
627
|
+
while (end < rows.length && rows[end]?._isEmptyData) {
|
|
628
|
+
end++
|
|
629
|
+
}
|
|
630
|
+
last.end = end
|
|
631
|
+
return ranges
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
@action
|
|
635
|
+
repackVerticalMultiByPages() {
|
|
636
|
+
if (!this.pages?.length) return
|
|
637
|
+
this.config.contents.forEach((content, contentIndex) => {
|
|
638
|
+
if (content?.type !== 'table' || !isMultiTable(content.dataKey)) {
|
|
639
|
+
return
|
|
640
|
+
}
|
|
641
|
+
const dataKey = content.dataKey
|
|
642
|
+
const isVertical =
|
|
643
|
+
content.arrange === 'vertical' || /_vertical$/.test(dataKey)
|
|
644
|
+
if (!isVertical) return
|
|
645
|
+
|
|
646
|
+
const sourceKey = dataKey.replace(/_vertical$/, '')
|
|
647
|
+
const verticalKey = /_vertical$/.test(dataKey)
|
|
648
|
+
? dataKey
|
|
649
|
+
: `${sourceKey}_vertical`
|
|
650
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
651
|
+
const verticalRows = this.data._table[verticalKey]
|
|
652
|
+
if (!verticalRows?.length) return
|
|
653
|
+
|
|
654
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
655
|
+
const sourceRows =
|
|
656
|
+
this.data._table[singleKey] || this.data._table[sourceKey] || []
|
|
657
|
+
const sourceColNumber = isMultiTable(singleKey)
|
|
658
|
+
? getMultiNumber(singleKey)
|
|
659
|
+
: isMultiTable(sourceKey)
|
|
660
|
+
? colNumber
|
|
661
|
+
: 1
|
|
662
|
+
const sourceItems = flattenHorizontalPackedRows(
|
|
663
|
+
sourceRows,
|
|
664
|
+
sourceColNumber
|
|
665
|
+
)
|
|
666
|
+
// 无商品时仍可能需要给空行按列编序号
|
|
667
|
+
if (!sourceItems.length && !this.fillIndex) return
|
|
668
|
+
|
|
669
|
+
const pageRanges = this.getTablePageRanges(contentIndex, verticalRows)
|
|
670
|
+
this.data._table[verticalKey] = repackVerticalTableByPageRanges(
|
|
671
|
+
verticalRows,
|
|
672
|
+
colNumber,
|
|
673
|
+
pageRanges,
|
|
674
|
+
this.fillIndex,
|
|
675
|
+
sourceItems
|
|
676
|
+
)
|
|
677
|
+
this.dataRevision += 1
|
|
678
|
+
})
|
|
563
679
|
}
|
|
564
680
|
|
|
565
681
|
@action
|
|
@@ -628,13 +744,12 @@ class PrinterStore {
|
|
|
628
744
|
*/
|
|
629
745
|
templateTableRowSpan(text, dataKey, index, begin) {
|
|
630
746
|
try {
|
|
631
|
-
// 采购 / 分拣「按明细单行」展开后才做合并单元格(后缀 independent_rol_
|
|
747
|
+
// 采购 / 分拣「按明细单行」展开后才做合并单元格(后缀 independent_rol_* / detail_one_row_*,含 category)
|
|
632
748
|
const canMerge =
|
|
633
749
|
isIndependentRolDataKey(dataKey) ||
|
|
750
|
+
isDetailOneRowSelectKey(dataKey) ||
|
|
634
751
|
dataKey === 'taxRateSales' ||
|
|
635
|
-
dataKey === 'ordinary'
|
|
636
|
-
dataKey === 'purchase_detail_one_row' ||
|
|
637
|
-
dataKey === 'sorting_detail_detail_one_row'
|
|
752
|
+
dataKey === 'ordinary'
|
|
638
753
|
if (!canMerge) {
|
|
639
754
|
return null
|
|
640
755
|
}
|
|
@@ -670,7 +785,7 @@ class PrinterStore {
|
|
|
670
785
|
}
|
|
671
786
|
|
|
672
787
|
templateTable(text, dataKey, index, pageIndex) {
|
|
673
|
-
//
|
|
788
|
+
// 做好保护,出错就返回空串(勿回传原始 {{}},否则单元格会露出模板)
|
|
674
789
|
try {
|
|
675
790
|
let list = this.data._table[dataKey] || this.data._table.orders
|
|
676
791
|
|
|
@@ -679,18 +794,34 @@ class PrinterStore {
|
|
|
679
794
|
list = _.uniqBy(list, '序号')
|
|
680
795
|
}
|
|
681
796
|
|
|
797
|
+
const colNumber = detectColNumber(dataKey, list)
|
|
798
|
+
const sample = (list || []).find(item => item && !item._isEmptyData)
|
|
799
|
+
let row = list?.[index]
|
|
800
|
+
// 渲染 end 偶发超过数据长度时,用空行骨架兜底,避免 列=undefined 抛错露出 {{列.xxx_MULTI_SUFFIX}}
|
|
801
|
+
if (!row) {
|
|
802
|
+
if (!this.isAutoFilling) return ''
|
|
803
|
+
list = (list || []).slice()
|
|
804
|
+
while (list.length <= index) {
|
|
805
|
+
list.push(createEmptyRowSkeleton(sample, colNumber))
|
|
806
|
+
}
|
|
807
|
+
row = list[index]
|
|
808
|
+
}
|
|
809
|
+
row =
|
|
810
|
+
ensureRowSerialKeys(list, index, colNumber, this.fillIndex, dataKey) ||
|
|
811
|
+
row
|
|
812
|
+
|
|
682
813
|
return _.template(text, {
|
|
683
814
|
interpolate: /{{([\s\S]+?)}}/g
|
|
684
815
|
})({
|
|
685
816
|
...this.data.common,
|
|
686
817
|
|
|
687
|
-
[i18next.t('列')]:
|
|
818
|
+
[i18next.t('列')]: row,
|
|
688
819
|
[i18next.t('当前页码')]: pageIndex + 1,
|
|
689
820
|
[i18next.t('页码总数')]: Math.max(1, this.pages.length),
|
|
690
821
|
price: price // 提供一个价格处理函数
|
|
691
822
|
})
|
|
692
823
|
} catch (err) {
|
|
693
|
-
return
|
|
824
|
+
return ''
|
|
694
825
|
}
|
|
695
826
|
}
|
|
696
827
|
|
|
@@ -763,41 +894,176 @@ class PrinterStore {
|
|
|
763
894
|
const tr_count = Math.floor(
|
|
764
895
|
this.remainPageHeight / this.computedTableCustomerRowHeight
|
|
765
896
|
)
|
|
897
|
+
if (tr_count <= 0) return []
|
|
766
898
|
|
|
767
|
-
const
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
899
|
+
const sample = (tableData || []).find(item => item && !item._isEmptyData)
|
|
900
|
+
const colNumber = detectColNumber(
|
|
901
|
+
this.tableConfig?.dataKey || autoFillConfig?.dataKey,
|
|
902
|
+
tableData
|
|
903
|
+
)
|
|
904
|
+
return createEmptyRows(tr_count, sample, colNumber)
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/** 空行高度只由 getNormalTableBodyHeights 虚拟追加,禁止写入 body.heights(会双计溢页) */
|
|
908
|
+
@action
|
|
909
|
+
trimTableBodyHeightsToRealRows(dataKey) {
|
|
910
|
+
if (!dataKey || !this.tablesInfo) return
|
|
911
|
+
this.config.contents.forEach((content, index) => {
|
|
912
|
+
if (content?.type !== 'table') return
|
|
913
|
+
const resolved = getDataKey(content.dataKey, content.arrange)
|
|
914
|
+
if (resolved !== dataKey && content.dataKey !== dataKey) return
|
|
915
|
+
|
|
916
|
+
const name = `contents.table.${index}`
|
|
917
|
+
const info = this.tablesInfo[name]
|
|
918
|
+
if (!info?.body?.heights) return
|
|
919
|
+
|
|
920
|
+
const rows = this.data._table[resolved] || this.data._table[dataKey] || []
|
|
921
|
+
const realCount = rows.filter(row => row && !row._isEmptyData).length
|
|
922
|
+
if (info.body.heights.length > realCount) {
|
|
923
|
+
info.body.heights = info.body.heights.slice(0, realCount)
|
|
924
|
+
}
|
|
772
925
|
})
|
|
773
|
-
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/** 多栏表缺失时(如双栏切三栏),从单栏/低栏源表现场打包 */
|
|
929
|
+
ensureMultiTableData(dataKey) {
|
|
930
|
+
const existing = this.data._table[dataKey]
|
|
931
|
+
if (existing?.length) return existing
|
|
932
|
+
if (!isMultiTable(dataKey)) return existing || null
|
|
933
|
+
|
|
934
|
+
const isVertical = /_vertical$/.test(dataKey)
|
|
935
|
+
const sourceKey = dataKey.replace(/_vertical$/, '')
|
|
936
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
937
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
938
|
+
|
|
939
|
+
let sourceRows = this.data._table[singleKey]
|
|
940
|
+
let sourceColNumber = 1
|
|
941
|
+
if (!sourceRows?.length && /multi3/.test(sourceKey)) {
|
|
942
|
+
const dualKey = sourceKey.replace('multi3', 'multi')
|
|
943
|
+
sourceRows = this.data._table[dualKey]
|
|
944
|
+
sourceColNumber = 2
|
|
945
|
+
}
|
|
946
|
+
if (!sourceRows?.length) {
|
|
947
|
+
sourceRows = this.data._table[sourceKey]
|
|
948
|
+
sourceColNumber = isMultiTable(sourceKey) ? colNumber : 1
|
|
949
|
+
}
|
|
950
|
+
if (!sourceRows?.length) {
|
|
951
|
+
this.data._table[dataKey] = []
|
|
952
|
+
return []
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const sourceItems = flattenHorizontalPackedRows(sourceRows, sourceColNumber)
|
|
956
|
+
const baseRowCount = sourceItems.length
|
|
957
|
+
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
958
|
+
: 0
|
|
959
|
+
const packed = !baseRowCount
|
|
960
|
+
? []
|
|
961
|
+
: isVertical
|
|
962
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
963
|
+
: packHorizontalRowMajor(sourceItems, colNumber)
|
|
964
|
+
this.data._table[dataKey] = packed
|
|
965
|
+
return packed
|
|
966
|
+
}
|
|
774
967
|
|
|
775
|
-
|
|
968
|
+
fillTableEmptyIndex(dataKey) {
|
|
969
|
+
let tableData = this.data._table[dataKey]
|
|
970
|
+
if (!tableData && isMultiTable(dataKey)) {
|
|
971
|
+
tableData = this.ensureMultiTableData(dataKey)
|
|
972
|
+
}
|
|
973
|
+
if (!tableData) return
|
|
974
|
+
const emptyTable = tableData.filter(item => item._isEmptyData)
|
|
975
|
+
const table = tableData.filter(item => !item._isEmptyData)
|
|
976
|
+
const toFillEmptyCount =
|
|
977
|
+
emptyTable.length === 0 ? this.getFilledTableData(table).length : 0
|
|
978
|
+
const emptyCount =
|
|
979
|
+
emptyTable.length > 0 ? emptyTable.length : toFillEmptyCount
|
|
980
|
+
|
|
981
|
+
// 纵向多栏:源商品按对半行落位 + 追加空行;左列优先由 repack 按「数据行+空行」整段完成
|
|
982
|
+
if (/_vertical$/.test(dataKey)) {
|
|
983
|
+
const sourceKey = dataKey.replace(/_vertical$/, '')
|
|
984
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
985
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
986
|
+
// 横向源表缺失时先生成(双栏→三栏常见)
|
|
987
|
+
if (!this.data._table[sourceKey]?.length) {
|
|
988
|
+
this.ensureMultiTableData(sourceKey)
|
|
989
|
+
}
|
|
990
|
+
const sourceRows =
|
|
991
|
+
this.data._table[singleKey] || this.data._table[sourceKey] || []
|
|
992
|
+
const sourceColNumber = isMultiTable(singleKey)
|
|
993
|
+
? getMultiNumber(singleKey)
|
|
994
|
+
: isMultiTable(sourceKey)
|
|
995
|
+
? colNumber
|
|
996
|
+
: 1
|
|
997
|
+
const sourceItems = flattenHorizontalPackedRows(
|
|
998
|
+
sourceRows,
|
|
999
|
+
sourceColNumber
|
|
1000
|
+
)
|
|
1001
|
+
const baseRowCount = sourceItems.length
|
|
1002
|
+
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
1003
|
+
: 0
|
|
1004
|
+
// 钉死总行:left-first repack 后 _isEmptyData 变少,不能用 emptyTable.length 回推
|
|
1005
|
+
const emptyCount = resolveVerticalEmptyCount(
|
|
1006
|
+
tableData.length,
|
|
1007
|
+
baseRowCount,
|
|
1008
|
+
emptyTable.length > 0
|
|
1009
|
+
? emptyTable.length
|
|
1010
|
+
: this.getFilledTableData(table).length,
|
|
1011
|
+
emptyTable.length > 0
|
|
1012
|
+
)
|
|
1013
|
+
const dataRows = baseRowCount
|
|
1014
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
1015
|
+
: []
|
|
1016
|
+
const sample = dataRows[0] || sourceRows[0]
|
|
1017
|
+
const emptyRows = createEmptyRows(emptyCount, sample, colNumber)
|
|
1018
|
+
this.data._table[dataKey] = dataRows.concat(emptyRows)
|
|
1019
|
+
return
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
const colNumber = detectColNumber(dataKey, tableData)
|
|
1023
|
+
const templates =
|
|
1024
|
+
emptyCount === 0
|
|
1025
|
+
? []
|
|
1026
|
+
: emptyTable.length > 0
|
|
1027
|
+
? emptyTable
|
|
1028
|
+
: this.getFilledTableData(table)
|
|
1029
|
+
const withPartial = fillPartialLastRow(table, colNumber, this.fillIndex)
|
|
1030
|
+
const lastKey = getMaxSerial(withPartial, colNumber) + 1
|
|
1031
|
+
const sample = table[0]
|
|
1032
|
+
const fillList = templates.map((item, index) =>
|
|
1033
|
+
fillEmptyRowIndex(
|
|
1034
|
+
{
|
|
1035
|
+
...createEmptyRowSkeleton(sample, colNumber),
|
|
1036
|
+
...item,
|
|
1037
|
+
_isEmptyData: true
|
|
1038
|
+
},
|
|
1039
|
+
index,
|
|
1040
|
+
lastKey,
|
|
1041
|
+
colNumber,
|
|
1042
|
+
this.fillIndex
|
|
1043
|
+
)
|
|
1044
|
+
)
|
|
1045
|
+
withPartial.push(...fillList)
|
|
1046
|
+
this.data._table[dataKey] = withPartial
|
|
776
1047
|
}
|
|
777
1048
|
|
|
778
1049
|
@action.bound
|
|
779
1050
|
changeTableData() {
|
|
780
1051
|
const { autoFillConfig } = this.config
|
|
781
1052
|
if (!this.isAutoFilling) return
|
|
782
|
-
const dataKey = autoFillConfig?.dataKey
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
)
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (this.fillIndex) {
|
|
792
|
-
return { ...item, 序号: index + lastKey }
|
|
793
|
-
} else {
|
|
794
|
-
return { ...item, 序号: '' }
|
|
795
|
-
}
|
|
1053
|
+
const dataKey = this.tableConfig?.dataKey || autoFillConfig?.dataKey
|
|
1054
|
+
if (!dataKey) return
|
|
1055
|
+
this.fillTableEmptyIndex(dataKey)
|
|
1056
|
+
// 测高只含商品行;空行高度交给 getNormalTableBodyHeights,避免写入 heights 双计
|
|
1057
|
+
this.trimTableBodyHeightsToRealRows(dataKey)
|
|
1058
|
+
if (isMultiTable(dataKey)) {
|
|
1059
|
+
const verticalKey = getDataKey(dataKey, 'vertical')
|
|
1060
|
+
if (!this.data._table[verticalKey]) {
|
|
1061
|
+
this.data._table[verticalKey] = []
|
|
796
1062
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
this.
|
|
1063
|
+
this.fillTableEmptyIndex(verticalKey)
|
|
1064
|
+
this.trimTableBodyHeightsToRealRows(verticalKey)
|
|
1065
|
+
}
|
|
1066
|
+
this.repackVerticalMultiByPages()
|
|
801
1067
|
}
|
|
802
1068
|
}
|
|
803
1069
|
|
package/src/printer/table.js
CHANGED
|
@@ -360,15 +360,11 @@ class Table extends React.Component {
|
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
// 如果项为空对象展现一个占满一行的td
|
|
363
|
-
const isItemNone = !_.keys(tableData[i]).length
|
|
363
|
+
const isItemNone = !_.keys(tableData[i] || {}).length
|
|
364
364
|
return (
|
|
365
365
|
<tr style={{ height: `${customerRowHeight}px` }} key={i}>
|
|
366
|
-
{isItemNone ? (
|
|
367
|
-
|
|
368
|
-
<td colSpan='99' />
|
|
369
|
-
) : (
|
|
370
|
-
<></>
|
|
371
|
-
)
|
|
366
|
+
{isItemNone && !printerStore?.isAutoFilling ? (
|
|
367
|
+
<td colSpan='99' />
|
|
372
368
|
) : (
|
|
373
369
|
_.map(columns, (col, j) => {
|
|
374
370
|
const rowSpan = printerStore.templateTableRowSpan(
|
package/src/util.js
CHANGED
|
@@ -2,19 +2,23 @@ import _ from 'lodash'
|
|
|
2
2
|
import Big from 'big.js'
|
|
3
3
|
|
|
4
4
|
function getHeight(el) {
|
|
5
|
-
|
|
5
|
+
// 打印渲染在 iframe 内时,必须用元素所属 document 的 window,
|
|
6
|
+
// 否则 parent window.getComputedStyle 可能得到错误值、测高为 0
|
|
7
|
+
const view = (el.ownerDocument && el.ownerDocument.defaultView) || window
|
|
8
|
+
const styles = view.getComputedStyle(el)
|
|
6
9
|
const height = el.offsetHeight
|
|
7
|
-
const borderTopWidth = parseFloat(styles.borderTopWidth)
|
|
8
|
-
const borderBottomWidth = parseFloat(styles.borderBottomWidth)
|
|
9
|
-
const paddingTop = parseFloat(styles.paddingTop)
|
|
10
|
-
const paddingBottom = parseFloat(styles.paddingBottom)
|
|
10
|
+
const borderTopWidth = parseFloat(styles.borderTopWidth) || 0
|
|
11
|
+
const borderBottomWidth = parseFloat(styles.borderBottomWidth) || 0
|
|
12
|
+
const paddingTop = parseFloat(styles.paddingTop) || 0
|
|
13
|
+
const paddingBottom = parseFloat(styles.paddingBottom) || 0
|
|
11
14
|
return (
|
|
12
15
|
height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom
|
|
13
16
|
)
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
function getWidth(el) {
|
|
17
|
-
const
|
|
20
|
+
const view = (el.ownerDocument && el.ownerDocument.defaultView) || window
|
|
21
|
+
const styles = view.getComputedStyle(el)
|
|
18
22
|
// 取width保留小数点用 getBoundClientRect
|
|
19
23
|
const style = el.getBoundingClientRect()
|
|
20
24
|
const width = Math.round(style.width * 100) / 100 // 保留两位小数并四舍五入
|
|
@@ -82,13 +86,12 @@ function exchange(arr, target, source) {
|
|
|
82
86
|
return arr
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
let timer
|
|
86
|
-
|
|
87
89
|
function afterImgAndSvgLoaded(callback, $printer) {
|
|
88
90
|
const $imgList = $printer.querySelectorAll('img')
|
|
89
91
|
const $svgList = $printer.querySelectorAll('svg')
|
|
90
92
|
|
|
91
|
-
|
|
93
|
+
// timer 为函数内局部变量:computePages(导出测高)与 doPrint(打印)可能并发调用本函数,
|
|
94
|
+
// 若共享模块级 timer,后调用方会 clearTimeout 掉前一方的轮询,导致其 callback 永不执行
|
|
92
95
|
|
|
93
96
|
const everyThingIsOk =
|
|
94
97
|
_.every($imgList, img => img.complete) &&
|
|
@@ -96,7 +99,7 @@ function afterImgAndSvgLoaded(callback, $printer) {
|
|
|
96
99
|
if (everyThingIsOk) {
|
|
97
100
|
callback()
|
|
98
101
|
} else {
|
|
99
|
-
|
|
102
|
+
setTimeout(afterImgAndSvgLoaded.bind(this, callback, $printer), 300)
|
|
100
103
|
}
|
|
101
104
|
}
|
|
102
105
|
|