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 +4 -4
- package/lib/src/StkTable/StkTable.vue.d.ts +6 -6
- package/lib/src/StkTable/types/index.d.ts +4 -1
- package/lib/src/StkTable/useColResize.d.ts +3 -2
- package/lib/src/StkTable/useFixedCol.d.ts +2 -0
- package/lib/stk-table-vue.js +53 -37
- package/package.json +1 -1
- package/src/StkTable/StkTable.vue +26 -25
- package/src/StkTable/types/index.ts +4 -1
- package/src/StkTable/useColResize.ts +36 -14
- package/src/StkTable/useFixedCol.ts +2 -0
- package/src/StkTable/utils/index.ts +5 -4
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
|
|
254
|
+
* 排序变更触发。defaultSort.dataIndex 找不到时,col 将返回null。
|
|
255
|
+
* ```(col: StkTableColumn<DT> | null, order: Order, data: DT[])```
|
|
256
256
|
*/
|
|
257
|
-
(e: 'sort-change', col: StkTableColumn<DT
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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>,
|
|
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
|
/** 滚动条变化时,更新需要展示阴影的列 */
|
package/lib/stk-table-vue.js
CHANGED
|
@@ -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,
|
|
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
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -366,10 +366,10 @@ const props = withDefaults(
|
|
|
366
366
|
|
|
367
367
|
const emits = defineEmits<{
|
|
368
368
|
/**
|
|
369
|
-
*
|
|
370
|
-
* ```(col: StkTableColumn<DT
|
|
369
|
+
* 排序变更触发。defaultSort.dataIndex 找不到时,col 将返回null。
|
|
370
|
+
* ```(col: StkTableColumn<DT> | null, order: Order, data: DT[])```
|
|
371
371
|
*/
|
|
372
|
-
(e: 'sort-change', col: StkTableColumn<DT
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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
|
|
73
|
+
* @param leftHandle 是否是左侧的拖动条
|
|
72
74
|
*/
|
|
73
|
-
function onThResizeMouseDown(e: MouseEvent, col: StkTableColumn<DT>,
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
|
@@ -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));
|