stk-table-vue 0.4.9 → 0.4.10

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/README.md CHANGED
@@ -12,7 +12,7 @@ repo:
12
12
 
13
13
  ## Bug TODO:
14
14
  * [x] props.dataSource 为 shallowRef 时,高亮行不生效。(bug:2024.02.21)(resolved:0.2.3)
15
- * [] 固定列列宽拖动目标。
15
+ * [x] 右侧固定列列宽拖动目标。(v0.4.10)
16
16
  * [] 惯性滚动优化。
17
17
 
18
18
  ## Feature TODO:
@@ -251,10 +251,10 @@ export type StkProps = {
251
251
  ```js
252
252
  {
253
253
  /**
254
- * 排序变更触发
255
- * ```(col: StkTableColumn<DT>, order: Order, data: DT[])```
254
+ * 排序变更触发。defaultSort.dataIndex 找不到时,col 将返回null。
255
+ * ```(col: StkTableColumn<DT> | null, order: Order, data: DT[])```
256
256
  */
257
- (e: 'sort-change', col: StkTableColumn<DT>, order: Order, data: DT[], sortConfig: SortConfig): void;
257
+ (e: 'sort-change', col: StkTableColumn<DT> | null, order: Order, data: DT[], sortConfig: SortConfig): void;
258
258
  /**
259
259
  * 一行点击事件
260
260
  * ```(ev: MouseEvent, row: DT)```
@@ -4,10 +4,10 @@ import { HighlightConfig, Order, SeqConfig, SortConfig, SortOption, SortState, S
4
4
  type DT = any;
5
5
  /**
6
6
  * 选中一行,
7
- * @param {string} rowKey selected rowKey, null to unselect
7
+ * @param {string} rowKey selected rowKey, undefined to unselect
8
8
  * @param {boolean} option.silent 是否触发回调
9
9
  */
10
- declare function setCurrentRow(rowKey: string, option?: {
10
+ declare function setCurrentRow(rowKey: string | undefined, option?: {
11
11
  silent: boolean;
12
12
  }): void;
13
13
  /**
@@ -198,8 +198,8 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<__
198
198
  /** 设置高亮渐暗单元格 */
199
199
  setHighlightDimCell: (rowKeyValue: string, dataIndex: string, option?: {
200
200
  className?: string | undefined; /**
201
- * 排序变更触发
202
- * ```(col: StkTableColumn<DT>, order: Order, data: DT[])```
201
+ * 排序变更触发。defaultSort.dataIndex 找不到时,col 将返回null。
202
+ * ```(col: StkTableColumn<DT> | null, order: Order, data: DT[])```
203
203
  */
204
204
  method?: "animation" | "css" | undefined;
205
205
  keyframe?: Keyframe[] | PropertyIndexedKeyframes | null | undefined;
@@ -226,7 +226,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<__
226
226
  /** 获取表格数据 */
227
227
  getTableData: typeof getTableData;
228
228
  }, unknown, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
229
- "sort-change": (col: StkTableColumn<any>, order: Order, data: any[], sortConfig: SortConfig<any>) => void;
229
+ "sort-change": (col: StkTableColumn<any> | null, order: Order, data: any[], sortConfig: SortConfig<any>) => void;
230
230
  "row-click": (ev: MouseEvent, row: any) => void;
231
231
  "current-change": (ev: MouseEvent | null, row: any, data: {
232
232
  select: boolean;
@@ -406,7 +406,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<__
406
406
  "onTh-drag-start"?: ((dragStartKey: string) => any) | undefined;
407
407
  "onCol-order-change"?: ((dragStartKey: string, targetColKey: string) => any) | undefined;
408
408
  "onTh-drop"?: ((targetColKey: string) => any) | undefined;
409
- "onSort-change"?: ((col: StkTableColumn<any>, order: Order, data: any[], sortConfig: SortConfig<any>) => any) | undefined;
409
+ "onSort-change"?: ((col: StkTableColumn<any> | null, order: Order, data: any[], sortConfig: SortConfig<any>) => any) | undefined;
410
410
  "onRow-click"?: ((ev: MouseEvent, row: any) => any) | undefined;
411
411
  "onCurrent-change"?: ((ev: MouseEvent | null, row: any, data: {
412
412
  select: boolean;
@@ -121,8 +121,11 @@ export type SortConfig<T extends Record<string, any>> = {
121
121
  * 类似onMounted时,调用setSorter点了下表头。
122
122
  */
123
123
  defaultSort?: {
124
- dataIndex: keyof T;
124
+ dataIndex: StkTableColumn<T>['dataIndex'];
125
125
  order: Order;
126
+ sortField?: StkTableColumn<T>['sortField'];
127
+ sortType?: StkTableColumn<T>['sortType'];
128
+ sorter?: StkTableColumn<T>['sorter'];
126
129
  /** 是否禁止触发sort-change事件。默认false,表示触发事件。 */
127
130
  silent?: boolean;
128
131
  };
@@ -8,10 +8,11 @@ type Params<DT extends Record<string, any>> = {
8
8
  tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>;
9
9
  colResizeIndicatorRef: Ref<HTMLElement | undefined>;
10
10
  colKeyGen: ComputedRef<(p: any) => UniqKey>;
11
+ fixedCols: Ref<StkTableColumn<DT>[]>;
11
12
  };
12
13
  /** 列宽拖动 */
13
- export declare function useColResize<DT extends Record<string, any>>({ tableContainerRef, tableHeaderLast, colResizeIndicatorRef, props, emits, colKeyGen, }: Params<DT>): {
14
+ export declare function useColResize<DT extends Record<string, any>>({ tableContainerRef, tableHeaderLast, colResizeIndicatorRef, props, emits, colKeyGen, fixedCols, }: Params<DT>): {
14
15
  isColResizing: Ref<boolean>;
15
- onThResizeMouseDown: (e: MouseEvent, col: StkTableColumn<DT>, isPrev?: boolean) => void;
16
+ onThResizeMouseDown: (e: MouseEvent, col: StkTableColumn<DT>, leftHandle?: boolean) => void;
16
17
  };
17
18
  export {};
@@ -15,6 +15,8 @@ type Params<T extends Record<string, any>> = {
15
15
  * @returns
16
16
  */
17
17
  export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, getFixedColPosition, tableHeaders, tableHeaderLast, tableContainerRef, }: Params<DT>): {
18
+ /** 正在被固定的列 */
19
+ fixedCols: ShallowRef<StkTableColumn<DT>[]>;
18
20
  /** 固定列class */
19
21
  fixedColClassMap: ComputedRef<Map<any, any>>;
20
22
  /** 滚动条变化时,更新需要展示阴影的列 */
@@ -1,7 +1,7 @@
1
1
  import { onMounted, onBeforeUnmount, watch, ref, shallowRef, computed, defineComponent, nextTick, toRaw, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, createCommentVNode, createElementVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createTextVNode } from "vue";
2
2
  import { interpolateRgb } from "d3-interpolate";
3
3
  function isEmptyValue(val, isNumber) {
4
- let isEmpty = val === null || val === "";
4
+ let isEmpty = val === null || val === "" || val === void 0;
5
5
  if (isNumber) {
6
6
  isEmpty = isEmpty || typeof val === "boolean" || Number.isNaN(+val);
7
7
  }
@@ -69,7 +69,7 @@ function separatedData(sortOption, targetDataSource, isNumber) {
69
69
  for (let i = 0; i < targetDataSource.length; i++) {
70
70
  const row = targetDataSource[i];
71
71
  const sortField = sortOption.sortField || sortOption.dataIndex;
72
- const isEmpty = isEmptyValue(row[sortField], isNumber);
72
+ const isEmpty = isEmptyValue(row == null ? void 0 : row[sortField], isNumber);
73
73
  if (isEmpty) {
74
74
  emptyArr.push(row);
75
75
  } else {
@@ -79,7 +79,7 @@ function separatedData(sortOption, targetDataSource, isNumber) {
79
79
  return [valueArr, emptyArr];
80
80
  }
81
81
  function tableSort(sortOption, order, dataSource, sortConfig = {}) {
82
- if (!(dataSource == null ? void 0 : dataSource.length))
82
+ if (!(dataSource == null ? void 0 : dataSource.length) || !sortOption)
83
83
  return dataSource || [];
84
84
  sortConfig = { emptyToBottom: false, ...sortConfig };
85
85
  let targetDataSource = [...dataSource];
@@ -96,8 +96,8 @@ function tableSort(sortOption, order, dataSource, sortConfig = {}) {
96
96
  let { sortType } = sortOption;
97
97
  if (!sortType)
98
98
  sortType = typeof dataSource[0][sortField];
99
- const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, sortType === "number");
100
99
  const isNumber = sortType === "number";
100
+ const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
101
101
  if (order === "asc") {
102
102
  valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, sortConfig.stringLocaleCompare));
103
103
  } else {
@@ -234,15 +234,16 @@ function useColResize({
234
234
  colResizeIndicatorRef,
235
235
  props,
236
236
  emits,
237
- colKeyGen
237
+ colKeyGen,
238
+ fixedCols
238
239
  }) {
239
240
  const isColResizing = ref(false);
240
241
  let colResizeState = {
241
242
  currentCol: null,
242
- currentColIndex: 0,
243
243
  lastCol: null,
244
244
  startX: 0,
245
- startOffsetTableX: 0
245
+ startOffsetTableX: 0,
246
+ revertMoveX: false
246
247
  };
247
248
  onMounted(() => {
248
249
  initColResizeEvent();
@@ -258,7 +259,7 @@ function useColResize({
258
259
  window.removeEventListener("mousemove", onThResizeMouseMove);
259
260
  window.removeEventListener("mouseup", onThResizeMouseUp);
260
261
  }
261
- function onThResizeMouseDown(e, col, isPrev = false) {
262
+ function onThResizeMouseDown(e, col, leftHandle = false) {
262
263
  if (!tableContainerRef.value)
263
264
  return;
264
265
  e.stopPropagation();
@@ -267,19 +268,32 @@ function useColResize({
267
268
  const { scrollLeft, scrollTop } = tableContainerRef.value;
268
269
  const { left } = tableContainerRef.value.getBoundingClientRect();
269
270
  const tableHeaderLastValue = tableHeaderLast.value;
270
- let colIndex = tableHeaderLastValue.findIndex((it) => colKeyGen.value(it) === colKeyGen.value(col));
271
- if (isPrev) {
272
- colIndex -= 1;
273
- col = tableHeaderLastValue[colIndex];
271
+ let revertMoveX = false;
272
+ const colIndex = tableHeaderLastValue.findIndex((it) => colKeyGen.value(it) === colKeyGen.value(col));
273
+ const fixedIndex = fixedCols.value.indexOf(col);
274
+ const isFixed = fixedIndex !== -1;
275
+ if (leftHandle) {
276
+ if (isFixed && col.fixed === "right") {
277
+ revertMoveX = true;
278
+ } else {
279
+ if (colIndex - 1 >= 0) {
280
+ col = tableHeaderLastValue[colIndex - 1];
281
+ }
282
+ }
283
+ } else {
284
+ if (isFixed && col.fixed === "right") {
285
+ revertMoveX = true;
286
+ col = fixedCols.value[fixedIndex + 1] || col;
287
+ }
274
288
  }
275
289
  const offsetTableX = clientX - left + scrollLeft;
276
290
  isColResizing.value = true;
277
291
  Object.assign(colResizeState, {
278
292
  currentCol: col,
279
- currentColIndex: colIndex,
280
293
  lastCol: findLastChildCol(col),
281
294
  startX: clientX,
282
- startOffsetTableX: offsetTableX
295
+ startOffsetTableX: offsetTableX,
296
+ revertMoveX
283
297
  });
284
298
  if (colResizeIndicatorRef.value) {
285
299
  const style = colResizeIndicatorRef.value.style;
@@ -308,9 +322,9 @@ function useColResize({
308
322
  function onThResizeMouseUp(e) {
309
323
  if (!isColResizing.value)
310
324
  return;
311
- const { startX, lastCol } = colResizeState;
325
+ const { startX, lastCol, revertMoveX } = colResizeState;
312
326
  const { clientX } = e;
313
- const moveX = clientX - startX;
327
+ const moveX = revertMoveX ? startX - clientX : clientX - startX;
314
328
  let width = getCalculatedColWidth(lastCol) + moveX;
315
329
  if (width < props.colMinWidth)
316
330
  width = props.colMinWidth;
@@ -328,10 +342,10 @@ function useColResize({
328
342
  isColResizing.value = false;
329
343
  colResizeState = {
330
344
  currentCol: null,
331
- currentColIndex: 0,
332
345
  lastCol: null,
333
346
  startX: 0,
334
- startOffsetTableX: 0
347
+ startOffsetTableX: 0,
348
+ revertMoveX: false
335
349
  };
336
350
  }
337
351
  function findLastChildCol(column) {
@@ -435,6 +449,8 @@ function useFixedCol({
435
449
  fixedCols.value = fixedColsTemp;
436
450
  }
437
451
  return {
452
+ /** 正在被固定的列 */
453
+ fixedCols,
438
454
  /** 固定列class */
439
455
  fixedColClassMap,
440
456
  /** 滚动条变化时,更新需要展示阴影的列 */
@@ -1214,14 +1230,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1214
1230
  }
1215
1231
  });
1216
1232
  const rowKeyGenStore = /* @__PURE__ */ new WeakMap();
1217
- const { isColResizing, onThResizeMouseDown } = useColResize({
1218
- props,
1219
- emits,
1220
- colKeyGen,
1221
- colResizeIndicatorRef,
1222
- tableContainerRef,
1223
- tableHeaderLast
1224
- });
1225
1233
  const { onThDragStart, onThDragOver, onThDrop, isHeaderDraggable } = useThDrag({ props, emits });
1226
1234
  const {
1227
1235
  virtualScroll,
@@ -1260,7 +1268,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1260
1268
  tableHeaders,
1261
1269
  virtual_on
1262
1270
  });
1263
- const { fixedColClassMap, updateFixedShadow } = useFixedCol({
1271
+ const { fixedCols, fixedColClassMap, updateFixedShadow } = useFixedCol({
1264
1272
  props,
1265
1273
  colKeyGen,
1266
1274
  getFixedColPosition,
@@ -1268,6 +1276,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1268
1276
  tableHeaders,
1269
1277
  tableHeaderLast
1270
1278
  });
1279
+ const { isColResizing, onThResizeMouseDown } = useColResize({
1280
+ props,
1281
+ emits,
1282
+ colKeyGen,
1283
+ colResizeIndicatorRef,
1284
+ tableContainerRef,
1285
+ tableHeaderLast,
1286
+ fixedCols
1287
+ });
1271
1288
  watch(
1272
1289
  () => props.columns,
1273
1290
  () => {
@@ -1476,18 +1493,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1476
1493
  order = defaultSort.order || "desc";
1477
1494
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
1478
1495
  sortCol.value = defaultSort.dataIndex;
1479
- const c = props.columns.find((item) => item.dataIndex === defaultSort.dataIndex);
1480
- if (c) {
1481
- col = c;
1482
- } else {
1483
- console.error("defaultSort.dataIndex not found in columns");
1484
- col = props.columns[0];
1485
- }
1486
- if (!col)
1487
- return;
1496
+ col = props.columns.find((item) => item.dataIndex === defaultSort.dataIndex) || null;
1488
1497
  }
1489
1498
  if (!props.sortRemote || options.force) {
1490
- dataSourceCopy.value = tableSort(col, order, props.dataSource, sortConfig);
1499
+ const sortOption = col || defaultSort;
1500
+ if (sortOption) {
1501
+ dataSourceCopy.value = tableSort(sortOption, order, props.dataSource, sortConfig);
1502
+ }
1491
1503
  }
1492
1504
  if (click || options.emit) {
1493
1505
  emits("sort-change", col, order, toRaw(dataSourceCopy.value), sortConfig);
@@ -1596,6 +1608,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1596
1608
  function setCurrentRow(rowKey, option = { silent: false }) {
1597
1609
  if (!dataSourceCopy.value.length)
1598
1610
  return;
1611
+ if (rowKey === void 0) {
1612
+ currentRow.value = void 0;
1613
+ currentRowKey.value = void 0;
1614
+ }
1599
1615
  const row = dataSourceCopy.value.find((it) => rowKeyGen(it) === rowKey);
1600
1616
  if (!row) {
1601
1617
  console.warn("setCurrentRow failed.rowKey:", rowKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
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",
@@ -366,10 +366,10 @@ const props = withDefaults(
366
366
 
367
367
  const emits = defineEmits<{
368
368
  /**
369
- * 排序变更触发
370
- * ```(col: StkTableColumn<DT>, order: Order, data: DT[])```
369
+ * 排序变更触发。defaultSort.dataIndex 找不到时,col 将返回null。
370
+ * ```(col: StkTableColumn<DT> | null, order: Order, data: DT[])```
371
371
  */
372
- (e: 'sort-change', col: StkTableColumn<DT>, order: Order, data: DT[], sortConfig: SortConfig<DT>): void;
372
+ (e: 'sort-change', col: StkTableColumn<DT> | null, order: Order, data: DT[], sortConfig: SortConfig<DT>): void;
373
373
  /**
374
374
  * 一行点击事件
375
375
  * ```(ev: MouseEvent, row: DT)```
@@ -532,15 +532,6 @@ const getEmptyCellText = computed(() => {
532
532
  /** rowKey缓存 */
533
533
  const rowKeyGenStore = new WeakMap();
534
534
 
535
- const { isColResizing, onThResizeMouseDown } = useColResize({
536
- props,
537
- emits,
538
- colKeyGen,
539
- colResizeIndicatorRef,
540
- tableContainerRef,
541
- tableHeaderLast,
542
- });
543
-
544
535
  const { onThDragStart, onThDragOver, onThDrop, isHeaderDraggable } = useThDrag({ props, emits });
545
536
 
546
537
  const {
@@ -592,7 +583,7 @@ useKeyboardArrowScroll(tableContainerRef, {
592
583
  });
593
584
 
594
585
  /** 固定列处理 */
595
- const { fixedColClassMap, updateFixedShadow } = useFixedCol({
586
+ const { fixedCols, fixedColClassMap, updateFixedShadow } = useFixedCol({
596
587
  props,
597
588
  colKeyGen,
598
589
  getFixedColPosition,
@@ -601,6 +592,16 @@ const { fixedColClassMap, updateFixedShadow } = useFixedCol({
601
592
  tableHeaderLast,
602
593
  });
603
594
 
595
+ const { isColResizing, onThResizeMouseDown } = useColResize({
596
+ props,
597
+ emits,
598
+ colKeyGen,
599
+ colResizeIndicatorRef,
600
+ tableContainerRef,
601
+ tableHeaderLast,
602
+ fixedCols,
603
+ });
604
+
604
605
  watch(
605
606
  () => props.columns,
606
607
  () => {
@@ -840,7 +841,7 @@ function getHeaderTitle(col: StkTableColumn<DT>): string {
840
841
  * @param options.force sort-remote 开启后是否强制排序
841
842
  * @param options.emit 是否触发回调
842
843
  */
843
- function onColumnSort(col?: StkTableColumn<DT>, click = true, options: { force?: boolean; emit?: boolean } = {}) {
844
+ function onColumnSort(col: StkTableColumn<DT> | undefined | null, click = true, options: { force?: boolean; emit?: boolean } = {}) {
844
845
  if (!col?.sorter) return;
845
846
  options = { force: false, emit: false, ...options };
846
847
  if (sortCol.value !== col.dataIndex) {
@@ -864,17 +865,13 @@ function onColumnSort(col?: StkTableColumn<DT>, click = true, options: { force?:
864
865
  order = defaultSort.order || 'desc';
865
866
  sortOrderIndex.value = sortSwitchOrder.indexOf(order);
866
867
  sortCol.value = defaultSort.dataIndex as string;
867
- const c = props.columns.find(item => item.dataIndex === defaultSort.dataIndex);
868
- if (c) {
869
- col = c;
870
- } else {
871
- console.error('defaultSort.dataIndex not found in columns');
872
- col = props.columns[0];
873
- }
874
- if (!col) return;
868
+ col = props.columns.find(item => item.dataIndex === defaultSort.dataIndex) || null;
875
869
  }
876
870
  if (!props.sortRemote || options.force) {
877
- dataSourceCopy.value = tableSort(col, order, props.dataSource, sortConfig);
871
+ const sortOption = col || defaultSort;
872
+ if (sortOption) {
873
+ dataSourceCopy.value = tableSort(sortOption, order, props.dataSource, sortConfig);
874
+ }
878
875
  }
879
876
  // 只有点击才触发事件
880
877
  if (click || options.emit) {
@@ -1030,11 +1027,15 @@ function onTrMouseOver(_e: MouseEvent, row: DT) {
1030
1027
 
1031
1028
  /**
1032
1029
  * 选中一行,
1033
- * @param {string} rowKey selected rowKey, null to unselect
1030
+ * @param {string} rowKey selected rowKey, undefined to unselect
1034
1031
  * @param {boolean} option.silent 是否触发回调
1035
1032
  */
1036
- function setCurrentRow(rowKey: string, option = { silent: false }) {
1033
+ function setCurrentRow(rowKey: string | undefined, option = { silent: false }) {
1037
1034
  if (!dataSourceCopy.value.length) return;
1035
+ if (rowKey === void 0) {
1036
+ currentRow.value = void 0;
1037
+ currentRowKey.value = void 0;
1038
+ }
1038
1039
  const row = dataSourceCopy.value.find(it => rowKeyGen(it) === rowKey);
1039
1040
  if (!row) {
1040
1041
  console.warn('setCurrentRow failed.rowKey:', rowKey);
@@ -132,8 +132,11 @@ export type SortConfig<T extends Record<string, any>> = {
132
132
  * 类似onMounted时,调用setSorter点了下表头。
133
133
  */
134
134
  defaultSort?: {
135
- dataIndex: keyof T;
135
+ dataIndex: StkTableColumn<T>['dataIndex'];
136
136
  order: Order;
137
+ sortField?: StkTableColumn<T>['sortField'];
138
+ sortType?: StkTableColumn<T>['sortType'];
139
+ sorter?: StkTableColumn<T>['sorter'];
137
140
  /** 是否禁止触发sort-change事件。默认false,表示触发事件。 */
138
141
  silent?: boolean;
139
142
  };
@@ -5,14 +5,14 @@ import { getCalculatedColWidth } from './utils';
5
5
  type ColResizeState<DT extends Record<string, any>> = {
6
6
  /** 当前被拖动的列*/
7
7
  currentCol: StkTableColumn<DT> | null;
8
- /** 当前被拖动列的下标 */
9
- currentColIndex: number;
10
8
  /** 最后一个叶子列 */
11
9
  lastCol: StkTableColumn<DT> | null;
12
10
  /** 鼠标按下开始位置 */
13
11
  startX: number;
14
12
  /** 鼠标按下时鼠标对于表格的偏移量 */
15
13
  startOffsetTableX: 0;
14
+ /** 是否反向计算,true:左增右减。false:左减右增 */
15
+ revertMoveX: boolean;
16
16
  };
17
17
 
18
18
  type Params<DT extends Record<string, any>> = {
@@ -22,6 +22,7 @@ type Params<DT extends Record<string, any>> = {
22
22
  tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>;
23
23
  colResizeIndicatorRef: Ref<HTMLElement | undefined>;
24
24
  colKeyGen: ComputedRef<(p: any) => UniqKey>;
25
+ fixedCols: Ref<StkTableColumn<DT>[]>;
25
26
  };
26
27
 
27
28
  /** 列宽拖动 */
@@ -32,6 +33,7 @@ export function useColResize<DT extends Record<string, any>>({
32
33
  props,
33
34
  emits,
34
35
  colKeyGen,
36
+ fixedCols,
35
37
  }: Params<DT>) {
36
38
  /** 列宽是否在拖动 */
37
39
  const isColResizing = ref(false);
@@ -39,10 +41,10 @@ export function useColResize<DT extends Record<string, any>>({
39
41
  /** 列宽调整状态 */
40
42
  let colResizeState: ColResizeState<DT> = {
41
43
  currentCol: null,
42
- currentColIndex: 0,
43
44
  lastCol: null,
44
45
  startX: 0,
45
46
  startOffsetTableX: 0,
47
+ revertMoveX: false,
46
48
  };
47
49
 
48
50
  onMounted(() => {
@@ -68,9 +70,9 @@ export function useColResize<DT extends Record<string, any>>({
68
70
  * 拖动开始
69
71
  * @param e
70
72
  * @param col 当前列配置
71
- * @param isPrev 是否要上一列
73
+ * @param leftHandle 是否是左侧的拖动条
72
74
  */
73
- function onThResizeMouseDown(e: MouseEvent, col: StkTableColumn<DT>, isPrev = false) {
75
+ function onThResizeMouseDown(e: MouseEvent, col: StkTableColumn<DT>, leftHandle = false) {
74
76
  if (!tableContainerRef.value) return;
75
77
  e.stopPropagation();
76
78
  e.preventDefault();
@@ -78,23 +80,43 @@ export function useColResize<DT extends Record<string, any>>({
78
80
  const { scrollLeft, scrollTop } = tableContainerRef.value;
79
81
  const { left } = tableContainerRef.value.getBoundingClientRect();
80
82
  const tableHeaderLastValue = tableHeaderLast.value;
83
+ let revertMoveX = false;
81
84
  /** 列下标 */
82
- let colIndex = tableHeaderLastValue.findIndex(it => colKeyGen.value(it) === colKeyGen.value(col));
83
- if (isPrev) {
84
- // 上一列
85
- colIndex -= 1;
86
- col = tableHeaderLastValue[colIndex];
85
+ const colIndex = tableHeaderLastValue.findIndex(it => colKeyGen.value(it) === colKeyGen.value(col));
86
+ const fixedIndex = fixedCols.value.indexOf(col);
87
+ /** 是否正在被固定 */
88
+ const isFixed = fixedIndex !== -1;
89
+
90
+ if (leftHandle) {
91
+ // 左侧拖动条
92
+ if (isFixed && col.fixed === 'right') {
93
+ // 对于固定右侧的列,拖动左侧的把,需要反向计算
94
+ revertMoveX = true;
95
+ } else {
96
+ // 默认拖动右侧的把,取上一列
97
+ if (colIndex - 1 >= 0) {
98
+ col = tableHeaderLastValue[colIndex - 1];
99
+ }
100
+ }
101
+ } else {
102
+ // 右侧拖动条
103
+ if (isFixed && col.fixed === 'right') {
104
+ // 对于固定右侧的列,拖动右侧的把,需要拖动下一固定的列
105
+ revertMoveX = true;
106
+ col = fixedCols.value[fixedIndex + 1] || col;
107
+ }
87
108
  }
109
+
88
110
  const offsetTableX = clientX - left + scrollLeft;
89
111
 
90
112
  // 记录拖动状态
91
113
  isColResizing.value = true;
92
114
  Object.assign(colResizeState, {
93
115
  currentCol: col,
94
- currentColIndex: colIndex,
95
116
  lastCol: findLastChildCol(col),
96
117
  startX: clientX,
97
118
  startOffsetTableX: offsetTableX,
119
+ revertMoveX,
98
120
  });
99
121
 
100
122
  // 展示指示线,更新其位置
@@ -132,9 +154,9 @@ export function useColResize<DT extends Record<string, any>>({
132
154
  */
133
155
  function onThResizeMouseUp(e: MouseEvent) {
134
156
  if (!isColResizing.value) return;
135
- const { startX, lastCol } = colResizeState;
157
+ const { startX, lastCol, revertMoveX } = colResizeState;
136
158
  const { clientX } = e;
137
- const moveX = clientX - startX;
159
+ const moveX = revertMoveX ? startX - clientX : clientX - startX;
138
160
 
139
161
  // 移动量不小于最小列宽
140
162
  let width = getCalculatedColWidth(lastCol) + moveX;
@@ -157,10 +179,10 @@ export function useColResize<DT extends Record<string, any>>({
157
179
  isColResizing.value = false;
158
180
  colResizeState = {
159
181
  currentCol: null,
160
- currentColIndex: 0,
161
182
  lastCol: null,
162
183
  startX: 0,
163
184
  startOffsetTableX: 0,
185
+ revertMoveX: false,
164
186
  };
165
187
  }
166
188
 
@@ -125,6 +125,8 @@ export function useFixedCol<DT extends Record<string, any>>({
125
125
  }
126
126
 
127
127
  return {
128
+ /** 正在被固定的列 */
129
+ fixedCols,
128
130
  /** 固定列class */
129
131
  fixedColClassMap,
130
132
  /** 滚动条变化时,更新需要展示阴影的列 */
@@ -3,7 +3,7 @@ import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../typ
3
3
 
4
4
  /** 是否空值 */
5
5
  function isEmptyValue(val: any, isNumber?: boolean) {
6
- let isEmpty = val === null || val === '';
6
+ let isEmpty = val === null || val === '' || val === void 0;
7
7
  if (isNumber) {
8
8
  isEmpty = isEmpty || typeof val === 'boolean' || Number.isNaN(+val);
9
9
  }
@@ -104,7 +104,7 @@ function separatedData<T extends Record<string, any>>(sortOption: SortOption<T>,
104
104
  for (let i = 0; i < targetDataSource.length; i++) {
105
105
  const row = targetDataSource[i];
106
106
  const sortField = sortOption.sortField || sortOption.dataIndex;
107
- const isEmpty = isEmptyValue(row[sortField], isNumber);
107
+ const isEmpty = isEmptyValue(row?.[sortField], isNumber); // deal row is null
108
108
  if (isEmpty) {
109
109
  emptyArr.push(row);
110
110
  } else {
@@ -131,7 +131,8 @@ export function tableSort<T extends Record<string, any>>(
131
131
  dataSource: T[],
132
132
  sortConfig: SortConfig<T> = {},
133
133
  ): T[] {
134
- if (!dataSource?.length) return dataSource || [];
134
+ if (!dataSource?.length || !sortOption) return dataSource || [];
135
+
135
136
  sortConfig = { emptyToBottom: false, ...sortConfig };
136
137
  let targetDataSource = [...dataSource];
137
138
  let sortField = sortOption.sortField || sortOption.dataIndex;
@@ -149,8 +150,8 @@ export function tableSort<T extends Record<string, any>>(
149
150
  let { sortType } = sortOption;
150
151
  if (!sortType) sortType = typeof dataSource[0][sortField] as 'number' | 'string';
151
152
 
152
- const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, sortType === 'number');
153
153
  const isNumber = sortType === 'number';
154
+ const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
154
155
 
155
156
  if (order === 'asc') {
156
157
  valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, sortConfig.stringLocaleCompare));