stk-table-vue 0.6.9 → 0.6.12

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.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.6.9",
3
+ "version": "0.6.12",
4
4
  "description": "Simple realtime virtual table for vue3 and vue2.7",
5
5
  "main": "./lib/stk-table-vue.js",
6
6
  "types": "./lib/src/StkTable/index.d.ts",
7
- "packageManager": "pnpm@8.14.3",
7
+ "packageManager": "pnpm@10.7.0",
8
8
  "directories": {
9
9
  "test": "test"
10
10
  },
@@ -64,7 +64,7 @@
64
64
  "vite": "^5.4.10",
65
65
  "vite-plugin-dts": "3.9.1",
66
66
  "vitepress": "^1.5.0",
67
- "vitepress-demo-plugin": "^1.2.2",
67
+ "vitepress-demo-plugin": "^1.3.1",
68
68
  "vitest": "^2.1.3",
69
69
  "vue": "^3.5.12",
70
70
  "vue-eslint-parser": "^9.4.2"
@@ -7,6 +7,7 @@
7
7
  virtual,
8
8
  'virtual-x': virtualX,
9
9
  'vt-on': virtual_on,
10
+ light: theme === 'light',
10
11
  dark: theme === 'dark',
11
12
  headless,
12
13
  'is-col-resizing': isColResizing,
@@ -86,31 +87,25 @@
86
87
  @drop="onThDrop"
87
88
  @dragover="onThDragOver"
88
89
  >
90
+ <!-- 列宽拖动handler -->
91
+ <div
92
+ v-if="colResizeOn(col) && colIndex > 0"
93
+ class="table-header-resizer left"
94
+ @mousedown="e => onThResizeMouseDown(e, col, true)"
95
+ ></div>
89
96
  <div class="table-header-cell-wrapper" :style="{ '--row-span': virtualX_on ? 1 : col.rowSpan }">
90
97
  <component :is="col.customHeaderCell" v-if="col.customHeaderCell" :col="col" :colIndex="colIndex" :rowIndex="rowIndex" />
91
- <template v-else-if="col.type === 'seq'">
92
- <span class="table-header-title">{{ col.title }}</span>
93
- </template>
94
98
  <template v-else>
95
99
  <slot name="tableHeader" :col="col">
96
100
  <span class="table-header-title">{{ col.title }}</span>
97
101
  </slot>
98
102
  </template>
99
-
100
- <!-- 排序图图标 -->
101
- <span v-if="col.sorter" class="table-header-sorter">
102
- <SortIcon />
103
- </span>
104
- <!-- 列宽拖动handler -->
105
- <div
106
- v-if="colResizeOn(col) && colIndex > 0"
107
- class="table-header-resizer left"
108
- @mousedown="e => onThResizeMouseDown(e, col, true)"
109
- ></div>
110
- <div v-if="colResizeOn(col)" class="table-header-resizer right" @mousedown="e => onThResizeMouseDown(e, col)"></div>
103
+ <SortIcon v-if="col.sorter" class="table-header-sorter" />
111
104
  </div>
105
+ <!-- 列宽拖动handler -->
106
+ <div v-if="colResizeOn(col)" class="table-header-resizer right" @mousedown="e => onThResizeMouseDown(e, col)"></div>
112
107
  </th>
113
- <!-- 这个th用于横向虚拟滚动表格右边距 width、maxWidth 用于兼容低版本浏览器-->
108
+ <!-- 这个th用于横向虚拟滚动表格右边距 width, min-width 用于兼容低版本浏览器-->
114
109
  <th v-if="virtualX_on" class="vt-x-right" :style="`min-width:${virtualX_offsetRight}px;width:${virtualX_offsetRight}px`"></th>
115
110
  </tr>
116
111
  </thead>
@@ -176,12 +171,7 @@
176
171
  'drag-row-cell': col.type === 'dragRow',
177
172
  },
178
173
  ]"
179
- @click="
180
- e => {
181
- col.type === 'expand' && toggleExpandRow(row, col);
182
- onCellClick(e, row, col);
183
- }
184
- "
174
+ @click="e => onCellClick(e, row, col)"
185
175
  @mousedown="e => onCellMouseDown(e, row, col)"
186
176
  @mouseenter="e => onCellMouseEnter(e, row, col)"
187
177
  @mouseleave="e => onCellMouseLeave(e, row, col)"
@@ -240,7 +230,7 @@
240
230
  import { CSSProperties, computed, nextTick, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
241
231
  import DragHandle from './components/DragHandle.vue';
242
232
  import SortIcon from './components/SortIcon.vue';
243
- import { DEFAULT_ROW_HEIGHT, DEFAULT_SMOOTH_SCROLL, EXPANDED_ROW_KEY_PREFIX, IS_LEGACY_MODE } from './const';
233
+ import { CELL_KEY_SEPARATE, DEFAULT_ROW_HEIGHT, DEFAULT_SMOOTH_SCROLL, EXPANDED_ROW_KEY_PREFIX, IS_LEGACY_MODE } from './const';
244
234
  import {
245
235
  AutoRowHeightConfig,
246
236
  DragRowConfig,
@@ -403,7 +393,7 @@ const props = withDefaults(
403
393
  */
404
394
  cellFixedMode?: 'sticky' | 'relative';
405
395
  /**
406
- * 是否平滑滚动。default: chrome < 85 ? true : false
396
+ * 是否平滑滚动。default: chrome < 85 || chrome > 120 ? true : false
407
397
  * - false: 使用 onwheel 滚动。为了防止滚动过快导致白屏。
408
398
  * - true: 不使用 onwheel 滚动。鼠标滚轮滚动时更加平滑。滚动过快时会白屏。
409
399
  */
@@ -651,8 +641,6 @@ const sortSwitchOrder: Order[] = [null, 'desc', 'asc'];
651
641
  * ```
652
642
  */
653
643
  const tableHeaders = shallowRef<StkTableColumn<DT>[][]>([]);
654
- /** 若有多级表头时,最后一行的tableHeaders.内容是 props.columns 的引用集合 */
655
- const tableHeaderLast = shallowRef<StkTableColumn<DT>[]>([]);
656
644
 
657
645
  /**
658
646
  * 用于计算多级表头的tableHeaders。模拟rowSpan 位置的辅助数组。用于计算固定列。
@@ -674,26 +662,35 @@ const tableHeaderLast = shallowRef<StkTableColumn<DT>[]>([]);
674
662
  */
675
663
  const tableHeadersForCalc = shallowRef<PrivateStkTableColumn<DT>[][]>([]);
676
664
 
677
- const dataSourceCopy = shallowRef<DT[]>([...props.dataSource]);
665
+ /** 最后一行的tableHeaders.内容是 props.columns 的引用集合 */
666
+ const tableHeaderLast = computed(() => tableHeadersForCalc.value.slice(-1)[0] || []);
667
+
668
+ const dataSourceCopy = shallowRef<DT[]>(props.dataSource.slice());
669
+
670
+ const rowKeyGenComputed = computed(() => {
671
+ const { rowKey } = props;
672
+ if (typeof rowKey === 'function') {
673
+ return (row: DT) => (rowKey as (row: DT) => string)(row);
674
+ } else {
675
+ return (row: DT) => (row as any)[rowKey];
676
+ }
677
+ });
678
678
 
679
- /**
680
- * 列唯一键
681
- * @param col
682
- */
683
679
  const colKeyGen = computed<(col: StkTableColumn<DT>) => string>(() => {
684
- if (typeof props.colKey === 'function') {
685
- return col => (props.colKey as (col: StkTableColumn<DT>) => string)(col);
680
+ const { colKey } = props;
681
+ if (typeof colKey === 'function') {
682
+ return col => (colKey as (col: StkTableColumn<DT>) => string)(col);
686
683
  } else {
687
- return col => (col ? (col as any)[props.colKey as string] : null);
684
+ return col => (col as any)[colKey];
688
685
  }
689
686
  });
690
687
 
691
- /** 空单元格占位字符 */
692
688
  const getEmptyCellText = computed(() => {
693
- if (typeof props.emptyCellText === 'string') {
694
- return () => props.emptyCellText;
689
+ const { emptyCellText } = props;
690
+ if (typeof emptyCellText === 'string') {
691
+ return () => emptyCellText;
695
692
  } else {
696
- return (col: StkTableColumn<DT>, row: DT) => (props.emptyCellText as any)({ row, col });
693
+ return (col: StkTableColumn<DT>, row: DT) => emptyCellText({ row, col });
697
694
  }
698
695
  });
699
696
 
@@ -817,22 +814,20 @@ watch(
817
814
  if (dataSourceCopy.value.length !== val.length) {
818
815
  needInitVirtualScrollY = true;
819
816
  }
820
- dataSourceCopy.value = [...val];
817
+ dataSourceCopy.value = val.slice(); // 浅拷贝
821
818
  // 数据长度没变则不计算虚拟滚动
822
819
  if (needInitVirtualScrollY) {
823
820
  // 表格渲染后再执行。initVirtualScrollY 中有获取dom的操作。
824
821
  nextTick(() => initVirtualScrollY());
825
822
  }
826
-
827
- if (sortCol.value) {
823
+ const sortColValue = sortCol.value;
824
+ if (sortColValue) {
828
825
  // 排序
829
- const column = tableHeaderLast.value.find(it => colKeyGen.value(it) === sortCol.value);
826
+ const colKey = colKeyGen.value;
827
+ const column = tableHeaderLast.value.find(it => colKey(it) === sortColValue);
830
828
  onColumnSort(column, false);
831
829
  }
832
830
  },
833
- {
834
- deep: false,
835
- },
836
831
  );
837
832
 
838
833
  watch(
@@ -877,13 +872,12 @@ function dealColumns() {
877
872
  centerCol.push(col);
878
873
  }
879
874
  });
880
- copyColumn = [...leftCol, ...centerCol, ...rightCol];
875
+ copyColumn = leftCol.concat(centerCol).concat(rightCol);
881
876
  }
882
877
  const maxDeep = howDeepTheHeader(copyColumn);
883
- const tempHeaderLast: StkTableColumn<DT>[] = [];
884
878
 
885
879
  if (maxDeep > 0 && props.virtualX) {
886
- console.error('多级表头不支持横向虚拟滚动');
880
+ console.error('StkTableVue:多级表头不支持横向虚拟滚动!');
887
881
  }
888
882
 
889
883
  for (let i = 0; i <= maxDeep; i++) {
@@ -925,7 +919,6 @@ function dealColumns() {
925
919
  tableHeadersForCalcTemp[depth].push(col);
926
920
  } else {
927
921
  colWidth = getColWidth(col);
928
- tempHeaderLast.push(col); // 没有children的列作为colgroup
929
922
  for (let i = depth; i <= maxDeep; i++) {
930
923
  // 如有rowSpan 向下复制一个表头col,用于计算固定列
931
924
  tableHeadersForCalcTemp[i].push(col);
@@ -951,7 +944,6 @@ function dealColumns() {
951
944
 
952
945
  flat(copyColumn, null);
953
946
  tableHeaders.value = tableHeadersTemp;
954
- tableHeaderLast.value = tempHeaderLast;
955
947
  tableHeadersForCalc.value = tableHeadersForCalcTemp;
956
948
  }
957
949
 
@@ -960,13 +952,9 @@ function dealColumns() {
960
952
  */
961
953
  function rowKeyGen(row: DT | null | undefined) {
962
954
  if (!row) return row;
963
- let key = rowKeyGenStore.get(row);
955
+ let key = rowKeyGenStore.get(row) || (row as PrivateRowDT).__ROW_KEY__;
964
956
  if (!key) {
965
- if ((row as PrivateRowDT).__ROW_KEY__) {
966
- key = (row as PrivateRowDT).__ROW_KEY__;
967
- } else {
968
- key = typeof props.rowKey === 'function' ? props.rowKey(row) : row[props.rowKey];
969
- }
957
+ key = rowKeyGenComputed.value(row);
970
958
 
971
959
  if (key === void 0) {
972
960
  // key为undefined时,不应该高亮行。因此重新生成key
@@ -979,21 +967,21 @@ function rowKeyGen(row: DT | null | undefined) {
979
967
 
980
968
  /** 单元格唯一值 */
981
969
  function cellKeyGen(row: DT | null | undefined, col: StkTableColumn<DT>) {
982
- return rowKeyGen(row) + '--' + colKeyGen.value(col);
970
+ return rowKeyGen(row) + CELL_KEY_SEPARATE + colKeyGen.value(col);
983
971
  }
984
972
 
985
973
  /** 单元格样式 */
986
974
  const cellStyleMap = computed(() => {
987
975
  const thMap = new Map();
988
976
  const tdMap = new Map();
977
+ const { virtualX, colResizable } = props;
989
978
  tableHeaders.value.forEach((cols, depth) => {
990
979
  cols.forEach(col => {
991
- const colKey = colKeyGen.value(col);
992
- const width = props.virtualX ? getCalculatedColWidth(col) + 'px' : transformWidthToStr(col.width);
980
+ const width = virtualX ? getCalculatedColWidth(col) + 'px' : transformWidthToStr(col.width);
993
981
  const style: CSSProperties = {
994
982
  width,
995
983
  };
996
- if (props.colResizable) {
984
+ if (colResizable) {
997
985
  // 如果要调整列宽,列宽必须固定。
998
986
  style.minWidth = width;
999
987
  style.maxWidth = width;
@@ -1001,17 +989,9 @@ const cellStyleMap = computed(() => {
1001
989
  style.minWidth = transformWidthToStr(col.minWidth) ?? width;
1002
990
  style.maxWidth = transformWidthToStr(col.maxWidth) ?? width;
1003
991
  }
1004
-
1005
- thMap.set(colKey, {
1006
- ...style,
1007
- ...getFixedStyle(TagType.TH, col, depth),
1008
- textAlign: col.headerAlign,
1009
- });
1010
- tdMap.set(colKey, {
1011
- ...style,
1012
- ...getFixedStyle(TagType.TD, col, depth),
1013
- textAlign: col.align,
1014
- });
992
+ const colKey = colKeyGen.value(col);
993
+ thMap.set(colKey, Object.assign({ textAlign: col.headerAlign }, style, getFixedStyle(TagType.TH, col, depth)));
994
+ tdMap.set(colKey, Object.assign({ textAlign: col.align }, style, getFixedStyle(TagType.TD, col, depth)));
1015
995
  });
1016
996
  });
1017
997
  return {
@@ -1023,7 +1003,7 @@ const cellStyleMap = computed(() => {
1023
1003
  /** th title */
1024
1004
  function getHeaderTitle(col: StkTableColumn<DT>): string {
1025
1005
  const colKey = colKeyGen.value(col);
1026
- // 不展示title
1006
+ // hide title
1027
1007
  if (props.hideHeaderTitle === true || (Array.isArray(props.hideHeaderTitle) && props.hideHeaderTitle.includes(colKey))) {
1028
1008
  return '';
1029
1009
  }
@@ -1038,7 +1018,7 @@ function getHeaderTitle(col: StkTableColumn<DT>): string {
1038
1018
  */
1039
1019
  function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true, options: { force?: boolean; emit?: boolean } = {}) {
1040
1020
  if (!col) {
1041
- console.warn('onColumnSort: col is not found');
1021
+ console.warn('onColumnSort: not found col:', col);
1042
1022
  return;
1043
1023
  }
1044
1024
  if (!col.sorter && click) {
@@ -1052,26 +1032,32 @@ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true,
1052
1032
  sortCol.value = colKey;
1053
1033
  sortOrderIndex.value = 0;
1054
1034
  }
1035
+ const prevOrder = sortSwitchOrder[sortOrderIndex.value];
1055
1036
  if (click) sortOrderIndex.value++;
1056
1037
  sortOrderIndex.value = sortOrderIndex.value % 3;
1057
1038
 
1058
1039
  let order = sortSwitchOrder[sortOrderIndex.value];
1059
1040
  const sortConfig = { ...props.sortConfig, ...col.sortConfig };
1060
1041
  const defaultSort = sortConfig.defaultSort;
1042
+ const colKeyGenValue = colKeyGen.value;
1061
1043
 
1062
1044
  if (!order && defaultSort) {
1063
1045
  // if no order ,use default order
1064
- const colKey = defaultSort.key || defaultSort.dataIndex;
1065
- if (!colKey) {
1046
+ const defaultColKey = defaultSort.key || defaultSort.dataIndex;
1047
+ if (!defaultColKey) {
1066
1048
  console.error('sortConfig.defaultSort key or dataIndex is required');
1067
1049
  return;
1068
1050
  }
1069
- order = defaultSort.order || 'desc';
1051
+ if (colKey === defaultColKey && prevOrder === defaultSort.order) {
1052
+ order = sortSwitchOrder.find(o => o !== defaultSort.order && o) as Order;
1053
+ } else {
1054
+ order = defaultSort.order;
1055
+ }
1070
1056
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
1071
- sortCol.value = colKey as string;
1057
+ sortCol.value = defaultColKey as string;
1072
1058
  col = null;
1073
1059
  for (const row of tableHeaders.value) {
1074
- const c = row.find(item => colKeyGen.value(item) === colKey);
1060
+ const c = row.find(item => colKeyGenValue(item) === defaultColKey);
1075
1061
  if (c) {
1076
1062
  col = c;
1077
1063
  break;
@@ -1101,12 +1087,11 @@ function onRowClick(e: MouseEvent, row: DT) {
1101
1087
  // 点击同一行,取消当前选中行。
1102
1088
  currentRow.value = void 0;
1103
1089
  currentRowKey.value = void 0;
1104
- emits('current-change', e, row, { select: false });
1105
1090
  } else {
1106
1091
  currentRow.value = row;
1107
1092
  currentRowKey.value = rowKeyGen(row);
1108
- emits('current-change', e, row, { select: true });
1109
1093
  }
1094
+ emits('current-change', e, row, { select: !isCurrentRow });
1110
1095
  }
1111
1096
 
1112
1097
  function onRowDblclick(e: MouseEvent, row: DT) {
@@ -1123,17 +1108,51 @@ function onRowMenu(e: MouseEvent, row: DT) {
1123
1108
  emits('row-menu', e, row);
1124
1109
  }
1125
1110
 
1111
+ /**
1112
+ * proxy events
1113
+ */
1114
+ // function onTbodyClick(e: MouseEvent, type: 1 | 2) {
1115
+ // const el = (e.target as HTMLElement).closest<HTMLElement>('td,tr');
1116
+ // if (!el) return;
1117
+ // if (el.tagName === 'TD') {
1118
+ // const [rowKey, colKey] = el.dataset.cellKey?.split(CELL_KEY_SEPARATE) || [];
1119
+ // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1120
+ // const col = tableHeaderLast.value.find(item => colKeyGen.value(item) === colKey);
1121
+ // if (col) {
1122
+ // if (col.type === 'expand') {
1123
+ // toggleExpandRow(row, col);
1124
+ // }
1125
+ // if (type === 1) {
1126
+ // onCellClick(e, row, col);
1127
+ // } else if (type === 2) {
1128
+ // onCellMouseDown(e, row, col);
1129
+ // }
1130
+ // }
1131
+ // if (type === 1) {
1132
+ // onRowClick(e, row);
1133
+ // }
1134
+ // } else if (el.tagName === 'TR') {
1135
+ // const rowKey = el.dataset.rowKey;
1136
+ // const row = dataSourceCopy.value.find(item => rowKeyGen(item) === rowKey);
1137
+ // onRowClick(e, row);
1138
+ // }
1139
+ // }
1140
+
1126
1141
  /** 单元格单击 */
1127
1142
  function onCellClick(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1143
+ if (col.type === 'expand') {
1144
+ toggleExpandRow(row, col);
1145
+ }
1128
1146
  if (props.cellActive) {
1129
1147
  const cellKey = cellKeyGen(row, col);
1148
+ const result = { row, col, select: false };
1130
1149
  if (props.selectedCellRevokable && currentSelectedCellKey.value === cellKey) {
1131
1150
  currentSelectedCellKey.value = void 0;
1132
- emits('cell-selected', e, { select: false, row, col });
1133
1151
  } else {
1134
1152
  currentSelectedCellKey.value = cellKey;
1135
- emits('cell-selected', e, { select: true, row, col });
1153
+ result.select = true;
1136
1154
  }
1155
+ emits('cell-selected', e, result);
1137
1156
  }
1138
1157
  emits('cell-click', e, row, col);
1139
1158
  }
@@ -1145,13 +1164,11 @@ function onHeaderCellClick(e: MouseEvent, col: StkTableColumn<DT>) {
1145
1164
 
1146
1165
  /** td mouseenter */
1147
1166
  function onCellMouseEnter(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1148
- // currentColHoverKey.value = colKeyGen(col);
1149
1167
  emits('cell-mouseenter', e, row, col);
1150
1168
  }
1151
1169
 
1152
1170
  /** td mouseleave */
1153
1171
  function onCellMouseLeave(e: MouseEvent, row: DT, col: StkTableColumn<DT>) {
1154
- // currentColHoverKey.value = null;
1155
1172
  emits('cell-mouseleave', e, row, col);
1156
1173
  }
1157
1174
 
@@ -1215,7 +1232,7 @@ function onTableScroll(e: Event) {
1215
1232
  if (!e?.target) return;
1216
1233
 
1217
1234
  const { scrollTop, scrollLeft } = e.target as HTMLElement;
1218
- const { scrollTop: vScrollTop } = virtualScroll.value;
1235
+ const { scrollTop: vScrollTop, startIndex, endIndex } = virtualScroll.value;
1219
1236
  const { scrollLeft: vScrollLeft } = virtualScrollX.value;
1220
1237
  const isYScroll = scrollTop !== vScrollTop;
1221
1238
  const isXScroll = scrollLeft !== vScrollLeft;
@@ -1236,10 +1253,8 @@ function onTableScroll(e: Event) {
1236
1253
  updateFixedShadow(virtualScrollX);
1237
1254
  }
1238
1255
 
1239
- const { startIndex, endIndex } = virtualScroll.value;
1240
- const data = { startIndex, endIndex };
1241
1256
  if (isYScroll) {
1242
- emits('scroll', e, data);
1257
+ emits('scroll', e, { startIndex, endIndex });
1243
1258
  }
1244
1259
  if (isXScroll) {
1245
1260
  emits('scroll-x', e);
@@ -1310,10 +1325,11 @@ function setSorter(colKey: string, order: Order, option: { sortOption?: SortOpti
1310
1325
  const newOption = { silent: true, sortOption: null, sort: true, ...option };
1311
1326
  sortCol.value = colKey;
1312
1327
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
1328
+ const colKeyGenValue = colKeyGen.value;
1313
1329
 
1314
1330
  if (newOption.sort && dataSourceCopy.value?.length) {
1315
1331
  // 如果表格有数据,则进行排序
1316
- const column = newOption.sortOption || tableHeaderLast.value.find(it => colKeyGen.value(it) === sortCol.value);
1332
+ const column = newOption.sortOption || tableHeaderLast.value.find(it => colKeyGenValue(it) === sortCol.value);
1317
1333
  if (column) onColumnSort(column, false, { force: option.force ?? true, emit: !newOption.silent });
1318
1334
  else console.warn('Can not find column by key:', sortCol.value);
1319
1335
  }
@@ -1323,7 +1339,7 @@ function setSorter(colKey: string, order: Order, option: { sortOption?: SortOpti
1323
1339
  function resetSorter() {
1324
1340
  sortCol.value = void 0;
1325
1341
  sortOrderIndex.value = 0;
1326
- dataSourceCopy.value = [...props.dataSource];
1342
+ dataSourceCopy.value = props.dataSource.slice();
1327
1343
  }
1328
1344
 
1329
1345
  /**
@@ -1372,7 +1388,7 @@ function setRowExpand(rowKeyOrRow: string | undefined | DT, expand?: boolean, da
1372
1388
  } else {
1373
1389
  rowKey = rowKeyGen(rowKeyOrRow);
1374
1390
  }
1375
- const tempData = [...dataSourceCopy.value];
1391
+ const tempData = dataSourceCopy.value.slice();
1376
1392
  const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
1377
1393
  if (index === -1) {
1378
1394
  console.warn('expandRow failed.rowKey:', rowKey);
@@ -32,3 +32,6 @@ export const STK_ID_PREFIX = 'stk';
32
32
 
33
33
  /** expanded row key prefix */
34
34
  export const EXPANDED_ROW_KEY_PREFIX = 'expanded-';
35
+
36
+ /** cell key 的分隔符 */
37
+ export const CELL_KEY_SEPARATE = '--';
@@ -17,7 +17,7 @@
17
17
  --td-bgc: #fff;
18
18
  --td-hover-color: #71a2fd;
19
19
  --td-active-color: #386ccc;
20
- --th-bgc: #fafafc;
20
+ --th-bgc: #f1f1f9;
21
21
  --th-color: #272841;
22
22
  --tr-active-bgc: rgb(230, 247, 255);
23
23
  --tr-hover-bgc: rgba(230, 247, 255, 0.7);
@@ -488,14 +488,12 @@
488
488
 
489
489
  .table-header-cell-wrapper {
490
490
  max-width: 100%;
491
- /*最大宽度不超过列宽*/
492
491
  display: inline-flex;
493
492
  align-items: center;
494
493
  }
495
494
 
496
495
  .table-header-title {
497
496
  overflow: hidden;
498
- // align-self: flex-start;
499
497
  }
500
498
 
501
499
  .table-header-sorter {
@@ -89,8 +89,9 @@ export function useColResize<DT extends Record<string, any>>({
89
89
  const { left } = tableContainerRef.value.getBoundingClientRect();
90
90
  const tableHeaderLastValue = tableHeaderLast.value;
91
91
  let revertMoveX = false;
92
+ const colKey = colKeyGen.value;
92
93
  /** 列下标 */
93
- const colIndex = tableHeaderLastValue.findIndex(it => colKeyGen.value(it) === colKeyGen.value(col));
94
+ const colIndex = tableHeaderLastValue.findIndex(it => colKey(it) === colKey(col));
94
95
  const fixedIndex = fixedCols.value.indexOf(col);
95
96
  /** 是否正在被固定 */
96
97
  const isFixed = fixedIndex !== -1;
@@ -171,11 +172,13 @@ export function useColResize<DT extends Record<string, any>>({
171
172
  let width = getCalculatedColWidth(lastCol) + moveX;
172
173
  if (width < props.colMinWidth) width = props.colMinWidth;
173
174
 
174
- const curCol = tableHeaderLast.value.find(it => colKeyGen.value(it) === colKeyGen.value(lastCol));
175
+ const colKey = colKeyGen.value;
176
+
177
+ const curCol = tableHeaderLast.value.find(it => colKey(it) === colKey(lastCol));
175
178
  if (!curCol) return;
176
179
  curCol.width = width + 'px';
177
180
 
178
- emits('update:columns', [...props.columns]);
181
+ emits('update:columns', props.columns.slice());
179
182
  emits('col-resize', { ...curCol });
180
183
 
181
184
  // 隐藏指示线
@@ -199,7 +202,7 @@ export function useColResize<DT extends Record<string, any>>({
199
202
  /**获取最后一个叶子 */
200
203
  function findLastChildCol(column: StkTableColumn<DT> | null) {
201
204
  if (column?.children?.length) {
202
- const lastChild = column.children.at(-1) as StkTableColumn<DT>;
205
+ const lastChild = column.children.slice(-1)[0] as StkTableColumn<DT>;
203
206
  return findLastChildCol(lastChild);
204
207
  }
205
208
  return column;
@@ -33,18 +33,25 @@ export function useFixedCol<DT extends Record<string, any>>({
33
33
  /** 固定列的class */
34
34
  const fixedColClassMap = computed(() => {
35
35
  const colMap = new Map();
36
- // console.log('tableHeaderForCalc', tableHeaderForCalc.value);
37
36
  const fixedShadowColsValue = fixedShadowCols.value;
37
+ const fixedColsValue = fixedCols.value;
38
+ const colKey = colKeyGen.value;
39
+ const fixedColShadow = props.fixedColShadow;
38
40
  tableHeaders.value.forEach(cols => {
39
41
  cols.forEach(col => {
40
- const showShadow = props.fixedColShadow && col.fixed && fixedShadowColsValue.includes(col);
41
- const classObj = {
42
- 'fixed-cell': col.fixed,
43
- ['fixed-cell--' + col.fixed]: col.fixed,
44
- 'fixed-cell--shadow': showShadow,
45
- ['fixed-cell--active']: fixedCols.value.includes(col), // 表示该列正在被固定
42
+ const fixed = col.fixed;
43
+ const showShadow = fixedColShadow && fixed && fixedShadowColsValue.includes(col);
44
+ const classObj: Record<string, any> = {
45
+ 'fixed-cell--active': fixedColsValue.includes(col), // 表示该列正在被固定
46
46
  };
47
- colMap.set(colKeyGen.value(col), classObj);
47
+ if (fixed) {
48
+ classObj['fixed-cell'] = true;
49
+ classObj['fixed-cell--' + fixed] = true;
50
+ }
51
+ if (showShadow) {
52
+ classObj['fixed-cell--shadow'] = true;
53
+ }
54
+ colMap.set(colKey(col), classObj);
48
55
  });
49
56
  });
50
57
  return colMap;
@@ -76,17 +83,16 @@ export function useFixedCol<DT extends Record<string, any>>({
76
83
  /** 滚动条变化时,更新需要展示阴影的列 */
77
84
  function updateFixedShadow(virtualScrollX?: Ref<VirtualScrollXStore>) {
78
85
  const fixedColsTemp: StkTableColumn<DT>[] = [];
79
- let clientWidth, /* scrollWidth, */ scrollLeft;
86
+ const getFixedColPositionValue = getFixedColPosition.value;
87
+ let clientWidth, scrollLeft;
80
88
 
81
89
  if (virtualScrollX?.value) {
82
- const { containerWidth: cw, /* scrollWidth: sw, */ scrollLeft: sl } = virtualScrollX.value;
90
+ const { containerWidth: cw, scrollLeft: sl } = virtualScrollX.value;
83
91
  clientWidth = cw;
84
- // scrollWidth = sw;
85
92
  scrollLeft = sl;
86
93
  } else {
87
- const { clientWidth: cw, /* scrollWidth: sw, */ scrollLeft: sl } = tableContainerRef.value as HTMLDivElement;
94
+ const { clientWidth: cw, scrollLeft: sl } = tableContainerRef.value as HTMLDivElement;
88
95
  clientWidth = cw;
89
- // scrollWidth = sw;
90
96
  scrollLeft = sl;
91
97
  }
92
98
 
@@ -103,7 +109,7 @@ export function useFixedCol<DT extends Record<string, any>>({
103
109
  */
104
110
  let left = 0;
105
111
  row.forEach(col => {
106
- const position = getFixedColPosition.value(col);
112
+ const position = getFixedColPositionValue(col);
107
113
  const isFixedLeft = col.fixed === 'left';
108
114
  const isFixedRight = col.fixed === 'right';
109
115
 
@@ -125,7 +131,7 @@ export function useFixedCol<DT extends Record<string, any>>({
125
131
  });
126
132
 
127
133
  if (props.fixedColShadow) {
128
- fixedShadowCols.value = [...leftShadowCol, ...rightShadowCol].filter(Boolean) as StkTableColumn<DT>[];
134
+ fixedShadowCols.value = leftShadowCol.concat(rightShadowCol).filter(Boolean) as StkTableColumn<DT>[];
129
135
  }
130
136
 
131
137
  fixedCols.value = fixedColsTemp;
@@ -36,21 +36,20 @@ export function useFixedStyle<DT extends Record<string, any>>({
36
36
  if (tagType === TagType.TD && !fixed) return null;
37
37
 
38
38
  const style: CSSProperties = {};
39
-
39
+ const { headerRowHeight, rowHeight } = props;
40
40
  const isFixedLeft = fixed === 'left';
41
+ const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
42
+ const scrollRight = scrollWidth - containerWidth - scrollLeft;
43
+
41
44
  if (tagType === TagType.TH) {
42
45
  // TH
43
46
  if (isRelativeMode.value) {
44
47
  style.top = virtualScroll.value.scrollTop + 'px';
45
48
  } else {
46
- const rowHeight = props.headerRowHeight ?? props.rowHeight;
47
- style.top = depth * rowHeight + 'px';
49
+ style.top = depth * (headerRowHeight ?? rowHeight) + 'px';
48
50
  }
49
51
  }
50
52
 
51
- const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
52
- const scrollRight = scrollWidth - containerWidth - scrollLeft;
53
-
54
53
  if (fixed === 'left' || fixed === 'right') {
55
54
  if (isRelativeMode.value) {
56
55
  if (isFixedLeft) {