gm-printer 10.41.8 → 10.42.0
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/editor_customize_config.js +3 -0
- package/src/common/editor_store.js +219 -23
- 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 +297 -33
- package/src/printer/table.js +3 -7
- package/src/util.js +13 -10
package/package.json
CHANGED
|
@@ -24,6 +24,9 @@ class EditorCutomizedConfig extends React.Component {
|
|
|
24
24
|
handleFillIndex = value => {
|
|
25
25
|
const { editStore } = this.props
|
|
26
26
|
editStore.setFillIndex(value)
|
|
27
|
+
if (editStore.isAutoFilling) {
|
|
28
|
+
editStore.handleChangeTableData(true)
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
handleTaxFreeProductRateDisplay = e => {
|
|
@@ -2,7 +2,15 @@ import i18next from '../../locales'
|
|
|
2
2
|
import { action, computed, observable, set, toJS } from 'mobx'
|
|
3
3
|
import { pageTypeMap } from '../config'
|
|
4
4
|
import _ from 'lodash'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
dispatchMsg,
|
|
7
|
+
getBlockName,
|
|
8
|
+
exchange,
|
|
9
|
+
getColSpanLength,
|
|
10
|
+
isMultiTable,
|
|
11
|
+
getDataKey,
|
|
12
|
+
getMultiNumber
|
|
13
|
+
} from '../util'
|
|
6
14
|
import { accountRadioList } from './util'
|
|
7
15
|
import {
|
|
8
16
|
buildDataKey,
|
|
@@ -12,6 +20,18 @@ import {
|
|
|
12
20
|
} from './data_key_util'
|
|
13
21
|
import React from 'react'
|
|
14
22
|
import { createDiySummaryStoreMethods } from './diy_summary_helper'
|
|
23
|
+
import {
|
|
24
|
+
detectColNumber,
|
|
25
|
+
fillEmptyRowIndex,
|
|
26
|
+
fillPartialLastRow,
|
|
27
|
+
getMaxSerial,
|
|
28
|
+
flattenHorizontalPackedRows,
|
|
29
|
+
packVerticalNewspaper,
|
|
30
|
+
packHorizontalRowMajor,
|
|
31
|
+
createEmptyRows,
|
|
32
|
+
createEmptyRowSkeleton,
|
|
33
|
+
resolveVerticalEmptyCount
|
|
34
|
+
} from '../printer/multi_column'
|
|
15
35
|
|
|
16
36
|
class EditorStore {
|
|
17
37
|
@observable
|
|
@@ -207,6 +227,7 @@ class EditorStore {
|
|
|
207
227
|
vv.columns.length +
|
|
208
228
|
vv.className +
|
|
209
229
|
vv.dataKey +
|
|
230
|
+
(vv.arrange || 'lateral') +
|
|
210
231
|
vv.subtotal.show +
|
|
211
232
|
vv.summaryConfig?.pageSummaryShow +
|
|
212
233
|
vv.customerRowHeight
|
|
@@ -246,14 +267,54 @@ class EditorStore {
|
|
|
246
267
|
tr_count = Math.floor(
|
|
247
268
|
this.remainPageHeihgt / this.computedTableCustomerRowHeight
|
|
248
269
|
)
|
|
270
|
+
if (tr_count <= 0) return []
|
|
249
271
|
|
|
250
|
-
const
|
|
251
|
-
|
|
272
|
+
const sample = (tableData || []).find(item => item && !item._isEmptyData)
|
|
273
|
+
const dataKey =
|
|
274
|
+
this.computedTableSpecialConfig?.dataKey || autoFillConfig?.dataKey
|
|
275
|
+
const colNumber = detectColNumber(dataKey, tableData)
|
|
276
|
+
return createEmptyRows(tr_count, sample, colNumber)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** 多栏表缺失时(如双栏切三栏),从单栏/双栏源表现场打包到 mockData */
|
|
280
|
+
@action
|
|
281
|
+
ensureMockMultiTable(dataKey) {
|
|
282
|
+
if (!dataKey || !isMultiTable(dataKey)) return
|
|
283
|
+
if (!this.mockData._table) {
|
|
284
|
+
this.mockData._table = {}
|
|
285
|
+
}
|
|
286
|
+
if (this.mockData._table[dataKey]?.length) return
|
|
287
|
+
|
|
288
|
+
const isVertical = /_vertical$/.test(dataKey)
|
|
289
|
+
const sourceKey = dataKey.replace(/_vertical$/, '')
|
|
290
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
291
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
292
|
+
|
|
293
|
+
let sourceRows = this.mockData._table[singleKey]
|
|
294
|
+
let sourceColNumber = 1
|
|
295
|
+
if (!sourceRows?.length && /multi3/.test(sourceKey)) {
|
|
296
|
+
const dualKey = sourceKey.replace('multi3', 'multi')
|
|
297
|
+
sourceRows = this.mockData._table[dualKey]
|
|
298
|
+
sourceColNumber = 2
|
|
299
|
+
}
|
|
300
|
+
if (!sourceRows?.length) {
|
|
301
|
+
sourceRows = this.mockData._table[sourceKey]
|
|
302
|
+
sourceColNumber = isMultiTable(sourceKey) ? colNumber : 1
|
|
303
|
+
}
|
|
304
|
+
if (!sourceRows?.length) {
|
|
305
|
+
this.mockData._table[dataKey] = []
|
|
306
|
+
return
|
|
252
307
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
308
|
+
|
|
309
|
+
const sourceItems = flattenHorizontalPackedRows(sourceRows, sourceColNumber)
|
|
310
|
+
const baseRowCount = sourceItems.length
|
|
311
|
+
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
312
|
+
: 0
|
|
313
|
+
this.mockData._table[dataKey] = !baseRowCount
|
|
314
|
+
? []
|
|
315
|
+
: isVertical
|
|
316
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
317
|
+
: packHorizontalRowMajor(sourceItems, colNumber)
|
|
257
318
|
}
|
|
258
319
|
|
|
259
320
|
@action.bound
|
|
@@ -262,9 +323,6 @@ class EditorStore {
|
|
|
262
323
|
if (!this.selectedRegion && !autoFillConfig?.checked) return
|
|
263
324
|
const dataKey =
|
|
264
325
|
this.computedTableSpecialConfig?.dataKey || autoFillConfig?.dataKey
|
|
265
|
-
// 每次都更新一下?
|
|
266
|
-
const table = this.mockData._table[dataKey]
|
|
267
|
-
// 赋值一下
|
|
268
326
|
this.setAutoFillingConfig(isAutoFilling)
|
|
269
327
|
this.setFillIndex(autoFillConfig?.fillIndex || false)
|
|
270
328
|
set(this.config, {
|
|
@@ -277,24 +335,112 @@ class EditorStore {
|
|
|
277
335
|
}
|
|
278
336
|
})
|
|
279
337
|
|
|
280
|
-
|
|
338
|
+
if (dataKey && isMultiTable(dataKey)) {
|
|
339
|
+
this.ensureMockMultiTable(dataKey)
|
|
340
|
+
this.ensureMockMultiTable(getDataKey(dataKey, 'vertical'))
|
|
341
|
+
}
|
|
281
342
|
|
|
282
|
-
|
|
343
|
+
const syncEmptyRows = key => {
|
|
344
|
+
if (!this.mockData._table?.[key]) return
|
|
345
|
+
const list = this.mockData._table[key]
|
|
346
|
+
const hasHadEmptyData = _.some(list, data => data?._isEmptyData)
|
|
347
|
+
if (isAutoFilling && !hasHadEmptyData) {
|
|
348
|
+
list.push(...this.getFilledTableData(list))
|
|
349
|
+
}
|
|
350
|
+
if (!isAutoFilling) {
|
|
351
|
+
this.clearExtraTableData(key)
|
|
352
|
+
return
|
|
353
|
+
}
|
|
354
|
+
this.mockData._table[key] = list
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const numberEmptyRows = key => {
|
|
358
|
+
const list = this.mockData._table?.[key]
|
|
359
|
+
if (!list) return
|
|
360
|
+
const table = list.filter(item => !item._isEmptyData)
|
|
361
|
+
const emptyTable = list.filter(item => item._isEmptyData)
|
|
362
|
+
// 纵向表:对半数据行 + 空行占位;左列优先交给 Printer.repack
|
|
363
|
+
if (/_vertical$/.test(key)) {
|
|
364
|
+
const sourceKey = key.replace(/_vertical$/, '')
|
|
365
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
366
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
367
|
+
const sourceRows =
|
|
368
|
+
this.mockData._table[singleKey] ||
|
|
369
|
+
this.mockData._table[sourceKey] ||
|
|
370
|
+
[]
|
|
371
|
+
const sourceColNumber = isMultiTable(singleKey)
|
|
372
|
+
? getMultiNumber(singleKey)
|
|
373
|
+
: isMultiTable(sourceKey)
|
|
374
|
+
? colNumber
|
|
375
|
+
: 1
|
|
376
|
+
const sourceItems = flattenHorizontalPackedRows(
|
|
377
|
+
sourceRows,
|
|
378
|
+
sourceColNumber
|
|
379
|
+
)
|
|
380
|
+
const baseRowCount = sourceItems.length
|
|
381
|
+
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
382
|
+
: 0
|
|
383
|
+
// 钉死总行:repack 后 _isEmptyData 会变少,不能再用 emptyTable.length
|
|
384
|
+
const emptyCount = resolveVerticalEmptyCount(
|
|
385
|
+
list.length,
|
|
386
|
+
baseRowCount,
|
|
387
|
+
emptyTable.length > 0
|
|
388
|
+
? emptyTable.length
|
|
389
|
+
: this.getFilledTableData(list).length,
|
|
390
|
+
emptyTable.length > 0
|
|
391
|
+
)
|
|
392
|
+
const dataRows = baseRowCount
|
|
393
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
394
|
+
: []
|
|
395
|
+
const sample = dataRows[0] || sourceRows[0]
|
|
396
|
+
this.mockData._table[key] = dataRows.concat(
|
|
397
|
+
createEmptyRows(emptyCount, sample, colNumber)
|
|
398
|
+
)
|
|
399
|
+
return
|
|
400
|
+
}
|
|
401
|
+
const colNumber = detectColNumber(key, list)
|
|
402
|
+
const withPartial = fillPartialLastRow(table, colNumber, this.fillIndex)
|
|
403
|
+
const lastKey = getMaxSerial(withPartial, colNumber) + 1
|
|
404
|
+
const sample = table[0]
|
|
405
|
+
this.mockData._table[key] = withPartial.concat(
|
|
406
|
+
emptyTable.map((item, index) =>
|
|
407
|
+
fillEmptyRowIndex(
|
|
408
|
+
{
|
|
409
|
+
...createEmptyRowSkeleton(sample, colNumber),
|
|
410
|
+
...item,
|
|
411
|
+
_isEmptyData: true
|
|
412
|
+
},
|
|
413
|
+
index,
|
|
414
|
+
lastKey,
|
|
415
|
+
colNumber,
|
|
416
|
+
this.fillIndex
|
|
417
|
+
)
|
|
418
|
+
)
|
|
419
|
+
)
|
|
420
|
+
}
|
|
283
421
|
|
|
284
|
-
|
|
285
|
-
|
|
422
|
+
syncEmptyRows(dataKey)
|
|
423
|
+
if (dataKey && isMultiTable(dataKey)) {
|
|
424
|
+
const verticalKey = getDataKey(dataKey, 'vertical')
|
|
425
|
+
if (!this.mockData._table[verticalKey]) {
|
|
426
|
+
this.mockData._table[verticalKey] = []
|
|
427
|
+
}
|
|
428
|
+
syncEmptyRows(verticalKey)
|
|
286
429
|
}
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
|
|
430
|
+
if (isAutoFilling) {
|
|
431
|
+
numberEmptyRows(dataKey)
|
|
432
|
+
if (dataKey && isMultiTable(dataKey)) {
|
|
433
|
+
numberEmptyRows(getDataKey(dataKey, 'vertical'))
|
|
434
|
+
}
|
|
290
435
|
}
|
|
291
|
-
this.mockData._table[dataKey] = table
|
|
292
436
|
}
|
|
293
437
|
|
|
294
438
|
@action
|
|
295
439
|
clearExtraTableData(dataKey) {
|
|
296
|
-
|
|
297
|
-
this.mockData._table[dataKey] =
|
|
440
|
+
if (!this.mockData._table?.[dataKey]) return
|
|
441
|
+
this.mockData._table[dataKey] = this.mockData._table[dataKey].filter(
|
|
442
|
+
x => !x._isEmptyData
|
|
443
|
+
)
|
|
298
444
|
}
|
|
299
445
|
|
|
300
446
|
@action
|
|
@@ -549,12 +695,39 @@ class EditorStore {
|
|
|
549
695
|
for (const [key, table] of Object.entries(tableData)) {
|
|
550
696
|
tableData[key] = table.filter(x => !x._isEmptyData)
|
|
551
697
|
}
|
|
552
|
-
//
|
|
698
|
+
// 纵向 left-fill 后商品行数 > 对半行且无 _isEmptyData,只滤空行会留下偏多行,
|
|
699
|
+
// 重挂载测高/remain 偏小,多栏切换后空行补不回来。收回到对半商品行。
|
|
700
|
+
Object.keys(tableData).forEach(key => {
|
|
701
|
+
if (!/_vertical$/.test(key) || !isMultiTable(key)) return
|
|
702
|
+
this.collapseVerticalMultiToBaseRows(key)
|
|
703
|
+
})
|
|
553
704
|
set(this.mockData, {
|
|
554
705
|
_table: tableData
|
|
555
706
|
})
|
|
556
707
|
}
|
|
557
708
|
|
|
709
|
+
/** 纵向多栏收到「对半」商品行,去掉 left-fill 撑开的多余行 */
|
|
710
|
+
@action
|
|
711
|
+
collapseVerticalMultiToBaseRows(key) {
|
|
712
|
+
const sourceKey = key.replace(/_vertical$/, '')
|
|
713
|
+
const singleKey = sourceKey.replace(/_multi3?/, '')
|
|
714
|
+
const colNumber = getMultiNumber(sourceKey)
|
|
715
|
+
const sourceRows =
|
|
716
|
+
this.mockData._table[singleKey] || this.mockData._table[sourceKey] || []
|
|
717
|
+
const sourceColNumber = isMultiTable(singleKey)
|
|
718
|
+
? getMultiNumber(singleKey)
|
|
719
|
+
: isMultiTable(sourceKey)
|
|
720
|
+
? colNumber
|
|
721
|
+
: 1
|
|
722
|
+
const sourceItems = flattenHorizontalPackedRows(sourceRows, sourceColNumber)
|
|
723
|
+
const baseRowCount = sourceItems.length
|
|
724
|
+
? Math.max(1, Math.ceil(sourceItems.length / colNumber))
|
|
725
|
+
: 0
|
|
726
|
+
this.mockData._table[key] = baseRowCount
|
|
727
|
+
? packVerticalNewspaper(sourceItems, colNumber, baseRowCount, false)
|
|
728
|
+
: []
|
|
729
|
+
}
|
|
730
|
+
|
|
558
731
|
@action
|
|
559
732
|
addConfigBlock(name, type, pos = {}, link = '') {
|
|
560
733
|
let blocks
|
|
@@ -1023,6 +1196,13 @@ class EditorStore {
|
|
|
1023
1196
|
|
|
1024
1197
|
this.config.contents[arr[2]].dataKey = newDataKey.join('_')
|
|
1025
1198
|
|
|
1199
|
+
// 双栏↔三栏等切换时,mock 可能缺对应 _table,现场兜底生成,避免整表空白
|
|
1200
|
+
const joinedKey = newDataKey.join('_')
|
|
1201
|
+
if (isMultiTable(joinedKey)) {
|
|
1202
|
+
this.ensureMockMultiTable(joinedKey)
|
|
1203
|
+
this.ensureMockMultiTable(getDataKey(joinedKey, 'vertical'))
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1026
1206
|
// 三级分类相关 token(商品三级分类/三级分类小计)是纯分组、标题能力,
|
|
1027
1207
|
// 与每页/整单合计可共存,切换时不再强制关闭合计开关;
|
|
1028
1208
|
// 其余 token(多栏/一级分类/标签等)保持历史行为:切换时强制关闭
|
|
@@ -1044,7 +1224,7 @@ class EditorStore {
|
|
|
1044
1224
|
autoFillConfig: {
|
|
1045
1225
|
...(this.config.autoFillConfig || {}),
|
|
1046
1226
|
region: this.selectedRegion || this.config.autoFillConfig?.region,
|
|
1047
|
-
dataKey:
|
|
1227
|
+
dataKey: joinedKey,
|
|
1048
1228
|
checked: true,
|
|
1049
1229
|
fillIndex: this.fillIndex
|
|
1050
1230
|
}
|
|
@@ -1487,10 +1667,26 @@ class EditorStore {
|
|
|
1487
1667
|
if (this.selectedRegion) {
|
|
1488
1668
|
const arr = this.selectedRegion.split('.')
|
|
1489
1669
|
if (arr.includes('table')) {
|
|
1670
|
+
const table = this.config.contents[arr[2]]
|
|
1490
1671
|
this.config.contents[arr[2]] = {
|
|
1491
|
-
...
|
|
1672
|
+
...table,
|
|
1492
1673
|
arrange: val
|
|
1493
1674
|
}
|
|
1675
|
+
// 只改排列并清掉旧空行;保持填充开关,交给 Printer 重挂载后
|
|
1676
|
+
// 「先补空 → 再重新分页」恢复空行(勿在此处用旧 remainHeight 立刻补)
|
|
1677
|
+
if (this.isAutoFilling || this.config?.autoFillConfig?.checked) {
|
|
1678
|
+
this.clearAllTableEmptyData()
|
|
1679
|
+
this.setAutoFillingConfig(true)
|
|
1680
|
+
set(this.config, {
|
|
1681
|
+
autoFillConfig: {
|
|
1682
|
+
...(this.config.autoFillConfig || {}),
|
|
1683
|
+
region: this.selectedRegion,
|
|
1684
|
+
dataKey: table.dataKey,
|
|
1685
|
+
checked: true,
|
|
1686
|
+
fillIndex: this.fillIndex
|
|
1687
|
+
}
|
|
1688
|
+
})
|
|
1689
|
+
}
|
|
1494
1690
|
}
|
|
1495
1691
|
}
|
|
1496
1692
|
}
|
package/src/index.js
CHANGED
|
@@ -20,7 +20,8 @@ import {
|
|
|
20
20
|
getCSS,
|
|
21
21
|
getPrintContainerHTML,
|
|
22
22
|
doBatchFinancePrint,
|
|
23
|
-
setPrintStyle
|
|
23
|
+
setPrintStyle,
|
|
24
|
+
computePages
|
|
24
25
|
} from './printer'
|
|
25
26
|
import { MULTI_SUFFIX, MULTI_SUFFIX3 } from './config'
|
|
26
27
|
|
|
@@ -49,5 +50,6 @@ export {
|
|
|
49
50
|
MULTI_SUFFIX3,
|
|
50
51
|
getPrintContainerHTML,
|
|
51
52
|
doBatchFinancePrint,
|
|
52
|
-
setPrintStyle
|
|
53
|
+
setPrintStyle,
|
|
54
|
+
computePages
|
|
53
55
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import ReactDOM from 'react-dom'
|
|
3
|
+
import _ from 'lodash'
|
|
4
|
+
import { toJS } from 'mobx'
|
|
5
|
+
import Printer from './printer'
|
|
6
|
+
import getCSS from './get_css'
|
|
7
|
+
import { afterImgAndSvgLoaded } from '../util'
|
|
8
|
+
import { LONG_PRINT } from '../config'
|
|
9
|
+
|
|
10
|
+
// 与 do_print.js 的容器隔离,使用独立 iframe,避免和打印任务互相 unmount 对方内容
|
|
11
|
+
const printerId = '_gm-printer-compute-pages_' + Math.random()
|
|
12
|
+
let $printer = null
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 初始化隐藏渲染容器
|
|
16
|
+
* 复制自 do_print.js 的 init({ isTest: true }) 分支(iframe 创建 + getCSS 注入),
|
|
17
|
+
* 差异仅 id 前缀与「永远隐藏」。⚠️ get_css / 容器初始化逻辑变更时两处需同步,
|
|
18
|
+
* 否则测量环境与打印环境漂移,分页边界不再一致
|
|
19
|
+
*/
|
|
20
|
+
function init() {
|
|
21
|
+
if (!$printer) {
|
|
22
|
+
$printer = window.document.createElement('iframe')
|
|
23
|
+
$printer.id = printerId
|
|
24
|
+
$printer.style.position = 'fixed'
|
|
25
|
+
$printer.style.top = '0'
|
|
26
|
+
$printer.style.width = '100%'
|
|
27
|
+
// 隐藏起来,用户不可见
|
|
28
|
+
$printer.style.left = '-2000px'
|
|
29
|
+
window.document.body.appendChild($printer)
|
|
30
|
+
|
|
31
|
+
const idocument = $printer.contentDocument
|
|
32
|
+
idocument.open()
|
|
33
|
+
idocument.write('<!DOCTYPE html><html><head></head><body></body></html>')
|
|
34
|
+
idocument.close()
|
|
35
|
+
|
|
36
|
+
const doc = $printer.contentWindow.document
|
|
37
|
+
|
|
38
|
+
const style = doc.createElement('style')
|
|
39
|
+
style.appendChild(doc.createTextNode(getCSS()))
|
|
40
|
+
doc.head.appendChild(style)
|
|
41
|
+
|
|
42
|
+
const div = doc.createElement('div')
|
|
43
|
+
div.id = 'appContainer'
|
|
44
|
+
|
|
45
|
+
doc.body.appendChild(div)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 按打印分页逻辑计算分页结果(不触发打印)
|
|
51
|
+
*
|
|
52
|
+
* 场景:导出功能需要拿到与打印完全一致的分页边界
|
|
53
|
+
*
|
|
54
|
+
* 不支持的模板类型(返回空 pages,调用方需自行降级):
|
|
55
|
+
* - batchPrintConfig === 2(合并打印):componentDidMount 不跑 computedPages,pages 恒空
|
|
56
|
+
* - page.type === LONG_PRINT(长条打印):走 renderLongPage 全量渲染,pages 不对应真实布局
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} options
|
|
59
|
+
* @param {Object} options.data 打印数据(结构同 doPrint 的 data,含 _table)
|
|
60
|
+
* @param {Object} options.config 模板配置(结构同 doPrint 的 config)
|
|
61
|
+
* @param {boolean} [options.isSomeSubtotalTr] 每页合计是否展示多个字段(对齐 doPrint 第三参,
|
|
62
|
+
* 影响合计行渲染与行高,进而影响分页边界)
|
|
63
|
+
* @returns {Promise<{pages: Array, remainPageHeight: number, tableCustomerRowHeight: number}>}
|
|
64
|
+
* pages: [[{type, index, begin, end}, ...], ...] 对 data._table[contents[i].dataKey] 行号的切片
|
|
65
|
+
* remainPageHeight: 最后一页剩余高度(供行数填充换算)
|
|
66
|
+
* tableCustomerRowHeight: 表格行高(供行数填充换算)
|
|
67
|
+
*/
|
|
68
|
+
function computePages({ data, config, isSomeSubtotalTr }) {
|
|
69
|
+
// 不支持的模板类型提前告警(不阻断,返回结果交由调用方降级处理)
|
|
70
|
+
if (config.batchPrintConfig === 2 || config.page?.type === LONG_PRINT) {
|
|
71
|
+
console.warn(
|
|
72
|
+
'[gm-printer] computePages: 当前模板为合并打印或长条打印,computedPages 不生效,pages 将为空'
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return new window.Promise(resolve => {
|
|
77
|
+
init()
|
|
78
|
+
|
|
79
|
+
const $app = $printer.contentWindow.document.getElementById('appContainer')
|
|
80
|
+
ReactDOM.unmountComponentAtNode($app)
|
|
81
|
+
|
|
82
|
+
// computedPages 处理采购明细拆行时会原地 splice data._table,
|
|
83
|
+
// 深拷贝一份,避免污染调用方数据
|
|
84
|
+
const clonedData = _.cloneDeep(data)
|
|
85
|
+
// computedPages 会往 config 顶层写 isSave(store.js),浅拷贝隔离开调用方的
|
|
86
|
+
// template 对象(stationv2 导出时同一 template 跨多个 sheet 复用)
|
|
87
|
+
const clonedConfig = { ...config }
|
|
88
|
+
|
|
89
|
+
// 依赖 WithStorePrinter 实例字段 printerStore(printer.js)读取分页结果,
|
|
90
|
+
// Printer 组件重构(store 挂载方式变化)时此处需同步
|
|
91
|
+
let printerRef = null
|
|
92
|
+
ReactDOM.render(
|
|
93
|
+
<Printer
|
|
94
|
+
ref={ref => {
|
|
95
|
+
printerRef = ref
|
|
96
|
+
}}
|
|
97
|
+
isSomeSubtotalTr={isSomeSubtotalTr}
|
|
98
|
+
config={clonedConfig}
|
|
99
|
+
data={clonedData}
|
|
100
|
+
onReady={() => {
|
|
101
|
+
// onReady 触发时 componentDidMount 已同步执行完 computedPages(),pages 就绪
|
|
102
|
+
// 模板含图片时等图片加载完成,避免图片撑高导致测量偏差
|
|
103
|
+
afterImgAndSvgLoaded(() => {
|
|
104
|
+
const store = printerRef.printerStore
|
|
105
|
+
const result = {
|
|
106
|
+
pages: toJS(store.pages),
|
|
107
|
+
remainPageHeight: store.remainPageHeight,
|
|
108
|
+
tableCustomerRowHeight: store.computedTableCustomerRowHeight
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 读取完成后卸载,避免 DOM 累积
|
|
112
|
+
ReactDOM.unmountComponentAtNode($app)
|
|
113
|
+
resolve(result)
|
|
114
|
+
}, $app)
|
|
115
|
+
}}
|
|
116
|
+
/>,
|
|
117
|
+
$app
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { computePages }
|
package/src/printer/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
doBatchFinancePrint,
|
|
8
8
|
setPrintStyle
|
|
9
9
|
} from './do_print'
|
|
10
|
+
import { computePages } from './compute_pages'
|
|
10
11
|
import getCSS from './get_css'
|
|
11
12
|
|
|
12
13
|
export {
|
|
@@ -17,5 +18,6 @@ export {
|
|
|
17
18
|
getCSS,
|
|
18
19
|
getPrintContainerHTML,
|
|
19
20
|
doBatchFinancePrint,
|
|
20
|
-
setPrintStyle
|
|
21
|
+
setPrintStyle,
|
|
22
|
+
computePages
|
|
21
23
|
}
|