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.
@@ -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 // 修改默认dataKey
30
+ this.defaultTableDataKey = defaultTableDataKey
9
31
  }
10
32
 
11
33
  @observable
12
34
  customerTag = false
13
35
 
14
- /* start---------设置采购明细相关--------- */
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
- // 单列-总表最后一列,在columns上修改
29
- if (
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
- // 通过detailsType属性区分单列-总表最后一列的数据是否换行展示
49
- dataKey === 'purchase_last_col'
50
- ? (tableConfig.columns[
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
- // 单列-总表最后一列,在columns上修改
66
- if (
67
- tableConfig.dataKey === 'purchase_last_col' ||
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
- // 单列-总表最后一列,在columns上修改
82
- if (
83
- tableConfig.dataKey === 'purchase_last_col' ||
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
- // 单列-总表最后一列,在columns上修改
98
- if (
99
- tableConfig.dataKey === 'purchase_last_col' ||
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)
@@ -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({}, () => {
@@ -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
- this.setIsSave(false)
266
- // 每次先初始化置空
267
- this.pages = []
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 = this.height.header + this.height.footer
289
+ const allPagesHaveThisHeight = heightMap.header + heightMap.footer
270
290
  // 退出计算! 因为页眉 + 页脚 > currentPageHeight,页面装不下其他东西
271
- if (allPagesHaveThisHeight > this.pageHeight) {
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 < this.config.contents.length) {
289
- const content = this.config.contents[index]
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 = this.tablesInfo[`contents.table.${index}`]
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 = +new Big(this.pageHeight)
334
- .minus(currentPageHeight)
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
- currentTableHeight += heights[end]
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 += heights[end]
397
+ currentPageHeight += rowHeight
360
398
  // 当前页没有多余空间
361
399
  if (currentTableHeight > pageAccomodateTableHeight) {
362
- currentRemainTableHeight = +Big(pageAccomodateTableHeight)
363
- .minus(currentTableHeight)
364
- .plus(heights[end])
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
- * 说明: 1. currentRemainTableHeight至少要是minHeight的 2倍,不然每次到这都进入if,同时留下一点空白距离
368
- * 2. heights[end]至少要是currentRemainTableHeight的 1倍,怕出现打印时最后一行文字显示一半的情况
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
- // 拆分明细后,同时也要更新body.heights 不能影响后续计算
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.setIsSave(true)
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
- // 修复 OOM:某行高度本身超过单页可容纳的表格高度时,end 无法推进会导致 while 死循环
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
- this.pages.push(page)
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
- this.pages.push(page)
467
+ pages.push(page)
426
468
  page = []
427
469
  }
428
470
 
429
471
  begin = end
430
472
  // 开启新一页,重置页面高度
431
- pageAccomodateTableHeight = +new Big(this.pageHeight).minus(
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,并轮下一个contents
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 = this.height[`contents.panel.${index}`]
504
+ const panelHeight = heightMap[`contents.panel.${index}`]
455
505
  currentPageHeight += panelHeight
456
506
 
457
507
  // 当 panel + allPagesHaveThisHeight > 页高度, 停止. 避免死循环
458
- if (panelHeight + allPagesHaveThisHeight > this.pageHeight) {
508
+ if (panelHeight + allPagesHaveThisHeight > pageHeight) {
459
509
  break
460
510
  }
461
511
 
462
512
  // 如果是最后一页,必须要加上sign的高度,否则会重叠
463
- if (index === this.config.contents.length - 1) {
464
- currentPageHeight += this.height?.sign
513
+ if (index === contentsLength - 1) {
514
+ currentPageHeight += heightMap?.sign || 0
465
515
  }
466
516
 
467
- if (currentPageHeight <= this.pageHeight) {
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
- this.pages.push(page)
527
+ pages.push(page)
478
528
 
479
529
  // 为下一页做准备
480
530
  page = []
@@ -482,8 +532,11 @@ class PrinterStore {
482
532
  }
483
533
  }
484
534
  }
485
- this.pages.push(page)
486
- this.remainPageHeight = +Big(this.pageHeight - currentPageHeight).toFixed(0)
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
- if (
556
- dataKey !== 'purchase_detail_one_row' &&
557
- dataKey !== 'purchase_independent_rol_sku' &&
558
- dataKey !== 'purchase_independent_rol_address' &&
559
- dataKey !== 'taxRateSales' &&
560
- dataKey !== 'ordinary'
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(text, { interpolate: /{{([\s\S]+?)}}/g })
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 text
732
+ return templateText
676
733
  }
677
734
  }
678
735
 
@@ -412,7 +412,8 @@ class Table extends React.Component {
412
412
  ? printerStore.templateSpecialDetails(
413
413
  col,
414
414
  dataKey,
415
- i
415
+ i,
416
+ config.specialConfig?.template_text
416
417
  )
417
418
  : printerStore
418
419
  .templateTable(col.text, dataKey, i, pageIndex)
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)