vxe-table 4.19.0-beta.2 → 4.19.0-beta.3

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.
Files changed (121) hide show
  1. package/LICENSE +20 -20
  2. package/README.en.md +118 -118
  3. package/README.ja-JP.md +117 -117
  4. package/README.md +268 -268
  5. package/README.zh-TW.md +117 -117
  6. package/es/style.css +1 -1
  7. package/es/table/render/index.js +1 -1
  8. package/es/ui/index.js +1 -1
  9. package/es/ui/src/log.js +1 -1
  10. package/lib/index.umd.js +2767 -2851
  11. package/lib/index.umd.min.js +1 -1
  12. package/lib/style.css +1 -1
  13. package/lib/table/render/index.js +1 -1
  14. package/lib/table/render/index.min.js +1 -1
  15. package/lib/ui/index.js +1 -1
  16. package/lib/ui/index.min.js +1 -1
  17. package/lib/ui/src/log.js +1 -1
  18. package/lib/ui/src/log.min.js +1 -1
  19. package/package.json +92 -92
  20. package/packages/colgroup/index.ts +22 -22
  21. package/packages/column/index.ts +22 -22
  22. package/packages/components.ts +43 -43
  23. package/packages/grid/index.ts +18 -18
  24. package/packages/grid/src/emits.ts +19 -19
  25. package/packages/grid/src/grid.ts +1768 -1768
  26. package/packages/grid/src/props.ts +23 -23
  27. package/packages/index.ts +4 -4
  28. package/packages/locale/lang/ar-EG.ts +840 -840
  29. package/packages/locale/lang/de-DE.ts +840 -840
  30. package/packages/locale/lang/en-US.ts +840 -840
  31. package/packages/locale/lang/es-ES.ts +840 -840
  32. package/packages/locale/lang/fr-FR.ts +840 -840
  33. package/packages/locale/lang/hu-HU.ts +840 -840
  34. package/packages/locale/lang/hy-AM.ts +840 -840
  35. package/packages/locale/lang/id-ID.ts +840 -840
  36. package/packages/locale/lang/it-IT.ts +840 -840
  37. package/packages/locale/lang/ja-JP.ts +840 -840
  38. package/packages/locale/lang/ko-KR.ts +840 -840
  39. package/packages/locale/lang/ms-MY.ts +840 -840
  40. package/packages/locale/lang/nb-NO.ts +840 -840
  41. package/packages/locale/lang/pt-BR.ts +840 -840
  42. package/packages/locale/lang/ru-RU.ts +840 -840
  43. package/packages/locale/lang/th-TH.ts +840 -840
  44. package/packages/locale/lang/ug-CN.ts +840 -840
  45. package/packages/locale/lang/uk-UA.ts +840 -840
  46. package/packages/locale/lang/uz-UZ.ts +840 -840
  47. package/packages/locale/lang/vi-VN.ts +840 -840
  48. package/packages/locale/lang/zh-CHT.ts +840 -840
  49. package/packages/locale/lang/zh-CN.ts +840 -840
  50. package/packages/locale/lang/zh-HK.ts +3 -3
  51. package/packages/locale/lang/zh-MO.ts +3 -3
  52. package/packages/locale/lang/zh-TC.ts +3 -3
  53. package/packages/locale/lang/zh-TW.ts +3 -3
  54. package/packages/table/index.ts +26 -26
  55. package/packages/table/module/custom/hook.ts +422 -422
  56. package/packages/table/module/custom/panel.ts +1512 -1512
  57. package/packages/table/module/edit/hook.ts +1064 -1064
  58. package/packages/table/module/export/export-panel.ts +567 -567
  59. package/packages/table/module/export/hook.ts +1654 -1654
  60. package/packages/table/module/export/import-panel.ts +266 -266
  61. package/packages/table/module/export/util.ts +24 -24
  62. package/packages/table/module/filter/hook.ts +468 -468
  63. package/packages/table/module/filter/panel.ts +301 -301
  64. package/packages/table/module/keyboard/hook.ts +494 -494
  65. package/packages/table/module/menu/hook.ts +325 -325
  66. package/packages/table/module/menu/panel.ts +201 -201
  67. package/packages/table/module/validator/hook.ts +631 -631
  68. package/packages/table/render/index.ts +1440 -1440
  69. package/packages/table/src/body.ts +935 -935
  70. package/packages/table/src/cell.ts +1290 -1290
  71. package/packages/table/src/column.ts +190 -190
  72. package/packages/table/src/columnInfo.ts +225 -225
  73. package/packages/table/src/emits.ts +125 -125
  74. package/packages/table/src/footer.ts +368 -368
  75. package/packages/table/src/group.ts +59 -59
  76. package/packages/table/src/header.ts +561 -561
  77. package/packages/table/src/props.ts +324 -324
  78. package/packages/table/src/store.ts +14 -14
  79. package/packages/table/src/table.ts +14274 -14274
  80. package/packages/table/src/use/cell-view.ts +44 -44
  81. package/packages/table/src/use/index.ts +1 -1
  82. package/packages/table/src/util.ts +1086 -1086
  83. package/packages/toolbar/index.ts +18 -18
  84. package/packages/toolbar/src/toolbar.ts +701 -701
  85. package/packages/ui/index.ts +532 -532
  86. package/packages/ui/src/anime.ts +52 -52
  87. package/packages/ui/src/comp.ts +3 -3
  88. package/packages/ui/src/dom.ts +264 -264
  89. package/packages/ui/src/log.ts +8 -8
  90. package/packages/ui/src/utils.ts +56 -56
  91. package/packages/ui/src/vn.ts +55 -55
  92. package/packages/v-x-e-table/index.d.ts +4 -4
  93. package/packages/v-x-e-table/index.ts +4 -4
  94. package/styles/all.scss +7 -7
  95. package/styles/base.scss +16 -16
  96. package/styles/components/grid.scss +89 -89
  97. package/styles/components/icon.scss +225 -225
  98. package/styles/components/old-icon.scss +715 -715
  99. package/styles/components/table-module/all.scss +6 -6
  100. package/styles/components/table-module/custom.scss +550 -550
  101. package/styles/components/table-module/export.scss +130 -130
  102. package/styles/components/table-module/filter.scss +130 -130
  103. package/styles/components/table-module/menu.scss +81 -81
  104. package/styles/components/table.scss +2679 -2679
  105. package/styles/components/toolbar.scss +119 -119
  106. package/styles/default.scss +2 -2
  107. package/styles/helpers/baseMixin.scss +95 -95
  108. package/styles/index.scss +4 -4
  109. package/styles/modules.scss +5 -5
  110. package/styles/theme/base.scss +93 -93
  111. package/styles/theme/dark.scss +49 -49
  112. package/styles/theme/light.scss +44 -44
  113. package/styles/variable.scss +43 -43
  114. package/types/all.d.ts +37 -37
  115. package/types/index.d.ts +4 -4
  116. /package/es/{iconfont.1778157083004.ttf → iconfont.1778318183872.ttf} +0 -0
  117. /package/es/{iconfont.1778157083004.woff → iconfont.1778318183872.woff} +0 -0
  118. /package/es/{iconfont.1778157083004.woff2 → iconfont.1778318183872.woff2} +0 -0
  119. /package/lib/{iconfont.1778157083004.ttf → iconfont.1778318183872.ttf} +0 -0
  120. /package/lib/{iconfont.1778157083004.woff → iconfont.1778318183872.woff} +0 -0
  121. /package/lib/{iconfont.1778157083004.woff2 → iconfont.1778318183872.woff2} +0 -0
@@ -1,1086 +1,1086 @@
1
- import { watch, reactive } from 'vue'
2
- import XEUtils from 'xe-utils'
3
- import { ColumnInfo } from './columnInfo'
4
- import { isPx, isScale, queryElement } from '../../ui/src/dom'
5
- import { eqEmptyValue } from '../../ui/src/utils'
6
-
7
- import type { VxeTableConstructor, VxeTablePrivateMethods, VxeTableDefines, VxeTablePropTypes, TableReactData, TableInternalData } from '../../../types'
8
-
9
- export function createInternalData (): TableInternalData {
10
- return {
11
- tZindex: 0,
12
- currKeyField: '',
13
- isCurrDeepKey: false,
14
- elemStore: {},
15
- // 存放横向 X 虚拟滚动相关的信息
16
- scrollXStore: {
17
- preloadSize: 0,
18
- offsetSize: 0,
19
- visibleSize: 0,
20
- visibleStartIndex: 0,
21
- visibleEndIndex: 0,
22
- startIndex: 0,
23
- endIndex: 0
24
- },
25
- // 存放纵向 Y 虚拟滚动相关信息
26
- scrollYStore: {
27
- preloadSize: 0,
28
- offsetSize: 0,
29
- visibleSize: 0,
30
- visibleStartIndex: 0,
31
- visibleEndIndex: 0,
32
- startIndex: 0,
33
- endIndex: 0
34
- },
35
- // 表格宽度
36
- tableWidth: 0,
37
- // 表格高度
38
- tableHeight: 0,
39
- customHeight: 0,
40
- customMinHeight: 0,
41
- customMaxHeight: 0,
42
- // 当前 hover 行
43
- hoverRow: null,
44
- // 最后滚动位置
45
- lastScrollLeft: 0,
46
- lastScrollTop: 0,
47
- // 单选框属性,已选中保留的行
48
- radioReserveRow: null,
49
- // 复选框属性,已选中保留的行集合
50
- checkboxReserveRowMap: {},
51
- // 行数据,已展开保留的行集合
52
- rowExpandedReserveRowMap: {},
53
- // 树结构数据,已展开保留的行集合
54
- treeExpandedReserveRowMap: {},
55
- // 树结构数据,不确定状态的集合
56
- treeIndeterminateRowMaps: {},
57
- // 列表完整数据、条件处理后
58
- tableFullData: [],
59
- afterFullData: [],
60
- afterTreeFullData: [],
61
- afterGroupFullData: [],
62
- // 列表条件处理后数据集合
63
- afterFullRowMaps: {},
64
- // 树结构完整数据、条件处理后
65
- tableFullTreeData: [],
66
- // 行分组全量数据、条件处理后
67
- tableFullGroupData: [],
68
- tableSynchData: [],
69
- tableSourceData: [],
70
- // 收集的列配置(带分组)
71
- collectColumn: [],
72
- // 完整所有列(不带分组)
73
- tableFullColumn: [],
74
- // 渲染所有列
75
- visibleColumn: [],
76
-
77
- // 全量数据集(包括当前和已删除)
78
- fullAllDataRowIdData: {},
79
- // 数据集(仅当前)
80
- fullDataRowIdData: {},
81
- // 数据集(仅可视)
82
- visibleDataRowIdData: {},
83
-
84
- keepUpdateFieldMaps: {},
85
-
86
- footerFullDataRowData: {},
87
-
88
- // 渲染中缓存数据
89
- sourceDataRowIdData: {},
90
- fullColumnIdData: {},
91
- fullColumnFieldData: {},
92
-
93
- // 当前行
94
- currentRow: null,
95
-
96
- // 合并表头单元格的数据
97
- mergeHeaderList: [],
98
- mergeHeaderMaps: {},
99
- // 已合并单元格数据集合
100
- mergeHeaderCellMaps: {},
101
- mergeHeaderRowMaps: {},
102
- mergeHeaderColMaps: {},
103
- // 合并单元格的数据
104
- mergeBodyList: [],
105
- mergeBodyMaps: {},
106
- // 已合并单元格数据集合
107
- mergeBodyCellMaps: {},
108
- mergeBodyRowMaps: {},
109
- mergeBodyColMaps: {},
110
- // 合并表尾的数据
111
- mergeFooterList: [],
112
- mergeFooterMaps: {},
113
- // 已合并表尾数据集合
114
- mergeFooterCellMaps: {},
115
- mergeFooterRowMaps: {},
116
- mergeFooterColMaps: {},
117
-
118
- // 已展开的行集合
119
- rowExpandedMaps: {},
120
- // 懒加载中的展开行的集合
121
- rowExpandLazyLoadedMaps: {},
122
- // 已展开的分组行
123
- rowGroupExpandedMaps: {},
124
- // 已展开树节点集合
125
- treeExpandedMaps: {},
126
- // 懒加载中的树节点的集合
127
- treeExpandLazyLoadedMaps: {},
128
- // 复选框属性,已选中的行集合
129
- selectCheckboxMaps: {},
130
- // 已标记的对象集
131
- pendingRowMaps: {},
132
- // 已新增的临时行
133
- insertRowMaps: {},
134
- // 已删除行
135
- removeRowMaps: {},
136
-
137
- cvCacheMaps: {},
138
-
139
- // 表头高度
140
- tHeaderHeight: 0,
141
- // 表体高度
142
- tBodyHeight: 0,
143
- // 表尾高度
144
- tFooterHeight: 0,
145
-
146
- stackHistoryStore: {
147
- undoStacks: [],
148
- redoStacks: []
149
- },
150
-
151
- teleportToWrapperElem: null,
152
- popupToWrapperElem: null,
153
- customPopupToElem: null,
154
-
155
- lastSTime: 0,
156
-
157
- // isCustomDragStatus: false,
158
-
159
- inited: false,
160
- tooltipTimeout: null,
161
- initStatus: false,
162
- isActivated: false
163
-
164
- // _sToTime: null
165
- }
166
- }
167
-
168
- export function createReactData (): TableReactData {
169
- return {
170
- updateColFlag: 0,
171
- // 低性能的静态列
172
- staticColumns: [],
173
- // 渲染的列分组
174
- tableGroupColumn: [],
175
- // 可视区渲染的列
176
- tableColumn: [],
177
- // 渲染中的数据
178
- tableData: [],
179
- // 是否启用了横向 X 可视渲染方式加载
180
- scrollXLoad: false,
181
- // 是否启用了纵向 Y 可视渲染方式加载
182
- scrollYLoad: false,
183
- // 是否存在纵向滚动条
184
- overflowY: true,
185
- // 是否存在横向滚动条
186
- overflowX: false,
187
- // 纵向滚动条的宽度
188
- scrollbarWidth: 0,
189
- // 横向滚动条的高度
190
- scrollbarHeight: 0,
191
- // 行高
192
- rowHeight: 0,
193
- // 表格父容器的高度
194
- parentHeight: 0,
195
- // 是否使用分组表头
196
- isGroup: false,
197
- isAllOverflow: false,
198
- // 复选框属性,是否全选
199
- isAllSelected: false,
200
- // 复选框属性,有选中且非全选状态
201
- isIndeterminate: false,
202
- // 单选框属性,选中列
203
- currentColumn: null,
204
- // 单选框属性,选中行
205
- selectRadioRow: null,
206
- // 表尾合计数据
207
- footerTableData: [],
208
- // 行分组列信息
209
- rowGroupColumn: null,
210
- // 展开列信息
211
- expandColumn: null,
212
- checkboxColumn: null,
213
- radioColumn: null,
214
- // 树节点列信息
215
- treeNodeColumn: null,
216
- hasFixedColumn: false,
217
- // 刷新列标识,当列筛选被改变时,触发表格刷新数据
218
- upDataFlag: 0,
219
- // 刷新列标识,当列的特定属性被改变时,触发表格刷新列
220
- reColumnFlag: 0,
221
- // 初始化标识
222
- initStore: {
223
- filter: false,
224
- import: false,
225
- export: false,
226
- custom: false
227
- },
228
- // 自定义列相关的信息
229
- customStore: {
230
- btnEl: null,
231
- isAll: false,
232
- isIndeterminate: false,
233
- activeBtn: false,
234
- activeWrapper: false,
235
- visible: false,
236
- maxHeight: null,
237
- popupStyle: {},
238
- oldSortMaps: {},
239
- oldFixedMaps: {},
240
- oldVisibleMaps: {}
241
- },
242
- customColumnList: [],
243
- // 当前选中的筛选列
244
- filterStore: {
245
- isAllSelected: false,
246
- isIndeterminate: false,
247
- style: null,
248
- column: null,
249
- visible: false,
250
- maxHeight: null
251
- },
252
- // 存放列相关的信息
253
- columnStore: {
254
- leftList: [],
255
- centerList: [],
256
- rightList: [],
257
- resizeList: [],
258
- pxList: [],
259
- pxMinList: [],
260
- autoMinList: [],
261
- scaleList: [],
262
- scaleMinList: [],
263
- autoList: [],
264
- remainList: []
265
- },
266
- // 存放快捷菜单的信息
267
- ctxMenuStore: {
268
- selected: null,
269
- visible: false,
270
- showChild: false,
271
- selectChild: null,
272
- list: [],
273
- style: null
274
- },
275
- // 存放可编辑相关信息
276
- editStore: {
277
- indexs: {
278
- columns: []
279
- },
280
- titles: {
281
- columns: []
282
- },
283
- // 选中源
284
- selected: {
285
- row: null,
286
- column: null
287
- },
288
- // 已复制源
289
- copyed: {
290
- cut: false,
291
- rows: [],
292
- columns: []
293
- },
294
- // 激活
295
- actived: {
296
- row: null,
297
- column: null
298
- },
299
- // 当前被强制聚焦单元格,只会在鼠标点击后算聚焦
300
- focused: {
301
- row: null,
302
- column: null
303
- }
304
- },
305
- // 存放 tooltip 相关信息
306
- tooltipStore: {
307
- row: null,
308
- column: null,
309
- content: '',
310
- visible: false,
311
- type: null,
312
- currOpts: {}
313
- },
314
- // 存放数据校验相关信息
315
- validStore: {
316
- visible: false
317
- },
318
- validErrorMaps: {},
319
- // 导入相关信息
320
- importStore: {
321
- inited: false,
322
- file: null,
323
- type: '',
324
- modeList: [],
325
- typeList: [],
326
- filename: '',
327
- visible: false
328
- },
329
- importParams: {
330
- mode: '',
331
- types: null,
332
- message: true
333
- },
334
- // 导出相关信息
335
- exportStore: {
336
- inited: false,
337
- name: '',
338
- modeList: [],
339
- typeList: [],
340
- columns: [],
341
- isPrint: false,
342
- hasFooter: false,
343
- hasMerge: false,
344
- hasTree: false,
345
- hasColgroup: false,
346
- visible: false
347
- },
348
- exportParams: {
349
- filename: '',
350
- sheetName: '',
351
- mode: '',
352
- type: '',
353
- isColgroup: false,
354
- isMerge: false,
355
- isAllExpand: false,
356
- useStyle: false,
357
- original: false,
358
- message: true,
359
- isHeader: false,
360
- isTitle: false,
361
- isFooter: false
362
- },
363
-
364
- visiblwRowsFlag: 1,
365
-
366
- isRowGroupStatus: false,
367
- rowGroupList: [],
368
- aggHandleFields: [],
369
- aggHandleAggColumns: [],
370
-
371
- rowGroupExpandedFlag: 1,
372
- rowExpandedFlag: 1,
373
- treeExpandedFlag: 1,
374
- updateCheckboxFlag: 1,
375
- pendingRowFlag: 1,
376
- insertRowFlag: 1,
377
- removeRowFlag: 1,
378
-
379
- mergeHeadFlag: 1,
380
- mergeBodyFlag: 1,
381
- mergeFootFlag: 1,
382
-
383
- rowHeightStore: {
384
- large: 52,
385
- default: 48,
386
- medium: 44,
387
- small: 40,
388
- mini: 36
389
- },
390
-
391
- scrollVMLoading: false,
392
- scrollYHeight: 0,
393
- scrollYTop: 0,
394
- isScrollYBig: false,
395
- scrollXLeft: 0,
396
- scrollXWidth: 0,
397
- isScrollXBig: false,
398
-
399
- lazScrollLoading: false,
400
-
401
- rowExpandHeightFlag: 1,
402
- calcCellHeightFlag: 1,
403
- resizeHeightFlag: 1,
404
- resizeWidthFlag: 1,
405
-
406
- isCustomStatus: false,
407
- isCustomDragStatus: true,
408
- ctPopupFlag: 1,
409
-
410
- isCrossDragRow: false,
411
- dragRow: null,
412
- isCrossDragCol: false,
413
- dragCol: null,
414
- dragTipText: '',
415
-
416
- isDragResize: false,
417
- isRowLoading: false,
418
- isColLoading: false
419
- }
420
- }
421
-
422
- const getAllConvertColumns = (columns: any, parentColumn?: any) => {
423
- const result: any[] = []
424
- columns.forEach((column: any) => {
425
- column.parentId = parentColumn ? parentColumn.id : null
426
- if (column.visible) {
427
- if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
428
- result.push(column)
429
- result.push(...getAllConvertColumns(column.children, column))
430
- } else {
431
- result.push(column)
432
- }
433
- }
434
- })
435
- return result
436
- }
437
-
438
- export const convertHeaderColumnToRows = (originColumns: any): any[][] => {
439
- let maxLevel = 1
440
- const traverse = (column: any, parent?: any) => {
441
- if (parent) {
442
- column.level = parent.level + 1
443
- if (maxLevel < column.level) {
444
- maxLevel = column.level
445
- }
446
- }
447
- if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
448
- let colSpan = 0
449
- column.children.forEach((subColumn: any) => {
450
- if (subColumn.visible) {
451
- traverse(subColumn, column)
452
- colSpan += subColumn.colSpan
453
- }
454
- })
455
- column.colSpan = colSpan
456
- } else {
457
- column.colSpan = 1
458
- }
459
- }
460
-
461
- originColumns.forEach((column: any) => {
462
- column.level = 1
463
- traverse(column)
464
- })
465
-
466
- const rows: any[] = []
467
- for (let i = 0; i < maxLevel; i++) {
468
- rows.push([])
469
- }
470
-
471
- const allColumns = getAllConvertColumns(originColumns)
472
-
473
- allColumns.forEach((column) => {
474
- if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
475
- column.rowSpan = 1
476
- } else {
477
- column.rowSpan = maxLevel - column.level + 1
478
- }
479
- rows[column.level - 1].push(column)
480
- })
481
-
482
- return rows
483
- }
484
-
485
- export function convertHeaderToGridRows (spanColumns: VxeTableDefines.ColumnInfo[][]) {
486
- const rSize = spanColumns.length
487
- const cSize = spanColumns[0].reduce((sum, cell) => sum + cell.colSpan, 0)
488
-
489
- const occupiedRows: boolean[][] = []
490
- const fullRows: any[][] = []
491
- for (let rIndex = 0; rIndex < rSize; rIndex++) {
492
- const oCols: boolean[] = []
493
- const dCols: string[] = []
494
- for (let cIndex = 0; cIndex < cSize; cIndex++) {
495
- oCols.push(false)
496
- dCols.push('')
497
- }
498
- occupiedRows.push(oCols)
499
- fullRows.push(dCols)
500
- }
501
-
502
- for (let rIndex = 0; rIndex < rSize; rIndex++) {
503
- let currColIndex = 0
504
- for (const column of spanColumns[rIndex]) {
505
- const { colSpan, rowSpan } = column
506
- let startColIndex = -1
507
- for (let ccIndex = currColIndex; ccIndex <= cSize - colSpan; ccIndex++) {
508
- let oFlag = true
509
- for (let csIndex = 0; csIndex < colSpan; csIndex++) {
510
- if (occupiedRows[rIndex][ccIndex + csIndex]) {
511
- oFlag = false
512
- break
513
- }
514
- }
515
- if (oFlag) {
516
- startColIndex = ccIndex
517
- break
518
- }
519
- }
520
- if (startColIndex === -1) {
521
- for (let j = 0; j <= cSize - colSpan; j++) {
522
- let oFlag = true
523
- for (let k = 0; k < colSpan; k++) {
524
- if (occupiedRows[rIndex][j + k]) {
525
- oFlag = false
526
- break
527
- }
528
- }
529
- if (oFlag) {
530
- startColIndex = j
531
- break
532
- }
533
- }
534
- if (startColIndex === -1) {
535
- // error
536
- break
537
- }
538
- }
539
-
540
- for (let srIndex = rIndex; srIndex < rIndex + rowSpan; srIndex++) {
541
- for (let scIndex = startColIndex; scIndex < startColIndex + colSpan; scIndex++) {
542
- occupiedRows[srIndex][scIndex] = true
543
- fullRows[srIndex][scIndex] = column
544
- }
545
- }
546
- currColIndex = startColIndex + colSpan
547
- }
548
- }
549
- return fullRows
550
- }
551
-
552
- export function restoreScrollLocation ($xeTable: VxeTableConstructor, scrollLeft: number, scrollTop: number) {
553
- const internalData = $xeTable.internalData
554
-
555
- if (scrollLeft || scrollTop) {
556
- internalData.intoRunScroll = false
557
- internalData.inVirtualScroll = false
558
- internalData.inWheelScroll = false
559
- internalData.inHeaderScroll = false
560
- internalData.inBodyScroll = false
561
- internalData.inFooterScroll = false
562
- internalData.scrollRenderType = ''
563
- // 还原滚动状态
564
- return $xeTable.scrollTo(scrollLeft, scrollTop)
565
- }
566
- return $xeTable.clearScroll()
567
- }
568
-
569
- export function getRowUniqueId () {
570
- return XEUtils.uniqueId('row_')
571
- }
572
-
573
- /**
574
- * 生成行的唯一主键
575
- */
576
- export function createRowId (rowOpts: VxeTablePropTypes.RowConfig, row: any, keyField: string) {
577
- const { createKeyMethod } = rowOpts
578
- if (createKeyMethod) {
579
- return createKeyMethod({ row, keyField })
580
- }
581
- return getRowUniqueId()
582
- }
583
-
584
- export function hasDeepKey (rowKey: string) {
585
- return rowKey.indexOf('.') > -1
586
- }
587
-
588
- // 行主键 key
589
- export function getRowkey ($xeTable: VxeTableConstructor) {
590
- const { currKeyField } = $xeTable.internalData
591
- return currKeyField
592
- }
593
-
594
- // 行主键 value
595
- export function getRowid ($xeTable: VxeTableConstructor, row: any) {
596
- const internalData = $xeTable.internalData
597
- const { isCurrDeepKey, currKeyField } = internalData
598
- return row ? encodeRowid((isCurrDeepKey ? getDeepRowIdByKey : getFastRowIdByKey)(row, currKeyField)) : ''
599
- }
600
-
601
- export function createHandleUpdateRowId ($xeTable: VxeTableConstructor) {
602
- const internalData = $xeTable.internalData
603
- const { isCurrDeepKey, currKeyField } = internalData
604
- const { computeRowOpts } = $xeTable.getComputeMaps()
605
- const rowOpts = computeRowOpts.value
606
- const updateRId = isCurrDeepKey ? updateDeepRowKey : updateFastRowKey
607
- return {
608
- rowKey: currKeyField,
609
- handleUpdateRowId (row: any) {
610
- return row ? updateRId(rowOpts, row, currKeyField) : ''
611
- }
612
- }
613
- }
614
-
615
- export function createHandleGetRowId ($xeTable: VxeTableConstructor) {
616
- const internalData = $xeTable.internalData
617
- const { isCurrDeepKey, currKeyField } = internalData
618
- const getRId = isCurrDeepKey ? getDeepRowIdByKey : getFastRowIdByKey
619
- return {
620
- rowKey: currKeyField,
621
- handleGetRowId (row: any) {
622
- return row ? encodeRowid(getRId(row, currKeyField)) : ''
623
- }
624
- }
625
- }
626
-
627
- // 编码行主键
628
- export function encodeRowid (rowVal: string) {
629
- return XEUtils.eqNull(rowVal) ? '' : encodeURIComponent(rowVal)
630
- }
631
-
632
- function getDeepRowIdByKey (row: any, rowKey: string) {
633
- return XEUtils.get(row, rowKey)
634
- }
635
-
636
- function updateDeepRowKey (rowOpts: VxeTablePropTypes.RowConfig, row: any, rowKey: string) {
637
- let rowid = encodeRowid(getDeepRowIdByKey(row, rowKey))
638
- if (eqEmptyValue(rowid)) {
639
- const newRowid = createRowId(rowOpts, row, rowKey)
640
- rowid = '' + newRowid
641
- XEUtils.set(row, rowKey, rowid)
642
- }
643
- return rowid
644
- }
645
-
646
- function getFastRowIdByKey (row: any, rowKey: string) {
647
- return row[rowKey]
648
- }
649
-
650
- function updateFastRowKey (rowOpts: VxeTablePropTypes.RowConfig, row: any, rowKey: string) {
651
- let rowid = encodeRowid(getFastRowIdByKey(row, rowKey))
652
- if (eqEmptyValue(rowid)) {
653
- const newRowid = createRowId(rowOpts, row, rowKey)
654
- rowid = '' + newRowid
655
- row[rowKey] = newRowid
656
- }
657
- return rowid
658
- }
659
-
660
- export interface XEColumnInstance {
661
- columnConfig: ColumnInfo;
662
- }
663
-
664
- export function handleFieldOrColumn ($xeTable: VxeTableConstructor, fieldOrColumn: string | VxeTableDefines.ColumnInfo | null) {
665
- if (fieldOrColumn) {
666
- return XEUtils.isString(fieldOrColumn) || XEUtils.isNumber(fieldOrColumn) ? $xeTable.getColumnByField(`${fieldOrColumn}`) : fieldOrColumn
667
- }
668
- return null
669
- }
670
-
671
- export function handleRowidOrRow ($xeTable: VxeTableConstructor, rowidOrRow: any) {
672
- if (rowidOrRow) {
673
- const rowid = XEUtils.isString(rowidOrRow) || XEUtils.isNumber(rowidOrRow) ? rowidOrRow : getRowid($xeTable, rowidOrRow)
674
- return $xeTable.getRowById(rowid)
675
- }
676
- return null
677
- }
678
-
679
- export function getCellRestHeight (rowRest: VxeTableDefines.RowCacheItem, cellOpts: VxeTablePropTypes.CellConfig, rowOpts: VxeTablePropTypes.RowConfig, defaultRowHeight: number) {
680
- return rowRest.resizeHeight || cellOpts.height || rowOpts.height || rowRest.height || defaultRowHeight
681
- }
682
-
683
- function getPaddingLeftRightSize (elem: HTMLElement | null) {
684
- if (elem) {
685
- const computedStyle = getComputedStyle(elem)
686
- const paddingLeft = XEUtils.toNumber(computedStyle.paddingLeft)
687
- const paddingRight = XEUtils.toNumber(computedStyle.paddingRight)
688
- return paddingLeft + paddingRight
689
- }
690
- return 0
691
- }
692
-
693
- function getElementMarginAndWidth (elem: HTMLElement | null) {
694
- if (elem) {
695
- const computedStyle = getComputedStyle(elem)
696
- const marginLeft = XEUtils.toNumber(computedStyle.marginLeft)
697
- const marginRight = XEUtils.toNumber(computedStyle.marginRight)
698
- return elem.offsetWidth + marginLeft + marginRight
699
- }
700
- return 0
701
- }
702
-
703
- export function toFilters (filters: any, colid?: string) {
704
- if (filters) {
705
- if (XEUtils.isArray(filters)) {
706
- return filters.map(({ label, value, data, resetValue, checked }) => {
707
- return { label, value, data, resetValue, checked: !!checked, _checked: !!checked, _colId: colid }
708
- })
709
- }
710
- return []
711
- }
712
- return filters
713
- }
714
-
715
- export function toTreePathSeq (path: any[]) {
716
- return path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('')
717
- }
718
-
719
- export function getCellValue (row: any, column: VxeTableDefines.ColumnInfo | null) {
720
- if (column) {
721
- return XEUtils.get(row, column.field)
722
- }
723
- return null
724
- }
725
-
726
- export function setCellValue (row: any, column: VxeTableDefines.ColumnInfo | null, value: any) {
727
- if (column) {
728
- XEUtils.set(row, column.field, value)
729
- }
730
- }
731
-
732
- export function getRefElem (refEl: any) {
733
- if (refEl) {
734
- const rest = refEl.value
735
- if (rest) {
736
- return (rest.$el || rest) as HTMLElement
737
- }
738
- }
739
- return null
740
- }
741
-
742
- export function getCalcHeight (height: number | 'unset' | undefined | null) {
743
- if (height === 'unset') {
744
- return 0
745
- }
746
- return height || 0
747
- }
748
-
749
- /**
750
- * 列宽拖动最大宽度
751
- * @param params
752
- * @returns
753
- */
754
- export function getColReMaxWidth (params: {
755
- $table: VxeTableConstructor & VxeTablePrivateMethods;
756
- column: VxeTableDefines.ColumnInfo;
757
- columnIndex: number;
758
- $columnIndex: number;
759
- $rowIndex: number;
760
- cell: HTMLTableCellElement;
761
- }) {
762
- const { $table } = params
763
- const { computeResizableOpts } = $table.getComputeMaps()
764
- const resizableOpts = computeResizableOpts.value
765
- const { maxWidth: reMaxWidth } = resizableOpts
766
- // 如果自定义调整宽度逻辑
767
- if (reMaxWidth) {
768
- const customMaxWidth = XEUtils.isFunction(reMaxWidth) ? reMaxWidth(params) : reMaxWidth
769
- if (customMaxWidth !== 'auto') {
770
- return Math.max(1, XEUtils.toNumber(customMaxWidth))
771
- }
772
- }
773
- return -1
774
- }
775
-
776
- /**
777
- * 列宽拖动最小宽度
778
- * @param params
779
- * @returns
780
- */
781
- export function getColReMinWidth (params: {
782
- $table: VxeTableConstructor & VxeTablePrivateMethods;
783
- column: VxeTableDefines.ColumnInfo;
784
- columnIndex: number;
785
- $columnIndex: number;
786
- $rowIndex: number;
787
- cell: HTMLTableCellElement;
788
- }) {
789
- const { $table, column, cell } = params
790
- const tableProps = $table.props
791
- const internalData = $table.internalData
792
- const { computeResizableOpts } = $table.getComputeMaps()
793
- const resizableOpts = computeResizableOpts.value
794
- const { minWidth: reMinWidth } = resizableOpts
795
- // 如果自定义调整宽度逻辑
796
- if (reMinWidth) {
797
- const customMinWidth = XEUtils.isFunction(reMinWidth) ? reMinWidth(params) : reMinWidth
798
- if (customMinWidth !== 'auto') {
799
- return Math.max(1, XEUtils.toNumber(customMinWidth))
800
- }
801
- }
802
- const { elemStore } = internalData
803
- const { showHeaderOverflow: allColumnHeaderOverflow } = tableProps
804
- const { showHeaderOverflow, minWidth: colMinWidth } = column
805
- const headOverflow = XEUtils.isUndefined(showHeaderOverflow) || XEUtils.isNull(showHeaderOverflow) ? allColumnHeaderOverflow : showHeaderOverflow
806
- const showEllipsis = headOverflow === 'ellipsis'
807
- const showTitle = headOverflow === 'title'
808
- const showTooltip = headOverflow === true || headOverflow === 'tooltip'
809
- const hasEllipsis = showTitle || showTooltip || showEllipsis
810
- const minTitleWidth = XEUtils.floor((XEUtils.toNumber(getComputedStyle(cell).fontSize) || 14) * 1.8)
811
- const paddingLeftRight = getPaddingLeftRightSize(cell) + getPaddingLeftRightSize(queryElement(cell, '.vxe-cell'))
812
- let mWidth = minTitleWidth + paddingLeftRight
813
- // 默认最小宽处理
814
- if (hasEllipsis) {
815
- const dragIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--drag-handle'))
816
- const checkboxIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--checkbox'))
817
- const requiredIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--required-icon'))
818
- const editIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--edit-icon'))
819
- const prefixIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell-title-prefix-icon'))
820
- const suffixIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell-title-suffix-icon'))
821
- const sortIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--sort'))
822
- const filterIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--filter'))
823
- mWidth += dragIconWidth + checkboxIconWidth + requiredIconWidth + editIconWidth + prefixIconWidth + suffixIconWidth + filterIconWidth + sortIconWidth
824
- }
825
- // 如果设置最小宽
826
- if (colMinWidth) {
827
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
828
- if (bodyScrollElem) {
829
- if (isScale(colMinWidth)) {
830
- const bodyWidth = bodyScrollElem.clientWidth - 1
831
- const meanWidth = bodyWidth / 100
832
- return Math.max(mWidth, Math.floor(XEUtils.toInteger(colMinWidth) * meanWidth))
833
- } else if (isPx(colMinWidth)) {
834
- return Math.max(mWidth, XEUtils.toInteger(colMinWidth))
835
- }
836
- }
837
- }
838
- return mWidth
839
- }
840
-
841
- export function isColumnInfo (column: any): column is ColumnInfo {
842
- return column && (column.constructor === ColumnInfo || column instanceof ColumnInfo)
843
- }
844
-
845
- // 获取所有的列,排除分组
846
- export function getColumnList (columns: VxeTableDefines.ColumnInfo[]) {
847
- const result: VxeTableDefines.ColumnInfo[] = []
848
- columns.forEach((column) => {
849
- result.push(...(column.children && column.children.length ? getColumnList(column.children) : [column]))
850
- })
851
- return result
852
- }
853
-
854
- export function createColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, options: VxeTableDefines.ColumnOptions | VxeTableDefines.ColumnInfo, renderOptions: any): any {
855
- return isColumnInfo(options) ? options : reactive(new ColumnInfo($xeTable, options, renderOptions))
856
- }
857
-
858
- export function watchColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, props: any, column: ColumnInfo) {
859
- Object.keys(props).forEach(name => {
860
- watch(() => props[name], (value: any) => {
861
- column.update(name, value)
862
- if ($xeTable) {
863
- if (name === 'filters') {
864
- $xeTable.setFilter(column as any, value)
865
- $xeTable.handleUpdateDataQueue()
866
- } else if (['visible', 'fixed', 'width', 'minWidth', 'maxWidth'].includes(name)) {
867
- $xeTable.handleRefreshColumnQueue()
868
- }
869
- }
870
- })
871
- })
872
- }
873
-
874
- export function assembleColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, elem: HTMLElement, column: ColumnInfo, colgroup: XEColumnInstance | null) {
875
- const { reactData } = $xeTable
876
- const { staticColumns } = reactData
877
- const parentElem = elem.parentNode
878
- const parentColumn = colgroup ? colgroup.columnConfig : null
879
- const parentCols = parentColumn ? parentColumn.children : staticColumns
880
- if (parentElem && parentCols) {
881
- column.defaultParentId = parentColumn ? parentColumn.id : null
882
- parentCols.splice(XEUtils.arrayIndexOf(parentElem.children, elem), 0, column)
883
- reactData.staticColumns = staticColumns.slice(0)
884
- }
885
- }
886
-
887
- export function destroyColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: ColumnInfo) {
888
- const { reactData } = $xeTable
889
- const { staticColumns } = reactData
890
- const matchObj = XEUtils.findTree(staticColumns, item => item.id === column.id, { children: 'children' })
891
- if (matchObj) {
892
- matchObj.items.splice(matchObj.index, 1)
893
- }
894
- reactData.staticColumns = staticColumns.slice(0)
895
- }
896
-
897
- export function getRootColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: ColumnInfo) {
898
- const { internalData } = $xeTable
899
-
900
- const { fullColumnIdData } = internalData
901
- if (!column) {
902
- return null
903
- }
904
- let parentColId = column.parentId
905
- while (fullColumnIdData[parentColId]) {
906
- const column = fullColumnIdData[parentColId].column
907
- parentColId = column.parentId
908
- if (!parentColId) {
909
- return column
910
- }
911
- }
912
- return column
913
- }
914
-
915
- export function getFirstChildColumn (column: VxeTableDefines.ColumnInfo): VxeTableDefines.ColumnInfo {
916
- const { children } = column
917
- if (children && children.length) {
918
- return getFirstChildColumn(XEUtils.first(children))
919
- }
920
- return column
921
- }
922
-
923
- export function getLastChildColumn (column: VxeTableDefines.ColumnInfo): VxeTableDefines.ColumnInfo {
924
- const { children } = column
925
- if (children && children.length) {
926
- return getFirstChildColumn(XEUtils.last(children))
927
- }
928
- return column
929
- }
930
-
931
- export function clearTableDefaultStatus ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
932
- const { props, internalData } = $xeTable
933
-
934
- internalData.initStatus = false
935
- const actionList = [
936
- $xeTable.clearSort(),
937
- $xeTable.clearCurrentRow(),
938
- $xeTable.clearCurrentColumn(),
939
- $xeTable.clearRadioRow(),
940
- $xeTable.clearRadioReserve(),
941
- $xeTable.clearCheckboxRow(),
942
- $xeTable.clearCheckboxReserve(),
943
- $xeTable.clearRowExpand(),
944
- $xeTable.clearTreeExpand(),
945
- $xeTable.clearTreeExpandReserve(),
946
- $xeTable.clearPendingRow()
947
- ]
948
- if ($xeTable.clearFilter) {
949
- actionList.push(
950
- $xeTable.clearFilter()
951
- )
952
- }
953
- if ($xeTable.clearSelected && (props.keyboardConfig || props.mouseConfig)) {
954
- actionList.push(
955
- $xeTable.clearSelected()
956
- )
957
- }
958
- if ($xeTable.clearCellAreas && props.mouseConfig) {
959
- actionList.push(
960
- $xeTable.clearCellAreas(),
961
- $xeTable.clearCopyCellArea()
962
- )
963
- }
964
- return Promise.all(actionList).then(() => {
965
- return $xeTable.clearScroll()
966
- })
967
- }
968
-
969
- export function clearTableAllStatus ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
970
- if ($xeTable.clearFilter) {
971
- $xeTable.clearFilter()
972
- }
973
- return clearTableDefaultStatus($xeTable)
974
- }
975
-
976
- export function rowToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, row: any) {
977
- const reactData = $xeTable.reactData
978
- const internalData = $xeTable.internalData
979
-
980
- const { computeLeftFixedWidth, computeRightFixedWidth, computeRowOpts, computeCellOpts, computeDefaultRowHeight } = $xeTable.getComputeMaps()
981
- const { scrollYLoad, scrollYTop, isAllOverflow } = reactData
982
- const { elemStore, afterFullData, fullAllDataRowIdData, isResizeCellHeight } = internalData
983
- const rowOpts = computeRowOpts.value
984
- const cellOpts = computeCellOpts.value
985
- const defaultRowHeight = computeDefaultRowHeight.value
986
- const leftFixedWidth = computeLeftFixedWidth.value
987
- const rightFixedWidth = computeRightFixedWidth.value
988
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
989
- const rowid = getRowid($xeTable, row)
990
- if (bodyScrollElem) {
991
- const bodyHeight = bodyScrollElem.clientHeight
992
- const bodyScrollTop = bodyScrollElem.scrollTop
993
- const trElem: HTMLTableRowElement | null = bodyScrollElem.querySelector(`[rowid="${rowid}"]`)
994
- if (trElem) {
995
- const trOffsetTop = trElem.offsetTop + (scrollYLoad ? scrollYTop : 0)
996
- const trHeight = trElem.clientHeight
997
- // 检测行是否在可视区中
998
- if (trOffsetTop < bodyScrollTop || trOffsetTop > bodyScrollTop + bodyHeight) {
999
- return $xeTable.scrollTo(null, trOffsetTop)
1000
- } else if (trOffsetTop + trHeight >= bodyHeight + bodyScrollTop) {
1001
- return $xeTable.scrollTo(null, bodyScrollTop + trHeight)
1002
- }
1003
- } else {
1004
- // 如果是虚拟渲染滚动
1005
- if (scrollYLoad) {
1006
- const isCustomCellHeight = isResizeCellHeight || cellOpts.height || rowOpts.height
1007
- if (!isCustomCellHeight && isAllOverflow) {
1008
- return $xeTable.scrollTo(null, ($xeTable.findRowIndexOf(afterFullData, row) - 1) * defaultRowHeight)
1009
- }
1010
- const rowRest = fullAllDataRowIdData[rowid] || {}
1011
- const rHeight = rowRest.resizeHeight || cellOpts.height || rowOpts.height || rowRest.height || defaultRowHeight
1012
- const scrollTop = rowRest.oTop
1013
- if (scrollTop < bodyScrollTop) {
1014
- return $xeTable.scrollTo(null, scrollTop - leftFixedWidth - 1)
1015
- }
1016
- return $xeTable.scrollTo(null, (scrollTop + rHeight) - (bodyHeight - rightFixedWidth - 1))
1017
- }
1018
- }
1019
- }
1020
- return Promise.resolve()
1021
- }
1022
-
1023
- export function colToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, isForce: boolean, column: VxeTableDefines.ColumnInfo, row?: any) {
1024
- const reactData = $xeTable.reactData
1025
- const internalData = $xeTable.internalData
1026
-
1027
- const { computeLeftFixedWidth, computeRightFixedWidth } = $xeTable.getComputeMaps()
1028
- const { scrollXLoad, scrollXLeft } = reactData
1029
- const { elemStore, visibleColumn } = internalData
1030
- const leftFixedWidth = computeLeftFixedWidth.value
1031
- const rightFixedWidth = computeRightFixedWidth.value
1032
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1033
- if (column.fixed) {
1034
- return Promise.resolve()
1035
- }
1036
- if (bodyScrollElem) {
1037
- const bodyWidth = bodyScrollElem.clientWidth
1038
- const bodyScrollLeft = bodyScrollElem.scrollLeft
1039
- let tdElem: HTMLTableCellElement | null = null
1040
- if (row) {
1041
- const rowid = getRowid($xeTable, row)
1042
- tdElem = bodyScrollElem.querySelector(`[rowid="${rowid}"] .${column.id}`)
1043
- }
1044
- if (!tdElem) {
1045
- tdElem = bodyScrollElem.querySelector(`.${column.id}`)
1046
- }
1047
- if (tdElem) {
1048
- const tdOffsetLeft = tdElem.offsetLeft + (scrollXLoad ? scrollXLeft : 0)
1049
- const cellWidth = tdElem.clientWidth
1050
- // 检测是否在可视区中
1051
- if (isForce || (
1052
- !(tdOffsetLeft <= (bodyScrollLeft + leftFixedWidth) && (tdOffsetLeft + cellWidth) > (bodyScrollLeft + leftFixedWidth)) &&
1053
- !(tdOffsetLeft >= (bodyScrollLeft + leftFixedWidth) && tdOffsetLeft < (bodyScrollLeft + bodyWidth - rightFixedWidth))
1054
- )) {
1055
- if (tdOffsetLeft < (bodyScrollLeft + leftFixedWidth)) {
1056
- return $xeTable.scrollTo(tdOffsetLeft - leftFixedWidth - 1)
1057
- } else if ((tdOffsetLeft + cellWidth - bodyScrollLeft) > (bodyWidth - rightFixedWidth)) {
1058
- return $xeTable.scrollTo((tdOffsetLeft + cellWidth) - (bodyWidth - rightFixedWidth - 1))
1059
- }
1060
- }
1061
- } else {
1062
- if (scrollXLoad) {
1063
- let tdOffsetLeft = 0
1064
- const cellWidth = column.renderWidth
1065
- for (let i = 0; i < visibleColumn.length; i++) {
1066
- const currCol = visibleColumn[i]
1067
- if (currCol === column || currCol.id === column.id) {
1068
- break
1069
- }
1070
- tdOffsetLeft += currCol.renderWidth
1071
- }
1072
- // 检测是否在可视区中
1073
- if (isForce || (
1074
- !(tdOffsetLeft <= (bodyScrollLeft + leftFixedWidth) && (tdOffsetLeft + cellWidth) > (bodyScrollLeft + leftFixedWidth)) &&
1075
- !(tdOffsetLeft >= (bodyScrollLeft + leftFixedWidth) && tdOffsetLeft < (bodyScrollLeft + bodyWidth - rightFixedWidth))
1076
- )) {
1077
- if (tdOffsetLeft < bodyScrollLeft) {
1078
- return $xeTable.scrollTo(tdOffsetLeft - leftFixedWidth - 1)
1079
- }
1080
- return $xeTable.scrollTo((tdOffsetLeft + cellWidth) - (bodyWidth - rightFixedWidth - 1))
1081
- }
1082
- }
1083
- }
1084
- }
1085
- return Promise.resolve()
1086
- }
1
+ import { watch, reactive } from 'vue'
2
+ import XEUtils from 'xe-utils'
3
+ import { ColumnInfo } from './columnInfo'
4
+ import { isPx, isScale, queryElement } from '../../ui/src/dom'
5
+ import { eqEmptyValue } from '../../ui/src/utils'
6
+
7
+ import type { VxeTableConstructor, VxeTablePrivateMethods, VxeTableDefines, VxeTablePropTypes, TableReactData, TableInternalData } from '../../../types'
8
+
9
+ export function createInternalData (): TableInternalData {
10
+ return {
11
+ tZindex: 0,
12
+ currKeyField: '',
13
+ isCurrDeepKey: false,
14
+ elemStore: {},
15
+ // 存放横向 X 虚拟滚动相关的信息
16
+ scrollXStore: {
17
+ preloadSize: 0,
18
+ offsetSize: 0,
19
+ visibleSize: 0,
20
+ visibleStartIndex: 0,
21
+ visibleEndIndex: 0,
22
+ startIndex: 0,
23
+ endIndex: 0
24
+ },
25
+ // 存放纵向 Y 虚拟滚动相关信息
26
+ scrollYStore: {
27
+ preloadSize: 0,
28
+ offsetSize: 0,
29
+ visibleSize: 0,
30
+ visibleStartIndex: 0,
31
+ visibleEndIndex: 0,
32
+ startIndex: 0,
33
+ endIndex: 0
34
+ },
35
+ // 表格宽度
36
+ tableWidth: 0,
37
+ // 表格高度
38
+ tableHeight: 0,
39
+ customHeight: 0,
40
+ customMinHeight: 0,
41
+ customMaxHeight: 0,
42
+ // 当前 hover 行
43
+ hoverRow: null,
44
+ // 最后滚动位置
45
+ lastScrollLeft: 0,
46
+ lastScrollTop: 0,
47
+ // 单选框属性,已选中保留的行
48
+ radioReserveRow: null,
49
+ // 复选框属性,已选中保留的行集合
50
+ checkboxReserveRowMap: {},
51
+ // 行数据,已展开保留的行集合
52
+ rowExpandedReserveRowMap: {},
53
+ // 树结构数据,已展开保留的行集合
54
+ treeExpandedReserveRowMap: {},
55
+ // 树结构数据,不确定状态的集合
56
+ treeIndeterminateRowMaps: {},
57
+ // 列表完整数据、条件处理后
58
+ tableFullData: [],
59
+ afterFullData: [],
60
+ afterTreeFullData: [],
61
+ afterGroupFullData: [],
62
+ // 列表条件处理后数据集合
63
+ afterFullRowMaps: {},
64
+ // 树结构完整数据、条件处理后
65
+ tableFullTreeData: [],
66
+ // 行分组全量数据、条件处理后
67
+ tableFullGroupData: [],
68
+ tableSynchData: [],
69
+ tableSourceData: [],
70
+ // 收集的列配置(带分组)
71
+ collectColumn: [],
72
+ // 完整所有列(不带分组)
73
+ tableFullColumn: [],
74
+ // 渲染所有列
75
+ visibleColumn: [],
76
+
77
+ // 全量数据集(包括当前和已删除)
78
+ fullAllDataRowIdData: {},
79
+ // 数据集(仅当前)
80
+ fullDataRowIdData: {},
81
+ // 数据集(仅可视)
82
+ visibleDataRowIdData: {},
83
+
84
+ keepUpdateFieldMaps: {},
85
+
86
+ footerFullDataRowData: {},
87
+
88
+ // 渲染中缓存数据
89
+ sourceDataRowIdData: {},
90
+ fullColumnIdData: {},
91
+ fullColumnFieldData: {},
92
+
93
+ // 当前行
94
+ currentRow: null,
95
+
96
+ // 合并表头单元格的数据
97
+ mergeHeaderList: [],
98
+ mergeHeaderMaps: {},
99
+ // 已合并单元格数据集合
100
+ mergeHeaderCellMaps: {},
101
+ mergeHeaderRowMaps: {},
102
+ mergeHeaderColMaps: {},
103
+ // 合并单元格的数据
104
+ mergeBodyList: [],
105
+ mergeBodyMaps: {},
106
+ // 已合并单元格数据集合
107
+ mergeBodyCellMaps: {},
108
+ mergeBodyRowMaps: {},
109
+ mergeBodyColMaps: {},
110
+ // 合并表尾的数据
111
+ mergeFooterList: [],
112
+ mergeFooterMaps: {},
113
+ // 已合并表尾数据集合
114
+ mergeFooterCellMaps: {},
115
+ mergeFooterRowMaps: {},
116
+ mergeFooterColMaps: {},
117
+
118
+ // 已展开的行集合
119
+ rowExpandedMaps: {},
120
+ // 懒加载中的展开行的集合
121
+ rowExpandLazyLoadedMaps: {},
122
+ // 已展开的分组行
123
+ rowGroupExpandedMaps: {},
124
+ // 已展开树节点集合
125
+ treeExpandedMaps: {},
126
+ // 懒加载中的树节点的集合
127
+ treeExpandLazyLoadedMaps: {},
128
+ // 复选框属性,已选中的行集合
129
+ selectCheckboxMaps: {},
130
+ // 已标记的对象集
131
+ pendingRowMaps: {},
132
+ // 已新增的临时行
133
+ insertRowMaps: {},
134
+ // 已删除行
135
+ removeRowMaps: {},
136
+
137
+ cvCacheMaps: {},
138
+
139
+ // 表头高度
140
+ tHeaderHeight: 0,
141
+ // 表体高度
142
+ tBodyHeight: 0,
143
+ // 表尾高度
144
+ tFooterHeight: 0,
145
+
146
+ stackHistoryStore: {
147
+ undoStacks: [],
148
+ redoStacks: []
149
+ },
150
+
151
+ teleportToWrapperElem: null,
152
+ popupToWrapperElem: null,
153
+ customPopupToElem: null,
154
+
155
+ lastSTime: 0,
156
+
157
+ // isCustomDragStatus: false,
158
+
159
+ inited: false,
160
+ tooltipTimeout: null,
161
+ initStatus: false,
162
+ isActivated: false
163
+
164
+ // _sToTime: null
165
+ }
166
+ }
167
+
168
+ export function createReactData (): TableReactData {
169
+ return {
170
+ updateColFlag: 0,
171
+ // 低性能的静态列
172
+ staticColumns: [],
173
+ // 渲染的列分组
174
+ tableGroupColumn: [],
175
+ // 可视区渲染的列
176
+ tableColumn: [],
177
+ // 渲染中的数据
178
+ tableData: [],
179
+ // 是否启用了横向 X 可视渲染方式加载
180
+ scrollXLoad: false,
181
+ // 是否启用了纵向 Y 可视渲染方式加载
182
+ scrollYLoad: false,
183
+ // 是否存在纵向滚动条
184
+ overflowY: true,
185
+ // 是否存在横向滚动条
186
+ overflowX: false,
187
+ // 纵向滚动条的宽度
188
+ scrollbarWidth: 0,
189
+ // 横向滚动条的高度
190
+ scrollbarHeight: 0,
191
+ // 行高
192
+ rowHeight: 0,
193
+ // 表格父容器的高度
194
+ parentHeight: 0,
195
+ // 是否使用分组表头
196
+ isGroup: false,
197
+ isAllOverflow: false,
198
+ // 复选框属性,是否全选
199
+ isAllSelected: false,
200
+ // 复选框属性,有选中且非全选状态
201
+ isIndeterminate: false,
202
+ // 单选框属性,选中列
203
+ currentColumn: null,
204
+ // 单选框属性,选中行
205
+ selectRadioRow: null,
206
+ // 表尾合计数据
207
+ footerTableData: [],
208
+ // 行分组列信息
209
+ rowGroupColumn: null,
210
+ // 展开列信息
211
+ expandColumn: null,
212
+ checkboxColumn: null,
213
+ radioColumn: null,
214
+ // 树节点列信息
215
+ treeNodeColumn: null,
216
+ hasFixedColumn: false,
217
+ // 刷新列标识,当列筛选被改变时,触发表格刷新数据
218
+ upDataFlag: 0,
219
+ // 刷新列标识,当列的特定属性被改变时,触发表格刷新列
220
+ reColumnFlag: 0,
221
+ // 初始化标识
222
+ initStore: {
223
+ filter: false,
224
+ import: false,
225
+ export: false,
226
+ custom: false
227
+ },
228
+ // 自定义列相关的信息
229
+ customStore: {
230
+ btnEl: null,
231
+ isAll: false,
232
+ isIndeterminate: false,
233
+ activeBtn: false,
234
+ activeWrapper: false,
235
+ visible: false,
236
+ maxHeight: null,
237
+ popupStyle: {},
238
+ oldSortMaps: {},
239
+ oldFixedMaps: {},
240
+ oldVisibleMaps: {}
241
+ },
242
+ customColumnList: [],
243
+ // 当前选中的筛选列
244
+ filterStore: {
245
+ isAllSelected: false,
246
+ isIndeterminate: false,
247
+ style: null,
248
+ column: null,
249
+ visible: false,
250
+ maxHeight: null
251
+ },
252
+ // 存放列相关的信息
253
+ columnStore: {
254
+ leftList: [],
255
+ centerList: [],
256
+ rightList: [],
257
+ resizeList: [],
258
+ pxList: [],
259
+ pxMinList: [],
260
+ autoMinList: [],
261
+ scaleList: [],
262
+ scaleMinList: [],
263
+ autoList: [],
264
+ remainList: []
265
+ },
266
+ // 存放快捷菜单的信息
267
+ ctxMenuStore: {
268
+ selected: null,
269
+ visible: false,
270
+ showChild: false,
271
+ selectChild: null,
272
+ list: [],
273
+ style: null
274
+ },
275
+ // 存放可编辑相关信息
276
+ editStore: {
277
+ indexs: {
278
+ columns: []
279
+ },
280
+ titles: {
281
+ columns: []
282
+ },
283
+ // 选中源
284
+ selected: {
285
+ row: null,
286
+ column: null
287
+ },
288
+ // 已复制源
289
+ copyed: {
290
+ cut: false,
291
+ rows: [],
292
+ columns: []
293
+ },
294
+ // 激活
295
+ actived: {
296
+ row: null,
297
+ column: null
298
+ },
299
+ // 当前被强制聚焦单元格,只会在鼠标点击后算聚焦
300
+ focused: {
301
+ row: null,
302
+ column: null
303
+ }
304
+ },
305
+ // 存放 tooltip 相关信息
306
+ tooltipStore: {
307
+ row: null,
308
+ column: null,
309
+ content: '',
310
+ visible: false,
311
+ type: null,
312
+ currOpts: {}
313
+ },
314
+ // 存放数据校验相关信息
315
+ validStore: {
316
+ visible: false
317
+ },
318
+ validErrorMaps: {},
319
+ // 导入相关信息
320
+ importStore: {
321
+ inited: false,
322
+ file: null,
323
+ type: '',
324
+ modeList: [],
325
+ typeList: [],
326
+ filename: '',
327
+ visible: false
328
+ },
329
+ importParams: {
330
+ mode: '',
331
+ types: null,
332
+ message: true
333
+ },
334
+ // 导出相关信息
335
+ exportStore: {
336
+ inited: false,
337
+ name: '',
338
+ modeList: [],
339
+ typeList: [],
340
+ columns: [],
341
+ isPrint: false,
342
+ hasFooter: false,
343
+ hasMerge: false,
344
+ hasTree: false,
345
+ hasColgroup: false,
346
+ visible: false
347
+ },
348
+ exportParams: {
349
+ filename: '',
350
+ sheetName: '',
351
+ mode: '',
352
+ type: '',
353
+ isColgroup: false,
354
+ isMerge: false,
355
+ isAllExpand: false,
356
+ useStyle: false,
357
+ original: false,
358
+ message: true,
359
+ isHeader: false,
360
+ isTitle: false,
361
+ isFooter: false
362
+ },
363
+
364
+ visiblwRowsFlag: 1,
365
+
366
+ isRowGroupStatus: false,
367
+ rowGroupList: [],
368
+ aggHandleFields: [],
369
+ aggHandleAggColumns: [],
370
+
371
+ rowGroupExpandedFlag: 1,
372
+ rowExpandedFlag: 1,
373
+ treeExpandedFlag: 1,
374
+ updateCheckboxFlag: 1,
375
+ pendingRowFlag: 1,
376
+ insertRowFlag: 1,
377
+ removeRowFlag: 1,
378
+
379
+ mergeHeadFlag: 1,
380
+ mergeBodyFlag: 1,
381
+ mergeFootFlag: 1,
382
+
383
+ rowHeightStore: {
384
+ large: 52,
385
+ default: 48,
386
+ medium: 44,
387
+ small: 40,
388
+ mini: 36
389
+ },
390
+
391
+ scrollVMLoading: false,
392
+ scrollYHeight: 0,
393
+ scrollYTop: 0,
394
+ isScrollYBig: false,
395
+ scrollXLeft: 0,
396
+ scrollXWidth: 0,
397
+ isScrollXBig: false,
398
+
399
+ lazScrollLoading: false,
400
+
401
+ rowExpandHeightFlag: 1,
402
+ calcCellHeightFlag: 1,
403
+ resizeHeightFlag: 1,
404
+ resizeWidthFlag: 1,
405
+
406
+ isCustomStatus: false,
407
+ isCustomDragStatus: true,
408
+ ctPopupFlag: 1,
409
+
410
+ isCrossDragRow: false,
411
+ dragRow: null,
412
+ isCrossDragCol: false,
413
+ dragCol: null,
414
+ dragTipText: '',
415
+
416
+ isDragResize: false,
417
+ isRowLoading: false,
418
+ isColLoading: false
419
+ }
420
+ }
421
+
422
+ const getAllConvertColumns = (columns: any, parentColumn?: any) => {
423
+ const result: any[] = []
424
+ columns.forEach((column: any) => {
425
+ column.parentId = parentColumn ? parentColumn.id : null
426
+ if (column.visible) {
427
+ if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
428
+ result.push(column)
429
+ result.push(...getAllConvertColumns(column.children, column))
430
+ } else {
431
+ result.push(column)
432
+ }
433
+ }
434
+ })
435
+ return result
436
+ }
437
+
438
+ export const convertHeaderColumnToRows = (originColumns: any): any[][] => {
439
+ let maxLevel = 1
440
+ const traverse = (column: any, parent?: any) => {
441
+ if (parent) {
442
+ column.level = parent.level + 1
443
+ if (maxLevel < column.level) {
444
+ maxLevel = column.level
445
+ }
446
+ }
447
+ if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
448
+ let colSpan = 0
449
+ column.children.forEach((subColumn: any) => {
450
+ if (subColumn.visible) {
451
+ traverse(subColumn, column)
452
+ colSpan += subColumn.colSpan
453
+ }
454
+ })
455
+ column.colSpan = colSpan
456
+ } else {
457
+ column.colSpan = 1
458
+ }
459
+ }
460
+
461
+ originColumns.forEach((column: any) => {
462
+ column.level = 1
463
+ traverse(column)
464
+ })
465
+
466
+ const rows: any[] = []
467
+ for (let i = 0; i < maxLevel; i++) {
468
+ rows.push([])
469
+ }
470
+
471
+ const allColumns = getAllConvertColumns(originColumns)
472
+
473
+ allColumns.forEach((column) => {
474
+ if (column.children && column.children.length && column.children.some((column: any) => column.visible)) {
475
+ column.rowSpan = 1
476
+ } else {
477
+ column.rowSpan = maxLevel - column.level + 1
478
+ }
479
+ rows[column.level - 1].push(column)
480
+ })
481
+
482
+ return rows
483
+ }
484
+
485
+ export function convertHeaderToGridRows (spanColumns: VxeTableDefines.ColumnInfo[][]) {
486
+ const rSize = spanColumns.length
487
+ const cSize = spanColumns[0].reduce((sum, cell) => sum + cell.colSpan, 0)
488
+
489
+ const occupiedRows: boolean[][] = []
490
+ const fullRows: any[][] = []
491
+ for (let rIndex = 0; rIndex < rSize; rIndex++) {
492
+ const oCols: boolean[] = []
493
+ const dCols: string[] = []
494
+ for (let cIndex = 0; cIndex < cSize; cIndex++) {
495
+ oCols.push(false)
496
+ dCols.push('')
497
+ }
498
+ occupiedRows.push(oCols)
499
+ fullRows.push(dCols)
500
+ }
501
+
502
+ for (let rIndex = 0; rIndex < rSize; rIndex++) {
503
+ let currColIndex = 0
504
+ for (const column of spanColumns[rIndex]) {
505
+ const { colSpan, rowSpan } = column
506
+ let startColIndex = -1
507
+ for (let ccIndex = currColIndex; ccIndex <= cSize - colSpan; ccIndex++) {
508
+ let oFlag = true
509
+ for (let csIndex = 0; csIndex < colSpan; csIndex++) {
510
+ if (occupiedRows[rIndex][ccIndex + csIndex]) {
511
+ oFlag = false
512
+ break
513
+ }
514
+ }
515
+ if (oFlag) {
516
+ startColIndex = ccIndex
517
+ break
518
+ }
519
+ }
520
+ if (startColIndex === -1) {
521
+ for (let j = 0; j <= cSize - colSpan; j++) {
522
+ let oFlag = true
523
+ for (let k = 0; k < colSpan; k++) {
524
+ if (occupiedRows[rIndex][j + k]) {
525
+ oFlag = false
526
+ break
527
+ }
528
+ }
529
+ if (oFlag) {
530
+ startColIndex = j
531
+ break
532
+ }
533
+ }
534
+ if (startColIndex === -1) {
535
+ // error
536
+ break
537
+ }
538
+ }
539
+
540
+ for (let srIndex = rIndex; srIndex < rIndex + rowSpan; srIndex++) {
541
+ for (let scIndex = startColIndex; scIndex < startColIndex + colSpan; scIndex++) {
542
+ occupiedRows[srIndex][scIndex] = true
543
+ fullRows[srIndex][scIndex] = column
544
+ }
545
+ }
546
+ currColIndex = startColIndex + colSpan
547
+ }
548
+ }
549
+ return fullRows
550
+ }
551
+
552
+ export function restoreScrollLocation ($xeTable: VxeTableConstructor, scrollLeft: number, scrollTop: number) {
553
+ const internalData = $xeTable.internalData
554
+
555
+ if (scrollLeft || scrollTop) {
556
+ internalData.intoRunScroll = false
557
+ internalData.inVirtualScroll = false
558
+ internalData.inWheelScroll = false
559
+ internalData.inHeaderScroll = false
560
+ internalData.inBodyScroll = false
561
+ internalData.inFooterScroll = false
562
+ internalData.scrollRenderType = ''
563
+ // 还原滚动状态
564
+ return $xeTable.scrollTo(scrollLeft, scrollTop)
565
+ }
566
+ return $xeTable.clearScroll()
567
+ }
568
+
569
+ export function getRowUniqueId () {
570
+ return XEUtils.uniqueId('row_')
571
+ }
572
+
573
+ /**
574
+ * 生成行的唯一主键
575
+ */
576
+ export function createRowId (rowOpts: VxeTablePropTypes.RowConfig, row: any, keyField: string) {
577
+ const { createKeyMethod } = rowOpts
578
+ if (createKeyMethod) {
579
+ return createKeyMethod({ row, keyField })
580
+ }
581
+ return getRowUniqueId()
582
+ }
583
+
584
+ export function hasDeepKey (rowKey: string) {
585
+ return rowKey.indexOf('.') > -1
586
+ }
587
+
588
+ // 行主键 key
589
+ export function getRowkey ($xeTable: VxeTableConstructor) {
590
+ const { currKeyField } = $xeTable.internalData
591
+ return currKeyField
592
+ }
593
+
594
+ // 行主键 value
595
+ export function getRowid ($xeTable: VxeTableConstructor, row: any) {
596
+ const internalData = $xeTable.internalData
597
+ const { isCurrDeepKey, currKeyField } = internalData
598
+ return row ? encodeRowid((isCurrDeepKey ? getDeepRowIdByKey : getFastRowIdByKey)(row, currKeyField)) : ''
599
+ }
600
+
601
+ export function createHandleUpdateRowId ($xeTable: VxeTableConstructor) {
602
+ const internalData = $xeTable.internalData
603
+ const { isCurrDeepKey, currKeyField } = internalData
604
+ const { computeRowOpts } = $xeTable.getComputeMaps()
605
+ const rowOpts = computeRowOpts.value
606
+ const updateRId = isCurrDeepKey ? updateDeepRowKey : updateFastRowKey
607
+ return {
608
+ rowKey: currKeyField,
609
+ handleUpdateRowId (row: any) {
610
+ return row ? updateRId(rowOpts, row, currKeyField) : ''
611
+ }
612
+ }
613
+ }
614
+
615
+ export function createHandleGetRowId ($xeTable: VxeTableConstructor) {
616
+ const internalData = $xeTable.internalData
617
+ const { isCurrDeepKey, currKeyField } = internalData
618
+ const getRId = isCurrDeepKey ? getDeepRowIdByKey : getFastRowIdByKey
619
+ return {
620
+ rowKey: currKeyField,
621
+ handleGetRowId (row: any) {
622
+ return row ? encodeRowid(getRId(row, currKeyField)) : ''
623
+ }
624
+ }
625
+ }
626
+
627
+ // 编码行主键
628
+ export function encodeRowid (rowVal: string) {
629
+ return XEUtils.eqNull(rowVal) ? '' : encodeURIComponent(rowVal)
630
+ }
631
+
632
+ function getDeepRowIdByKey (row: any, rowKey: string) {
633
+ return XEUtils.get(row, rowKey)
634
+ }
635
+
636
+ function updateDeepRowKey (rowOpts: VxeTablePropTypes.RowConfig, row: any, rowKey: string) {
637
+ let rowid = encodeRowid(getDeepRowIdByKey(row, rowKey))
638
+ if (eqEmptyValue(rowid)) {
639
+ const newRowid = createRowId(rowOpts, row, rowKey)
640
+ rowid = '' + newRowid
641
+ XEUtils.set(row, rowKey, rowid)
642
+ }
643
+ return rowid
644
+ }
645
+
646
+ function getFastRowIdByKey (row: any, rowKey: string) {
647
+ return row[rowKey]
648
+ }
649
+
650
+ function updateFastRowKey (rowOpts: VxeTablePropTypes.RowConfig, row: any, rowKey: string) {
651
+ let rowid = encodeRowid(getFastRowIdByKey(row, rowKey))
652
+ if (eqEmptyValue(rowid)) {
653
+ const newRowid = createRowId(rowOpts, row, rowKey)
654
+ rowid = '' + newRowid
655
+ row[rowKey] = newRowid
656
+ }
657
+ return rowid
658
+ }
659
+
660
+ export interface XEColumnInstance {
661
+ columnConfig: ColumnInfo;
662
+ }
663
+
664
+ export function handleFieldOrColumn ($xeTable: VxeTableConstructor, fieldOrColumn: string | VxeTableDefines.ColumnInfo | null) {
665
+ if (fieldOrColumn) {
666
+ return XEUtils.isString(fieldOrColumn) || XEUtils.isNumber(fieldOrColumn) ? $xeTable.getColumnByField(`${fieldOrColumn}`) : fieldOrColumn
667
+ }
668
+ return null
669
+ }
670
+
671
+ export function handleRowidOrRow ($xeTable: VxeTableConstructor, rowidOrRow: any) {
672
+ if (rowidOrRow) {
673
+ const rowid = XEUtils.isString(rowidOrRow) || XEUtils.isNumber(rowidOrRow) ? rowidOrRow : getRowid($xeTable, rowidOrRow)
674
+ return $xeTable.getRowById(rowid)
675
+ }
676
+ return null
677
+ }
678
+
679
+ export function getCellRestHeight (rowRest: VxeTableDefines.RowCacheItem, cellOpts: VxeTablePropTypes.CellConfig, rowOpts: VxeTablePropTypes.RowConfig, defaultRowHeight: number) {
680
+ return rowRest.resizeHeight || cellOpts.height || rowOpts.height || rowRest.height || defaultRowHeight
681
+ }
682
+
683
+ function getPaddingLeftRightSize (elem: HTMLElement | null) {
684
+ if (elem) {
685
+ const computedStyle = getComputedStyle(elem)
686
+ const paddingLeft = XEUtils.toNumber(computedStyle.paddingLeft)
687
+ const paddingRight = XEUtils.toNumber(computedStyle.paddingRight)
688
+ return paddingLeft + paddingRight
689
+ }
690
+ return 0
691
+ }
692
+
693
+ function getElementMarginAndWidth (elem: HTMLElement | null) {
694
+ if (elem) {
695
+ const computedStyle = getComputedStyle(elem)
696
+ const marginLeft = XEUtils.toNumber(computedStyle.marginLeft)
697
+ const marginRight = XEUtils.toNumber(computedStyle.marginRight)
698
+ return elem.offsetWidth + marginLeft + marginRight
699
+ }
700
+ return 0
701
+ }
702
+
703
+ export function toFilters (filters: any, colid?: string) {
704
+ if (filters) {
705
+ if (XEUtils.isArray(filters)) {
706
+ return filters.map(({ label, value, data, resetValue, checked }) => {
707
+ return { label, value, data, resetValue, checked: !!checked, _checked: !!checked, _colId: colid }
708
+ })
709
+ }
710
+ return []
711
+ }
712
+ return filters
713
+ }
714
+
715
+ export function toTreePathSeq (path: any[]) {
716
+ return path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('')
717
+ }
718
+
719
+ export function getCellValue (row: any, column: VxeTableDefines.ColumnInfo | null) {
720
+ if (column) {
721
+ return XEUtils.get(row, column.field)
722
+ }
723
+ return null
724
+ }
725
+
726
+ export function setCellValue (row: any, column: VxeTableDefines.ColumnInfo | null, value: any) {
727
+ if (column) {
728
+ XEUtils.set(row, column.field, value)
729
+ }
730
+ }
731
+
732
+ export function getRefElem (refEl: any) {
733
+ if (refEl) {
734
+ const rest = refEl.value
735
+ if (rest) {
736
+ return (rest.$el || rest) as HTMLElement
737
+ }
738
+ }
739
+ return null
740
+ }
741
+
742
+ export function getCalcHeight (height: number | 'unset' | undefined | null) {
743
+ if (height === 'unset') {
744
+ return 0
745
+ }
746
+ return height || 0
747
+ }
748
+
749
+ /**
750
+ * 列宽拖动最大宽度
751
+ * @param params
752
+ * @returns
753
+ */
754
+ export function getColReMaxWidth (params: {
755
+ $table: VxeTableConstructor & VxeTablePrivateMethods;
756
+ column: VxeTableDefines.ColumnInfo;
757
+ columnIndex: number;
758
+ $columnIndex: number;
759
+ $rowIndex: number;
760
+ cell: HTMLTableCellElement;
761
+ }) {
762
+ const { $table } = params
763
+ const { computeResizableOpts } = $table.getComputeMaps()
764
+ const resizableOpts = computeResizableOpts.value
765
+ const { maxWidth: reMaxWidth } = resizableOpts
766
+ // 如果自定义调整宽度逻辑
767
+ if (reMaxWidth) {
768
+ const customMaxWidth = XEUtils.isFunction(reMaxWidth) ? reMaxWidth(params) : reMaxWidth
769
+ if (customMaxWidth !== 'auto') {
770
+ return Math.max(1, XEUtils.toNumber(customMaxWidth))
771
+ }
772
+ }
773
+ return -1
774
+ }
775
+
776
+ /**
777
+ * 列宽拖动最小宽度
778
+ * @param params
779
+ * @returns
780
+ */
781
+ export function getColReMinWidth (params: {
782
+ $table: VxeTableConstructor & VxeTablePrivateMethods;
783
+ column: VxeTableDefines.ColumnInfo;
784
+ columnIndex: number;
785
+ $columnIndex: number;
786
+ $rowIndex: number;
787
+ cell: HTMLTableCellElement;
788
+ }) {
789
+ const { $table, column, cell } = params
790
+ const tableProps = $table.props
791
+ const internalData = $table.internalData
792
+ const { computeResizableOpts } = $table.getComputeMaps()
793
+ const resizableOpts = computeResizableOpts.value
794
+ const { minWidth: reMinWidth } = resizableOpts
795
+ // 如果自定义调整宽度逻辑
796
+ if (reMinWidth) {
797
+ const customMinWidth = XEUtils.isFunction(reMinWidth) ? reMinWidth(params) : reMinWidth
798
+ if (customMinWidth !== 'auto') {
799
+ return Math.max(1, XEUtils.toNumber(customMinWidth))
800
+ }
801
+ }
802
+ const { elemStore } = internalData
803
+ const { showHeaderOverflow: allColumnHeaderOverflow } = tableProps
804
+ const { showHeaderOverflow, minWidth: colMinWidth } = column
805
+ const headOverflow = XEUtils.isUndefined(showHeaderOverflow) || XEUtils.isNull(showHeaderOverflow) ? allColumnHeaderOverflow : showHeaderOverflow
806
+ const showEllipsis = headOverflow === 'ellipsis'
807
+ const showTitle = headOverflow === 'title'
808
+ const showTooltip = headOverflow === true || headOverflow === 'tooltip'
809
+ const hasEllipsis = showTitle || showTooltip || showEllipsis
810
+ const minTitleWidth = XEUtils.floor((XEUtils.toNumber(getComputedStyle(cell).fontSize) || 14) * 1.8)
811
+ const paddingLeftRight = getPaddingLeftRightSize(cell) + getPaddingLeftRightSize(queryElement(cell, '.vxe-cell'))
812
+ let mWidth = minTitleWidth + paddingLeftRight
813
+ // 默认最小宽处理
814
+ if (hasEllipsis) {
815
+ const dragIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--drag-handle'))
816
+ const checkboxIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--checkbox'))
817
+ const requiredIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--required-icon'))
818
+ const editIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--edit-icon'))
819
+ const prefixIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell-title-prefix-icon'))
820
+ const suffixIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell-title-suffix-icon'))
821
+ const sortIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--sort'))
822
+ const filterIconWidth = getElementMarginAndWidth(queryElement(cell, '.vxe-cell--filter'))
823
+ mWidth += dragIconWidth + checkboxIconWidth + requiredIconWidth + editIconWidth + prefixIconWidth + suffixIconWidth + filterIconWidth + sortIconWidth
824
+ }
825
+ // 如果设置最小宽
826
+ if (colMinWidth) {
827
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
828
+ if (bodyScrollElem) {
829
+ if (isScale(colMinWidth)) {
830
+ const bodyWidth = bodyScrollElem.clientWidth - 1
831
+ const meanWidth = bodyWidth / 100
832
+ return Math.max(mWidth, Math.floor(XEUtils.toInteger(colMinWidth) * meanWidth))
833
+ } else if (isPx(colMinWidth)) {
834
+ return Math.max(mWidth, XEUtils.toInteger(colMinWidth))
835
+ }
836
+ }
837
+ }
838
+ return mWidth
839
+ }
840
+
841
+ export function isColumnInfo (column: any): column is ColumnInfo {
842
+ return column && (column.constructor === ColumnInfo || column instanceof ColumnInfo)
843
+ }
844
+
845
+ // 获取所有的列,排除分组
846
+ export function getColumnList (columns: VxeTableDefines.ColumnInfo[]) {
847
+ const result: VxeTableDefines.ColumnInfo[] = []
848
+ columns.forEach((column) => {
849
+ result.push(...(column.children && column.children.length ? getColumnList(column.children) : [column]))
850
+ })
851
+ return result
852
+ }
853
+
854
+ export function createColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, options: VxeTableDefines.ColumnOptions | VxeTableDefines.ColumnInfo, renderOptions: any): any {
855
+ return isColumnInfo(options) ? options : reactive(new ColumnInfo($xeTable, options, renderOptions))
856
+ }
857
+
858
+ export function watchColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, props: any, column: ColumnInfo) {
859
+ Object.keys(props).forEach(name => {
860
+ watch(() => props[name], (value: any) => {
861
+ column.update(name, value)
862
+ if ($xeTable) {
863
+ if (name === 'filters') {
864
+ $xeTable.setFilter(column as any, value)
865
+ $xeTable.handleUpdateDataQueue()
866
+ } else if (['visible', 'fixed', 'width', 'minWidth', 'maxWidth'].includes(name)) {
867
+ $xeTable.handleRefreshColumnQueue()
868
+ }
869
+ }
870
+ })
871
+ })
872
+ }
873
+
874
+ export function assembleColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, elem: HTMLElement, column: ColumnInfo, colgroup: XEColumnInstance | null) {
875
+ const { reactData } = $xeTable
876
+ const { staticColumns } = reactData
877
+ const parentElem = elem.parentNode
878
+ const parentColumn = colgroup ? colgroup.columnConfig : null
879
+ const parentCols = parentColumn ? parentColumn.children : staticColumns
880
+ if (parentElem && parentCols) {
881
+ column.defaultParentId = parentColumn ? parentColumn.id : null
882
+ parentCols.splice(XEUtils.arrayIndexOf(parentElem.children, elem), 0, column)
883
+ reactData.staticColumns = staticColumns.slice(0)
884
+ }
885
+ }
886
+
887
+ export function destroyColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: ColumnInfo) {
888
+ const { reactData } = $xeTable
889
+ const { staticColumns } = reactData
890
+ const matchObj = XEUtils.findTree(staticColumns, item => item.id === column.id, { children: 'children' })
891
+ if (matchObj) {
892
+ matchObj.items.splice(matchObj.index, 1)
893
+ }
894
+ reactData.staticColumns = staticColumns.slice(0)
895
+ }
896
+
897
+ export function getRootColumn ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: ColumnInfo) {
898
+ const { internalData } = $xeTable
899
+
900
+ const { fullColumnIdData } = internalData
901
+ if (!column) {
902
+ return null
903
+ }
904
+ let parentColId = column.parentId
905
+ while (fullColumnIdData[parentColId]) {
906
+ const column = fullColumnIdData[parentColId].column
907
+ parentColId = column.parentId
908
+ if (!parentColId) {
909
+ return column
910
+ }
911
+ }
912
+ return column
913
+ }
914
+
915
+ export function getFirstChildColumn (column: VxeTableDefines.ColumnInfo): VxeTableDefines.ColumnInfo {
916
+ const { children } = column
917
+ if (children && children.length) {
918
+ return getFirstChildColumn(XEUtils.first(children))
919
+ }
920
+ return column
921
+ }
922
+
923
+ export function getLastChildColumn (column: VxeTableDefines.ColumnInfo): VxeTableDefines.ColumnInfo {
924
+ const { children } = column
925
+ if (children && children.length) {
926
+ return getFirstChildColumn(XEUtils.last(children))
927
+ }
928
+ return column
929
+ }
930
+
931
+ export function clearTableDefaultStatus ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
932
+ const { props, internalData } = $xeTable
933
+
934
+ internalData.initStatus = false
935
+ const actionList = [
936
+ $xeTable.clearSort(),
937
+ $xeTable.clearCurrentRow(),
938
+ $xeTable.clearCurrentColumn(),
939
+ $xeTable.clearRadioRow(),
940
+ $xeTable.clearRadioReserve(),
941
+ $xeTable.clearCheckboxRow(),
942
+ $xeTable.clearCheckboxReserve(),
943
+ $xeTable.clearRowExpand(),
944
+ $xeTable.clearTreeExpand(),
945
+ $xeTable.clearTreeExpandReserve(),
946
+ $xeTable.clearPendingRow()
947
+ ]
948
+ if ($xeTable.clearFilter) {
949
+ actionList.push(
950
+ $xeTable.clearFilter()
951
+ )
952
+ }
953
+ if ($xeTable.clearSelected && (props.keyboardConfig || props.mouseConfig)) {
954
+ actionList.push(
955
+ $xeTable.clearSelected()
956
+ )
957
+ }
958
+ if ($xeTable.clearCellAreas && props.mouseConfig) {
959
+ actionList.push(
960
+ $xeTable.clearCellAreas(),
961
+ $xeTable.clearCopyCellArea()
962
+ )
963
+ }
964
+ return Promise.all(actionList).then(() => {
965
+ return $xeTable.clearScroll()
966
+ })
967
+ }
968
+
969
+ export function clearTableAllStatus ($xeTable: VxeTableConstructor & VxeTablePrivateMethods) {
970
+ if ($xeTable.clearFilter) {
971
+ $xeTable.clearFilter()
972
+ }
973
+ return clearTableDefaultStatus($xeTable)
974
+ }
975
+
976
+ export function rowToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, row: any) {
977
+ const reactData = $xeTable.reactData
978
+ const internalData = $xeTable.internalData
979
+
980
+ const { computeLeftFixedWidth, computeRightFixedWidth, computeRowOpts, computeCellOpts, computeDefaultRowHeight } = $xeTable.getComputeMaps()
981
+ const { scrollYLoad, scrollYTop, isAllOverflow } = reactData
982
+ const { elemStore, afterFullData, fullAllDataRowIdData, isResizeCellHeight } = internalData
983
+ const rowOpts = computeRowOpts.value
984
+ const cellOpts = computeCellOpts.value
985
+ const defaultRowHeight = computeDefaultRowHeight.value
986
+ const leftFixedWidth = computeLeftFixedWidth.value
987
+ const rightFixedWidth = computeRightFixedWidth.value
988
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
989
+ const rowid = getRowid($xeTable, row)
990
+ if (bodyScrollElem) {
991
+ const bodyHeight = bodyScrollElem.clientHeight
992
+ const bodyScrollTop = bodyScrollElem.scrollTop
993
+ const trElem: HTMLTableRowElement | null = bodyScrollElem.querySelector(`[rowid="${rowid}"]`)
994
+ if (trElem) {
995
+ const trOffsetTop = trElem.offsetTop + (scrollYLoad ? scrollYTop : 0)
996
+ const trHeight = trElem.clientHeight
997
+ // 检测行是否在可视区中
998
+ if (trOffsetTop < bodyScrollTop || trOffsetTop > bodyScrollTop + bodyHeight) {
999
+ return $xeTable.scrollTo(null, trOffsetTop)
1000
+ } else if (trOffsetTop + trHeight >= bodyHeight + bodyScrollTop) {
1001
+ return $xeTable.scrollTo(null, bodyScrollTop + trHeight)
1002
+ }
1003
+ } else {
1004
+ // 如果是虚拟渲染滚动
1005
+ if (scrollYLoad) {
1006
+ const isCustomCellHeight = isResizeCellHeight || cellOpts.height || rowOpts.height
1007
+ if (!isCustomCellHeight && isAllOverflow) {
1008
+ return $xeTable.scrollTo(null, ($xeTable.findRowIndexOf(afterFullData, row) - 1) * defaultRowHeight)
1009
+ }
1010
+ const rowRest = fullAllDataRowIdData[rowid] || {}
1011
+ const rHeight = rowRest.resizeHeight || cellOpts.height || rowOpts.height || rowRest.height || defaultRowHeight
1012
+ const scrollTop = rowRest.oTop
1013
+ if (scrollTop < bodyScrollTop) {
1014
+ return $xeTable.scrollTo(null, scrollTop - leftFixedWidth - 1)
1015
+ }
1016
+ return $xeTable.scrollTo(null, (scrollTop + rHeight) - (bodyHeight - rightFixedWidth - 1))
1017
+ }
1018
+ }
1019
+ }
1020
+ return Promise.resolve()
1021
+ }
1022
+
1023
+ export function colToVisible ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, isForce: boolean, column: VxeTableDefines.ColumnInfo, row?: any) {
1024
+ const reactData = $xeTable.reactData
1025
+ const internalData = $xeTable.internalData
1026
+
1027
+ const { computeLeftFixedWidth, computeRightFixedWidth } = $xeTable.getComputeMaps()
1028
+ const { scrollXLoad, scrollXLeft } = reactData
1029
+ const { elemStore, visibleColumn } = internalData
1030
+ const leftFixedWidth = computeLeftFixedWidth.value
1031
+ const rightFixedWidth = computeRightFixedWidth.value
1032
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
1033
+ if (column.fixed) {
1034
+ return Promise.resolve()
1035
+ }
1036
+ if (bodyScrollElem) {
1037
+ const bodyWidth = bodyScrollElem.clientWidth
1038
+ const bodyScrollLeft = bodyScrollElem.scrollLeft
1039
+ let tdElem: HTMLTableCellElement | null = null
1040
+ if (row) {
1041
+ const rowid = getRowid($xeTable, row)
1042
+ tdElem = bodyScrollElem.querySelector(`[rowid="${rowid}"] .${column.id}`)
1043
+ }
1044
+ if (!tdElem) {
1045
+ tdElem = bodyScrollElem.querySelector(`.${column.id}`)
1046
+ }
1047
+ if (tdElem) {
1048
+ const tdOffsetLeft = tdElem.offsetLeft + (scrollXLoad ? scrollXLeft : 0)
1049
+ const cellWidth = tdElem.clientWidth
1050
+ // 检测是否在可视区中
1051
+ if (isForce || (
1052
+ !(tdOffsetLeft <= (bodyScrollLeft + leftFixedWidth) && (tdOffsetLeft + cellWidth) > (bodyScrollLeft + leftFixedWidth)) &&
1053
+ !(tdOffsetLeft >= (bodyScrollLeft + leftFixedWidth) && tdOffsetLeft < (bodyScrollLeft + bodyWidth - rightFixedWidth))
1054
+ )) {
1055
+ if (tdOffsetLeft < (bodyScrollLeft + leftFixedWidth)) {
1056
+ return $xeTable.scrollTo(tdOffsetLeft - leftFixedWidth - 1)
1057
+ } else if ((tdOffsetLeft + cellWidth - bodyScrollLeft) > (bodyWidth - rightFixedWidth)) {
1058
+ return $xeTable.scrollTo((tdOffsetLeft + cellWidth) - (bodyWidth - rightFixedWidth - 1))
1059
+ }
1060
+ }
1061
+ } else {
1062
+ if (scrollXLoad) {
1063
+ let tdOffsetLeft = 0
1064
+ const cellWidth = column.renderWidth
1065
+ for (let i = 0; i < visibleColumn.length; i++) {
1066
+ const currCol = visibleColumn[i]
1067
+ if (currCol === column || currCol.id === column.id) {
1068
+ break
1069
+ }
1070
+ tdOffsetLeft += currCol.renderWidth
1071
+ }
1072
+ // 检测是否在可视区中
1073
+ if (isForce || (
1074
+ !(tdOffsetLeft <= (bodyScrollLeft + leftFixedWidth) && (tdOffsetLeft + cellWidth) > (bodyScrollLeft + leftFixedWidth)) &&
1075
+ !(tdOffsetLeft >= (bodyScrollLeft + leftFixedWidth) && tdOffsetLeft < (bodyScrollLeft + bodyWidth - rightFixedWidth))
1076
+ )) {
1077
+ if (tdOffsetLeft < bodyScrollLeft) {
1078
+ return $xeTable.scrollTo(tdOffsetLeft - leftFixedWidth - 1)
1079
+ }
1080
+ return $xeTable.scrollTo((tdOffsetLeft + cellWidth) - (bodyWidth - rightFixedWidth - 1))
1081
+ }
1082
+ }
1083
+ }
1084
+ }
1085
+ return Promise.resolve()
1086
+ }