vxe-table 3.18.0-beta.8 → 3.18.1

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 (54) hide show
  1. package/es/locale/lang/en-US.js +12 -12
  2. package/es/style.css +1 -1
  3. package/es/table/module/edit/mixin.js +58 -20
  4. package/es/table/module/filter/mixin.js +12 -10
  5. package/es/table/module/keyboard/mixin.js +175 -172
  6. package/es/table/module/menu/mixin.js +16 -9
  7. package/es/table/module/validator/mixin.js +4 -2
  8. package/es/table/src/methods.js +344 -46
  9. package/es/table/src/store.js +8 -0
  10. package/es/table/src/table.js +35 -9
  11. package/es/ui/index.js +1 -1
  12. package/es/ui/src/log.js +1 -1
  13. package/lib/index.umd.js +713 -289
  14. package/lib/index.umd.min.js +1 -1
  15. package/lib/locale/lang/en-US.js +12 -12
  16. package/lib/locale/lang/en-US.min.js +1 -1
  17. package/lib/locale/lang/en-US.umd.js +12 -12
  18. package/lib/style.css +1 -1
  19. package/lib/table/module/edit/mixin.js +55 -16
  20. package/lib/table/module/edit/mixin.min.js +1 -1
  21. package/lib/table/module/filter/mixin.js +12 -10
  22. package/lib/table/module/filter/mixin.min.js +1 -1
  23. package/lib/table/module/keyboard/mixin.js +184 -185
  24. package/lib/table/module/keyboard/mixin.min.js +1 -1
  25. package/lib/table/module/menu/mixin.js +20 -13
  26. package/lib/table/module/menu/mixin.min.js +1 -1
  27. package/lib/table/module/validator/mixin.js +4 -2
  28. package/lib/table/module/validator/mixin.min.js +1 -1
  29. package/lib/table/src/methods.js +388 -52
  30. package/lib/table/src/methods.min.js +1 -1
  31. package/lib/table/src/store.js +15 -0
  32. package/lib/table/src/store.min.js +1 -0
  33. package/lib/table/src/table.js +39 -9
  34. package/lib/table/src/table.min.js +1 -1
  35. package/lib/ui/index.js +1 -1
  36. package/lib/ui/index.min.js +1 -1
  37. package/lib/ui/src/log.js +1 -1
  38. package/lib/ui/src/log.min.js +1 -1
  39. package/package.json +1 -1
  40. package/packages/locale/lang/en-US.ts +12 -12
  41. package/packages/table/module/edit/mixin.ts +59 -23
  42. package/packages/table/module/filter/mixin.ts +17 -13
  43. package/packages/table/module/keyboard/mixin.ts +169 -165
  44. package/packages/table/module/menu/mixin.ts +16 -9
  45. package/packages/table/module/validator/mixin.ts +8 -4
  46. package/packages/table/src/methods.ts +362 -50
  47. package/packages/table/src/store.ts +15 -0
  48. package/packages/table/src/table.ts +37 -9
  49. /package/es/{iconfont.1755775629306.ttf → iconfont.1756272539382.ttf} +0 -0
  50. /package/es/{iconfont.1755775629306.woff → iconfont.1756272539382.woff} +0 -0
  51. /package/es/{iconfont.1755775629306.woff2 → iconfont.1756272539382.woff2} +0 -0
  52. /package/lib/{iconfont.1755775629306.ttf → iconfont.1756272539382.ttf} +0 -0
  53. /package/lib/{iconfont.1755775629306.woff → iconfont.1756272539382.woff} +0 -0
  54. /package/lib/{iconfont.1755775629306.woff2 → iconfont.1756272539382.woff2} +0 -0
@@ -107,14 +107,18 @@ function handleInsertRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMetho
107
107
 
108
108
  const { treeConfig } = props
109
109
  const { isRowGroupStatus } = reactData
110
- const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps } = internalData
110
+ const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps, removeRowMaps } = internalData
111
111
  const treeOpts = $xeTable.computeTreeOpts
112
- const { transform, rowField, mapChildrenField } = treeOpts
112
+ const { transform, parentField, rowField, mapChildrenField } = treeOpts
113
113
  const childrenField = treeOpts.children || treeOpts.childrenField
114
114
  if (!XEUtils.isArray(records)) {
115
115
  records = [records]
116
116
  }
117
117
  const newRecords: any[] = $xeTable.defineField(records.map(record => Object.assign(treeConfig && transform ? { [mapChildrenField]: [], [childrenField]: [] } : {}, record)))
118
+ let treeRecords: any[] = []
119
+ if (treeConfig && transform) {
120
+ treeRecords = XEUtils.toArrayTree(newRecords, { key: rowField, parentKey: parentField, children: childrenField })
121
+ }
118
122
  if (XEUtils.eqNull(targetRow)) {
119
123
  // 如果为虚拟树
120
124
  if (treeConfig && transform) {
@@ -168,42 +172,49 @@ function handleInsertRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMetho
168
172
  } else {
169
173
  // 如果为虚拟树
170
174
  if (treeConfig && transform) {
171
- const matchMapObj = XEUtils.findTree(tableFullTreeData, (item: any) => targetRow[rowField] === item[rowField], { children: mapChildrenField })
175
+ const matchMapObj = XEUtils.findTree(tableFullTreeData, item => targetRow[rowField] === item[rowField], { children: mapChildrenField })
172
176
  if (matchMapObj) {
173
- const { parent: parentRow } = matchMapObj as any
177
+ const { parent: parentRow } = matchMapObj
174
178
  const parentMapChilds = parentRow ? parentRow[mapChildrenField] : tableFullTreeData
175
179
  const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)]
176
180
  const parentLevel = parentRest ? parentRest.level : 0
177
- newRecords.forEach((item: any, i: any) => {
178
- const rowid = getRowid($xeTable, item)
179
- if (item[treeOpts.parentField]) {
180
- if (parentRow && item[treeOpts.parentField] !== parentRow[rowField]) {
181
- errLog('vxe.error.errProp', [`${treeOpts.parentField}=${item[treeOpts.parentField]}`, `${treeOpts.parentField}=${parentRow[rowField]}`])
182
- }
183
- }
181
+ treeRecords.forEach((row, i) => {
184
182
  if (parentRow) {
185
- item[treeOpts.parentField] = parentRow[rowField]
183
+ if (row[parentField] !== parentRow[rowField]) {
184
+ row[parentField] = parentRow[rowField]
185
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, `${parentField}=${parentRow[rowField]}`])
186
+ }
187
+ } else {
188
+ if (row[parentField] !== null) {
189
+ row[parentField] = null
190
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, 'null'])
191
+ }
186
192
  }
187
193
  let targetIndex = matchMapObj.index + i
188
194
  if (isInsertNextRow) {
189
195
  targetIndex = targetIndex + 1
190
196
  }
191
- parentMapChilds.splice(targetIndex, 0, item)
197
+ parentMapChilds.splice(targetIndex, 0, row)
198
+ })
199
+ XEUtils.eachTree(treeRecords, (item) => {
200
+ const rowid = getRowid($xeTable, item)
192
201
  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 }
202
+ if (item[childrenField]) {
203
+ item[mapChildrenField] = item[childrenField]
204
+ }
193
205
  fullDataRowIdData[rowid] = rest
194
206
  fullAllDataRowIdData[rowid] = rest
195
- })
196
-
207
+ }, { children: childrenField })
197
208
  // 源
198
209
  if (parentRow) {
199
- const matchObj = XEUtils.findTree(tableFullTreeData, (item: any) => targetRow[rowField] === item[rowField], { children: childrenField })
210
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => targetRow[rowField] === item[rowField], { children: childrenField })
200
211
  if (matchObj) {
201
212
  const parentChilds = matchObj.items
202
213
  let targetIndex = matchObj.index
203
214
  if (isInsertNextRow) {
204
215
  targetIndex = targetIndex + 1
205
216
  }
206
- parentChilds.splice(targetIndex, 0, ...newRecords)
217
+ parentChilds.splice(targetIndex, 0, ...treeRecords)
207
218
  }
208
219
  }
209
220
  } else {
@@ -234,7 +245,7 @@ function handleInsertRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMetho
234
245
  afIndex = Math.min(afterFullData.length, afIndex + 1)
235
246
  }
236
247
  if (afIndex === -1) {
237
- throw new Error(errLog('vxe.error.unableInsert'))
248
+ throw new Error(getI18n('vxe.error.unableInsert'))
238
249
  }
239
250
  afterFullData.splice(afIndex, 0, ...newRecords)
240
251
  const tfIndex = $xeTable.findRowIndexOf(tableFullData, targetRow)
@@ -255,10 +266,27 @@ function handleInsertRowAt ($xeTable: VxeTableConstructor & VxeTablePrivateMetho
255
266
  }
256
267
  }
257
268
  }
258
- newRecords.forEach(newRow => {
269
+
270
+ const handleStatus = (newRow: any) => {
259
271
  const rowid = getRowid($xeTable, newRow)
260
- insertRowMaps[rowid] = newRow
261
- })
272
+ // 如果是被删除的数据,则还原状态
273
+ if (removeRowMaps[rowid]) {
274
+ delete removeRowMaps[rowid]
275
+ if (insertRowMaps[rowid]) {
276
+ delete insertRowMaps[rowid]
277
+ }
278
+ } else {
279
+ insertRowMaps[rowid] = newRow
280
+ }
281
+ }
282
+ // 如果为虚拟树
283
+ if (treeConfig && transform) {
284
+ XEUtils.eachTree(treeRecords, handleStatus, { children: mapChildrenField })
285
+ } else {
286
+ newRecords.forEach(handleStatus)
287
+ }
288
+
289
+ reactData.removeRowFlag++
262
290
  reactData.insertRowFlag++
263
291
  $xeTable.cacheRowMap(false)
264
292
  $xeTable.updateScrollYStatus()
@@ -815,7 +843,12 @@ export default {
815
843
  const { editStore } = reactData
816
844
  const { row, column } = editStore.actived
817
845
  if (column && row) {
818
- return { row, column }
846
+ return {
847
+ row,
848
+ rowIndex: $xeTable.getRowIndex(row),
849
+ column,
850
+ columnIndex: $xeTable.getColumnIndex(column)
851
+ }
819
852
  }
820
853
  return null
821
854
  },
@@ -1008,7 +1041,10 @@ export default {
1008
1041
  const { editStore } = reactData
1009
1042
  const { row, column } = editStore.selected
1010
1043
  if (row && column) {
1011
- return { row, column }
1044
+ return {
1045
+ row,
1046
+ column
1047
+ }
1012
1048
  }
1013
1049
  return null
1014
1050
  },
@@ -15,11 +15,13 @@ export default {
15
15
  * @param column
16
16
  */
17
17
  _openFilter (fieldOrColumn: any) {
18
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
19
+
18
20
  const column = handleFieldOrColumn(this, fieldOrColumn)
19
21
  if (column && column.filters) {
20
22
  const { elemStore } = this
21
23
  const { fixed } = column
22
- return this.scrollToColumn(column).then(() => {
24
+ return $xeTable.scrollToColumn(column).then(() => {
23
25
  const headerWrapperElem = elemStore[`${fixed || 'main'}-header-wrapper`] || elemStore['main-header-wrapper']
24
26
  if (headerWrapperElem) {
25
27
  const filterBtnElem = headerWrapperElem.querySelector(`.vxe-header--column.${column.id} .vxe-cell--filter`)
@@ -27,7 +29,7 @@ export default {
27
29
  }
28
30
  })
29
31
  }
30
- return this.$nextTick()
32
+ return $xeTable.$nextTick()
31
33
  },
32
34
  /**
33
35
  * 修改筛选条件列表
@@ -195,9 +197,9 @@ export default {
195
197
  return filterList
196
198
  },
197
199
  handleColumnConfirmFilter (column: VxeTableDefines.ColumnInfo, evnt: Event | null) {
198
- const $xeTable = this
200
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
199
201
  const props = $xeTable
200
- const reactData = $xeTable
202
+ const reactData = $xeTable as unknown as TableReactData
201
203
 
202
204
  const { mouseConfig } = props
203
205
  const { scrollXLoad: oldScrollXLoad, scrollYLoad: oldScrollYLoad } = reactData
@@ -212,22 +214,22 @@ export default {
212
214
  datas.push(item.data)
213
215
  }
214
216
  })
215
- const filterList = this.getCheckedFilters()
216
- const params = { $table: this, $event: evnt, column, field, property: field, values, datas, filters: filterList, filterList }
217
+ const filterList = $xeTable.getCheckedFilters()
218
+ const params = { $table: $xeTable, $event: evnt as Event, column, field, property: field, values, datas, filters: filterList, filterList }
217
219
  // 如果是服务端筛选,则跳过本地筛选处理
218
220
  if (!filterOpts.remote) {
219
- this.handleTableData(true)
220
- this.checkSelectionStatus()
221
+ $xeTable.handleTableData(true)
222
+ $xeTable.checkSelectionStatus()
221
223
  }
222
- if (mouseConfig && mouseOpts.area && this.handleFilterEvent) {
223
- $xeTable.handleFilterEvent(evnt, params)
224
+ if (mouseConfig && mouseOpts.area && $xeTable.handleFilterEvent) {
225
+ $xeTable.handleFilterEvent(evnt as Event, params)
224
226
  }
225
227
  if (evnt) {
226
- $xeTable.emitEvent('filter-change', params, evnt)
228
+ $xeTable.dispatchEvent('filter-change', params, evnt)
227
229
  }
228
230
  $xeTable.closeFilter()
229
231
  return $xeTable.updateFooter().then(() => {
230
- const { scrollXLoad, scrollYLoad } = this
232
+ const { scrollXLoad, scrollYLoad } = reactData
231
233
  if ((oldScrollXLoad || scrollXLoad) || (oldScrollYLoad || scrollYLoad)) {
232
234
  if ((oldScrollXLoad || scrollXLoad)) {
233
235
  $xeTable.updateScrollXSpace()
@@ -259,6 +261,8 @@ export default {
259
261
  $xeTable.handleColumnConfirmFilter(column, evnt)
260
262
  },
261
263
  handleClearFilter (column: any) {
264
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
265
+
262
266
  if (column) {
263
267
  const { filters, filterRender } = column
264
268
  if (filters) {
@@ -272,7 +276,7 @@ export default {
272
276
  }
273
277
  })
274
278
  if (filterResetMethod) {
275
- filterResetMethod({ options: filters, column, $table: this })
279
+ filterResetMethod({ options: filters, column, $table: $xeTable })
276
280
  }
277
281
  }
278
282
  }
@@ -130,6 +130,167 @@ function handleMoveSelected ($xeTable: VxeTableConstructor & VxeTablePrivateMeth
130
130
  return params
131
131
  }
132
132
 
133
+ function handleCheckboxRangeEvent ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, evnt: any, params: any) {
134
+ const internalData = $xeTable as unknown as TableInternalData
135
+
136
+ const { elemStore } = internalData
137
+ const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
138
+ const leftScrollElem = getRefElem(elemStore['left-body-scroll'])
139
+ const rightScrollElem = getRefElem(elemStore['right-body-scroll'])
140
+ const { column, cell } = params
141
+ if (column.type === 'checkbox') {
142
+ let bodyWrapperElem = bodyScrollElem as HTMLElement
143
+ if (leftScrollElem && column.fixed === 'left') {
144
+ bodyWrapperElem = leftScrollElem
145
+ } else if (rightScrollElem && column.fixed === 'right') {
146
+ bodyWrapperElem = rightScrollElem
147
+ }
148
+ if (!bodyWrapperElem) {
149
+ return
150
+ }
151
+ const el = $xeTable.$refs.refElem as HTMLDivElement
152
+ const disX = evnt.clientX
153
+ const disY = evnt.clientY
154
+ const checkboxRangeElem = bodyWrapperElem.querySelector('.vxe-table--checkbox-range') as HTMLElement
155
+ const trElem = cell.parentNode
156
+ const selectRecords = $xeTable.getCheckboxRecords()
157
+ let lastRangeRows = []
158
+ const marginSize = 1
159
+ const offsetRest = getTargetOffset(evnt.target, bodyWrapperElem)
160
+ const startTop = offsetRest.offsetTop + evnt.offsetY
161
+ const startLeft = offsetRest.offsetLeft + evnt.offsetX
162
+ const startScrollTop = bodyWrapperElem.scrollTop
163
+ const rowHeight = trElem.offsetHeight
164
+ const trRect = trElem.getBoundingClientRect()
165
+ const offsetClientTop = disY - trRect.y
166
+ let mouseScrollTimeout: any = null
167
+ let isMouseScrollDown: any = false
168
+ let mouseScrollSpaceSize = 1
169
+ const triggerEvent = (type: any, evnt: any) => {
170
+ $xeTable.dispatchEvent(`checkbox-range-${type}` as 'checkbox-range-change' | 'checkbox-range-start' | 'checkbox-range-end', {
171
+ records: () => $xeTable.getCheckboxRecords(),
172
+ reserves: () => $xeTable.getCheckboxReserveRecords()
173
+ }, evnt)
174
+ }
175
+ const handleChecked = (evnt: any) => {
176
+ const { clientX, clientY } = evnt
177
+ const offsetLeft = clientX - disX
178
+ const offsetTop = clientY - disY + (bodyWrapperElem.scrollTop - startScrollTop)
179
+ let rangeHeight = Math.abs(offsetTop)
180
+ let rangeWidth = Math.abs(offsetLeft)
181
+ let rangeTop = startTop
182
+ let rangeLeft = startLeft
183
+ if (offsetTop < marginSize) {
184
+ // 向上
185
+ rangeTop += offsetTop
186
+ if (rangeTop < marginSize) {
187
+ rangeTop = marginSize
188
+ rangeHeight = startTop
189
+ }
190
+ } else {
191
+ // 向下
192
+ rangeHeight = Math.min(rangeHeight, bodyWrapperElem.scrollHeight - startTop - marginSize)
193
+ }
194
+ if (offsetLeft < marginSize) {
195
+ // 向左
196
+ rangeLeft += offsetLeft
197
+ if (rangeWidth > startLeft) {
198
+ rangeLeft = marginSize
199
+ rangeWidth = startLeft
200
+ }
201
+ } else {
202
+ // 向右
203
+ rangeWidth = Math.min(rangeWidth, bodyWrapperElem.clientWidth - startLeft - marginSize)
204
+ }
205
+ checkboxRangeElem.style.height = `${rangeHeight}px`
206
+ checkboxRangeElem.style.width = `${rangeWidth}px`
207
+ checkboxRangeElem.style.left = `${rangeLeft}px`
208
+ checkboxRangeElem.style.top = `${rangeTop}px`
209
+ checkboxRangeElem.style.display = 'block'
210
+ const rangeRows = getCheckboxRangeRows($xeTable, evnt, params, trElem, trRect, offsetClientTop, offsetTop < marginSize ? -rangeHeight : rangeHeight)
211
+ // 至少滑动 10px 才能有效匹配
212
+ if (rangeHeight > 10 && rangeRows.length !== lastRangeRows.length) {
213
+ const isControlKey = hasControlKey(evnt)
214
+ lastRangeRows = rangeRows
215
+ if (isControlKey) {
216
+ rangeRows.forEach((row: any) => {
217
+ $xeTable.handleBatchSelectRows([row], selectRecords.indexOf(row) === -1)
218
+ })
219
+ } else {
220
+ $xeTable.setAllCheckboxRow(false)
221
+ $xeTable.handleCheckedCheckboxRow(rangeRows, true, false)
222
+ }
223
+ triggerEvent('change', evnt)
224
+ }
225
+ }
226
+ // 停止鼠标滚动
227
+ const stopMouseScroll = () => {
228
+ clearTimeout(mouseScrollTimeout)
229
+ mouseScrollTimeout = null
230
+ }
231
+ // 开始鼠标滚动
232
+ const startMouseScroll = (evnt: any) => {
233
+ stopMouseScroll()
234
+ mouseScrollTimeout = setTimeout(() => {
235
+ if (mouseScrollTimeout) {
236
+ const { scrollLeft, scrollTop, clientHeight, scrollHeight } = bodyWrapperElem
237
+ const topSize = Math.ceil(mouseScrollSpaceSize * 50 / rowHeight)
238
+ if (isMouseScrollDown) {
239
+ if (scrollTop + clientHeight < scrollHeight) {
240
+ $xeTable.scrollTo(scrollLeft, scrollTop + topSize)
241
+ startMouseScroll(evnt)
242
+ handleChecked(evnt)
243
+ } else {
244
+ stopMouseScroll()
245
+ }
246
+ } else {
247
+ if (scrollTop) {
248
+ $xeTable.scrollTo(scrollLeft, scrollTop - topSize)
249
+ startMouseScroll(evnt)
250
+ handleChecked(evnt)
251
+ } else {
252
+ stopMouseScroll()
253
+ }
254
+ }
255
+ }
256
+ }, 50)
257
+ }
258
+ addClass(el, 'drag--range')
259
+ document.onmousemove = evnt => {
260
+ evnt.preventDefault()
261
+ evnt.stopPropagation()
262
+ const { clientY } = evnt
263
+ const { boundingTop } = getAbsolutePos(bodyWrapperElem)
264
+ // 如果超过可视区,触发滚动
265
+ if (clientY < boundingTop) {
266
+ isMouseScrollDown = false
267
+ mouseScrollSpaceSize = boundingTop - clientY
268
+ if (!mouseScrollTimeout) {
269
+ startMouseScroll(evnt)
270
+ }
271
+ } else if (clientY > boundingTop + bodyWrapperElem.clientHeight) {
272
+ isMouseScrollDown = true
273
+ mouseScrollSpaceSize = clientY - boundingTop - bodyWrapperElem.clientHeight
274
+ if (!mouseScrollTimeout) {
275
+ startMouseScroll(evnt)
276
+ }
277
+ } else if (mouseScrollTimeout) {
278
+ stopMouseScroll()
279
+ }
280
+ handleChecked(evnt)
281
+ }
282
+ document.onmouseup = (evnt) => {
283
+ stopMouseScroll()
284
+ removeClass(el, 'drag--range')
285
+ checkboxRangeElem.removeAttribute('style')
286
+ document.onmousemove = null
287
+ document.onmouseup = null
288
+ triggerEvent('end', evnt)
289
+ }
290
+ triggerEvent('start', evnt)
291
+ }
292
+ }
293
+
133
294
  export default {
134
295
  methods: {
135
296
  // 处理 Tab 键移动
@@ -344,181 +505,24 @@ export default {
344
505
  },
345
506
  handleCellMousedownEvent (evnt: any, params: any) {
346
507
  const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
508
+ const props = $xeTable
347
509
 
348
- const { editConfig, editOpts, handleSelected, checkboxConfig, checkboxOpts, mouseConfig, mouseOpts } = this
510
+ const { editConfig, checkboxConfig, mouseConfig } = props
511
+ const checkboxOpts = $xeTable.computeCheckboxOpts
512
+ const mouseOpts = $xeTable.computeMouseOpts
513
+ const editOpts = $xeTable.computeEditOpts
349
514
  if (mouseConfig && mouseOpts.area && $xeTable.triggerCellAreaModnEvent) {
350
515
  return $xeTable.triggerCellAreaModnEvent(evnt, params)
351
516
  } else {
352
517
  if (checkboxConfig && checkboxOpts.range) {
353
- this.handleCheckboxRangeEvent(evnt, params)
518
+ handleCheckboxRangeEvent($xeTable, evnt, params)
354
519
  }
355
520
  if (mouseConfig && mouseOpts.selected) {
356
521
  if (!editConfig || editOpts.mode === 'cell') {
357
- handleSelected(params, evnt)
358
- }
359
- }
360
- }
361
- },
362
- handleCheckboxRangeEvent (evnt: any, params: any) {
363
- const $xeTable = this
364
- const internalData = $xeTable
365
-
366
- const { elemStore } = internalData
367
- const bodyScrollElem = getRefElem(elemStore['main-body-scroll'])
368
- const leftScrollElem = getRefElem(elemStore['left-body-scroll'])
369
- const rightScrollElem = getRefElem(elemStore['right-body-scroll'])
370
- const { column, cell } = params
371
- if (column.type === 'checkbox') {
372
- let bodyWrapperElem = bodyScrollElem as HTMLElement
373
- if (leftScrollElem && column.fixed === 'left') {
374
- bodyWrapperElem = leftScrollElem
375
- } else if (rightScrollElem && column.fixed === 'right') {
376
- bodyWrapperElem = rightScrollElem
377
- }
378
- if (!bodyWrapperElem) {
379
- return
380
- }
381
- const el = $xeTable.$refs.refElem as HTMLDivElement
382
- const disX = evnt.clientX
383
- const disY = evnt.clientY
384
- const checkboxRangeElem = bodyWrapperElem.querySelector('.vxe-table--checkbox-range') as HTMLElement
385
- const trElem = cell.parentNode
386
- const selectRecords = this.getCheckboxRecords()
387
- let lastRangeRows = []
388
- const marginSize = 1
389
- const offsetRest = getTargetOffset(evnt.target, bodyWrapperElem)
390
- const startTop = offsetRest.offsetTop + evnt.offsetY
391
- const startLeft = offsetRest.offsetLeft + evnt.offsetX
392
- const startScrollTop = bodyWrapperElem.scrollTop
393
- const rowHeight = trElem.offsetHeight
394
- const trRect = trElem.getBoundingClientRect()
395
- const offsetClientTop = disY - trRect.y
396
- let mouseScrollTimeout: any = null
397
- let isMouseScrollDown: any = false
398
- let mouseScrollSpaceSize = 1
399
- const triggerEvent = (type: any, evnt: any) => {
400
- this.emitEvent(`checkbox-range-${type}`, {
401
- records: () => this.getCheckboxRecords(),
402
- reserves: () => this.getCheckboxReserveRecords()
403
- }, evnt)
404
- }
405
- const handleChecked = (evnt: any) => {
406
- const { clientX, clientY } = evnt
407
- const offsetLeft = clientX - disX
408
- const offsetTop = clientY - disY + (bodyWrapperElem.scrollTop - startScrollTop)
409
- let rangeHeight = Math.abs(offsetTop)
410
- let rangeWidth = Math.abs(offsetLeft)
411
- let rangeTop = startTop
412
- let rangeLeft = startLeft
413
- if (offsetTop < marginSize) {
414
- // 向上
415
- rangeTop += offsetTop
416
- if (rangeTop < marginSize) {
417
- rangeTop = marginSize
418
- rangeHeight = startTop
419
- }
420
- } else {
421
- // 向下
422
- rangeHeight = Math.min(rangeHeight, bodyWrapperElem.scrollHeight - startTop - marginSize)
423
- }
424
- if (offsetLeft < marginSize) {
425
- // 向左
426
- rangeLeft += offsetLeft
427
- if (rangeWidth > startLeft) {
428
- rangeLeft = marginSize
429
- rangeWidth = startLeft
430
- }
431
- } else {
432
- // 向右
433
- rangeWidth = Math.min(rangeWidth, bodyWrapperElem.clientWidth - startLeft - marginSize)
434
- }
435
- checkboxRangeElem.style.height = `${rangeHeight}px`
436
- checkboxRangeElem.style.width = `${rangeWidth}px`
437
- checkboxRangeElem.style.left = `${rangeLeft}px`
438
- checkboxRangeElem.style.top = `${rangeTop}px`
439
- checkboxRangeElem.style.display = 'block'
440
- const rangeRows = getCheckboxRangeRows(this, evnt, params, trElem, trRect, offsetClientTop, offsetTop < marginSize ? -rangeHeight : rangeHeight)
441
- // 至少滑动 10px 才能有效匹配
442
- if (rangeHeight > 10 && rangeRows.length !== lastRangeRows.length) {
443
- const isControlKey = hasControlKey(evnt)
444
- lastRangeRows = rangeRows
445
- if (isControlKey) {
446
- rangeRows.forEach((row: any) => {
447
- $xeTable.handleBatchSelectRows([row], selectRecords.indexOf(row) === -1)
448
- })
449
- } else {
450
- this.setAllCheckboxRow(false)
451
- this.handleCheckedCheckboxRow(rangeRows, true, false)
452
- }
453
- triggerEvent('change', evnt)
454
- }
455
- }
456
- // 停止鼠标滚动
457
- const stopMouseScroll = () => {
458
- clearTimeout(mouseScrollTimeout)
459
- mouseScrollTimeout = null
460
- }
461
- // 开始鼠标滚动
462
- const startMouseScroll = (evnt: any) => {
463
- stopMouseScroll()
464
- mouseScrollTimeout = setTimeout(() => {
465
- if (mouseScrollTimeout) {
466
- const { scrollLeft, scrollTop, clientHeight, scrollHeight } = bodyWrapperElem
467
- const topSize = Math.ceil(mouseScrollSpaceSize * 50 / rowHeight)
468
- if (isMouseScrollDown) {
469
- if (scrollTop + clientHeight < scrollHeight) {
470
- this.scrollTo(scrollLeft, scrollTop + topSize)
471
- startMouseScroll(evnt)
472
- handleChecked(evnt)
473
- } else {
474
- stopMouseScroll()
475
- }
476
- } else {
477
- if (scrollTop) {
478
- this.scrollTo(scrollLeft, scrollTop - topSize)
479
- startMouseScroll(evnt)
480
- handleChecked(evnt)
481
- } else {
482
- stopMouseScroll()
483
- }
484
- }
485
- }
486
- }, 50)
487
- }
488
- addClass(el, 'drag--range')
489
- document.onmousemove = evnt => {
490
- evnt.preventDefault()
491
- evnt.stopPropagation()
492
- const { clientY } = evnt
493
- const { boundingTop } = getAbsolutePos(bodyWrapperElem)
494
- // 如果超过可视区,触发滚动
495
- if (clientY < boundingTop) {
496
- isMouseScrollDown = false
497
- mouseScrollSpaceSize = boundingTop - clientY
498
- if (!mouseScrollTimeout) {
499
- startMouseScroll(evnt)
500
- }
501
- } else if (clientY > boundingTop + bodyWrapperElem.clientHeight) {
502
- isMouseScrollDown = true
503
- mouseScrollSpaceSize = clientY - boundingTop - bodyWrapperElem.clientHeight
504
- if (!mouseScrollTimeout) {
505
- startMouseScroll(evnt)
506
- }
507
- } else if (mouseScrollTimeout) {
508
- stopMouseScroll()
522
+ $xeTable.handleSelected(params, evnt)
509
523
  }
510
- handleChecked(evnt)
511
524
  }
512
- document.onmouseup = (evnt) => {
513
- stopMouseScroll()
514
- removeClass(el, 'drag--range')
515
- checkboxRangeElem.removeAttribute('style')
516
- document.onmousemove = null
517
- document.onmouseup = null
518
- triggerEvent('end', evnt)
519
- }
520
- triggerEvent('start', evnt)
521
525
  }
522
526
  }
523
- } as any
527
+ }
524
528
  }
@@ -105,22 +105,29 @@ export default {
105
105
  const params: any = { type: layout, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, columns: this.visibleColumn.slice(0), $event: evnt }
106
106
  if (columnTargetNode.flag) {
107
107
  const cell = columnTargetNode.targetElem
108
- const column = this.getColumnNode(cell).item
108
+ const columnNodeRest = $xeTable.getColumnNode(cell)
109
+ const column = columnNodeRest ? columnNodeRest.item : null
109
110
  let typePrefix = `${layout}-`
110
- Object.assign(params, { column, columnIndex: this.getColumnIndex(column), cell })
111
+ if (column) {
112
+ Object.assign(params, { column, columnIndex: $xeTable.getColumnIndex(column), cell })
113
+ }
111
114
  if (layout === 'body') {
112
- const row = this.getRowNode(cell.parentNode).item
115
+ const rowNodeRest = $xeTable.getRowNode(cell.parentNode)
116
+ const row = rowNodeRest ? rowNodeRest.item : null
113
117
  typePrefix = ''
114
- params.row = row
115
- params.rowIndex = this.getRowIndex(row)
118
+ if (row) {
119
+ params.row = row
120
+ params.rowIndex = $xeTable.getRowIndex(row)
121
+ }
116
122
  }
123
+ const eventType = `${typePrefix}cell-menu` as 'cell-menu' | 'header-cell-menu' | 'footer-cell-menu'
117
124
  this.handleOpenMenuEvent(evnt, layout, params)
118
125
  // 在 v4 中废弃事件 cell-context-menu、header-cell-context-menu、footer-cell-context-menu
119
126
  if (this.$listeners[`${typePrefix}cell-context-menu`]) {
120
127
  warnLog('vxe.error.delEvent', [`${typePrefix}cell-context-menu`, `${typePrefix}cell-menu`])
121
- this.emitEvent(`${typePrefix}cell-context-menu`, params, evnt)
128
+ $xeTable.dispatchEvent(`${typePrefix}cell-context-menu` as any, params, evnt)
122
129
  } else {
123
- this.emitEvent(`${typePrefix}cell-menu`, params, evnt)
130
+ $xeTable.dispatchEvent(eventType, params, evnt)
124
131
  }
125
132
  return
126
133
  } else if (getEventTargetNode(evnt, this.$el, `vxe-table--${layout}-wrapper`, target => target.getAttribute('xid') === tId).flag) {
@@ -271,9 +278,9 @@ export default {
271
278
  // 在 v4 中废弃事件 context-menu-click
272
279
  if (this.$listeners['context-menu-click']) {
273
280
  warnLog('vxe.error.delEvent', ['context-menu-click', 'menu-click'])
274
- this.emitEvent('context-menu-click', params, evnt)
281
+ $xeTable.dispatchEvent('context-menu-click' as any, params, evnt)
275
282
  } else {
276
- this.emitEvent('menu-click', params, evnt)
283
+ $xeTable.dispatchEvent('menu-click', params, evnt)
277
284
  }
278
285
  this.closeMenu()
279
286
  }