vxe-table 4.16.0 → 4.16.2

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 (73) hide show
  1. package/es/grid/src/grid.js +1 -1
  2. package/es/index.css +1 -1
  3. package/es/index.min.css +1 -1
  4. package/es/style.css +1 -1
  5. package/es/style.min.css +1 -1
  6. package/es/table/module/edit/hook.js +55 -17
  7. package/es/table/src/column.js +2 -0
  8. package/es/table/src/columnInfo.js +1 -0
  9. package/es/table/src/emits.js +5 -0
  10. package/es/table/src/header.js +47 -16
  11. package/es/table/src/props.js +11 -3
  12. package/es/table/src/store.js +8 -0
  13. package/es/table/src/table.js +579 -87
  14. package/es/table/src/util.js +70 -2
  15. package/es/table/style.css +11 -17
  16. package/es/table/style.min.css +1 -1
  17. package/es/ui/index.js +2 -2
  18. package/es/ui/src/log.js +1 -1
  19. package/es/vxe-table/style.css +11 -17
  20. package/es/vxe-table/style.min.css +1 -1
  21. package/lib/grid/src/grid.js +1 -1
  22. package/lib/grid/src/grid.min.js +1 -1
  23. package/lib/index.css +1 -1
  24. package/lib/index.min.css +1 -1
  25. package/lib/index.umd.js +265 -65
  26. package/lib/index.umd.min.js +1 -1
  27. package/lib/style.css +1 -1
  28. package/lib/style.min.css +1 -1
  29. package/lib/table/module/edit/hook.js +54 -15
  30. package/lib/table/module/edit/hook.min.js +1 -1
  31. package/lib/table/src/column.js +2 -0
  32. package/lib/table/src/column.min.js +1 -1
  33. package/lib/table/src/columnInfo.js +1 -0
  34. package/lib/table/src/columnInfo.min.js +1 -1
  35. package/lib/table/src/emits.js +1 -1
  36. package/lib/table/src/emits.min.js +1 -1
  37. package/lib/table/src/header.js +62 -13
  38. package/lib/table/src/header.min.js +1 -1
  39. package/lib/table/src/props.js +11 -3
  40. package/lib/table/src/props.min.js +1 -1
  41. package/lib/table/src/store.js +15 -0
  42. package/lib/table/src/store.min.js +1 -0
  43. package/lib/table/src/table.js +45 -25
  44. package/lib/table/src/table.min.js +1 -1
  45. package/lib/table/src/util.js +74 -2
  46. package/lib/table/src/util.min.js +1 -1
  47. package/lib/table/style/style.css +11 -17
  48. package/lib/table/style/style.min.css +1 -1
  49. package/lib/ui/index.js +2 -2
  50. package/lib/ui/index.min.js +1 -1
  51. package/lib/ui/src/log.js +1 -1
  52. package/lib/ui/src/log.min.js +1 -1
  53. package/lib/vxe-table/style/style.css +11 -17
  54. package/lib/vxe-table/style/style.min.css +1 -1
  55. package/package.json +2 -2
  56. package/packages/grid/src/grid.ts +1 -1
  57. package/packages/table/module/edit/hook.ts +55 -19
  58. package/packages/table/src/column.ts +2 -0
  59. package/packages/table/src/columnInfo.ts +1 -0
  60. package/packages/table/src/emits.ts +6 -0
  61. package/packages/table/src/header.ts +49 -17
  62. package/packages/table/src/props.ts +11 -3
  63. package/packages/table/src/store.ts +14 -0
  64. package/packages/table/src/table.ts +583 -83
  65. package/packages/table/src/util.ts +76 -2
  66. package/packages/ui/index.ts +1 -1
  67. package/styles/components/table.scss +33 -55
  68. /package/es/{iconfont.1756083655214.ttf → iconfont.1756452373591.ttf} +0 -0
  69. /package/es/{iconfont.1756083655214.woff → iconfont.1756452373591.woff} +0 -0
  70. /package/es/{iconfont.1756083655214.woff2 → iconfont.1756452373591.woff2} +0 -0
  71. /package/lib/{iconfont.1756083655214.ttf → iconfont.1756452373591.ttf} +0 -0
  72. /package/lib/{iconfont.1756083655214.woff → iconfont.1756452373591.woff} +0 -0
  73. /package/lib/{iconfont.1756083655214.woff2 → iconfont.1756452373591.woff2} +0 -0
@@ -98,14 +98,18 @@ hooks.add('tableEditModule', {
98
98
  const handleInsertRowAt = (records, targetRow, isInsertNextRow) => {
99
99
  const { treeConfig } = props;
100
100
  const { isRowGroupStatus } = reactData;
101
- const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps } = internalData;
101
+ const { tableFullTreeData, afterFullData, mergeBodyList, tableFullData, fullDataRowIdData, fullAllDataRowIdData, insertRowMaps, removeRowMaps } = internalData;
102
102
  const treeOpts = computeTreeOpts.value;
103
- const { transform, rowField, mapChildrenField } = treeOpts;
103
+ const { transform, parentField, rowField, mapChildrenField } = treeOpts;
104
104
  const childrenField = treeOpts.children || treeOpts.childrenField;
105
105
  if (!XEUtils.isArray(records)) {
106
106
  records = [records];
107
107
  }
108
108
  const newRecords = reactive($xeTable.defineField(records.map((record) => Object.assign(treeConfig && transform ? { [mapChildrenField]: [], [childrenField]: [] } : {}, record))));
109
+ let treeRecords = [];
110
+ if (treeConfig && transform) {
111
+ treeRecords = XEUtils.toArrayTree(newRecords, { key: rowField, parentKey: parentField, children: childrenField });
112
+ }
109
113
  if (XEUtils.eqNull(targetRow)) {
110
114
  // 如果为虚拟树
111
115
  if (treeConfig && transform) {
@@ -171,25 +175,34 @@ hooks.add('tableEditModule', {
171
175
  const parentMapChilds = parentRow ? parentRow[mapChildrenField] : tableFullTreeData;
172
176
  const parentRest = fullAllDataRowIdData[getRowid($xeTable, parentRow)];
173
177
  const parentLevel = parentRest ? parentRest.level : 0;
174
- newRecords.forEach((item, i) => {
175
- const rowid = getRowid($xeTable, item);
176
- if (item[treeOpts.parentField]) {
177
- if (parentRow && item[treeOpts.parentField] !== parentRow[rowField]) {
178
- errLog('vxe.error.errProp', [`${treeOpts.parentField}=${item[treeOpts.parentField]}`, `${treeOpts.parentField}=${parentRow[rowField]}`]);
178
+ treeRecords.forEach((row, i) => {
179
+ if (parentRow) {
180
+ if (row[parentField] !== parentRow[rowField]) {
181
+ row[parentField] = parentRow[rowField];
182
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, `${parentField}=${parentRow[rowField]}`]);
179
183
  }
180
184
  }
181
- if (parentRow) {
182
- item[treeOpts.parentField] = parentRow[rowField];
185
+ else {
186
+ if (row[parentField] !== null) {
187
+ row[parentField] = null;
188
+ errLog('vxe.error.errProp', [`${parentField}=${row[parentField]}`, 'null']);
189
+ }
183
190
  }
184
191
  let targetIndex = matchMapObj.index + i;
185
192
  if (isInsertNextRow) {
186
193
  targetIndex = targetIndex + 1;
187
194
  }
188
- parentMapChilds.splice(targetIndex, 0, item);
195
+ parentMapChilds.splice(targetIndex, 0, row);
196
+ });
197
+ XEUtils.eachTree(treeRecords, (item) => {
198
+ const rowid = getRowid($xeTable, item);
189
199
  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 };
200
+ if (item[childrenField]) {
201
+ item[mapChildrenField] = item[childrenField];
202
+ }
190
203
  fullDataRowIdData[rowid] = rest;
191
204
  fullAllDataRowIdData[rowid] = rest;
192
- });
205
+ }, { children: childrenField });
193
206
  // 源
194
207
  if (parentRow) {
195
208
  const matchObj = XEUtils.findTree(tableFullTreeData, item => targetRow[rowField] === item[rowField], { children: childrenField });
@@ -199,7 +212,7 @@ hooks.add('tableEditModule', {
199
212
  if (isInsertNextRow) {
200
213
  targetIndex = targetIndex + 1;
201
214
  }
202
- parentChilds.splice(targetIndex, 0, ...newRecords);
215
+ parentChilds.splice(targetIndex, 0, ...treeRecords);
203
216
  }
204
217
  }
205
218
  }
@@ -257,10 +270,27 @@ hooks.add('tableEditModule', {
257
270
  }
258
271
  }
259
272
  }
260
- newRecords.forEach(newRow => {
273
+ const handleStatus = (newRow) => {
261
274
  const rowid = getRowid($xeTable, newRow);
262
- insertRowMaps[rowid] = newRow;
263
- });
275
+ // 如果是被删除的数据,则还原状态
276
+ if (removeRowMaps[rowid]) {
277
+ delete removeRowMaps[rowid];
278
+ if (insertRowMaps[rowid]) {
279
+ delete insertRowMaps[rowid];
280
+ }
281
+ }
282
+ else {
283
+ insertRowMaps[rowid] = newRow;
284
+ }
285
+ };
286
+ // 如果为虚拟树
287
+ if (treeConfig && transform) {
288
+ XEUtils.eachTree(treeRecords, handleStatus, { children: mapChildrenField });
289
+ }
290
+ else {
291
+ newRecords.forEach(handleStatus);
292
+ }
293
+ reactData.removeRowFlag++;
264
294
  reactData.insertRowFlag++;
265
295
  $xeTable.cacheRowMap(false);
266
296
  $xeTable.updateScrollYStatus();
@@ -736,7 +766,12 @@ hooks.add('tableEditModule', {
736
766
  const { editStore } = reactData;
737
767
  const { row, column } = editStore.actived;
738
768
  if (column && row) {
739
- return { row, column };
769
+ return {
770
+ row,
771
+ rowIndex: $xeTable.getRowIndex(row),
772
+ column,
773
+ columnIndex: $xeTable.getColumnIndex(column)
774
+ };
740
775
  }
741
776
  return null;
742
777
  },
@@ -747,7 +782,10 @@ hooks.add('tableEditModule', {
747
782
  const { editStore } = reactData;
748
783
  const { row, column } = editStore.selected;
749
784
  if (row && column) {
750
- return { row, column };
785
+ return {
786
+ row,
787
+ column
788
+ };
751
789
  }
752
790
  return null;
753
791
  },
@@ -53,6 +53,8 @@ export const columnProps = {
53
53
  footerClassName: [String, Function],
54
54
  // 格式化显示内容
55
55
  formatter: [Function, Array, String],
56
+ // 格式化表头显示内容
57
+ headerFormatter: [Function, Array, String],
56
58
  // 格式化表尾显示内容
57
59
  footerFormatter: [Function, Array, String],
58
60
  // 是否显示间距
@@ -80,6 +80,7 @@ export class ColumnInfo {
80
80
  headerClassName: _vm.headerClassName,
81
81
  footerClassName: _vm.footerClassName,
82
82
  formatter: formatter,
83
+ headerFormatter: _vm.headerFormatter,
83
84
  footerFormatter: _vm.footerFormatter,
84
85
  padding: _vm.padding,
85
86
  verticalAlign: _vm.verticalAlign,
@@ -6,6 +6,9 @@ export const tableEmits = [
6
6
  'paste',
7
7
  'copy',
8
8
  'cut',
9
+ 'columns-change',
10
+ 'data-change',
11
+ 'footer-data-change',
9
12
  'current-change',
10
13
  'current-row-change',
11
14
  'current-row-disabled',
@@ -51,6 +54,8 @@ export const tableEmits = [
51
54
  'row-dragstart',
52
55
  'row-dragover',
53
56
  'row-dragend',
57
+ 'row-remove-dragend',
58
+ 'row-insert-dragend',
54
59
  'column-dragstart',
55
60
  'column-dragover',
56
61
  'column-dragend',
@@ -2,7 +2,7 @@ import { h, ref, inject, nextTick, watch, onMounted, onUnmounted } from 'vue';
2
2
  import { defineVxeComponent } from '../../ui/src/comp';
3
3
  import XEUtils from 'xe-utils';
4
4
  import { VxeUI } from '../../ui';
5
- import { getCalcHeight, convertHeaderColumnToRows } from './util';
5
+ import { getCalcHeight, convertHeaderColumnToRows, convertHeaderToGridRows } from './util';
6
6
  const { renderer, renderEmptyElement } = VxeUI;
7
7
  const renderType = 'header';
8
8
  export default defineVxeComponent({
@@ -30,16 +30,26 @@ export default defineVxeComponent({
30
30
  const refHeaderXSpace = ref();
31
31
  const refHeaderBorderRepair = ref();
32
32
  const uploadColumn = () => {
33
+ const { showCustomHeader } = tableProps;
34
+ const { collectColumn, visibleColumn } = tableInternalData;
35
+ const { tableGroupColumn } = props;
33
36
  const { isGroup } = tableReactData;
34
- headerColumn.value = isGroup ? convertHeaderColumnToRows(props.tableGroupColumn) : [];
37
+ let spanColumns = isGroup ? convertHeaderColumnToRows(tableGroupColumn) : [];
38
+ let visibleColgroups = [];
39
+ if (showCustomHeader && spanColumns.length > 1) {
40
+ visibleColgroups = convertHeaderToGridRows(spanColumns);
41
+ spanColumns = visibleColgroups;
42
+ }
43
+ headerColumn.value = spanColumns;
44
+ $xeTable.dispatchEvent('columns-change', { visibleColgroups, collectColumn, visibleColumn }, null);
35
45
  };
36
- const renderRows = (isGroup, isOptimizeMode, cols, $rowIndex) => {
46
+ const renderRows = (isGroup, isOptimizeMode, headerGroups, $rowIndex, cols) => {
37
47
  const $xeGrid = $xeTable.xeGrid;
38
48
  const $xeGantt = $xeTable.xeGantt;
39
49
  const { fixedType } = props;
40
- const { resizable: allResizable, columnKey, headerCellClassName, headerCellStyle, showHeaderOverflow: allColumnHeaderOverflow, headerAlign: allHeaderAlign, align: allAlign, mouseConfig } = tableProps;
41
- const { currentColumn, dragCol, scrollXLoad, scrollYLoad, overflowX, tableColumn } = tableReactData;
42
- const { fullColumnIdData, scrollXStore } = tableInternalData;
50
+ const { resizable: allResizable, columnKey, showCustomHeader, headerCellClassName, headerCellStyle, showHeaderOverflow: allColumnHeaderOverflow, headerAlign: allHeaderAlign, align: allAlign, mouseConfig } = tableProps;
51
+ const { currentColumn, dragCol, scrollXLoad, scrollYLoad, overflowX, mergeHeadFlag, tableColumn } = tableReactData;
52
+ const { fullColumnIdData, scrollXStore, mergeHeaderList, mergeHeaderCellMaps } = tableInternalData;
43
53
  const virtualXOpts = computeVirtualXOpts.value;
44
54
  const columnOpts = computeColumnOpts.value;
45
55
  const columnDragOpts = computeColumnDragOpts.value;
@@ -48,6 +58,7 @@ export default defineVxeComponent({
48
58
  const headerCellOpts = computeHeaderCellOpts.value;
49
59
  const currCellHeight = getCalcHeight(headerCellOpts.height) || defaultRowHeight;
50
60
  const { disabledMethod: dragDisabledMethod, isCrossDrag, isPeerDrag } = columnDragOpts;
61
+ const isLastRow = $rowIndex === headerGroups.length - 1;
51
62
  return cols.map((column, $columnIndex) => {
52
63
  const { type, showHeaderOverflow, headerAlign, align, filters, headerClassName, editRender, cellRender } = column;
53
64
  const colid = column.id;
@@ -87,10 +98,31 @@ export default defineVxeComponent({
87
98
  hasFilter
88
99
  };
89
100
  const thAttrs = {
90
- colid,
91
- colspan: column.colSpan > 1 ? column.colSpan : null,
92
- rowspan: column.rowSpan > 1 ? column.rowSpan : null
101
+ colid
93
102
  };
103
+ let isMergeCell = false;
104
+ // 合并行或列
105
+ if (!showCustomHeader) {
106
+ thAttrs.colspan = column.colSpan > 1 ? column.colSpan : null;
107
+ thAttrs.rowspan = column.rowSpan > 1 ? column.rowSpan : null;
108
+ }
109
+ if (mergeHeadFlag && mergeHeaderList.length && (showCustomHeader || isLastRow)) {
110
+ const spanRest = mergeHeaderCellMaps[`${$rowIndex}:${showCustomHeader ? $columnIndex : _columnIndex}`];
111
+ if (spanRest) {
112
+ const { rowspan, colspan } = spanRest;
113
+ if (!rowspan || !colspan) {
114
+ return null;
115
+ }
116
+ if (rowspan > 1) {
117
+ isMergeCell = true;
118
+ thAttrs.rowspan = rowspan;
119
+ }
120
+ if (colspan > 1) {
121
+ isMergeCell = true;
122
+ thAttrs.colspan = colspan;
123
+ }
124
+ }
125
+ }
94
126
  const thOns = {
95
127
  onClick: (evnt) => $xeTable.triggerHeaderCellClickEvent(evnt, cellParams),
96
128
  onDblclick: (evnt) => $xeTable.triggerHeaderCellDblclickEvent(evnt, cellParams)
@@ -117,7 +149,7 @@ export default defineVxeComponent({
117
149
  const showResizable = (XEUtils.isBoolean(column.resizable) ? column.resizable : (columnOpts.resizable || allResizable));
118
150
  const isAutoCellWidth = !column.resizeWidth && (column.minWidth === 'auto' || column.width === 'auto');
119
151
  let isVNPreEmptyStatus = false;
120
- if (isOptimizeMode && overflowX && !isGroup) {
152
+ if (isOptimizeMode && overflowX && !isGroup && !isMergeCell) {
121
153
  if (!dragCol || dragCol.id !== colid) {
122
154
  if (scrollXLoad && tableColumn.length > 10 && !column.fixed && !virtualXOpts.immediate && (_columnIndex < scrollXStore.visibleStartIndex - scrollXStore.preloadSize || _columnIndex > scrollXStore.visibleEndIndex + scrollXStore.preloadSize)) {
123
155
  isVNPreEmptyStatus = true;
@@ -131,7 +163,7 @@ export default defineVxeComponent({
131
163
  else {
132
164
  tcStyle.minHeight = `${currCellHeight}px`;
133
165
  }
134
- return h('th', Object.assign(Object.assign(Object.assign({ class: ['vxe-table--column vxe-header--column', colid, {
166
+ return h('th', Object.assign(Object.assign(Object.assign({ class: ['vxe-table--column vxe-header--column', colid, fixedHiddenColumn ? 'fixed--hidden' : 'fixed--visible', {
135
167
  [`col--${headAlign}`]: headAlign,
136
168
  [`col--${type}`]: type,
137
169
  'col--last': isLastColumn,
@@ -139,7 +171,6 @@ export default defineVxeComponent({
139
171
  'col--group': isColGroup,
140
172
  'col--ellipsis': hasEllipsis,
141
173
  'fixed--width': !isAutoCellWidth,
142
- 'fixed--hidden': fixedHiddenColumn,
143
174
  'is--padding': isPadding,
144
175
  'is--sortable': column.sortable,
145
176
  'col--filter': !!filters,
@@ -150,7 +181,7 @@ export default defineVxeComponent({
150
181
  },
151
182
  headerClassName ? (XEUtils.isFunction(headerClassName) ? headerClassName(cellParams) : headerClassName) : '',
152
183
  headerCellClassName ? (XEUtils.isFunction(headerCellClassName) ? headerCellClassName(cellParams) : headerCellClassName) : ''
153
- ], style: headerCellStyle ? (XEUtils.isFunction(headerCellStyle) ? headerCellStyle(cellParams) : headerCellStyle) : null }, thAttrs), thOns), { key: columnKey || scrollXLoad || scrollYLoad || columnOpts.useKey || columnOpts.drag || isColGroup ? colid : $columnIndex }), [
184
+ ], style: headerCellStyle ? (XEUtils.isFunction(headerCellStyle) ? headerCellStyle(cellParams) : headerCellStyle) : null }, thAttrs), thOns), { key: showCustomHeader ? `${colid}${$columnIndex}` : (columnKey || scrollXLoad || scrollYLoad || columnOpts.useKey || columnOpts.drag || isColGroup ? colid : $columnIndex) }), [
154
185
  h('div', {
155
186
  class: ['vxe-cell', {
156
187
  'c--title': showTitle,
@@ -169,7 +200,7 @@ export default defineVxeComponent({
169
200
  /**
170
201
  * 列宽拖动
171
202
  */
172
- !fixedHiddenColumn && showResizable
203
+ !fixedHiddenColumn && showResizable && (!showCustomHeader || isLastRow)
173
204
  ? h('div', {
174
205
  class: 'vxe-cell--col-resizable',
175
206
  onMousedown: (evnt) => $xeTable.handleColResizeMousedownEvent(evnt, fixedType, cellParams),
@@ -191,7 +222,7 @@ export default defineVxeComponent({
191
222
  headerRowClassName ? (XEUtils.isFunction(headerRowClassName) ? headerRowClassName(params) : headerRowClassName) : ''
192
223
  ],
193
224
  style: headerRowStyle ? (XEUtils.isFunction(headerRowStyle) ? headerRowStyle(params) : headerRowStyle) : null
194
- }, renderRows(isGroup, isOptimizeMode, cols, $rowIndex));
225
+ }, renderRows(isGroup, isOptimizeMode, headerGroups, $rowIndex, cols));
195
226
  });
196
227
  };
197
228
  const renderVN = () => {
@@ -200,7 +231,7 @@ export default defineVxeComponent({
200
231
  const { isGroup, isColLoading, overflowX, scrollXLoad, dragCol } = tableReactData;
201
232
  const { visibleColumn, fullColumnIdData } = tableInternalData;
202
233
  const mouseOpts = computeMouseOpts.value;
203
- let renderHeaderList = headerColumn.value;
234
+ let renderHeaderList = headerColumn.value || [];
204
235
  let renderColumnList = tableColumn;
205
236
  let isOptimizeMode = false;
206
237
  if (isGroup) {
@@ -10,7 +10,7 @@ export const tableProps = {
10
10
  // 表格的最小高度
11
11
  minHeight: {
12
12
  type: [Number, String],
13
- default: () => getConfig().table.minHeight
13
+ default: () => null
14
14
  },
15
15
  // 表格的最大高度
16
16
  maxHeight: [Number, String],
@@ -129,9 +129,17 @@ export const tableProps = {
129
129
  headerRowStyle: [Object, Function],
130
130
  // 给表尾行附加样式
131
131
  footerRowStyle: [Object, Function],
132
- // 合并指定单元格
132
+ // 用于分组表头,显示为自定义列头,配合 mergeHeaderCells 灵活实现自定义合并
133
+ showCustomHeader: {
134
+ type: Boolean,
135
+ default: () => getConfig().table.showCustomHeader
136
+ },
137
+ // 临时合并指定的表头单元格
138
+ mergeHeaderCells: Array,
139
+ // 临时合并指定的单元格
133
140
  mergeCells: Array,
134
- // 合并指定的表尾
141
+ // 临时合并指定的表尾单元格
142
+ mergeFooterCells: Array,
135
143
  mergeFooterItems: Array,
136
144
  // 自定义合并行或列的方法
137
145
  spanMethod: Function,
@@ -0,0 +1,8 @@
1
+ import { reactive } from 'vue';
2
+ // 跨表拖拽
3
+ export const crossTableDragRowInfo = reactive({
4
+ row: null
5
+ });
6
+ export function getCrossTableDragRowInfo() {
7
+ return crossTableDragRowInfo;
8
+ }