vxe-table 4.23.7 → 4.23.9

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 (148) hide show
  1. package/dist/all.esm.js +5859 -4018
  2. package/es/colgroup/index.js +1 -1
  3. package/es/column/index.js +1 -1
  4. package/es/components.d.ts +3 -0
  5. package/es/components.js +4 -8
  6. package/es/grid/index.js +1 -1
  7. package/es/grid/src/emits.js +1 -15
  8. package/es/grid/src/grid.js +398 -121
  9. package/es/grid/src/props.js +1 -1
  10. package/es/index.esm.js +6 -0
  11. package/es/index.js +6 -0
  12. package/es/table/index.js +1 -1
  13. package/es/table/module/custom/hook.js +50 -43
  14. package/es/table/module/custom/panel.js +778 -528
  15. package/es/table/module/edit/hook.js +141 -63
  16. package/es/table/module/export/export-panel.js +400 -317
  17. package/es/table/module/export/hook.js +396 -338
  18. package/es/table/module/export/import-panel.js +153 -124
  19. package/es/table/module/filter/hook.js +17 -3
  20. package/es/table/module/filter/panel.js +147 -85
  21. package/es/table/module/keyboard/hook.js +9 -5
  22. package/es/table/module/menu/hook.js +1 -1
  23. package/es/table/module/menu/panel.js +198 -127
  24. package/es/table/module/validator/hook.js +1 -1
  25. package/es/table/render/index.js +152 -99
  26. package/es/table/src/body.js +356 -234
  27. package/es/table/src/cell.js +427 -270
  28. package/es/table/src/columnInfo.js +2 -1
  29. package/es/table/src/footer.js +145 -100
  30. package/es/table/src/group.js +7 -3
  31. package/es/table/src/header.js +230 -173
  32. package/es/table/src/props.js +1 -1
  33. package/es/table/src/table.js +1504 -1031
  34. package/es/table/src/util.js +15 -19
  35. package/es/toolbar/index.js +1 -1
  36. package/es/toolbar/src/toolbar.js +133 -76
  37. package/es/ui/index.d.ts +0 -1
  38. package/es/ui/index.js +1 -2
  39. package/es/ui/src/dom.js +9 -6
  40. package/es/ui/src/log.js +1 -1
  41. package/es/ui/src/utils.d.ts +1 -1
  42. package/es/v-x-e-table/index.d.ts +0 -1
  43. package/es/v-x-e-table/index.js +0 -1
  44. package/lib/colgroup/index.js +5 -5
  45. package/lib/column/index.js +5 -5
  46. package/lib/components.js +8 -12
  47. package/lib/grid/index.js +4 -4
  48. package/lib/grid/src/emits.js +1 -15
  49. package/lib/grid/src/grid.js +419 -142
  50. package/lib/grid/src/props.js +2 -2
  51. package/lib/index.common.js +6 -0
  52. package/lib/index.js +6 -0
  53. package/lib/index.umd.js +5825 -3945
  54. package/lib/index.umd.min.js +3 -3
  55. package/lib/table/index.js +5 -5
  56. package/lib/table/module/custom/hook.js +51 -44
  57. package/lib/table/module/custom/panel.js +790 -540
  58. package/lib/table/module/edit/hook.js +142 -64
  59. package/lib/table/module/export/export-panel.js +406 -323
  60. package/lib/table/module/export/hook.js +419 -361
  61. package/lib/table/module/export/import-panel.js +157 -128
  62. package/lib/table/module/filter/hook.js +18 -4
  63. package/lib/table/module/filter/panel.js +149 -87
  64. package/lib/table/module/keyboard/hook.js +10 -6
  65. package/lib/table/module/menu/hook.js +2 -2
  66. package/lib/table/module/menu/panel.js +199 -128
  67. package/lib/table/module/validator/hook.js +2 -2
  68. package/lib/table/render/index.js +153 -100
  69. package/lib/table/src/body.js +357 -235
  70. package/lib/table/src/cell.js +428 -271
  71. package/lib/table/src/columnInfo.js +3 -2
  72. package/lib/table/src/footer.js +146 -101
  73. package/lib/table/src/group.js +7 -3
  74. package/lib/table/src/header.js +231 -174
  75. package/lib/table/src/props.js +2 -2
  76. package/lib/table/src/table.js +1487 -1045
  77. package/lib/table/src/util.js +15 -19
  78. package/lib/toolbar/index.js +4 -4
  79. package/lib/toolbar/src/toolbar.js +135 -78
  80. package/lib/ui/index.js +1 -3
  81. package/lib/ui/src/dom.js +9 -6
  82. package/lib/ui/src/log.js +1 -1
  83. package/lib/v-x-e-table/index.js +0 -2
  84. package/package.json +8 -3
  85. package/packages/colgroup/index.ts +22 -22
  86. package/packages/column/index.ts +22 -22
  87. package/packages/components.ts +41 -43
  88. package/packages/grid/index.ts +18 -18
  89. package/packages/grid/src/emits.ts +5 -19
  90. package/packages/grid/src/grid.ts +2229 -1925
  91. package/packages/grid/src/props.ts +22 -23
  92. package/packages/index.ts +11 -4
  93. package/packages/locale/lang/fr-FR.ts +15 -15
  94. package/packages/locale/lang/it-IT.ts +4 -4
  95. package/packages/locale/lang/uk-UA.ts +1 -1
  96. package/packages/locale/lang/uz-UZ.ts +13 -13
  97. package/packages/locale/lang/zh-CN.ts +907 -907
  98. package/packages/table/index.ts +26 -26
  99. package/packages/table/module/custom/hook.ts +510 -503
  100. package/packages/table/module/custom/panel.ts +2002 -1743
  101. package/packages/table/module/edit/hook.ts +1224 -1131
  102. package/packages/table/module/export/export-panel.ts +697 -611
  103. package/packages/table/module/export/hook.ts +2160 -2059
  104. package/packages/table/module/export/import-panel.ts +319 -279
  105. package/packages/table/module/export/util.ts +25 -24
  106. package/packages/table/module/filter/hook.ts +519 -501
  107. package/packages/table/module/filter/panel.ts +368 -304
  108. package/packages/table/module/keyboard/hook.ts +498 -494
  109. package/packages/table/module/menu/hook.ts +330 -330
  110. package/packages/table/module/menu/panel.ts +272 -201
  111. package/packages/table/module/validator/hook.ts +653 -635
  112. package/packages/table/render/index.ts +1819 -1744
  113. package/packages/table/src/body.ts +1078 -955
  114. package/packages/table/src/cell.ts +1524 -1359
  115. package/packages/table/src/column.ts +192 -192
  116. package/packages/table/src/columnInfo.ts +232 -232
  117. package/packages/table/src/emits.ts +134 -134
  118. package/packages/table/src/footer.ts +425 -380
  119. package/packages/table/src/group.ts +67 -63
  120. package/packages/table/src/header.ts +642 -581
  121. package/packages/table/src/props.ts +336 -336
  122. package/packages/table/src/store.ts +14 -14
  123. package/packages/table/src/table.ts +16011 -15454
  124. package/packages/table/src/use/cell-view.ts +41 -44
  125. package/packages/table/src/use/index.ts +1 -1
  126. package/packages/table/src/util.ts +1206 -1216
  127. package/packages/toolbar/index.ts +18 -18
  128. package/packages/toolbar/src/toolbar.ts +768 -706
  129. package/packages/ui/index.ts +519 -521
  130. package/packages/ui/src/anime.ts +51 -52
  131. package/packages/ui/src/comp.ts +3 -3
  132. package/packages/ui/src/dom.ts +466 -463
  133. package/packages/ui/src/log.ts +19 -19
  134. package/packages/ui/src/utils.ts +66 -66
  135. package/packages/ui/src/vn.ts +55 -55
  136. package/packages/v-x-e-table/index.d.ts +3 -4
  137. package/packages/v-x-e-table/index.ts +3 -4
  138. package/types/all.d.ts +76 -76
  139. package/types/index.d.ts +4 -4
  140. /package/dist/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  141. /package/dist/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  142. /package/dist/{iconfont.1792979665397.woff2 → iconfont.1793009263429.woff2} +0 -0
  143. /package/es/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  144. /package/es/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  145. /package/es/{iconfont.1792979665397.woff2 → iconfont.1793009263429.woff2} +0 -0
  146. /package/lib/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  147. /package/lib/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  148. /package/lib/{iconfont.1792979665397.woff2 → iconfont.1793009263429.woff2} +0 -0
@@ -1,1131 +1,1224 @@
1
- import { reactive, nextTick } from 'vue'
2
- import XEUtils from 'xe-utils'
3
- import { VxeUI } from '../../../ui'
4
- import { hasEnableConf, isEnableConf } from '../../../ui/src/utils'
5
- import { getCellValue, setCellValue, getRowid } from '../../src/util'
6
- import { removeClass, addClass } from '../../../ui/src/dom'
7
- import { createComponentLog } from '../../../ui/src/log'
8
-
9
- import type { VxeTableConstructor, TableEditMethods, TableEditPrivateMethods, VxeTableDefines, VxeGlobalRendererHandles } from '../../../../types'
10
-
11
- const { warnLog, errLog } = createComponentLog('table')
12
-
13
- const { getConfig, renderer, hooks, getI18n } = VxeUI
14
-
15
- const tableEditMethodKeys: (keyof TableEditMethods)[] = ['insert', 'insertAt', 'insertNextAt', 'insertChild', 'insertChildAt', 'insertChildNextAt', 'remove', 'removeCheckboxRow', 'removeRadioRow', 'removeCurrentRow', 'getRecordset', 'getInsertRecords', 'getRemoveRecords', 'getUpdateRecords', 'getEditRecord', 'getActiveRecord', 'getEditCell', 'getSelectedCell', 'clearEdit', 'clearActived', 'clearSelected', 'isEditByRow', 'isActiveByRow', 'setEditRow', 'setActiveRow', 'setEditCell', 'setActiveCell', 'setSelectCell']
16
-
17
- hooks.add('tableEditModule', {
18
- setupTable ($xeTable) {
19
- const { props, reactData, internalData } = $xeTable
20
- const { refElem } = $xeTable.getRefMaps()
21
- const { computeMouseOpts, computeEditOpts, computeCheckboxOpts, computeTreeOpts, computeValidOpts, computeRendererOpts } = $xeTable.getComputeMaps()
22
-
23
- const browseObj = XEUtils.browse()
24
-
25
- let editMethods = {} as TableEditMethods
26
- let editPrivateMethods = {} as TableEditPrivateMethods
27
-
28
- const getEditColumnModel = (row: any, column: VxeTableDefines.ColumnInfo) => {
29
- const { model, editRender } = column
30
- if (editRender) {
31
- model.value = getCellValue(row, column)
32
- model.update = false
33
- }
34
- }
35
-
36
- const setEditColumnModel = (row: any, column: VxeTableDefines.ColumnInfo) => {
37
- const { model, editRender } = column
38
- if (editRender && model.update) {
39
- setCellValue(row, column, model.value)
40
- model.update = false
41
- model.value = null
42
- }
43
- }
44
-
45
- const removeCellSelectedClass = () => {
46
- const el = refElem.value
47
- if (el) {
48
- const cell = el.querySelector('.col--selected')
49
- if (cell) {
50
- removeClass(cell, 'col--selected')
51
- }
52
- }
53
- }
54
-
55
- const syncActivedCell = () => {
56
- const { editStore, tableColumn } = reactData
57
- const editOpts = computeEditOpts.value
58
- const { actived } = editStore
59
- const { row, column } = actived
60
- if (row && column) {
61
- if (editOpts.mode === 'row') {
62
- tableColumn.forEach((column) => setEditColumnModel(row, column))
63
- } else {
64
- setEditColumnModel(row, column)
65
- }
66
- }
67
- }
68
-
69
- const insertTreeRow = (newRecords: any[], isAppend: boolean) => {
70
- const { tableFullTreeData, afterFullData, fullDataRowIdData, fullAllDataRowIdData } = internalData
71
- const treeOpts = computeTreeOpts.value
72
- const { rowField, parentField, mapChildrenField } = treeOpts
73
- const childrenField = treeOpts.children || treeOpts.childrenField
74
- const funcName = isAppend ? 'push' : 'unshift'
75
- newRecords.forEach(item => {
76
- const parentRowId = item[parentField]
77
- const rowid = getRowid($xeTable, item)
78
- const matchObj = parentRowId ? XEUtils.findTree(tableFullTreeData, item => parentRowId === item[rowField], { children: mapChildrenField }) : null
79
- if (matchObj) {
80
- const { item: parentRow } = matchObj
81
- const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
82
- const parentLevel = parentRest ? parentRest.level : 0
83
- let pChilds = parentRow[childrenField]
84
- let pMapChilds = parentRow[mapChildrenField]
85
- if (!XEUtils.isArray(pChilds)) {
86
- pChilds = parentRow[childrenField] = []
87
- }
88
- if (!XEUtils.isArray(pMapChilds)) {
89
- pMapChilds = parentRow[mapChildrenField] = []
90
- }
91
- pChilds[funcName](item)
92
- pMapChilds[funcName](item)
93
- const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: pChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
94
- fullDataRowIdData[rowid] = rest
95
- fullAllDataRowIdData[rowid] = rest
96
- } else {
97
- if (parentRowId) {
98
- warnLog('vxe.error.unableInsert')
99
- }
100
- afterFullData[funcName](item)
101
- tableFullTreeData[funcName](item)
102
- const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: tableFullTreeData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
103
- fullDataRowIdData[rowid] = rest
104
- fullAllDataRowIdData[rowid] = rest
105
- }
106
- })
107
- }
108
-
109
- // const insertGroupRow = (newRecords: any[], isAppend: boolean) => {
110
-
111
- // }
112
-
113
- const handleInsertRowAt = (records: any, targetRowOrRowid: any, isInsertNextRow?: boolean) => {
114
- const { treeConfig } = props
115
- const { isRowGroupStatus } = reactData
116
- const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps, removeRowMaps } = internalData
117
- const treeOpts = computeTreeOpts.value
118
- const { transform, parentField, rowField, mapChildrenField } = treeOpts
119
- const childrenField = treeOpts.children || treeOpts.childrenField
120
- if (!XEUtils.isArray(records)) {
121
- records = [records]
122
- }
123
- let targetRow = targetRowOrRowid
124
- if (XEUtils.isString(targetRowOrRowid) || XEUtils.isNumber(targetRowOrRowid)) {
125
- const rowRest = fullAllDataRowIdData[targetRowOrRowid]
126
- if (rowRest) {
127
- targetRow = rowRest.row
128
- }
129
- }
130
- if (!records.length) {
131
- return Promise.resolve({ row: null, rows: [] })
132
- }
133
- $xeTable.handlePushStack()
134
- const newRecords: any[] = reactive($xeTable.defineField(records.map((record: any) => Object.assign(treeConfig && transform ? { [mapChildrenField]: [], [childrenField]: [] } : {}, record))))
135
- let treeRecords: any[] = []
136
- if (treeConfig && transform) {
137
- treeRecords = XEUtils.toArrayTree(newRecords, { key: rowField, parentKey: parentField, children: childrenField })
138
- }
139
- if (XEUtils.eqNull(targetRow)) {
140
- // 如果为虚拟树
141
- if (treeConfig && transform) {
142
- insertTreeRow(newRecords, false)
143
- } else if (isRowGroupStatus) {
144
- // 如果分组
145
- if (treeConfig) {
146
- throw new Error(getI18n('vxe.error.noTree', ['insert']))
147
- }
148
- errLog(getI18n('vxe.error.noGroup', ['insert']))
149
- // insertGroupRow(newRecords, false)
150
- } else {
151
- newRecords.forEach(item => {
152
- const rowid = getRowid($xeTable, item)
153
- const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
154
- fullDataRowIdData[rowid] = rest
155
- fullAllDataRowIdData[rowid] = rest
156
- afterFullData.unshift(item)
157
- tableFullData.unshift(item)
158
- })
159
- // 刷新单元格合并
160
- mergeBodyList.forEach((mergeItem: any) => {
161
- const { row: mergeRowIndex } = mergeItem
162
- if (mergeRowIndex >= 0) {
163
- mergeItem.row = mergeRowIndex + newRecords.length
164
- }
165
- })
166
- }
167
- } else {
168
- if (targetRow === -1) {
169
- // 如果为虚拟树
170
- if (treeConfig && transform) {
171
- insertTreeRow(newRecords, true)
172
- } else if (isRowGroupStatus) {
173
- // 如果分组
174
- if (treeConfig) {
175
- throw new Error(getI18n('vxe.error.noTree', ['insert']))
176
- }
177
- errLog(getI18n('vxe.error.noGroup', ['insert']))
178
- // insertGroupRow(newRecords, true)
179
- } else {
180
- newRecords.forEach(item => {
181
- const rowid = getRowid($xeTable, item)
182
- const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, treeIndex: -1, _tIndex: -1, $index: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
183
- fullDataRowIdData[rowid] = rest
184
- fullAllDataRowIdData[rowid] = rest
185
- afterFullData.push(item)
186
- tableFullData.push(item)
187
- })
188
- }
189
- } else {
190
- // 如果为虚拟树
191
- if (treeConfig && transform) {
192
- const matchMapObj = XEUtils.findTree(tableFullTreeData, item => targetRow[rowField] === item[rowField], { children: mapChildrenField })
193
- if (matchMapObj) {
194
- const { parent: parentRow } = matchMapObj
195
- const parentMapChilds = parentRow ? parentRow[mapChildrenField] : tableFullTreeData
196
- const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
197
- const parentLevel = parentRest ? parentRest.level : 0
198
- treeRecords.forEach((row, i) => {
199
- if (parentRow) {
200
- if (row[parentField] !== parentRow[rowField]) {
201
- errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, `${parentField}=${parentRow[rowField]}`])
202
- row[parentField] = parentRow[rowField]
203
- }
204
- } else {
205
- if (row[parentField] !== null) {
206
- if (!XEUtils.eqNull(row[parentField])) {
207
- errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, 'null'])
208
- }
209
- row[parentField] = null
210
- }
211
- }
212
- let targetIndex = matchMapObj.index + i
213
- if (isInsertNextRow) {
214
- targetIndex = targetIndex + 1
215
- }
216
- parentMapChilds.splice(targetIndex, 0, row)
217
- })
218
- XEUtils.eachTree(treeRecords, (item) => {
219
- const rowid = getRowid($xeTable, item)
220
- const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: parentMapChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
221
- if (item[childrenField]) {
222
- item[mapChildrenField] = item[childrenField]
223
- }
224
- fullDataRowIdData[rowid] = rest
225
- fullAllDataRowIdData[rowid] = rest
226
- }, { children: childrenField })
227
- // 源
228
- if (parentRow) {
229
- const matchObj = XEUtils.findTree(tableFullTreeData, item => targetRow[rowField] === item[rowField], { children: childrenField })
230
- if (matchObj) {
231
- const parentChilds = matchObj.items
232
- let targetIndex = matchObj.index
233
- if (isInsertNextRow) {
234
- targetIndex = targetIndex + 1
235
- }
236
- parentChilds.splice(targetIndex, 0, ...treeRecords)
237
- }
238
- }
239
- } else {
240
- warnLog('vxe.error.unableInsert')
241
- insertTreeRow(newRecords, true)
242
- }
243
- } else if (isRowGroupStatus) {
244
- // 如果分组
245
- if (treeConfig) {
246
- throw new Error(getI18n('vxe.error.noTree', ['insert']))
247
- }
248
- errLog(getI18n('vxe.error.noGroup', ['insert']))
249
- } else {
250
- if (treeConfig) {
251
- throw new Error(getI18n('vxe.error.noTree', ['insert']))
252
- }
253
- let afIndex = -1
254
- // 如果是可视索引
255
- if (XEUtils.isNumber(targetRow)) {
256
- if (targetRow < afterFullData.length) {
257
- afIndex = targetRow
258
- }
259
- } else {
260
- afIndex = $xeTable.findRowIndexOf(afterFullData, targetRow)
261
- }
262
- // 如果是插入指定行的下一行
263
- if (isInsertNextRow) {
264
- afIndex = Math.min(afterFullData.length, afIndex + 1)
265
- }
266
- if (afIndex === -1) {
267
- throw new Error(getI18n('vxe.error.unableInsert'))
268
- }
269
- afterFullData.splice(afIndex, 0, ...newRecords)
270
- const tfIndex = $xeTable.findRowIndexOf(tableFullData, targetRow)
271
- if (tfIndex > -1) {
272
- tableFullData.splice(tfIndex + (isInsertNextRow ? 1 : 0), 0, ...newRecords)
273
- } else {
274
- tableFullData.push(...newRecords)
275
- }
276
- // 刷新单元格合并
277
- mergeBodyList.forEach((mergeItem: any) => {
278
- const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
279
- if (mergeRowIndex >= afIndex) {
280
- mergeItem.row = mergeRowIndex + newRecords.length
281
- } else if (isInsertNextRow ? (mergeRowIndex + mergeRowspan >= afIndex) : (mergeRowIndex + mergeRowspan > afIndex)) {
282
- mergeItem.rowspan = mergeRowspan + newRecords.length
283
- }
284
- })
285
- }
286
- }
287
- }
288
-
289
- const handleStatus = (newRow: any) => {
290
- const rowid = getRowid($xeTable, newRow)
291
- // 如果是被删除的数据,则还原状态
292
- if (removeRowMaps[rowid]) {
293
- delete removeRowMaps[rowid]
294
- if (insertRowMaps[rowid]) {
295
- delete insertRowMaps[rowid]
296
- }
297
- } else {
298
- insertRowMaps[rowid] = newRow
299
- }
300
- }
301
- // 如果为虚拟树
302
- if (treeConfig && transform) {
303
- XEUtils.eachTree(treeRecords, handleStatus, { children: mapChildrenField })
304
- } else {
305
- newRecords.forEach(handleStatus)
306
- }
307
-
308
- reactData.removeRowFlag++
309
- reactData.insertRowFlag++
310
- $xeTable.cacheRowMap(false, false)
311
- $xeTable.updateScrollYStatus()
312
- $xeTable.handleTableData(treeConfig && transform)
313
- if (!(treeConfig && transform)) {
314
- $xeTable.updateAfterDataIndex()
315
- }
316
- $xeTable.updateFooter()
317
- $xeTable.handleUpdateBodyMerge()
318
- $xeTable.checkSelectionStatus()
319
- if (reactData.scrollYLoad) {
320
- $xeTable.updateScrollYSpace()
321
- }
322
- return nextTick().then(() => {
323
- $xeTable.updateCellAreas()
324
- return $xeTable.recalculate(true)
325
- }).then(() => {
326
- return {
327
- row: newRecords.length ? newRecords[newRecords.length - 1] : null,
328
- rows: newRecords
329
- }
330
- })
331
- }
332
-
333
- const handleInsertChildRowAt = (records: any, parentRowOrParentId: any, targetRow: any, isInsertNextRow?: boolean) => {
334
- const { treeConfig } = props
335
- const { fullAllDataRowIdData } = internalData
336
- const treeOpts = computeTreeOpts.value
337
- const { transform, rowField, parentField } = treeOpts
338
- if (treeConfig && transform) {
339
- if (!XEUtils.isArray(records)) {
340
- records = [records]
341
- }
342
- let parentRow = parentRowOrParentId
343
- if (XEUtils.isString(parentRowOrParentId) || XEUtils.isNumber(parentRowOrParentId)) {
344
- const rowRest = fullAllDataRowIdData[parentRowOrParentId]
345
- if (rowRest) {
346
- parentRow = rowRest.row
347
- }
348
- }
349
- return handleInsertRowAt(records.map((item: any) => Object.assign({}, item, { [parentField]: parentRow[rowField] })), targetRow, isInsertNextRow)
350
- } else {
351
- errLog('vxe.error.errProp', ['tree-config.transform=false', 'tree-config.transform=true'])
352
- }
353
- return Promise.resolve({ row: null, rows: [] })
354
- }
355
-
356
- const handleClearEdit = (evnt: Event | null, targetRow?: any) => {
357
- const { editStore } = reactData
358
- const { actived, focused } = editStore
359
- const { row, column } = actived
360
- const validOpts = computeValidOpts.value
361
- if (row || column) {
362
- if (targetRow && getRowid($xeTable, targetRow) !== getRowid($xeTable, row)) {
363
- return nextTick()
364
- }
365
- syncActivedCell()
366
- $xeTable.updateFooter()
367
- actived.args = null
368
- actived.row = null
369
- actived.column = null
370
- $xeTable.dispatchEvent('edit-closed', {
371
- row,
372
- rowIndex: $xeTable.getRowIndex(row),
373
- $rowIndex: $xeTable.getVMRowIndex(row),
374
- column,
375
- columnIndex: $xeTable.getColumnIndex(column),
376
- $columnIndex: $xeTable.getVMColumnIndex(column)
377
- }, evnt || null)
378
- }
379
- focused.row = null
380
- focused.column = null
381
- if (validOpts.autoClear) {
382
- if (validOpts.msgMode !== 'full' || getConfig().cellVaildMode === 'obsolete') {
383
- if ($xeTable.clearValidate) {
384
- return $xeTable.clearValidate()
385
- }
386
- }
387
- }
388
- return nextTick().then(() => $xeTable.updateCellAreas())
389
- }
390
-
391
- const handleEditActive = (params: {
392
- $table: VxeTableConstructor
393
- column: VxeTableDefines.ColumnInfo
394
- columnIndex: number
395
- _columnIndex: number
396
- $columnIndex: number
397
- rowIndex: number
398
- $rowIndex: number
399
- _rowIndex: number
400
- row: any
401
- cell?: HTMLElement
402
- }, evnt: Event | null, options: {
403
- isClear?: boolean
404
- isFocus?: boolean
405
- isPos?: boolean
406
- }) => {
407
- const $xeGrid = $xeTable.xeGrid
408
- const $xeGantt = $xeTable.xeGantt
409
-
410
- const { editConfig, mouseConfig } = props
411
- const { editStore, tableColumn } = reactData
412
- const editOpts = computeEditOpts.value
413
- const mouseOpts = computeMouseOpts.value
414
- const { mode } = editOpts
415
- const { actived, focused } = editStore
416
- const { row, column } = params
417
- const { editRender } = column
418
- const { isFocus, isPos, isClear } = options
419
- const cell = (params.cell || $xeTable.getCellElement(row, column)) as HTMLElement
420
- const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod
421
- const editParams = { ...params, cell }
422
- if (cell && isEnableConf(editConfig) && isEnableConf(editRender)) {
423
- // 激活编辑
424
- if (!$xeTable.isPendingByRow(row) && !$xeTable.isAggregateRecord(row)) {
425
- if (actived.row !== row || (mode === 'cell' ? actived.column !== column : false)) {
426
- // 判断是否禁用编辑
427
- let type: 'edit-disabled' | 'edit-activated' = 'edit-disabled'
428
- if (!beforeEditMethod || beforeEditMethod({ ...editParams, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })) {
429
- if (hasEnableConf(mouseConfig, mouseOpts)) {
430
- $xeTable.clearSelected()
431
- if ($xeTable.clearCellAreas) {
432
- $xeTable.clearCellAreas()
433
- $xeTable.clearCopyCellArea()
434
- }
435
- }
436
- $xeTable.closeTooltip()
437
- if (actived.column) {
438
- handleClearEdit(evnt)
439
- }
440
- type = 'edit-activated'
441
- column.renderHeight = cell.offsetHeight
442
- actived.args = editParams
443
- actived.row = row
444
- actived.column = column
445
- $xeTable.handlePushStack()
446
- if (isClear) {
447
- setCellValue(row, column, null)
448
- }
449
- if (mode === 'row') {
450
- tableColumn.forEach((column: any) => getEditColumnModel(row, column))
451
- } else {
452
- getEditColumnModel(row, column)
453
- }
454
- const afterEditMethod = editOpts.afterEditMethod
455
- nextTick(() => {
456
- if (isFocus) {
457
- $xeTable.handleFocus(editParams, evnt)
458
- }
459
- if (afterEditMethod) {
460
- afterEditMethod({ ...editParams, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
461
- }
462
- })
463
- }
464
- $xeTable.dispatchEvent(type, {
465
- row,
466
- rowIndex: $xeTable.getRowIndex(row),
467
- $rowIndex: $xeTable.getVMRowIndex(row),
468
- column,
469
- columnIndex: $xeTable.getColumnIndex(column),
470
- $columnIndex: $xeTable.getVMColumnIndex(column)
471
- }, evnt)
472
-
473
- // v4已废弃
474
- if (type === 'edit-activated') {
475
- $xeTable.dispatchEvent('edit-actived', {
476
- row,
477
- rowIndex: $xeTable.getRowIndex(row),
478
- $rowIndex: $xeTable.getVMRowIndex(row),
479
- column,
480
- columnIndex: $xeTable.getColumnIndex(column),
481
- $columnIndex: $xeTable.getVMColumnIndex(column)
482
- }, evnt)
483
- }
484
- } else {
485
- const { column: oldColumn } = actived
486
- if (hasEnableConf(mouseConfig, mouseOpts)) {
487
- $xeTable.clearSelected()
488
- if ($xeTable.clearCellAreas) {
489
- $xeTable.clearCellAreas()
490
- $xeTable.clearCopyCellArea()
491
- }
492
- }
493
- if (oldColumn && oldColumn !== column) {
494
- const { model: oldModel } = oldColumn
495
- if (oldModel.update) {
496
- setCellValue(row, oldColumn, oldModel.value)
497
- }
498
- if ($xeTable.clearValidate) {
499
- $xeTable.clearValidate(row, column)
500
- }
501
- }
502
- column.renderHeight = cell.offsetHeight
503
- actived.args = editParams
504
- actived.column = column
505
- if (isPos) {
506
- setTimeout(() => {
507
- $xeTable.handleFocus(editParams, evnt)
508
- })
509
- }
510
- }
511
- focused.column = null
512
- focused.row = null
513
- $xeTable.focus()
514
- }
515
- }
516
- return nextTick()
517
- }
518
-
519
- const handleEditCell = (row: any, fieldOrColumn: string | VxeTableDefines.ColumnInfo | null, options: {
520
- isClear?: boolean | undefined;
521
- isFocus?: boolean | undefined;
522
- isPos?: boolean | undefined;
523
- }) => {
524
- const { editConfig } = props
525
- const { isPos } = options
526
- const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
527
- if (row && column && isEnableConf(editConfig) && isEnableConf(column.editRender) && !$xeTable.isAggregateRecord(row)) {
528
- return Promise.resolve(isPos ? $xeTable.scrollToRow(row, column) : null).then(() => {
529
- const cell = $xeTable.getCellElement(row, column)
530
- if (cell) {
531
- handleEditActive({
532
- row,
533
- rowIndex: $xeTable.getRowIndex(row),
534
- $rowIndex: $xeTable.getVMRowIndex(row),
535
- _rowIndex: $xeTable.getVTRowIndex(row),
536
- column,
537
- columnIndex: $xeTable.getColumnIndex(column),
538
- $columnIndex: $xeTable.getVMColumnIndex(column),
539
- _columnIndex: $xeTable.getVTColumnIndex(column),
540
- cell,
541
- $table: $xeTable
542
- }, null, {
543
- isFocus: isPos,
544
- isPos
545
- })
546
- internalData._lastCallTime = Date.now()
547
- }
548
- return nextTick()
549
- })
550
- }
551
- return nextTick()
552
- }
553
-
554
- editMethods = {
555
- /**
556
- * 往表格中插入临时数据
557
- *
558
- * @param {*} records
559
- */
560
- insert (records) {
561
- return handleInsertRowAt(records, null)
562
- },
563
- /**
564
- * 往表格指定行中插入临时数据
565
- * 如果 row 为空则从插入到顶部,如果为树结构,则插入到目标节点顶部
566
- * 如果 row 为 -1 则从插入到底部,如果为树结构,则插入到目标节点底部
567
- * 如果 row 为有效行则插入到该行的位置,如果为树结构,则有插入到效的目标节点该行的位置
568
- */
569
- insertAt (records, targetRowOrRowid) {
570
- return handleInsertRowAt(records, targetRowOrRowid)
571
- },
572
- insertNextAt (records, targetRowOrRowid) {
573
- return handleInsertRowAt(records, targetRowOrRowid, true)
574
- },
575
- insertChild (records, parentRowOrParentId) {
576
- return handleInsertChildRowAt(records, parentRowOrParentId, null)
577
- },
578
- insertChildAt (records, parentRowOrParentId, targetRow) {
579
- return handleInsertChildRowAt(records, parentRowOrParentId, targetRow)
580
- },
581
- insertChildNextAt (records, parentRowOrParentId, targetRow) {
582
- return handleInsertChildRowAt(records, parentRowOrParentId, targetRow, true)
583
- },
584
- /**
585
- * 删除指定行数据
586
- * 如果传 row 则删除一行
587
- * 如果传 rows 则删除多行
588
- * 如果为空则删除所有
589
- */
590
- remove (rows: any) {
591
- const { treeConfig } = props
592
- const { editStore, isRowGroupStatus } = reactData
593
- const { tableFullTreeData, selectCheckboxMaps, afterFullData, mergeBodyList, tableFullData, pendingRowMaps, insertRowMaps, removeRowMaps } = internalData
594
- const checkboxOpts = computeCheckboxOpts.value
595
- const treeOpts = computeTreeOpts.value
596
- const { transform, mapChildrenField } = treeOpts
597
- const childrenField = treeOpts.children || treeOpts.childrenField
598
- const { actived } = editStore
599
- const { checkField } = checkboxOpts
600
- let delList: any[] = []
601
- if (!rows) {
602
- rows = tableFullData
603
- } else if (!XEUtils.isArray(rows)) {
604
- rows = [rows]
605
- }
606
- if (!rows.length) {
607
- return Promise.resolve({ row: null, rows: [] })
608
- }
609
- $xeTable.handlePushStack()
610
- // 如果是新增,则保存记录
611
- rows.forEach((row: any) => {
612
- if (!$xeTable.isInsertByRow(row)) {
613
- const rowid = getRowid($xeTable, row)
614
- removeRowMaps[rowid] = row
615
- }
616
- })
617
- // 如果绑定了多选属性,则更新状态
618
- if (!checkField) {
619
- rows.forEach((row: any) => {
620
- const rowid = getRowid($xeTable, row)
621
- if (selectCheckboxMaps[rowid]) {
622
- delete selectCheckboxMaps[rowid]
623
- }
624
- })
625
- reactData.updateCheckboxFlag++
626
- }
627
- // 从数据源中移除
628
- if (tableFullData === rows) {
629
- rows = delList = tableFullData.slice(0)
630
- internalData.tableFullData = []
631
- internalData.afterFullData = []
632
- $xeTable.clearMergeCells()
633
- } else {
634
- // 如果为虚拟树
635
- if (treeConfig && transform) {
636
- rows.forEach((row: any) => {
637
- const rowid = getRowid($xeTable, row)
638
- const matchMapObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid($xeTable, item), { children: mapChildrenField })
639
- if (matchMapObj) {
640
- const rItems = matchMapObj.items.splice(matchMapObj.index, 1)
641
- delList.push(rItems[0])
642
- }
643
- const matchObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid($xeTable, item), { children: childrenField })
644
- if (matchObj) {
645
- matchObj.items.splice(matchObj.index, 1)
646
- }
647
- const afIndex = $xeTable.findRowIndexOf(afterFullData, row)
648
- if (afIndex > -1) {
649
- afterFullData.splice(afIndex, 1)
650
- }
651
- })
652
- } else if (isRowGroupStatus) {
653
- // 如果分组
654
- warnLog(getI18n('vxe.error.noGroup', ['remove']))
655
- } else {
656
- rows.forEach((row: any) => {
657
- const tfIndex = $xeTable.findRowIndexOf(tableFullData, row)
658
- if (tfIndex > -1) {
659
- const rItems = tableFullData.splice(tfIndex, 1)
660
- delList.push(rItems[0])
661
- }
662
- const afIndex = $xeTable.findRowIndexOf(afterFullData, row)
663
- if (afIndex > -1) {
664
- // 刷新单元格合并
665
- mergeBodyList.forEach((mergeItem) => {
666
- const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
667
- if (mergeRowIndex > afIndex) {
668
- mergeItem.row = mergeRowIndex - 1
669
- } else if (mergeRowIndex + mergeRowspan > afIndex) {
670
- mergeItem.rowspan = mergeRowspan - 1
671
- }
672
- })
673
- afterFullData.splice(afIndex, 1)
674
- }
675
- })
676
- }
677
- }
678
- // 如果当前行被激活编辑,则清除激活状态
679
- if (actived.row && $xeTable.findRowIndexOf(rows, actived.row) > -1) {
680
- editMethods.clearEdit()
681
- }
682
- // 从新增中移除已删除的数据
683
- rows.forEach((row: any) => {
684
- const rowid = getRowid($xeTable, row)
685
- if (insertRowMaps[rowid]) {
686
- delete insertRowMaps[rowid]
687
- }
688
- if (pendingRowMaps[rowid]) {
689
- delete pendingRowMaps[rowid]
690
- }
691
- })
692
- reactData.removeRowFlag++
693
- reactData.insertRowFlag++
694
- reactData.pendingRowFlag++
695
- $xeTable.cacheRowMap(false, false)
696
- $xeTable.handleTableData(treeConfig && transform)
697
- $xeTable.updateFooter()
698
- $xeTable.handleUpdateBodyMerge()
699
- if (!(treeConfig && transform)) {
700
- $xeTable.updateAfterDataIndex()
701
- }
702
- $xeTable.checkSelectionStatus()
703
- if (reactData.scrollYLoad) {
704
- $xeTable.updateScrollYSpace()
705
- }
706
- return nextTick().then(() => {
707
- $xeTable.updateCellAreas()
708
- return $xeTable.recalculate(true)
709
- }).then(() => {
710
- return { row: delList.length ? delList[delList.length - 1] : null, rows: delList }
711
- })
712
- },
713
- /**
714
- * 删除复选框选中的数据
715
- */
716
- removeCheckboxRow () {
717
- return editMethods.remove($xeTable.getCheckboxRecords()).then((params: any) => {
718
- $xeTable.clearCheckboxRow()
719
- return params
720
- })
721
- },
722
- /**
723
- * 删除单选框选中的数据
724
- */
725
- removeRadioRow () {
726
- const radioRecord = $xeTable.getRadioRecord()
727
- return editMethods.remove(radioRecord || []).then((params: any) => {
728
- $xeTable.clearRadioRow()
729
- return params
730
- })
731
- },
732
- /**
733
- * 删除当前行选中的数据
734
- */
735
- removeCurrentRow () {
736
- const currentRecord = $xeTable.getCurrentRecord()
737
- return editMethods.remove(currentRecord || []).then((params: any) => {
738
- $xeTable.clearCurrentRow()
739
- return params
740
- })
741
- },
742
- /**
743
- * 获取表格数据集,包含新增、删除、修改、标记
744
- */
745
- getRecordset () {
746
- const removeRecords = editMethods.getRemoveRecords()
747
- const pendingRecords = $xeTable.getPendingRecords()
748
- const delRecords = removeRecords.concat(pendingRecords)
749
- // 如果已经被删除,则无需放到更新数组
750
- const updateRecords = editMethods.getUpdateRecords().filter(row => {
751
- return !delRecords.some(item => $xeTable.eqRow(item, row))
752
- })
753
- return {
754
- insertRecords: editMethods.getInsertRecords(),
755
- removeRecords,
756
- updateRecords,
757
- pendingRecords
758
- }
759
- },
760
- /**
761
- * 获取新增的临时数据
762
- */
763
- getInsertRecords () {
764
- const { fullAllDataRowIdData, insertRowMaps } = internalData
765
- const insertRecords: any[] = []
766
- XEUtils.each(insertRowMaps, (row, rowid) => {
767
- if (fullAllDataRowIdData[rowid]) {
768
- insertRecords.push(row)
769
- }
770
- })
771
- return insertRecords
772
- },
773
- /**
774
- * 获取已删除的数据
775
- */
776
- getRemoveRecords () {
777
- const { removeRowMaps } = internalData
778
- const removeRecords: any[] = []
779
- XEUtils.each(removeRowMaps, (row) => {
780
- removeRecords.push(row)
781
- })
782
- return removeRecords
783
- },
784
- /**
785
- * 获取更新数据
786
- * 只精准匹配 row 的更改
787
- * 如果是树表格,子节点更改状态不会影响父节点的更新状态
788
- */
789
- getUpdateRecords () {
790
- const { keepSource, treeConfig } = props
791
- const { tableFullData, tableFullTreeData } = internalData
792
- const treeOpts = computeTreeOpts.value
793
- const updateRecords: any[] = []
794
- if (keepSource) {
795
- syncActivedCell()
796
- if (treeConfig) {
797
- const childrenField = treeOpts.children || treeOpts.childrenField
798
- XEUtils.eachTree(tableFullTreeData, row => {
799
- if ($xeTable.isUpdateByRow(row)) {
800
- updateRecords.push(row)
801
- }
802
- }, { children: childrenField })
803
- } else {
804
- tableFullData.forEach((row) => {
805
- if ($xeTable.isUpdateByRow(row)) {
806
- updateRecords.push(row)
807
- }
808
- })
809
- }
810
- }
811
- return updateRecords
812
- },
813
- getActiveRecord () {
814
- warnLog('vxe.error.delFunc', ['getActiveRecord', 'getEditCell'])
815
- const { editStore } = reactData
816
- const { fullAllDataRowIdData } = internalData
817
- const { args, row } = editStore.actived
818
- if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
819
- return Object.assign({}, args, { row })
820
- }
821
- return null
822
- },
823
- getEditRecord () {
824
- warnLog('vxe.error.delFunc', ['getEditRecord', 'getEditCell'])
825
- const { editStore } = reactData
826
- const { fullAllDataRowIdData } = internalData
827
- const { args, row } = editStore.actived
828
- if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
829
- return Object.assign({}, args, { row })
830
- }
831
- return null
832
- },
833
- getEditCell () {
834
- const { editStore } = reactData
835
- const { row, column } = editStore.actived
836
- if (column && row) {
837
- return {
838
- row,
839
- rowIndex: $xeTable.getRowIndex(row),
840
- column,
841
- columnIndex: $xeTable.getColumnIndex(column)
842
- }
843
- }
844
- return null
845
- },
846
- /**
847
- * 获取选中的单元格
848
- */
849
- getSelectedCell () {
850
- const { editStore } = reactData
851
- const { row, column } = editStore.selected
852
- if (row && column) {
853
- return {
854
- row,
855
- column
856
- }
857
- }
858
- return null
859
- },
860
- clearActived (row) {
861
- // 即将废弃
862
- warnLog('vxe.error.delFunc', ['clearActived', 'clearEdit'])
863
- return $xeTable.clearEdit(row)
864
- },
865
- /**
866
- * 清除激活的编辑
867
- */
868
- clearEdit (row) {
869
- return handleClearEdit(null, row)
870
- },
871
- /**
872
- * 清除所选中源状态
873
- */
874
- clearSelected () {
875
- const { editStore } = reactData
876
- const { selected } = editStore
877
- selected.row = null
878
- selected.column = null
879
- removeCellSelectedClass()
880
- return nextTick()
881
- },
882
- isActiveByRow (row) {
883
- warnLog('vxe.error.delFunc', ['isActiveByRow', 'isEditByRow'])
884
- // 即将废弃
885
- return $xeTable.isEditByRow(row)
886
- },
887
- /**
888
- * 判断行是否为激活编辑状态
889
- * @param {Row} row 行对象
890
- */
891
- isEditByRow (row) {
892
- const { editStore } = reactData
893
- return editStore.actived.row === row
894
- },
895
- setActiveRow (row) {
896
- warnLog('vxe.error.delFunc', ['setActiveRow', 'setEditRow'])
897
- // 即将废弃
898
- return editMethods.setEditRow(row)
899
- },
900
- /**
901
- * 激活行编辑
902
- */
903
- setEditRow (row, fieldOrColumn, options) {
904
- const { visibleColumn } = internalData
905
- let column: any = XEUtils.find(visibleColumn, column => isEnableConf(column.editRender))
906
- let isPos = false
907
- if (fieldOrColumn) {
908
- isPos = true
909
- if (fieldOrColumn !== true) {
910
- column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
911
- }
912
- }
913
- return handleEditCell(row, column, Object.assign({
914
- isPos,
915
- isFocus: isPos
916
- }, options))
917
- },
918
- setActiveCell (row, fieldOrColumn) {
919
- warnLog('vxe.error.delFunc', ['setActiveCell', 'setEditCell'])
920
- // 即将废弃
921
- return editMethods.setEditCell(row, fieldOrColumn)
922
- },
923
- /**
924
- * 激活单元格编辑
925
- */
926
- setEditCell (row, fieldOrColumn, options) {
927
- return handleEditCell(row, fieldOrColumn, Object.assign({
928
- isFocus: true,
929
- isPos: true
930
- }, options))
931
- },
932
- /**
933
- * 只对 trigger=dblclick 有效,选中单元格
934
- */
935
- setSelectCell (row, fieldOrColumn) {
936
- const { tableData } = reactData
937
- const editOpts = computeEditOpts.value
938
- const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
939
- if (row && column && editOpts.trigger !== 'manual') {
940
- const rowIndex = $xeTable.findRowIndexOf(tableData, row)
941
- if (rowIndex > -1 && column) {
942
- const cell = $xeTable.getCellElement(row, column)
943
- const params = {
944
- $table: $xeTable,
945
- row,
946
- rowIndex,
947
- $rowIndex: $xeTable.getVMRowIndex(row),
948
- _rowIndex: $xeTable.getVTRowIndex(row),
949
- column,
950
- columnIndex: $xeTable.getColumnIndex(column),
951
- $columnIndex: $xeTable.getVMColumnIndex(column),
952
- _columnIndex: $xeTable.getVTColumnIndex(column),
953
- cell
954
- }
955
- $xeTable.handleSelected(params, null)
956
- }
957
- }
958
- return nextTick()
959
- }
960
- }
961
-
962
- const handleCellFocus = (cell: HTMLElement, params: {
963
- $table: VxeTableConstructor
964
- column: VxeTableDefines.ColumnInfo
965
- row: any
966
- }) => {
967
- const { editConfig } = props
968
- const { column } = params
969
- const { editRender } = column
970
- const editOpts = computeEditOpts.value
971
- if (editConfig && isEnableConf(editRender)) {
972
- const rendererOpts = computeRendererOpts.value
973
- const renderName = editRender.name
974
- const compRender = renderName ? (rendererOpts[renderName] || renderer.get(renderName)) : null
975
- let autoFocus: boolean | string | ((params: VxeGlobalRendererHandles.TableAutoFocusParams) => HTMLElement | null) | null | undefined = editRender.autofocus || editRender.autoFocus
976
- let autoSelect = editRender.autoSelect || editRender.autoselect
977
- let inputElem: HTMLElement | null = null
978
- // 是否启用聚焦
979
- if (editOpts.autoFocus) {
980
- if (!autoFocus && compRender) {
981
- autoFocus = compRender.tableAutoFocus || compRender.tableAutofocus || compRender.autofocus
982
- }
983
- if (!autoSelect && compRender) {
984
- autoSelect = compRender.tableAutoSelect || compRender.autoselect
985
- }
986
- // 如果指定了聚焦 class
987
- if (XEUtils.isFunction(autoFocus)) {
988
- inputElem = autoFocus(params)
989
- } else if (autoFocus) {
990
- if (autoFocus === true) {
991
- // 自动匹配模式,会自动匹配第一个可输入元素
992
- inputElem = cell.querySelector('input,textarea')
993
- } else {
994
- inputElem = cell.querySelector(autoFocus)
995
- }
996
- if (inputElem) {
997
- inputElem.focus()
998
- }
999
- }
1000
- }
1001
- return inputElem as HTMLInputElement
1002
- }
1003
- return null
1004
- }
1005
-
1006
- editPrivateMethods = {
1007
- /**
1008
- * 处理激活编辑
1009
- */
1010
- handleEdit (params, evnt, options) {
1011
- return handleEditActive(params, evnt, Object.assign({
1012
- isFocus: true,
1013
- isPos: true
1014
- }, options))
1015
- },
1016
- /**
1017
- * @deprecated
1018
- */
1019
- handleActived (params, evnt) {
1020
- return editPrivateMethods.handleEdit(params, evnt)
1021
- },
1022
- /**
1023
- * 处理取消编辑
1024
- * @param evnt
1025
- * @returns
1026
- */
1027
- handleClearEdit,
1028
- handleCellFocus,
1029
- /**
1030
- * 处理聚焦
1031
- */
1032
- handleFocus (params) {
1033
- const { row, column, cell } = params
1034
- const { editRender } = column
1035
- const editOpts = computeEditOpts.value
1036
- if (isEnableConf(editRender)) {
1037
- const autoSelect = editRender.autoSelect || editRender.autoselect
1038
- const inputElem = handleCellFocus(cell, params)
1039
- if (inputElem) {
1040
- if (autoSelect) {
1041
- inputElem.select()
1042
- } else {
1043
- // 保持一致行为,光标移到末端
1044
- if (browseObj.msie) {
1045
- const textRange = (inputElem as any).createTextRange()
1046
- textRange.collapse(false)
1047
- textRange.select()
1048
- }
1049
- }
1050
- } else {
1051
- // 是否自动定位
1052
- if (editOpts.autoPos) {
1053
- if (!column.fixed) {
1054
- // 显示到可视区中
1055
- $xeTable.scrollToRow(row, column)
1056
- }
1057
- }
1058
- }
1059
- }
1060
- },
1061
- /**
1062
- * 处理选中源
1063
- */
1064
- handleSelected (params, evnt) {
1065
- const { mouseConfig, editConfig } = props
1066
- const { editStore } = reactData
1067
- const mouseOpts = computeMouseOpts.value
1068
- const editOpts = computeEditOpts.value
1069
- const { actived, selected } = editStore
1070
- const { row, column } = params
1071
- const isMouseSelected = hasEnableConf(mouseConfig, mouseOpts) && mouseOpts.selected
1072
- const selectMethod = () => {
1073
- if (isMouseSelected && (selected.row !== row || selected.column !== column)) {
1074
- if (actived.row !== row || (editOpts.mode === 'cell' ? actived.column !== column : false)) {
1075
- handleClearEdit(evnt)
1076
- $xeTable.clearSelected()
1077
- if ($xeTable.clearCellAreas) {
1078
- $xeTable.clearCellAreas()
1079
- $xeTable.clearCopyCellArea()
1080
- }
1081
- selected.args = params
1082
- selected.row = row
1083
- selected.column = column
1084
- if (isMouseSelected) {
1085
- editPrivateMethods.addCellSelectedClass()
1086
- }
1087
- $xeTable.focus()
1088
- // 如果是支持可复用控件
1089
- if (editConfig && editOpts.isReuseKeep && isEnableConf(editOpts) && isEnableConf(column.editRender)) {
1090
- setTimeout(() => {
1091
- const cell = $xeTable.getCellElement(row, column)
1092
- if (cell) {
1093
- const hasReusekeep = cell.querySelector('.vxe-reusekeep-control')
1094
- if (hasReusekeep) {
1095
- handleCellFocus(cell, params)
1096
- }
1097
- }
1098
- }, 0)
1099
- }
1100
- if (evnt) {
1101
- $xeTable.dispatchEvent('cell-selected', params, evnt)
1102
- }
1103
- }
1104
- }
1105
- return nextTick()
1106
- }
1107
- return selectMethod()
1108
- },
1109
- addCellSelectedClass () {
1110
- const { editStore } = reactData
1111
- const { selected } = editStore
1112
- const { row, column } = selected
1113
- removeCellSelectedClass()
1114
- if (row && column) {
1115
- const cell = $xeTable.getCellElement(row, column)
1116
- if (cell) {
1117
- addClass(cell, 'col--selected')
1118
- }
1119
- }
1120
- }
1121
- }
1122
-
1123
- return { ...editMethods, ...editPrivateMethods }
1124
- },
1125
- setupGrid ($xeGrid) {
1126
- return $xeGrid.extendTableMethods(tableEditMethodKeys)
1127
- },
1128
- setupGantt ($xeGantt) {
1129
- return $xeGantt.extendTableMethods(tableEditMethodKeys)
1130
- }
1131
- })
1
+ import { reactive, nextTick } from 'vue'
2
+ import XEUtils from 'xe-utils'
3
+ import { VxeUI } from '@vxe-ui/core'
4
+ import { hasEnableConf, isEnableConf } from '../../../ui/src/utils'
5
+ import { getCellValue, setCellValue, getRowid } from '../../src/util'
6
+ import { removeClass, addClass } from '../../../ui/src/dom'
7
+ import { createComponentLog } from '../../../ui/src/log'
8
+
9
+ import type { VxeTableConstructor, TableEditMethods, TableEditPrivateMethods, VxeTableDefines, VxeGlobalRendererHandles } from '../../../../types'
10
+
11
+ const { warnLog, errLog } = createComponentLog('table')
12
+
13
+ const { getConfig, renderer, hooks, getI18n } = VxeUI
14
+
15
+ const tableEditMethodKeys: (keyof TableEditMethods)[] = [
16
+ 'insert',
17
+ 'insertAt',
18
+ 'insertNextAt',
19
+ 'insertChild',
20
+ 'insertChildAt',
21
+ 'insertChildNextAt',
22
+ 'remove',
23
+ 'removeCheckboxRow',
24
+ 'removeRadioRow',
25
+ 'removeCurrentRow',
26
+ 'getRecordset',
27
+ 'getInsertRecords',
28
+ 'getRemoveRecords',
29
+ 'getUpdateRecords',
30
+ 'getEditRecord',
31
+ 'getActiveRecord',
32
+ 'getEditCell',
33
+ 'getSelectedCell',
34
+ 'clearEdit',
35
+ 'clearActived',
36
+ 'clearSelected',
37
+ 'isEditByRow',
38
+ 'isActiveByRow',
39
+ 'setEditRow',
40
+ 'setActiveRow',
41
+ 'setEditCell',
42
+ 'setActiveCell',
43
+ 'setSelectCell'
44
+ ]
45
+
46
+ hooks.add('tableEditModule', {
47
+ setupTable($xeTable) {
48
+ const { props, reactData, internalData } = $xeTable
49
+ const { refElem } = $xeTable.getRefMaps()
50
+ const { computeMouseOpts, computeEditOpts, computeCheckboxOpts, computeTreeOpts, computeValidOpts, computeRendererOpts } = $xeTable.getComputeMaps()
51
+
52
+ const browseObj = XEUtils.browse()
53
+
54
+ let editMethods = {} as TableEditMethods
55
+ let editPrivateMethods = {} as TableEditPrivateMethods
56
+
57
+ const getEditColumnModel = (row: any, column: VxeTableDefines.ColumnInfo) => {
58
+ const { model, editRender } = column
59
+ if (editRender) {
60
+ model.value = getCellValue(row, column)
61
+ model.update = false
62
+ }
63
+ }
64
+
65
+ const setEditColumnModel = (row: any, column: VxeTableDefines.ColumnInfo) => {
66
+ const { model, editRender } = column
67
+ if (editRender && model.update) {
68
+ setCellValue(row, column, model.value)
69
+ model.update = false
70
+ model.value = null
71
+ }
72
+ }
73
+
74
+ const removeCellSelectedClass = () => {
75
+ const el = refElem.value
76
+ if (el) {
77
+ const cell = el.querySelector('.col--selected')
78
+ if (cell) {
79
+ removeClass(cell, 'col--selected')
80
+ }
81
+ }
82
+ }
83
+
84
+ const syncActivedCell = () => {
85
+ const { editStore, tableColumn } = reactData
86
+ const editOpts = computeEditOpts.value
87
+ const { actived } = editStore
88
+ const { row, column } = actived
89
+ if (row && column) {
90
+ if (editOpts.mode === 'row') {
91
+ tableColumn.forEach((column) => setEditColumnModel(row, column))
92
+ } else {
93
+ setEditColumnModel(row, column)
94
+ }
95
+ }
96
+ }
97
+
98
+ const insertTreeRow = (newRecords: any[], isAppend: boolean) => {
99
+ const { tableFullTreeData, afterFullData, fullDataRowIdData, fullAllDataRowIdData } = internalData
100
+ const treeOpts = computeTreeOpts.value
101
+ const { rowField, parentField, mapChildrenField } = treeOpts
102
+ const childrenField = treeOpts.children || treeOpts.childrenField
103
+ const funcName = isAppend ? 'push' : 'unshift'
104
+ newRecords.forEach((item) => {
105
+ const parentRowId = item[parentField]
106
+ const rowid = getRowid($xeTable, item)
107
+ const matchObj = parentRowId ? XEUtils.findTree(tableFullTreeData, (item) => parentRowId === item[rowField], { children: mapChildrenField }) : null
108
+ if (matchObj) {
109
+ const { item: parentRow } = matchObj
110
+ const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
111
+ const parentLevel = parentRest ? parentRest.level : 0
112
+ let pChilds = parentRow[childrenField]
113
+ let pMapChilds = parentRow[mapChildrenField]
114
+ if (!XEUtils.isArray(pChilds)) {
115
+ pChilds = parentRow[childrenField] = []
116
+ }
117
+ if (!XEUtils.isArray(pMapChilds)) {
118
+ pMapChilds = parentRow[mapChildrenField] = []
119
+ }
120
+ pChilds[funcName](item)
121
+ pMapChilds[funcName](item)
122
+ const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: pChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
123
+ fullDataRowIdData[rowid] = rest
124
+ fullAllDataRowIdData[rowid] = rest
125
+ } else {
126
+ if (parentRowId) {
127
+ warnLog('vxe.error.unableInsert')
128
+ }
129
+ afterFullData[funcName](item)
130
+ tableFullTreeData[funcName](item)
131
+ const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: tableFullTreeData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
132
+ fullDataRowIdData[rowid] = rest
133
+ fullAllDataRowIdData[rowid] = rest
134
+ }
135
+ })
136
+ }
137
+
138
+ // const insertGroupRow = (newRecords: any[], isAppend: boolean) => {
139
+
140
+ // }
141
+
142
+ const handleInsertRowAt = (records: any, targetRowOrRowid: any, isInsertNextRow?: boolean) => {
143
+ const { treeConfig } = props
144
+ const { isRowGroupStatus } = reactData
145
+ const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps, removeRowMaps } = internalData
146
+ const treeOpts = computeTreeOpts.value
147
+ const { transform, parentField, rowField, mapChildrenField } = treeOpts
148
+ const childrenField = treeOpts.children || treeOpts.childrenField
149
+ if (!XEUtils.isArray(records)) {
150
+ records = [records]
151
+ }
152
+ let targetRow = targetRowOrRowid
153
+ if (XEUtils.isString(targetRowOrRowid) || XEUtils.isNumber(targetRowOrRowid)) {
154
+ const rowRest = fullAllDataRowIdData[targetRowOrRowid]
155
+ if (rowRest) {
156
+ targetRow = rowRest.row
157
+ }
158
+ }
159
+ if (!records.length) {
160
+ return Promise.resolve({ row: null, rows: [] })
161
+ }
162
+ $xeTable.handlePushStack()
163
+ const newRecords: any[] = reactive($xeTable.defineField(records.map((record: any) => Object.assign(treeConfig && transform ? { [mapChildrenField]: [], [childrenField]: [] } : {}, record))))
164
+ let treeRecords: any[] = []
165
+ if (treeConfig && transform) {
166
+ treeRecords = XEUtils.toArrayTree(newRecords, { key: rowField, parentKey: parentField, children: childrenField })
167
+ }
168
+ if (XEUtils.eqNull(targetRow)) {
169
+ // 如果为虚拟树
170
+ if (treeConfig && transform) {
171
+ insertTreeRow(newRecords, false)
172
+ } else if (isRowGroupStatus) {
173
+ // 如果分组
174
+ if (treeConfig) {
175
+ throw new Error(getI18n('vxe.error.noTree', ['insert']))
176
+ }
177
+ errLog(getI18n('vxe.error.noGroup', ['insert']))
178
+ // insertGroupRow(newRecords, false)
179
+ } else {
180
+ newRecords.forEach((item) => {
181
+ const rowid = getRowid($xeTable, item)
182
+ const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
183
+ fullDataRowIdData[rowid] = rest
184
+ fullAllDataRowIdData[rowid] = rest
185
+ afterFullData.unshift(item)
186
+ tableFullData.unshift(item)
187
+ })
188
+ // 刷新单元格合并
189
+ mergeBodyList.forEach((mergeItem: any) => {
190
+ const { row: mergeRowIndex } = mergeItem
191
+ if (mergeRowIndex >= 0) {
192
+ mergeItem.row = mergeRowIndex + newRecords.length
193
+ }
194
+ })
195
+ }
196
+ } else {
197
+ if (targetRow === -1) {
198
+ // 如果为虚拟树
199
+ if (treeConfig && transform) {
200
+ insertTreeRow(newRecords, true)
201
+ } else if (isRowGroupStatus) {
202
+ // 如果分组
203
+ if (treeConfig) {
204
+ throw new Error(getI18n('vxe.error.noTree', ['insert']))
205
+ }
206
+ errLog(getI18n('vxe.error.noGroup', ['insert']))
207
+ // insertGroupRow(newRecords, true)
208
+ } else {
209
+ newRecords.forEach((item) => {
210
+ const rowid = getRowid($xeTable, item)
211
+ const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, treeIndex: -1, _tIndex: -1, $index: -1, items: afterFullData, parent: null, level: 0, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
212
+ fullDataRowIdData[rowid] = rest
213
+ fullAllDataRowIdData[rowid] = rest
214
+ afterFullData.push(item)
215
+ tableFullData.push(item)
216
+ })
217
+ }
218
+ } else {
219
+ // 如果为虚拟树
220
+ if (treeConfig && transform) {
221
+ const matchMapObj = XEUtils.findTree(tableFullTreeData, (item) => targetRow[rowField] === item[rowField], { children: mapChildrenField })
222
+ if (matchMapObj) {
223
+ const { parent: parentRow } = matchMapObj
224
+ const parentMapChilds = parentRow ? parentRow[mapChildrenField] : tableFullTreeData
225
+ const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
226
+ const parentLevel = parentRest ? parentRest.level : 0
227
+ treeRecords.forEach((row, i) => {
228
+ if (parentRow) {
229
+ if (row[parentField] !== parentRow[rowField]) {
230
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, `${parentField}=${parentRow[rowField]}`])
231
+ row[parentField] = parentRow[rowField]
232
+ }
233
+ } else {
234
+ if (row[parentField] !== null) {
235
+ if (!XEUtils.eqNull(row[parentField])) {
236
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, 'null'])
237
+ }
238
+ row[parentField] = null
239
+ }
240
+ }
241
+ let targetIndex = matchMapObj.index + i
242
+ if (isInsertNextRow) {
243
+ targetIndex = targetIndex + 1
244
+ }
245
+ parentMapChilds.splice(targetIndex, 0, row)
246
+ })
247
+ XEUtils.eachTree(
248
+ treeRecords,
249
+ (item) => {
250
+ const rowid = getRowid($xeTable, item)
251
+ const rest = { row: item, rowid, _seq: -1, seq: -1, index: -1, _index: -1, $index: -1, treeIndex: -1, _tIndex: -1, items: parentMapChilds, parent: parentRow, level: parentLevel + 1, height: 0, resizeHeight: 0, oTop: 0, expandHeight: 0 }
252
+ if (item[childrenField]) {
253
+ item[mapChildrenField] = item[childrenField]
254
+ }
255
+ fullDataRowIdData[rowid] = rest
256
+ fullAllDataRowIdData[rowid] = rest
257
+ },
258
+ { children: childrenField }
259
+ )
260
+ // 源
261
+ if (parentRow) {
262
+ const matchObj = XEUtils.findTree(tableFullTreeData, (item) => targetRow[rowField] === item[rowField], { children: childrenField })
263
+ if (matchObj) {
264
+ const parentChilds = matchObj.items
265
+ let targetIndex = matchObj.index
266
+ if (isInsertNextRow) {
267
+ targetIndex = targetIndex + 1
268
+ }
269
+ parentChilds.splice(targetIndex, 0, ...treeRecords)
270
+ }
271
+ }
272
+ } else {
273
+ warnLog('vxe.error.unableInsert')
274
+ insertTreeRow(newRecords, true)
275
+ }
276
+ } else if (isRowGroupStatus) {
277
+ // 如果分组
278
+ if (treeConfig) {
279
+ throw new Error(getI18n('vxe.error.noTree', ['insert']))
280
+ }
281
+ errLog(getI18n('vxe.error.noGroup', ['insert']))
282
+ } else {
283
+ if (treeConfig) {
284
+ throw new Error(getI18n('vxe.error.noTree', ['insert']))
285
+ }
286
+ let afIndex = -1
287
+ // 如果是可视索引
288
+ if (XEUtils.isNumber(targetRow)) {
289
+ if (targetRow < afterFullData.length) {
290
+ afIndex = targetRow
291
+ }
292
+ } else {
293
+ afIndex = $xeTable.findRowIndexOf(afterFullData, targetRow)
294
+ }
295
+ // 如果是插入指定行的下一行
296
+ if (isInsertNextRow) {
297
+ afIndex = Math.min(afterFullData.length, afIndex + 1)
298
+ }
299
+ if (afIndex === -1) {
300
+ throw new Error(getI18n('vxe.error.unableInsert'))
301
+ }
302
+ afterFullData.splice(afIndex, 0, ...newRecords)
303
+ const tfIndex = $xeTable.findRowIndexOf(tableFullData, targetRow)
304
+ if (tfIndex > -1) {
305
+ tableFullData.splice(tfIndex + (isInsertNextRow ? 1 : 0), 0, ...newRecords)
306
+ } else {
307
+ tableFullData.push(...newRecords)
308
+ }
309
+ // 刷新单元格合并
310
+ mergeBodyList.forEach((mergeItem: any) => {
311
+ const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
312
+ if (mergeRowIndex >= afIndex) {
313
+ mergeItem.row = mergeRowIndex + newRecords.length
314
+ } else if (isInsertNextRow ? mergeRowIndex + mergeRowspan >= afIndex : mergeRowIndex + mergeRowspan > afIndex) {
315
+ mergeItem.rowspan = mergeRowspan + newRecords.length
316
+ }
317
+ })
318
+ }
319
+ }
320
+ }
321
+
322
+ const handleStatus = (newRow: any) => {
323
+ const rowid = getRowid($xeTable, newRow)
324
+ // 如果是被删除的数据,则还原状态
325
+ if (removeRowMaps[rowid]) {
326
+ delete removeRowMaps[rowid]
327
+ if (insertRowMaps[rowid]) {
328
+ delete insertRowMaps[rowid]
329
+ }
330
+ } else {
331
+ insertRowMaps[rowid] = newRow
332
+ }
333
+ }
334
+ // 如果为虚拟树
335
+ if (treeConfig && transform) {
336
+ XEUtils.eachTree(treeRecords, handleStatus, { children: mapChildrenField })
337
+ } else {
338
+ newRecords.forEach(handleStatus)
339
+ }
340
+
341
+ reactData.removeRowFlag++
342
+ reactData.insertRowFlag++
343
+ $xeTable.cacheRowMap(false, false)
344
+ $xeTable.updateScrollYStatus()
345
+ $xeTable.handleTableData(treeConfig && transform)
346
+ if (!(treeConfig && transform)) {
347
+ $xeTable.updateAfterDataIndex()
348
+ }
349
+ $xeTable.updateFooter()
350
+ $xeTable.handleUpdateBodyMerge()
351
+ $xeTable.checkSelectionStatus()
352
+ if (reactData.scrollYLoad) {
353
+ $xeTable.updateScrollYSpace()
354
+ }
355
+ return nextTick()
356
+ .then(() => {
357
+ $xeTable.updateCellAreas()
358
+ return $xeTable.recalculate(true)
359
+ })
360
+ .then(() => {
361
+ return {
362
+ row: newRecords.length ? newRecords[newRecords.length - 1] : null,
363
+ rows: newRecords
364
+ }
365
+ })
366
+ }
367
+
368
+ const handleInsertChildRowAt = (records: any, parentRowOrParentId: any, targetRow: any, isInsertNextRow?: boolean) => {
369
+ const { treeConfig } = props
370
+ const { fullAllDataRowIdData } = internalData
371
+ const treeOpts = computeTreeOpts.value
372
+ const { transform, rowField, parentField } = treeOpts
373
+ if (treeConfig && transform) {
374
+ if (!XEUtils.isArray(records)) {
375
+ records = [records]
376
+ }
377
+ let parentRow = parentRowOrParentId
378
+ if (XEUtils.isString(parentRowOrParentId) || XEUtils.isNumber(parentRowOrParentId)) {
379
+ const rowRest = fullAllDataRowIdData[parentRowOrParentId]
380
+ if (rowRest) {
381
+ parentRow = rowRest.row
382
+ }
383
+ }
384
+ return handleInsertRowAt(
385
+ records.map((item: any) => Object.assign({}, item, { [parentField]: parentRow[rowField] })),
386
+ targetRow,
387
+ isInsertNextRow
388
+ )
389
+ } else {
390
+ errLog('vxe.error.errProp', ['tree-config.transform=false', 'tree-config.transform=true'])
391
+ }
392
+ return Promise.resolve({ row: null, rows: [] })
393
+ }
394
+
395
+ const handleClearEdit = (evnt: Event | null, targetRow?: any) => {
396
+ const { editStore } = reactData
397
+ const { actived, focused } = editStore
398
+ const { row, column } = actived
399
+ const validOpts = computeValidOpts.value
400
+ if (row || column) {
401
+ if (targetRow && getRowid($xeTable, targetRow) !== getRowid($xeTable, row)) {
402
+ return nextTick()
403
+ }
404
+ syncActivedCell()
405
+ $xeTable.updateFooter()
406
+ actived.args = null
407
+ actived.row = null
408
+ actived.column = null
409
+ $xeTable.dispatchEvent(
410
+ 'edit-closed',
411
+ {
412
+ row,
413
+ rowIndex: $xeTable.getRowIndex(row),
414
+ $rowIndex: $xeTable.getVMRowIndex(row),
415
+ column,
416
+ columnIndex: $xeTable.getColumnIndex(column),
417
+ $columnIndex: $xeTable.getVMColumnIndex(column)
418
+ },
419
+ evnt || null
420
+ )
421
+ }
422
+ focused.row = null
423
+ focused.column = null
424
+ if (validOpts.autoClear) {
425
+ if (validOpts.msgMode !== 'full' || getConfig().cellVaildMode === 'obsolete') {
426
+ if ($xeTable.clearValidate) {
427
+ return $xeTable.clearValidate()
428
+ }
429
+ }
430
+ }
431
+ return nextTick().then(() => $xeTable.updateCellAreas())
432
+ }
433
+
434
+ const handleEditActive = (
435
+ params: {
436
+ $table: VxeTableConstructor
437
+ column: VxeTableDefines.ColumnInfo
438
+ columnIndex: number
439
+ _columnIndex: number
440
+ $columnIndex: number
441
+ rowIndex: number
442
+ $rowIndex: number
443
+ _rowIndex: number
444
+ row: any
445
+ cell?: HTMLElement
446
+ },
447
+ evnt: Event | null,
448
+ options: {
449
+ isClear?: boolean
450
+ isFocus?: boolean
451
+ isPos?: boolean
452
+ }
453
+ ) => {
454
+ const $xeGrid = $xeTable.xeGrid
455
+ const $xeGantt = $xeTable.xeGantt
456
+
457
+ const { editConfig, mouseConfig } = props
458
+ const { editStore, tableColumn } = reactData
459
+ const editOpts = computeEditOpts.value
460
+ const mouseOpts = computeMouseOpts.value
461
+ const { mode } = editOpts
462
+ const { actived, focused } = editStore
463
+ const { row, column } = params
464
+ const { editRender } = column
465
+ const { isFocus, isPos, isClear } = options
466
+ const cell = (params.cell || $xeTable.getCellElement(row, column)) as HTMLElement
467
+ const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod
468
+ const editParams = { ...params, cell }
469
+ if (cell && isEnableConf(editConfig) && isEnableConf(editRender)) {
470
+ // 激活编辑
471
+ if (!$xeTable.isPendingByRow(row) && !$xeTable.isAggregateRecord(row)) {
472
+ if (actived.row !== row || (mode === 'cell' ? actived.column !== column : false)) {
473
+ // 判断是否禁用编辑
474
+ let type: 'edit-disabled' | 'edit-activated' = 'edit-disabled'
475
+ if (!beforeEditMethod || beforeEditMethod({ ...editParams, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })) {
476
+ if (hasEnableConf(mouseConfig, mouseOpts)) {
477
+ $xeTable.clearSelected()
478
+ if ($xeTable.clearCellAreas) {
479
+ $xeTable.clearCellAreas()
480
+ $xeTable.clearCopyCellArea()
481
+ }
482
+ }
483
+ $xeTable.closeTooltip()
484
+ if (actived.column) {
485
+ handleClearEdit(evnt)
486
+ }
487
+ type = 'edit-activated'
488
+ column.renderHeight = cell.offsetHeight
489
+ actived.args = editParams
490
+ actived.row = row
491
+ actived.column = column
492
+ $xeTable.handlePushStack()
493
+ if (isClear) {
494
+ setCellValue(row, column, null)
495
+ }
496
+ if (mode === 'row') {
497
+ tableColumn.forEach((column: any) => getEditColumnModel(row, column))
498
+ } else {
499
+ getEditColumnModel(row, column)
500
+ }
501
+ const afterEditMethod = editOpts.afterEditMethod
502
+ nextTick(() => {
503
+ if (isFocus) {
504
+ $xeTable.handleFocus(editParams, evnt)
505
+ }
506
+ if (afterEditMethod) {
507
+ afterEditMethod({ ...editParams, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
508
+ }
509
+ })
510
+ }
511
+ $xeTable.dispatchEvent(
512
+ type,
513
+ {
514
+ row,
515
+ rowIndex: $xeTable.getRowIndex(row),
516
+ $rowIndex: $xeTable.getVMRowIndex(row),
517
+ column,
518
+ columnIndex: $xeTable.getColumnIndex(column),
519
+ $columnIndex: $xeTable.getVMColumnIndex(column)
520
+ },
521
+ evnt
522
+ )
523
+
524
+ // v4已废弃
525
+ if (type === 'edit-activated') {
526
+ $xeTable.dispatchEvent(
527
+ 'edit-actived',
528
+ {
529
+ row,
530
+ rowIndex: $xeTable.getRowIndex(row),
531
+ $rowIndex: $xeTable.getVMRowIndex(row),
532
+ column,
533
+ columnIndex: $xeTable.getColumnIndex(column),
534
+ $columnIndex: $xeTable.getVMColumnIndex(column)
535
+ },
536
+ evnt
537
+ )
538
+ }
539
+ } else {
540
+ const { column: oldColumn } = actived
541
+ if (hasEnableConf(mouseConfig, mouseOpts)) {
542
+ $xeTable.clearSelected()
543
+ if ($xeTable.clearCellAreas) {
544
+ $xeTable.clearCellAreas()
545
+ $xeTable.clearCopyCellArea()
546
+ }
547
+ }
548
+ if (oldColumn && oldColumn !== column) {
549
+ const { model: oldModel } = oldColumn
550
+ if (oldModel.update) {
551
+ setCellValue(row, oldColumn, oldModel.value)
552
+ }
553
+ if ($xeTable.clearValidate) {
554
+ $xeTable.clearValidate(row, column)
555
+ }
556
+ }
557
+ column.renderHeight = cell.offsetHeight
558
+ actived.args = editParams
559
+ actived.column = column
560
+ if (isPos) {
561
+ setTimeout(() => {
562
+ $xeTable.handleFocus(editParams, evnt)
563
+ })
564
+ }
565
+ }
566
+ focused.column = null
567
+ focused.row = null
568
+ $xeTable.focus()
569
+ }
570
+ }
571
+ return nextTick()
572
+ }
573
+
574
+ const handleEditCell = (
575
+ row: any,
576
+ fieldOrColumn: string | VxeTableDefines.ColumnInfo | null,
577
+ options: {
578
+ isClear?: boolean | undefined
579
+ isFocus?: boolean | undefined
580
+ isPos?: boolean | undefined
581
+ }
582
+ ) => {
583
+ const { editConfig } = props
584
+ const { isPos } = options
585
+ const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
586
+ if (row && column && isEnableConf(editConfig) && isEnableConf(column.editRender) && !$xeTable.isAggregateRecord(row)) {
587
+ return Promise.resolve(isPos ? $xeTable.scrollToRow(row, column) : null).then(() => {
588
+ const cell = $xeTable.getCellElement(row, column)
589
+ if (cell) {
590
+ handleEditActive(
591
+ {
592
+ row,
593
+ rowIndex: $xeTable.getRowIndex(row),
594
+ $rowIndex: $xeTable.getVMRowIndex(row),
595
+ _rowIndex: $xeTable.getVTRowIndex(row),
596
+ column,
597
+ columnIndex: $xeTable.getColumnIndex(column),
598
+ $columnIndex: $xeTable.getVMColumnIndex(column),
599
+ _columnIndex: $xeTable.getVTColumnIndex(column),
600
+ cell,
601
+ $table: $xeTable
602
+ },
603
+ null,
604
+ {
605
+ isFocus: isPos,
606
+ isPos
607
+ }
608
+ )
609
+ internalData._lastCallTime = Date.now()
610
+ }
611
+ return nextTick()
612
+ })
613
+ }
614
+ return nextTick()
615
+ }
616
+
617
+ editMethods = {
618
+ /**
619
+ * 往表格中插入临时数据
620
+ *
621
+ * @param {*} records
622
+ */
623
+ insert(records) {
624
+ return handleInsertRowAt(records, null)
625
+ },
626
+ /**
627
+ * 往表格指定行中插入临时数据
628
+ * 如果 row 为空则从插入到顶部,如果为树结构,则插入到目标节点顶部
629
+ * 如果 row 为 -1 则从插入到底部,如果为树结构,则插入到目标节点底部
630
+ * 如果 row 为有效行则插入到该行的位置,如果为树结构,则有插入到效的目标节点该行的位置
631
+ */
632
+ insertAt(records, targetRowOrRowid) {
633
+ return handleInsertRowAt(records, targetRowOrRowid)
634
+ },
635
+ insertNextAt(records, targetRowOrRowid) {
636
+ return handleInsertRowAt(records, targetRowOrRowid, true)
637
+ },
638
+ insertChild(records, parentRowOrParentId) {
639
+ return handleInsertChildRowAt(records, parentRowOrParentId, null)
640
+ },
641
+ insertChildAt(records, parentRowOrParentId, targetRow) {
642
+ return handleInsertChildRowAt(records, parentRowOrParentId, targetRow)
643
+ },
644
+ insertChildNextAt(records, parentRowOrParentId, targetRow) {
645
+ return handleInsertChildRowAt(records, parentRowOrParentId, targetRow, true)
646
+ },
647
+ /**
648
+ * 删除指定行数据
649
+ * 如果传 row 则删除一行
650
+ * 如果传 rows 则删除多行
651
+ * 如果为空则删除所有
652
+ */
653
+ remove(rows: any) {
654
+ const { treeConfig } = props
655
+ const { editStore, isRowGroupStatus } = reactData
656
+ const { tableFullTreeData, selectCheckboxMaps, afterFullData, mergeBodyList, tableFullData, pendingRowMaps, insertRowMaps, removeRowMaps } = internalData
657
+ const checkboxOpts = computeCheckboxOpts.value
658
+ const treeOpts = computeTreeOpts.value
659
+ const { transform, mapChildrenField } = treeOpts
660
+ const childrenField = treeOpts.children || treeOpts.childrenField
661
+ const { actived } = editStore
662
+ const { checkField } = checkboxOpts
663
+ let delList: any[] = []
664
+ if (!rows) {
665
+ rows = tableFullData
666
+ } else if (!XEUtils.isArray(rows)) {
667
+ rows = [rows]
668
+ }
669
+ if (!rows.length) {
670
+ return Promise.resolve({ row: null, rows: [] })
671
+ }
672
+ $xeTable.handlePushStack()
673
+ // 如果是新增,则保存记录
674
+ rows.forEach((row: any) => {
675
+ if (!$xeTable.isInsertByRow(row)) {
676
+ const rowid = getRowid($xeTable, row)
677
+ removeRowMaps[rowid] = row
678
+ }
679
+ })
680
+ // 如果绑定了多选属性,则更新状态
681
+ if (!checkField) {
682
+ rows.forEach((row: any) => {
683
+ const rowid = getRowid($xeTable, row)
684
+ if (selectCheckboxMaps[rowid]) {
685
+ delete selectCheckboxMaps[rowid]
686
+ }
687
+ })
688
+ reactData.updateCheckboxFlag++
689
+ }
690
+ // 从数据源中移除
691
+ if (tableFullData === rows) {
692
+ rows = delList = tableFullData.slice(0)
693
+ internalData.tableFullData = []
694
+ internalData.afterFullData = []
695
+ $xeTable.clearMergeCells()
696
+ } else {
697
+ // 如果为虚拟树
698
+ if (treeConfig && transform) {
699
+ rows.forEach((row: any) => {
700
+ const rowid = getRowid($xeTable, row)
701
+ const matchMapObj = XEUtils.findTree(tableFullTreeData, (item) => rowid === getRowid($xeTable, item), { children: mapChildrenField })
702
+ if (matchMapObj) {
703
+ const rItems = matchMapObj.items.splice(matchMapObj.index, 1)
704
+ delList.push(rItems[0])
705
+ }
706
+ const matchObj = XEUtils.findTree(tableFullTreeData, (item) => rowid === getRowid($xeTable, item), { children: childrenField })
707
+ if (matchObj) {
708
+ matchObj.items.splice(matchObj.index, 1)
709
+ }
710
+ const afIndex = $xeTable.findRowIndexOf(afterFullData, row)
711
+ if (afIndex > -1) {
712
+ afterFullData.splice(afIndex, 1)
713
+ }
714
+ })
715
+ } else if (isRowGroupStatus) {
716
+ // 如果分组
717
+ warnLog(getI18n('vxe.error.noGroup', ['remove']))
718
+ } else {
719
+ rows.forEach((row: any) => {
720
+ const tfIndex = $xeTable.findRowIndexOf(tableFullData, row)
721
+ if (tfIndex > -1) {
722
+ const rItems = tableFullData.splice(tfIndex, 1)
723
+ delList.push(rItems[0])
724
+ }
725
+ const afIndex = $xeTable.findRowIndexOf(afterFullData, row)
726
+ if (afIndex > -1) {
727
+ // 刷新单元格合并
728
+ mergeBodyList.forEach((mergeItem) => {
729
+ const { row: mergeRowIndex, rowspan: mergeRowspan } = mergeItem
730
+ if (mergeRowIndex > afIndex) {
731
+ mergeItem.row = mergeRowIndex - 1
732
+ } else if (mergeRowIndex + mergeRowspan > afIndex) {
733
+ mergeItem.rowspan = mergeRowspan - 1
734
+ }
735
+ })
736
+ afterFullData.splice(afIndex, 1)
737
+ }
738
+ })
739
+ }
740
+ }
741
+ // 如果当前行被激活编辑,则清除激活状态
742
+ if (actived.row && $xeTable.findRowIndexOf(rows, actived.row) > -1) {
743
+ editMethods.clearEdit()
744
+ }
745
+ // 从新增中移除已删除的数据
746
+ rows.forEach((row: any) => {
747
+ const rowid = getRowid($xeTable, row)
748
+ if (insertRowMaps[rowid]) {
749
+ delete insertRowMaps[rowid]
750
+ }
751
+ if (pendingRowMaps[rowid]) {
752
+ delete pendingRowMaps[rowid]
753
+ }
754
+ })
755
+ reactData.removeRowFlag++
756
+ reactData.insertRowFlag++
757
+ reactData.pendingRowFlag++
758
+ $xeTable.cacheRowMap(false, false)
759
+ $xeTable.handleTableData(treeConfig && transform)
760
+ $xeTable.updateFooter()
761
+ $xeTable.handleUpdateBodyMerge()
762
+ if (!(treeConfig && transform)) {
763
+ $xeTable.updateAfterDataIndex()
764
+ }
765
+ $xeTable.checkSelectionStatus()
766
+ if (reactData.scrollYLoad) {
767
+ $xeTable.updateScrollYSpace()
768
+ }
769
+ return nextTick()
770
+ .then(() => {
771
+ $xeTable.updateCellAreas()
772
+ return $xeTable.recalculate(true)
773
+ })
774
+ .then(() => {
775
+ return { row: delList.length ? delList[delList.length - 1] : null, rows: delList }
776
+ })
777
+ },
778
+ /**
779
+ * 删除复选框选中的数据
780
+ */
781
+ removeCheckboxRow() {
782
+ return editMethods.remove($xeTable.getCheckboxRecords()).then((params: any) => {
783
+ $xeTable.clearCheckboxRow()
784
+ return params
785
+ })
786
+ },
787
+ /**
788
+ * 删除单选框选中的数据
789
+ */
790
+ removeRadioRow() {
791
+ const radioRecord = $xeTable.getRadioRecord()
792
+ return editMethods.remove(radioRecord || []).then((params: any) => {
793
+ $xeTable.clearRadioRow()
794
+ return params
795
+ })
796
+ },
797
+ /**
798
+ * 删除当前行选中的数据
799
+ */
800
+ removeCurrentRow() {
801
+ const currentRecord = $xeTable.getCurrentRecord()
802
+ return editMethods.remove(currentRecord || []).then((params: any) => {
803
+ $xeTable.clearCurrentRow()
804
+ return params
805
+ })
806
+ },
807
+ /**
808
+ * 获取表格数据集,包含新增、删除、修改、标记
809
+ */
810
+ getRecordset() {
811
+ const removeRecords = editMethods.getRemoveRecords()
812
+ const pendingRecords = $xeTable.getPendingRecords()
813
+ const delRecords = removeRecords.concat(pendingRecords)
814
+ // 如果已经被删除,则无需放到更新数组
815
+ const updateRecords = editMethods.getUpdateRecords().filter((row) => {
816
+ return !delRecords.some((item) => $xeTable.eqRow(item, row))
817
+ })
818
+ return {
819
+ insertRecords: editMethods.getInsertRecords(),
820
+ removeRecords,
821
+ updateRecords,
822
+ pendingRecords
823
+ }
824
+ },
825
+ /**
826
+ * 获取新增的临时数据
827
+ */
828
+ getInsertRecords() {
829
+ const { fullAllDataRowIdData, insertRowMaps } = internalData
830
+ const insertRecords: any[] = []
831
+ XEUtils.each(insertRowMaps, (row, rowid) => {
832
+ if (fullAllDataRowIdData[rowid]) {
833
+ insertRecords.push(row)
834
+ }
835
+ })
836
+ return insertRecords
837
+ },
838
+ /**
839
+ * 获取已删除的数据
840
+ */
841
+ getRemoveRecords() {
842
+ const { removeRowMaps } = internalData
843
+ const removeRecords: any[] = []
844
+ XEUtils.each(removeRowMaps, (row) => {
845
+ removeRecords.push(row)
846
+ })
847
+ return removeRecords
848
+ },
849
+ /**
850
+ * 获取更新数据
851
+ * 只精准匹配 row 的更改
852
+ * 如果是树表格,子节点更改状态不会影响父节点的更新状态
853
+ */
854
+ getUpdateRecords() {
855
+ const { keepSource, treeConfig } = props
856
+ const { tableFullData, tableFullTreeData } = internalData
857
+ const treeOpts = computeTreeOpts.value
858
+ const updateRecords: any[] = []
859
+ if (keepSource) {
860
+ syncActivedCell()
861
+ if (treeConfig) {
862
+ const childrenField = treeOpts.children || treeOpts.childrenField
863
+ XEUtils.eachTree(
864
+ tableFullTreeData,
865
+ (row) => {
866
+ if ($xeTable.isUpdateByRow(row)) {
867
+ updateRecords.push(row)
868
+ }
869
+ },
870
+ { children: childrenField }
871
+ )
872
+ } else {
873
+ tableFullData.forEach((row) => {
874
+ if ($xeTable.isUpdateByRow(row)) {
875
+ updateRecords.push(row)
876
+ }
877
+ })
878
+ }
879
+ }
880
+ return updateRecords
881
+ },
882
+ getActiveRecord() {
883
+ warnLog('vxe.error.delFunc', ['getActiveRecord', 'getEditCell'])
884
+ const { editStore } = reactData
885
+ const { fullAllDataRowIdData } = internalData
886
+ const { args, row } = editStore.actived
887
+ if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
888
+ return Object.assign({}, args, { row })
889
+ }
890
+ return null
891
+ },
892
+ getEditRecord() {
893
+ warnLog('vxe.error.delFunc', ['getEditRecord', 'getEditCell'])
894
+ const { editStore } = reactData
895
+ const { fullAllDataRowIdData } = internalData
896
+ const { args, row } = editStore.actived
897
+ if (args && row && fullAllDataRowIdData[getRowid($xeTable, row)]) {
898
+ return Object.assign({}, args, { row })
899
+ }
900
+ return null
901
+ },
902
+ getEditCell() {
903
+ const { editStore } = reactData
904
+ const { row, column } = editStore.actived
905
+ if (column && row) {
906
+ return {
907
+ row,
908
+ rowIndex: $xeTable.getRowIndex(row),
909
+ column,
910
+ columnIndex: $xeTable.getColumnIndex(column)
911
+ }
912
+ }
913
+ return null
914
+ },
915
+ /**
916
+ * 获取选中的单元格
917
+ */
918
+ getSelectedCell() {
919
+ const { editStore } = reactData
920
+ const { row, column } = editStore.selected
921
+ if (row && column) {
922
+ return {
923
+ row,
924
+ column
925
+ }
926
+ }
927
+ return null
928
+ },
929
+ clearActived(row) {
930
+ // 即将废弃
931
+ warnLog('vxe.error.delFunc', ['clearActived', 'clearEdit'])
932
+ return $xeTable.clearEdit(row)
933
+ },
934
+ /**
935
+ * 清除激活的编辑
936
+ */
937
+ clearEdit(row) {
938
+ return handleClearEdit(null, row)
939
+ },
940
+ /**
941
+ * 清除所选中源状态
942
+ */
943
+ clearSelected() {
944
+ const { editStore } = reactData
945
+ const { selected } = editStore
946
+ selected.row = null
947
+ selected.column = null
948
+ removeCellSelectedClass()
949
+ return nextTick()
950
+ },
951
+ isActiveByRow(row) {
952
+ warnLog('vxe.error.delFunc', ['isActiveByRow', 'isEditByRow'])
953
+ // 即将废弃
954
+ return $xeTable.isEditByRow(row)
955
+ },
956
+ /**
957
+ * 判断行是否为激活编辑状态
958
+ * @param {Row} row 行对象
959
+ */
960
+ isEditByRow(row) {
961
+ const { editStore } = reactData
962
+ return editStore.actived.row === row
963
+ },
964
+ setActiveRow(row) {
965
+ warnLog('vxe.error.delFunc', ['setActiveRow', 'setEditRow'])
966
+ // 即将废弃
967
+ return editMethods.setEditRow(row)
968
+ },
969
+ /**
970
+ * 激活行编辑
971
+ */
972
+ setEditRow(row, fieldOrColumn, options) {
973
+ const { visibleColumn } = internalData
974
+ let column: any = XEUtils.find(visibleColumn, (column) => isEnableConf(column.editRender))
975
+ let isPos = false
976
+ if (fieldOrColumn) {
977
+ isPos = true
978
+ if (fieldOrColumn !== true) {
979
+ column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
980
+ }
981
+ }
982
+ return handleEditCell(
983
+ row,
984
+ column,
985
+ Object.assign(
986
+ {
987
+ isPos,
988
+ isFocus: isPos
989
+ },
990
+ options
991
+ )
992
+ )
993
+ },
994
+ setActiveCell(row, fieldOrColumn) {
995
+ warnLog('vxe.error.delFunc', ['setActiveCell', 'setEditCell'])
996
+ // 即将废弃
997
+ return editMethods.setEditCell(row, fieldOrColumn)
998
+ },
999
+ /**
1000
+ * 激活单元格编辑
1001
+ */
1002
+ setEditCell(row, fieldOrColumn, options) {
1003
+ return handleEditCell(
1004
+ row,
1005
+ fieldOrColumn,
1006
+ Object.assign(
1007
+ {
1008
+ isFocus: true,
1009
+ isPos: true
1010
+ },
1011
+ options
1012
+ )
1013
+ )
1014
+ },
1015
+ /**
1016
+ * 只对 trigger=dblclick 有效,选中单元格
1017
+ */
1018
+ setSelectCell(row, fieldOrColumn) {
1019
+ const { tableData } = reactData
1020
+ const editOpts = computeEditOpts.value
1021
+ const column = XEUtils.isString(fieldOrColumn) ? $xeTable.getColumnByField(fieldOrColumn) : fieldOrColumn
1022
+ if (row && column && editOpts.trigger !== 'manual') {
1023
+ const rowIndex = $xeTable.findRowIndexOf(tableData, row)
1024
+ if (rowIndex > -1 && column) {
1025
+ const cell = $xeTable.getCellElement(row, column)
1026
+ const params = {
1027
+ $table: $xeTable,
1028
+ row,
1029
+ rowIndex,
1030
+ $rowIndex: $xeTable.getVMRowIndex(row),
1031
+ _rowIndex: $xeTable.getVTRowIndex(row),
1032
+ column,
1033
+ columnIndex: $xeTable.getColumnIndex(column),
1034
+ $columnIndex: $xeTable.getVMColumnIndex(column),
1035
+ _columnIndex: $xeTable.getVTColumnIndex(column),
1036
+ cell
1037
+ }
1038
+ $xeTable.handleSelected(params, null)
1039
+ }
1040
+ }
1041
+ return nextTick()
1042
+ }
1043
+ }
1044
+
1045
+ const handleCellFocus = (
1046
+ cell: HTMLElement,
1047
+ params: {
1048
+ $table: VxeTableConstructor
1049
+ column: VxeTableDefines.ColumnInfo
1050
+ row: any
1051
+ }
1052
+ ) => {
1053
+ const { editConfig } = props
1054
+ const { column } = params
1055
+ const { editRender } = column
1056
+ const editOpts = computeEditOpts.value
1057
+ if (editConfig && isEnableConf(editRender)) {
1058
+ const rendererOpts = computeRendererOpts.value
1059
+ const renderName = editRender.name
1060
+ const compRender = renderName ? rendererOpts[renderName] || renderer.get(renderName) : null
1061
+ let autoFocus: boolean | string | ((params: VxeGlobalRendererHandles.TableAutoFocusParams) => HTMLElement | null) | null | undefined = editRender.autofocus || editRender.autoFocus
1062
+ let autoSelect = editRender.autoSelect || editRender.autoselect
1063
+ let inputElem: HTMLElement | null = null
1064
+ // 是否启用聚焦
1065
+ if (editOpts.autoFocus) {
1066
+ if (!autoFocus && compRender) {
1067
+ autoFocus = compRender.tableAutoFocus || compRender.tableAutofocus || compRender.autofocus
1068
+ }
1069
+ if (!autoSelect && compRender) {
1070
+ autoSelect = compRender.tableAutoSelect || compRender.autoselect
1071
+ }
1072
+ // 如果指定了聚焦 class
1073
+ if (XEUtils.isFunction(autoFocus)) {
1074
+ inputElem = autoFocus(params)
1075
+ } else if (autoFocus) {
1076
+ if (autoFocus === true) {
1077
+ // 自动匹配模式,会自动匹配第一个可输入元素
1078
+ inputElem = cell.querySelector('input,textarea')
1079
+ } else {
1080
+ inputElem = cell.querySelector(autoFocus)
1081
+ }
1082
+ if (inputElem) {
1083
+ inputElem.focus()
1084
+ }
1085
+ }
1086
+ }
1087
+ return inputElem as HTMLInputElement
1088
+ }
1089
+ return null
1090
+ }
1091
+
1092
+ editPrivateMethods = {
1093
+ /**
1094
+ * 处理激活编辑
1095
+ */
1096
+ handleEdit(params, evnt, options) {
1097
+ return handleEditActive(
1098
+ params,
1099
+ evnt,
1100
+ Object.assign(
1101
+ {
1102
+ isFocus: true,
1103
+ isPos: true
1104
+ },
1105
+ options
1106
+ )
1107
+ )
1108
+ },
1109
+ /**
1110
+ * @deprecated
1111
+ */
1112
+ handleActived(params, evnt) {
1113
+ return editPrivateMethods.handleEdit(params, evnt)
1114
+ },
1115
+ /**
1116
+ * 处理取消编辑
1117
+ * @param evnt
1118
+ * @returns
1119
+ */
1120
+ handleClearEdit,
1121
+ handleCellFocus,
1122
+ /**
1123
+ * 处理聚焦
1124
+ */
1125
+ handleFocus(params) {
1126
+ const { row, column, cell } = params
1127
+ const { editRender } = column
1128
+ const editOpts = computeEditOpts.value
1129
+ if (isEnableConf(editRender)) {
1130
+ const autoSelect = editRender.autoSelect || editRender.autoselect
1131
+ const inputElem = handleCellFocus(cell, params)
1132
+ if (inputElem) {
1133
+ if (autoSelect) {
1134
+ inputElem.select()
1135
+ } else {
1136
+ // 保持一致行为,光标移到末端
1137
+ if (browseObj.msie) {
1138
+ const textRange = (inputElem as any).createTextRange()
1139
+ textRange.collapse(false)
1140
+ textRange.select()
1141
+ }
1142
+ }
1143
+ } else {
1144
+ // 是否自动定位
1145
+ if (editOpts.autoPos) {
1146
+ if (!column.fixed) {
1147
+ // 显示到可视区中
1148
+ $xeTable.scrollToRow(row, column)
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+ },
1154
+ /**
1155
+ * 处理选中源
1156
+ */
1157
+ handleSelected(params, evnt) {
1158
+ const { mouseConfig, editConfig } = props
1159
+ const { editStore } = reactData
1160
+ const mouseOpts = computeMouseOpts.value
1161
+ const editOpts = computeEditOpts.value
1162
+ const { actived, selected } = editStore
1163
+ const { row, column } = params
1164
+ const isMouseSelected = hasEnableConf(mouseConfig, mouseOpts) && mouseOpts.selected
1165
+ const selectMethod = () => {
1166
+ if (isMouseSelected && (selected.row !== row || selected.column !== column)) {
1167
+ if (actived.row !== row || (editOpts.mode === 'cell' ? actived.column !== column : false)) {
1168
+ handleClearEdit(evnt)
1169
+ $xeTable.clearSelected()
1170
+ if ($xeTable.clearCellAreas) {
1171
+ $xeTable.clearCellAreas()
1172
+ $xeTable.clearCopyCellArea()
1173
+ }
1174
+ selected.args = params
1175
+ selected.row = row
1176
+ selected.column = column
1177
+ if (isMouseSelected) {
1178
+ editPrivateMethods.addCellSelectedClass()
1179
+ }
1180
+ $xeTable.focus()
1181
+ // 如果是支持可复用控件
1182
+ if (editConfig && editOpts.isReuseKeep && isEnableConf(editOpts) && isEnableConf(column.editRender)) {
1183
+ setTimeout(() => {
1184
+ const cell = $xeTable.getCellElement(row, column)
1185
+ if (cell) {
1186
+ const hasReusekeep = cell.querySelector('.vxe-reusekeep-control')
1187
+ if (hasReusekeep) {
1188
+ handleCellFocus(cell, params)
1189
+ }
1190
+ }
1191
+ }, 0)
1192
+ }
1193
+ if (evnt) {
1194
+ $xeTable.dispatchEvent('cell-selected', params, evnt)
1195
+ }
1196
+ }
1197
+ }
1198
+ return nextTick()
1199
+ }
1200
+ return selectMethod()
1201
+ },
1202
+ addCellSelectedClass() {
1203
+ const { editStore } = reactData
1204
+ const { selected } = editStore
1205
+ const { row, column } = selected
1206
+ removeCellSelectedClass()
1207
+ if (row && column) {
1208
+ const cell = $xeTable.getCellElement(row, column)
1209
+ if (cell) {
1210
+ addClass(cell, 'col--selected')
1211
+ }
1212
+ }
1213
+ }
1214
+ }
1215
+
1216
+ return { ...editMethods, ...editPrivateMethods }
1217
+ },
1218
+ setupGrid($xeGrid) {
1219
+ return $xeGrid.extendTableMethods(tableEditMethodKeys)
1220
+ },
1221
+ setupGantt($xeGantt) {
1222
+ return $xeGantt.extendTableMethods(tableEditMethodKeys)
1223
+ }
1224
+ })