vxe-table 4.18.7 → 4.18.8

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