n20-common-lib 2.22.47 → 2.22.49

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "2.22.47",
3
+ "version": "2.22.49",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -0,0 +1,60 @@
1
+ let vxeVersion = ''
2
+
3
+ export function getVxeCore(vxe) {
4
+ return vxe && (vxe.VXETable || vxe.default || vxe)
5
+ }
6
+
7
+ export function setVxeVersion(version) {
8
+ vxeVersion = version || ''
9
+ }
10
+
11
+ export function getVxeVersion() {
12
+ return vxeVersion
13
+ }
14
+
15
+ export function compareVersion(version, target) {
16
+ const versionParts = `${version}`.split('.').map((item) => Number.parseInt(item, 10) || 0)
17
+ const targetParts = `${target}`.split('.').map((item) => Number.parseInt(item, 10) || 0)
18
+ const len = Math.max(versionParts.length, targetParts.length)
19
+ for (let i = 0; i < len; i++) {
20
+ const current = versionParts[i] || 0
21
+ const next = targetParts[i] || 0
22
+ if (current > next) return 1
23
+ if (current < next) return -1
24
+ }
25
+ return 0
26
+ }
27
+
28
+ export function isVxe320OrNewer() {
29
+ return compareVersion(vxeVersion, '3.20.0') >= 0
30
+ }
31
+
32
+ export function resolveMaybeFunction(value) {
33
+ return typeof value === 'function' ? value() : value
34
+ }
35
+
36
+ export function normalizeArray(value) {
37
+ const resolved = resolveMaybeFunction(value)
38
+ return Array.isArray(resolved) ? resolved : []
39
+ }
40
+
41
+ export function getColumnField(column) {
42
+ if (!column) return undefined
43
+ return column.field || column.property
44
+ }
45
+
46
+ export function getEventField(params) {
47
+ if (!params) return undefined
48
+ return params.field || params.property || getColumnField(params.column)
49
+ }
50
+
51
+ export function getRowValue(row, field) {
52
+ if (!row || !field) return undefined
53
+ if (Object.prototype.hasOwnProperty.call(row, field)) {
54
+ return row[field]
55
+ }
56
+ return `${field}`.split('.').reduce((value, key) => {
57
+ if (value === undefined || value === null) return undefined
58
+ return value[key]
59
+ }, row)
60
+ }
@@ -5,11 +5,28 @@ import numerify from 'numerify'
5
5
  import dayjs from 'dayjs'
6
6
  import { $lc } from '../../utils/i18n/index.js'
7
7
  import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
8
+ import { getColumnField, getRowValue, getVxeCore, setVxeVersion } from './compat.js'
9
+
10
+ function getInstalledVxeVersion(vxe) {
11
+ const core = getVxeCore(vxe)
12
+ return (
13
+ (vxe && (vxe.tableVersion || vxe.version)) ||
14
+ (core && (core.tableVersion || core.version)) ||
15
+ ''
16
+ )
17
+ }
18
+
19
+ setVxeVersion(getInstalledVxeVersion(vxeTable))
20
+ const vxeCore = getVxeCore(vxeTable)
21
+ const setupVxeTable = (vxeTable && vxeTable.setup) || (vxeCore && vxeCore.setup)
22
+ const vxeRenderer = (vxeTable && vxeTable.renderer) || (vxeCore && vxeCore.renderer)
23
+ const vxeFormats = (vxeTable && vxeTable.formats) || (vxeCore && vxeCore.formats)
24
+
8
25
  // 打平对象
9
26
  function flattenObject(obj, prefix = '', result = {}) {
10
27
  // 遍历对象的每个属性
11
28
  for (const key in obj) {
12
- if (obj.hasOwnProperty(key)) {
29
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
13
30
  // 构建当前属性的完整键名
14
31
  const fullKey = prefix ? `${prefix}.${key}` : key
15
32
 
@@ -24,103 +41,110 @@ function flattenObject(obj, prefix = '', result = {}) {
24
41
  }
25
42
  return result
26
43
  }
27
- vxeTable.setup({
28
- size: 'small',
29
- table: {
30
- border: true,
31
- align: 'center',
32
- columnConfig: {
33
- resizable: true
44
+ if (typeof setupVxeTable === 'function') {
45
+ setupVxeTable.call(vxeCore || vxeTable, {
46
+ size: 'small',
47
+ table: {
48
+ border: true,
49
+ align: 'center',
50
+ columnConfig: {
51
+ resizable: true
52
+ }
53
+ },
54
+ // 对组件内置的提示语进行国际化翻译
55
+ i18n: (key, args) => {
56
+ return $lc(flattenObject(zhCN) && flattenObject(zhCN)[key])
34
57
  }
35
- },
36
- // 对组件内置的提示语进行国际化翻译
37
- i18n: (key, args) => {
38
- return $lc(flattenObject(zhCN) && flattenObject(zhCN)[key])
39
- }
40
- })
58
+ })
59
+ }
41
60
  // 创建一个简单的输入框筛选
42
- vxeTable.renderer.add('FilterInput', {
61
+ if (vxeRenderer && typeof vxeRenderer.add === 'function') {
62
+ vxeRenderer.add('FilterInput', {
43
63
  // 筛选模板
44
- renderFilter(h, renderOpts, params) {
45
- return <filterContent params={params}></filterContent>
46
- },
47
- // 不显示底部按钮,使用自定义的按钮
48
- showFilterFooter: false,
49
- // 重置数据方法
50
- filterResetMethod({ options }) {
51
- options.forEach((option) => {
64
+ renderFilter(h, renderOpts, params) {
65
+ return <filterContent params={params}></filterContent>
66
+ },
67
+ // 不显示底部按钮,使用自定义的按钮
68
+ showFilterFooter: false,
69
+ // 重置数据方法
70
+ filterResetMethod({ options }) {
71
+ options.forEach((option) => {
72
+ option.data = ''
73
+ })
74
+ },
75
+ // 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值)
76
+ filterRecoverMethod({ option }) {
52
77
  option.data = ''
53
- })
54
- },
55
- // 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值)
56
- filterRecoverMethod({ option }) {
57
- option.data = ''
58
- },
59
- // 筛选方法
60
- filterMethod({ option, row, column }) {
61
- const { data } = option
62
- const cellValue = row[column.property]
63
- if (cellValue) {
64
- return cellValue.indexOf(data) > -1
78
+ },
79
+ // 筛选方法
80
+ filterMethod({ option, row, column }) {
81
+ const { data } = option
82
+ const field = getColumnField(column)
83
+ const cellValue = getRowValue(row, field)
84
+ if (cellValue !== undefined && cellValue !== null) {
85
+ return `${cellValue}`.indexOf(data) > -1
86
+ }
87
+ return false
65
88
  }
66
- return false
67
- }
68
- })
89
+ })
90
+ }
69
91
 
70
92
  // 自定义全局的格式化处理函数
71
- vxeTable.formats.mixin({
72
- // 格式化内容 为空转为--
73
- formatName({ cellValue }) {
74
- return cellValue || '--'
75
- },
76
- // 格式化性别
77
- formatSex({ cellValue }) {
78
- return cellValue ? (cellValue === '1' ? '男' : '女') : '--'
79
- },
80
- // 格式化下拉选项
81
- formatSelect({ cellValue }, list) {
82
- const item = list.find((item) => item.value === cellValue)
83
- return item ? item.label : '--'
84
- },
85
- // 格式化日期,默认 yyyy-MM-dd
86
- formatDate({ cellValue }) {
87
- if (cellValue) {
88
- return dayjs(cellValue).format('YYYY-MM-DD')
89
- } else {
90
- return '--'
91
- }
92
- },
93
- // 四舍五入金额,每隔3位逗号分隔,默认2位数
94
- formatAmount({ cellValue }) {
95
- if (cellValue || cellValue === 0) {
96
- // 判断是否为字符串类数字
97
- if (/^-?\d+(\.\d+)?$/.test(cellValue)) {
98
- return numerify(cellValue, '0,0.00')
93
+ if (vxeFormats && typeof vxeFormats.mixin === 'function') {
94
+ vxeFormats.mixin({
95
+ // 格式化内容 为空转为--
96
+ formatName({ cellValue }) {
97
+ return cellValue || '--'
98
+ },
99
+ // 格式化性别
100
+ formatSex({ cellValue }) {
101
+ return cellValue ? (cellValue === '1' ? '男' : '女') : '--'
102
+ },
103
+ // 格式化下拉选项
104
+ formatSelect({ cellValue }, list) {
105
+ const item = list.find((item) => item.value === cellValue)
106
+ return item ? item.label : '--'
107
+ },
108
+ // 格式化日期,默认 yyyy-MM-dd
109
+ formatDate({ cellValue }) {
110
+ if (cellValue) {
111
+ return dayjs(cellValue).format('YYYY-MM-DD')
99
112
  } else {
100
- return cellValue
113
+ return '--'
114
+ }
115
+ },
116
+ // 四舍五入金额,每隔3位逗号分隔,默认2位数
117
+ formatAmount({ cellValue }) {
118
+ if (cellValue || cellValue === 0) {
119
+ // 判断是否为字符串类数字
120
+ if (/^-?\d+(\.\d+)?$/.test(cellValue)) {
121
+ return numerify(cellValue, '0,0.00')
122
+ } else {
123
+ return cellValue
124
+ }
125
+ // return numerify(cellValue, '0,0.00')
126
+ } else {
127
+ return '--'
128
+ }
129
+ },
130
+ // 利率
131
+ formatRate({ cellValue }) {
132
+ if (cellValue || cellValue === 0) {
133
+ return numerify(cellValue, '0.000000')
134
+ } else {
135
+ return '--'
136
+ }
137
+ },
138
+ // 格式化时间,默认 yyyy-MM-dd HH:mm:ss
139
+ formatDatetime({ cellValue }) {
140
+ if (cellValue) {
141
+ return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
142
+ } else {
143
+ return '--'
101
144
  }
102
- // return numerify(cellValue, '0,0.00')
103
- } else {
104
- return '--'
105
- }
106
- },
107
- // 利率
108
- formatRate({ cellValue }) {
109
- if (cellValue || cellValue === 0) {
110
- return numerify(cellValue, '0.000000')
111
- } else {
112
- return '--'
113
- }
114
- },
115
- // 格式化时间,默认 yyyy-MM-dd HH:mm:ss
116
- formatDatetime({ cellValue }) {
117
- if (cellValue) {
118
- return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss')
119
- } else {
120
- return '--'
121
145
  }
122
- }
123
- })
146
+ })
147
+ }
124
148
 
125
149
  function install(Vue) {
126
150
  Vue.use(vxeTable)
@@ -16,6 +16,7 @@
16
16
  show-header-overflow
17
17
  show-overflow
18
18
  :row-config="computedRowConfig"
19
+ :cell-config="computedCellConfig"
19
20
  :column-config="{
20
21
  resizable: true,
21
22
  useKey: true,
@@ -23,6 +24,7 @@
23
24
  ...$attrs['column-config']
24
25
  }"
25
26
  :scroll-y="computedScrollY"
27
+ :virtual-y-config="computedVirtualYConfig"
26
28
  :sort-config="{
27
29
  multiple: false,
28
30
  remote: true,
@@ -139,6 +141,7 @@
139
141
  import empty from '../Empty'
140
142
  import tableSetSize from '../TableSetSize/index.vue'
141
143
  import { $lc } from '../../utils/i18n/index.js'
144
+ import { getColumnField, getEventField, isVxe320OrNewer, normalizeArray } from './compat.js'
142
145
 
143
146
  /** 将 Element 表格风格的 show-overflow-tooltip 转为 vxe-column 的 show-overflow */
144
147
  function hasOverflowTooltipKey(item) {
@@ -180,13 +183,17 @@ function mapColumnOverflowForVxe(item) {
180
183
  }
181
184
  return applyTooltipToShowOverflow(item)
182
185
  }
183
- const DEFAULT_SCROLL_Y = { enabled: true, oSize: 20, gt: 30 }
186
+ // vxe-table 3.6 在渲染行数超过 40 时会防抖更新虚拟滚动数据,快速滚动容易露出空白。
187
+ // 保持较小的默认缓冲,让常见高度下走同步更新路径;业务仍可通过 scroll-y.oSize 覆盖。
188
+ const DEFAULT_SCROLL_Y = { enabled: true, oSize: 6, gt: 30 }
189
+ const DEFAULT_VIRTUAL_Y = { ...DEFAULT_SCROLL_Y, preSize: 1, immediate: true }
184
190
  const VXE_ROW_HEIGHT_MAP = {
185
191
  default: 48,
186
192
  medium: 44,
187
193
  small: 40,
188
194
  mini: 36
189
195
  }
196
+
190
197
  const renderer = {
191
198
  name: 'renderer',
192
199
  props: {
@@ -215,6 +222,10 @@ export default {
215
222
  return { ...DEFAULT_SCROLL_Y }
216
223
  }
217
224
  },
225
+ virtualYConfig: {
226
+ type: Object,
227
+ default: undefined
228
+ },
218
229
  dynamicRowHeight: {
219
230
  type: Boolean,
220
231
  default: false
@@ -294,8 +305,12 @@ export default {
294
305
  const small = attrs.small
295
306
  delete attrs.rowConfig
296
307
  delete attrs['row-config']
308
+ delete attrs.cellConfig
309
+ delete attrs['cell-config']
297
310
  delete attrs.scrollY
298
311
  delete attrs['scroll-y']
312
+ delete attrs.virtualYConfig
313
+ delete attrs['virtual-y-config']
299
314
  delete attrs.small
300
315
  return Object.assign({ size: this.sizeC || this.size }, attrs, this.sizeBind, small)
301
316
  },
@@ -309,12 +324,31 @@ export default {
309
324
  ...this.$attrs.rowConfig,
310
325
  ...this.$attrs['row-config']
311
326
  }
312
- if (!this.dynamicRowHeight && rowConfig.height === undefined) {
327
+ const isVxe320 = isVxe320OrNewer()
328
+ if (!this.dynamicRowHeight && !isVxe320 && rowConfig.height === undefined) {
313
329
  rowConfig.height = this.getVirtualRowHeight()
314
330
  }
331
+ if (isVxe320) {
332
+ delete rowConfig.height
333
+ }
315
334
  return rowConfig
316
335
  },
336
+ computedCellConfig() {
337
+ const cellConfig = {
338
+ ...this.$attrs.cellConfig,
339
+ ...this.$attrs['cell-config']
340
+ }
341
+ const hasCellConfig = Object.keys(cellConfig).length > 0
342
+ if (!isVxe320OrNewer()) {
343
+ return hasCellConfig ? cellConfig : undefined
344
+ }
345
+ if (!this.dynamicRowHeight && cellConfig.height === undefined) {
346
+ cellConfig.height = this.getVirtualRowHeight()
347
+ }
348
+ return cellConfig
349
+ },
317
350
  computedScrollY() {
351
+ if (isVxe320OrNewer()) return undefined
318
352
  const scrollY = {
319
353
  ...DEFAULT_SCROLL_Y,
320
354
  ...(this.scrollY || {})
@@ -328,6 +362,24 @@ export default {
328
362
  }
329
363
  return scrollY
330
364
  },
365
+ computedVirtualYConfig() {
366
+ const attrVirtualYConfig = {
367
+ ...this.$attrs.virtualYConfig,
368
+ ...this.$attrs['virtual-y-config']
369
+ }
370
+ if (!isVxe320OrNewer()) return undefined
371
+ const virtualYConfig = {
372
+ ...DEFAULT_VIRTUAL_Y,
373
+ ...(this.scrollY || {}),
374
+ ...attrVirtualYConfig,
375
+ ...(this.virtualYConfig || {})
376
+ }
377
+ delete virtualYConfig.rHeight
378
+ if (this.dynamicRowHeight) {
379
+ virtualYConfig.enabled = false
380
+ }
381
+ return virtualYConfig
382
+ },
331
383
  _columns() {
332
384
  const raw = this.isAutoWidth ? this.calcColumnWidth(this.columns) : this.columns
333
385
  return raw.map(mapColumnOverflowForVxe)
@@ -345,30 +397,45 @@ export default {
345
397
  data() {
346
398
  // 翻页清除选中
347
399
  if (this.clearSelect) {
348
- this.$refs.vxeTable.clearCheckboxRow()
400
+ this.callTableMethod('clearCheckboxRow')
349
401
  this.$emit('selection-change-method', [])
350
402
  }
351
403
  // 数据更新后重新设置合并单元格
352
404
  this.$nextTick(() => {
353
405
  if (this.mergeCells && this.mergeCells.length > 0 && this.$refs.vxeTable) {
354
- this.$refs.vxeTable.setMergeCells(this.mergeCells)
406
+ this.callTableMethod('setMergeCells', this.mergeCells)
355
407
  }
356
408
  this.refreshTableLayout()
357
409
  })
358
410
  }
359
411
  },
360
412
  activated() {
361
- this.$refs.vxeTable.loadData(this.data)
413
+ this.callTableMethod('loadData', this.data)
362
414
  // 数据更新后重新设置合并单元格
363
415
  this.$nextTick(() => {
364
416
  if (this.mergeCells && this.mergeCells.length > 0 && this.$refs.vxeTable) {
365
- this.$refs.vxeTable.setMergeCells(this.mergeCells)
417
+ this.callTableMethod('setMergeCells', this.mergeCells)
366
418
  }
367
419
  this.refreshTableLayout()
368
420
  })
369
421
  },
370
422
  methods: {
423
+ callTableMethod(methodName, ...args) {
424
+ const xTable = this.$refs.vxeTable
425
+ if (!xTable || typeof xTable[methodName] !== 'function') return undefined
426
+ return xTable[methodName](...args)
427
+ },
428
+ getTableRows(methodName, ...args) {
429
+ return normalizeArray(this.callTableMethod(methodName, ...args))
430
+ },
371
431
  getVirtualRowHeight() {
432
+ const cellConfig = {
433
+ ...this.$attrs.cellConfig,
434
+ ...this.$attrs['cell-config']
435
+ }
436
+ if (cellConfig.height !== undefined) {
437
+ return cellConfig.height
438
+ }
372
439
  const rowConfig = {
373
440
  ...this.$attrs.rowConfig,
374
441
  ...this.$attrs['row-config']
@@ -408,18 +475,18 @@ export default {
408
475
  return true
409
476
  })
410
477
  // 判断当前可选行是否已全部选中
411
- const checkedRows = this.$refs.vxeTable.getCheckboxRecords(false)
478
+ const checkedRows = this.getTableRows('getCheckboxRecords', false)
412
479
  const checkedSet = new Set(checkedRows)
413
480
  const isAllChecked = selectableRows.length > 0 && selectableRows.every((row) => checkedSet.has(row))
414
481
  if (isAllChecked) {
415
482
  // 已全选,则取消可选行的选中状态
416
483
  selectableRows.forEach((row) => {
417
- this.$refs.vxeTable.setCheckboxRow(row, false)
484
+ this.callTableMethod('setCheckboxRow', row, false)
418
485
  })
419
486
  } else {
420
487
  // 未全选,则选中所有可选行
421
488
  selectableRows.forEach((row) => {
422
- this.$refs.vxeTable.setCheckboxRow(row, true)
489
+ this.callTableMethod('setCheckboxRow', row, true)
423
490
  })
424
491
  }
425
492
  // 得手动触发
@@ -444,14 +511,14 @@ export default {
444
511
  // 清空选择
445
512
  clearSelection() {
446
513
  if (this.$refs.vxeTable) {
447
- this.$refs.vxeTable.setAllCheckboxRow(false)
514
+ this.callTableMethod('setAllCheckboxRow', false)
448
515
  // 得手动触发
449
516
  this.handleSelectionChange()
450
517
  }
451
518
  },
452
519
  // 选中某些行
453
520
  toggleRowSelection(row, state = true) {
454
- this.$refs.vxeTable.setCheckboxRow(row, state)
521
+ this.callTableMethod('setCheckboxRow', row, state)
455
522
  // 得手动触发
456
523
  this.handleSelectionChange()
457
524
  },
@@ -470,7 +537,7 @@ export default {
470
537
  return true
471
538
  })
472
539
  // 判断当前可选行是否已全部选中
473
- const checkedRows = $table.getCheckboxRecords(false)
540
+ const checkedRows = normalizeArray($table.getCheckboxRecords(false))
474
541
  const checkedSet = new Set(checkedRows)
475
542
  const isAllChecked = selectableRows.length > 0 && selectableRows.every((row) => checkedSet.has(row))
476
543
  if (isAllChecked) {
@@ -499,17 +566,17 @@ export default {
499
566
  this.key++
500
567
  this.handleSelectionChange(row)
501
568
  },
502
- customSortMethod({ sortList }) {
503
- const orders = sortList.map((item) => {
569
+ customSortMethod(data = {}) {
570
+ const orders = normalizeArray(data.sortList).map((item) => {
504
571
  return {
505
- column: item.field,
572
+ column: getEventField(item) || getColumnField(item.column),
506
573
  asc: item.order === 'asc'
507
574
  }
508
575
  })
509
576
  this.$emit('sort-change-method', orders)
510
577
  },
511
- filterChange(data) {
512
- const { filterList } = data
578
+ filterChange(data = {}) {
579
+ const filterList = normalizeArray(data.filterList || data.filters)
513
580
  // 输出全部条件
514
581
  const obj = {}
515
582
  // 复制默认筛选条件为空
@@ -519,17 +586,20 @@ export default {
519
586
  }
520
587
  })
521
588
  filterList.forEach((item) => {
522
- if (item.column.filterMultiple) {
523
- this.$set(obj, item.field, item.values)
589
+ const field = getEventField(item)
590
+ if (!field) return
591
+ if (item.column && item.column.filterMultiple) {
592
+ this.$set(obj, field, item.values)
524
593
  } else {
525
- this.$set(obj, item.field, item.values && item.values[0])
594
+ this.$set(obj, field, item.values && item.values[0])
526
595
  }
527
596
  })
528
597
  // 输出单个条件
529
598
  const singleObj = {}
599
+ const currentField = getEventField(data)
530
600
  for (let key in obj) {
531
- if (key === data.field) {
532
- singleObj[data.field] = obj[data.field]
601
+ if (key === currentField) {
602
+ singleObj[currentField] = obj[currentField]
533
603
  }
534
604
  }
535
605
  if (this.isFiliterSingle) {
@@ -540,16 +610,17 @@ export default {
540
610
  },
541
611
  // row当前单次勾选的哪一行数据 包含checked字段
542
612
  handleSelectionChange(row = '') {
543
- const val = this.$refs.vxeTable.getCheckboxRecords()
613
+ const currentRow = row && Object.prototype.hasOwnProperty.call(row, 'row') ? row.row : row
614
+ const val = this.getTableRows('getCheckboxRecords')
544
615
  // 支持跨页勾选
545
- const val1 = this.$refs.vxeTable.getCheckboxReserveRecords()
546
- this.$emit('selection-change-method', [...val, ...val1], row)
616
+ const val1 = this.getTableRows('getCheckboxReserveRecords')
617
+ this.$emit('selection-change-method', [...val, ...val1], currentRow)
547
618
  },
548
619
  // 点击行勾选/取消勾选
549
620
  handleCellClick({ row, column, $event }) {
550
621
  this.$emit('cell-click', { row, column, $event })
551
622
  // 如果点击的是 checkbox 列,不处理(由原生的 checkbox 处理)
552
- if (column.type === 'checkbox') {
623
+ if (column && column.type === 'checkbox') {
553
624
  return
554
625
  }
555
626
 
@@ -561,7 +632,8 @@ export default {
561
632
  // - [class*="button"]: 包含 button 类名的元素
562
633
  // - [class*="el-link--inner"]: Element UI 链接组件内部元素
563
634
  // - a[href]: 链接标签
564
- const target = $event.target
635
+ const target = $event && $event.target
636
+ if (!target) return
565
637
  const clickedButton = target.closest(
566
638
  'button, .el-button, .n20-button, [class*="button"], [class*="el-link--inner"], a[href]'
567
639
  )
@@ -590,7 +662,7 @@ export default {
590
662
 
591
663
  if (canCheck) {
592
664
  // 切换该行的勾选状态
593
- this.$refs.vxeTable.toggleCheckboxRow(row)
665
+ this.callTableMethod('toggleCheckboxRow', row)
594
666
  this.key++ // 强制刷新 checkbox 显示
595
667
  this.handleSelectionChange(row)
596
668
  }