stk-table-vue 0.2.2 → 0.2.5
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 +30 -8
- package/lib/src/StkTable/StkTable.vue.d.ts +29 -20
- package/lib/src/StkTable/index.d.ts +1 -0
- package/lib/src/StkTable/types/index.d.ts +17 -3
- package/lib/src/StkTable/useFixedStyle.d.ts +3 -3
- package/lib/src/StkTable/useHighlight.d.ts +10 -3
- package/lib/src/StkTable/useVirtualScroll.d.ts +3 -2
- package/lib/src/StkTable/utils.d.ts +6 -2
- package/lib/stk-table-vue.js +218 -122
- package/package.json +60 -60
- package/src/StkTable/StkTable.vue +78 -37
- package/src/StkTable/types/index.ts +17 -3
- package/src/StkTable/useFixedStyle.ts +49 -28
- package/src/StkTable/useHighlight.ts +50 -33
- package/src/StkTable/useKeyboardArrowScroll.ts +8 -4
- package/src/StkTable/useVirtualScroll.ts +42 -11
- package/src/StkTable/utils.ts +85 -47
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "stk-table-vue",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Simple realtime virtual table for vue3&vue2.7",
|
|
5
|
-
"main": "./lib/stk-table-vue.js",
|
|
6
|
-
"types": "./lib/StkTable/index.d.ts",
|
|
7
|
-
"packageManager": "pnpm@8.14.3",
|
|
8
|
-
"directories": {
|
|
9
|
-
"test": "test"
|
|
10
|
-
},
|
|
11
|
-
"type": "module",
|
|
12
|
-
"scripts": {
|
|
13
|
-
"dev": "vite",
|
|
14
|
-
"build": "vite build",
|
|
15
|
-
"test": "vitest"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"virtual table",
|
|
19
|
-
"vue",
|
|
20
|
-
"highlight",
|
|
21
|
-
"sticky"
|
|
22
|
-
],
|
|
23
|
-
"files": [
|
|
24
|
-
"lib",
|
|
25
|
-
"src"
|
|
26
|
-
],
|
|
27
|
-
"author": "japlus",
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "https://gitee.com/japlus/stk-table-vue"
|
|
31
|
-
},
|
|
32
|
-
"license": "MIT",
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/d3-interpolate": "^3.0.4",
|
|
35
|
-
"@types/node": "^20.11.14",
|
|
36
|
-
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
37
|
-
"@typescript-eslint/parser": "^6.14.0",
|
|
38
|
-
"@vitejs/plugin-vue": "^5.0.3",
|
|
39
|
-
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
|
40
|
-
"@vue/test-utils": "2.4.4",
|
|
41
|
-
"eslint": "^8.55.0",
|
|
42
|
-
"eslint-config-prettier": "^9.1.0",
|
|
43
|
-
"eslint-plugin-html": "^7.1.0",
|
|
44
|
-
"eslint-plugin-prettier": "^5.0.1",
|
|
45
|
-
"eslint-plugin-vue": "^9.19.2",
|
|
46
|
-
"happy-dom": "^12.10.3",
|
|
47
|
-
"less": "^4.2.0",
|
|
48
|
-
"postcss-discard-comments": "^6.0.1",
|
|
49
|
-
"postcss-preset-env": "^9.3.0",
|
|
50
|
-
"prettier": "^3.1.1",
|
|
51
|
-
"typescript": "^5.3.3",
|
|
52
|
-
"vite": "^5.
|
|
53
|
-
"vite-plugin-dts": "^3.
|
|
54
|
-
"vitest": "^1.1.0",
|
|
55
|
-
"vue": "^3.
|
|
56
|
-
"vue-eslint-parser": "^9.3.2"
|
|
57
|
-
},
|
|
58
|
-
"dependencies": {
|
|
59
|
-
"d3-interpolate": "^3.0.1"
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "stk-table-vue",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "Simple realtime virtual table for vue3&vue2.7",
|
|
5
|
+
"main": "./lib/stk-table-vue.js",
|
|
6
|
+
"types": "./lib/StkTable/index.d.ts",
|
|
7
|
+
"packageManager": "pnpm@8.14.3",
|
|
8
|
+
"directories": {
|
|
9
|
+
"test": "test"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"dev": "vite",
|
|
14
|
+
"build": "vite build",
|
|
15
|
+
"test": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"virtual table",
|
|
19
|
+
"vue",
|
|
20
|
+
"highlight",
|
|
21
|
+
"sticky"
|
|
22
|
+
],
|
|
23
|
+
"files": [
|
|
24
|
+
"lib",
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
27
|
+
"author": "japlus",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://gitee.com/japlus/stk-table-vue"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/d3-interpolate": "^3.0.4",
|
|
35
|
+
"@types/node": "^20.11.14",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
37
|
+
"@typescript-eslint/parser": "^6.14.0",
|
|
38
|
+
"@vitejs/plugin-vue": "^5.0.3",
|
|
39
|
+
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
|
40
|
+
"@vue/test-utils": "2.4.4",
|
|
41
|
+
"eslint": "^8.55.0",
|
|
42
|
+
"eslint-config-prettier": "^9.1.0",
|
|
43
|
+
"eslint-plugin-html": "^7.1.0",
|
|
44
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
45
|
+
"eslint-plugin-vue": "^9.19.2",
|
|
46
|
+
"happy-dom": "^12.10.3",
|
|
47
|
+
"less": "^4.2.0",
|
|
48
|
+
"postcss-discard-comments": "^6.0.1",
|
|
49
|
+
"postcss-preset-env": "^9.3.0",
|
|
50
|
+
"prettier": "^3.1.1",
|
|
51
|
+
"typescript": "^5.3.3",
|
|
52
|
+
"vite": "^5.1.4",
|
|
53
|
+
"vite-plugin-dts": "^3.7.3",
|
|
54
|
+
"vitest": "^1.1.0",
|
|
55
|
+
"vue": "^3.4.19",
|
|
56
|
+
"vue-eslint-parser": "^9.3.2"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"d3-interpolate": "^3.0.1"
|
|
60
|
+
}
|
|
61
61
|
}
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
:rowspan="virtualX_on ? 1 : col.rowSpan"
|
|
62
62
|
:colspan="col.colSpan"
|
|
63
63
|
:style="getCellStyle(1, col, rowIndex)"
|
|
64
|
-
:title="col
|
|
64
|
+
:title="getHeaderTitle(col)"
|
|
65
65
|
:class="[
|
|
66
66
|
col.sorter ? 'sortable' : '',
|
|
67
67
|
col.dataIndex === sortCol && sortOrderIndex !== 0 && 'sorter-' + sortSwitchOrder[sortOrderIndex],
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
[rowClassName(row, i)]: true,
|
|
149
149
|
}"
|
|
150
150
|
:style="{
|
|
151
|
-
backgroundColor: row
|
|
151
|
+
backgroundColor: highlightRowStore[rowKeyGen(row)]?.bgc,
|
|
152
152
|
}"
|
|
153
153
|
@click="e => onRowClick(e, row)"
|
|
154
154
|
@dblclick="e => onRowDblclick(e, row)"
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
*/
|
|
192
192
|
import { CSSProperties, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
|
|
193
193
|
import { Default_Row_Height } from './const';
|
|
194
|
-
import { Order, SortConfig, SortOption, SortState, StkTableColumn,
|
|
194
|
+
import { Order, SortConfig, SortOption, SortState, StkTableColumn, UniqKeyProp } from './types/index';
|
|
195
195
|
import { useAutoResize } from './useAutoResize';
|
|
196
196
|
import { useColResize } from './useColResize';
|
|
197
197
|
import { useFixedCol } from './useFixedCol';
|
|
@@ -200,7 +200,7 @@ import { useHighlight } from './useHighlight';
|
|
|
200
200
|
import { useKeyboardArrowScroll } from './useKeyboardArrowScroll';
|
|
201
201
|
import { useThDrag } from './useThDrag';
|
|
202
202
|
import { useVirtualScroll } from './useVirtualScroll';
|
|
203
|
-
import { howDeepTheHeader, tableSort } from './utils';
|
|
203
|
+
import { getColWidth, getColWidthStr, howDeepTheHeader, tableSort } from './utils';
|
|
204
204
|
|
|
205
205
|
/** Generic stands for DataType */
|
|
206
206
|
type DT = any;
|
|
@@ -235,11 +235,11 @@ const props = withDefaults(
|
|
|
235
235
|
/** 表格数据源 */
|
|
236
236
|
dataSource?: DT[];
|
|
237
237
|
/** 行唯一键 */
|
|
238
|
-
rowKey?:
|
|
238
|
+
rowKey?: UniqKeyProp;
|
|
239
239
|
/** 列唯一键 */
|
|
240
|
-
colKey?:
|
|
240
|
+
colKey?: UniqKeyProp;
|
|
241
241
|
/** 空值展示文字 */
|
|
242
|
-
emptyCellText?: string;
|
|
242
|
+
emptyCellText?: string; //TODO: 支持传入方法
|
|
243
243
|
/** 暂无数据兜底高度是否撑满 */
|
|
244
244
|
noDataFull?: boolean;
|
|
245
245
|
/** 是否展示暂无数据 */
|
|
@@ -286,7 +286,9 @@ const props = withDefaults(
|
|
|
286
286
|
/** 优化vue2 滚动 */
|
|
287
287
|
optimizeVue2Scroll?: boolean;
|
|
288
288
|
/** 排序配置 */
|
|
289
|
-
sortConfig?: SortConfig
|
|
289
|
+
sortConfig?: SortConfig<DT>;
|
|
290
|
+
/** 隐藏头部title。可传入dataIndex数组 */
|
|
291
|
+
hideHeaderTitle?: boolean | string[];
|
|
290
292
|
}>(),
|
|
291
293
|
{
|
|
292
294
|
width: '',
|
|
@@ -321,7 +323,9 @@ const props = withDefaults(
|
|
|
321
323
|
optimizeVue2Scroll: false,
|
|
322
324
|
sortConfig: () => ({
|
|
323
325
|
emptyToBottom: false,
|
|
326
|
+
stringLocaleCompare: true,
|
|
324
327
|
}),
|
|
328
|
+
hideHeaderTitle: false,
|
|
325
329
|
},
|
|
326
330
|
);
|
|
327
331
|
|
|
@@ -330,7 +334,7 @@ const emits = defineEmits<{
|
|
|
330
334
|
* 排序变更触发
|
|
331
335
|
* ```(col: StkTableColumn<DT>, order: Order, data: DT[])```
|
|
332
336
|
*/
|
|
333
|
-
(e: 'sort-change', col: StkTableColumn<DT>, order: Order, data: DT[], sortConfig: SortConfig): void;
|
|
337
|
+
(e: 'sort-change', col: StkTableColumn<DT>, order: Order, data: DT[], sortConfig: SortConfig<DT>): void;
|
|
334
338
|
/**
|
|
335
339
|
* 一行点击事件
|
|
336
340
|
* ```(ev: MouseEvent, row: DT)```
|
|
@@ -470,11 +474,11 @@ const {
|
|
|
470
474
|
initVirtualScrollX,
|
|
471
475
|
updateVirtualScrollY,
|
|
472
476
|
updateVirtualScrollX,
|
|
473
|
-
} = useVirtualScroll({ tableContainer, props, dataSourceCopy, tableHeaderLast });
|
|
477
|
+
} = useVirtualScroll({ tableContainer, props, dataSourceCopy, tableHeaderLast, tableHeaders });
|
|
474
478
|
|
|
475
|
-
const { getFixedStyle } = useFixedStyle({
|
|
479
|
+
const { getFixedStyle } = useFixedStyle<DT>({
|
|
476
480
|
props,
|
|
477
|
-
|
|
481
|
+
tableHeaders,
|
|
478
482
|
virtualScroll,
|
|
479
483
|
virtualScrollX,
|
|
480
484
|
virtualX_on,
|
|
@@ -484,7 +488,7 @@ const { getFixedStyle } = useFixedStyle({
|
|
|
484
488
|
/**
|
|
485
489
|
* 高亮行,高亮单元格
|
|
486
490
|
*/
|
|
487
|
-
const { setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer
|
|
491
|
+
const { highlightRowStore, setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer });
|
|
488
492
|
|
|
489
493
|
if (props.autoResize) {
|
|
490
494
|
useAutoResize({ tableContainer, initVirtualScroll, props, debounceMs: 200 });
|
|
@@ -548,8 +552,16 @@ watch(() => props.fixedColShadow, dealFixedColShadow);
|
|
|
548
552
|
onMounted(() => {
|
|
549
553
|
initVirtualScroll();
|
|
550
554
|
updateFixedShadow();
|
|
555
|
+
dealDefaultSorter();
|
|
551
556
|
});
|
|
552
557
|
|
|
558
|
+
/** 处理默认排序 */
|
|
559
|
+
function dealDefaultSorter() {
|
|
560
|
+
if (!props.sortConfig.defaultSort) return;
|
|
561
|
+
const { dataIndex, order } = props.sortConfig.defaultSort;
|
|
562
|
+
setSorter(dataIndex as string, order);
|
|
563
|
+
}
|
|
564
|
+
|
|
553
565
|
/**
|
|
554
566
|
* 处理多级表头
|
|
555
567
|
*/
|
|
@@ -559,7 +571,7 @@ function dealColumns() {
|
|
|
559
571
|
tableHeaderLast.value = [];
|
|
560
572
|
const copyColumn = props.columns; // do not deep clone
|
|
561
573
|
const deep = howDeepTheHeader(copyColumn);
|
|
562
|
-
const tempHeaderLast: StkTableColumn<
|
|
574
|
+
const tempHeaderLast: StkTableColumn<DT>[] = [];
|
|
563
575
|
|
|
564
576
|
if (deep > 1 && props.virtualX) {
|
|
565
577
|
console.error('多级表头不支持横向虚拟滚动');
|
|
@@ -579,6 +591,7 @@ function dealColumns() {
|
|
|
579
591
|
}
|
|
580
592
|
/** 所有子节点数量 */
|
|
581
593
|
let allChildrenLen = 0;
|
|
594
|
+
let allChildrenWidthSum = 0;
|
|
582
595
|
arr.forEach(col => {
|
|
583
596
|
// TODO: 继承父节点固定列配置
|
|
584
597
|
// if (parentFixed) {
|
|
@@ -588,10 +601,15 @@ function dealColumns() {
|
|
|
588
601
|
col.__PARENT__ = parent;
|
|
589
602
|
/** 一列中的子节点数量 */
|
|
590
603
|
let colChildrenLen = 1;
|
|
604
|
+
/** 多级表头的父节点宽度,通过叶子节点宽度计算得到 */
|
|
605
|
+
let colWidth = 0;
|
|
591
606
|
if (col.children) {
|
|
592
607
|
// DFS
|
|
593
|
-
|
|
608
|
+
const [len, widthSum] = flat(col.children, col, depth + 1 /* , col.fixed */);
|
|
609
|
+
colChildrenLen = len;
|
|
610
|
+
colWidth = widthSum;
|
|
594
611
|
} else {
|
|
612
|
+
colWidth = getColWidth(col);
|
|
595
613
|
tempHeaderLast.push(col); // 没有children的列作为colgroup
|
|
596
614
|
}
|
|
597
615
|
// 回溯
|
|
@@ -604,9 +622,14 @@ function dealColumns() {
|
|
|
604
622
|
if (colSpan !== 1) {
|
|
605
623
|
col.colSpan = colSpan;
|
|
606
624
|
}
|
|
625
|
+
if (!props.fixedMode && col.width === void 0) {
|
|
626
|
+
// 列赋值默认列宽。由于有些场景不需要设置width。
|
|
627
|
+
col.width = colWidth + 'px';
|
|
628
|
+
}
|
|
607
629
|
allChildrenLen += colChildrenLen;
|
|
630
|
+
allChildrenWidthSum += colWidth;
|
|
608
631
|
});
|
|
609
|
-
return allChildrenLen;
|
|
632
|
+
return [allChildrenLen, allChildrenWidthSum];
|
|
610
633
|
}
|
|
611
634
|
|
|
612
635
|
flat(copyColumn, null);
|
|
@@ -637,18 +660,18 @@ function colKeyGen(col: StkTableColumn<DT>) {
|
|
|
637
660
|
}
|
|
638
661
|
|
|
639
662
|
/** 获取列宽度样式 */
|
|
640
|
-
function getColWidthStyle(col: StkTableColumn<
|
|
663
|
+
function getColWidthStyle(col: StkTableColumn<DT>) {
|
|
664
|
+
const width = getColWidthStr(col);
|
|
665
|
+
const minWidth = getColWidthStr(col, 'minWidth');
|
|
666
|
+
const maxWidth = getColWidthStr(col, 'maxWidth');
|
|
641
667
|
const style: CSSProperties = {
|
|
642
|
-
width
|
|
643
|
-
minWidth:
|
|
644
|
-
maxWidth:
|
|
668
|
+
width,
|
|
669
|
+
minWidth: minWidth ?? width,
|
|
670
|
+
maxWidth: maxWidth ?? width,
|
|
645
671
|
};
|
|
646
672
|
if (props.colResizable) {
|
|
647
|
-
style.minWidth =
|
|
648
|
-
style.maxWidth =
|
|
649
|
-
} else {
|
|
650
|
-
style.minWidth = col.minWidth === void 0 ? col.width : col.minWidth;
|
|
651
|
-
style.maxWidth = col.maxWidth === void 0 ? col.width : col.maxWidth;
|
|
673
|
+
style.minWidth = width;
|
|
674
|
+
style.maxWidth = width;
|
|
652
675
|
}
|
|
653
676
|
|
|
654
677
|
return style;
|
|
@@ -662,7 +685,7 @@ function getColWidthStyle(col: StkTableColumn<any>) {
|
|
|
662
685
|
* @param col
|
|
663
686
|
* @param depth 表头层级
|
|
664
687
|
*/
|
|
665
|
-
function getCellStyle(tagType: 1 | 2, col: StkTableColumn<
|
|
688
|
+
function getCellStyle(tagType: 1 | 2, col: StkTableColumn<DT>, depth?: number): CSSProperties {
|
|
666
689
|
const style: CSSProperties = {
|
|
667
690
|
...getColWidthStyle(col),
|
|
668
691
|
...getFixedStyle(tagType, col, depth),
|
|
@@ -678,12 +701,22 @@ function getCellStyle(tagType: 1 | 2, col: StkTableColumn<any>, depth?: number):
|
|
|
678
701
|
return style;
|
|
679
702
|
}
|
|
680
703
|
|
|
704
|
+
/** th title */
|
|
705
|
+
function getHeaderTitle(col: StkTableColumn<DT>): string {
|
|
706
|
+
// 不展示title
|
|
707
|
+
if (props.hideHeaderTitle === true || (Array.isArray(props.hideHeaderTitle) && props.hideHeaderTitle.includes(col.dataIndex))) {
|
|
708
|
+
return '';
|
|
709
|
+
}
|
|
710
|
+
return col.title || '';
|
|
711
|
+
}
|
|
712
|
+
|
|
681
713
|
/**
|
|
682
714
|
* 表头点击排序
|
|
683
|
-
* @param
|
|
684
|
-
* @param
|
|
715
|
+
* @param click 是否为点击表头触发
|
|
716
|
+
* @param options.force sort-remote 开启后是否强制排序
|
|
717
|
+
* @param options.emit 是否触发回调
|
|
685
718
|
*/
|
|
686
|
-
function onColumnSort(col?: StkTableColumn<
|
|
719
|
+
function onColumnSort(col?: StkTableColumn<DT>, click = true, options: { force?: boolean; emit?: boolean } = {}) {
|
|
687
720
|
if (!col?.sorter) return;
|
|
688
721
|
options = { force: false, emit: false, ...options };
|
|
689
722
|
if (sortCol.value !== col.dataIndex) {
|
|
@@ -694,8 +727,16 @@ function onColumnSort(col?: StkTableColumn<any>, click = true, options: { force?
|
|
|
694
727
|
if (click) sortOrderIndex.value++;
|
|
695
728
|
sortOrderIndex.value = sortOrderIndex.value % 3;
|
|
696
729
|
|
|
697
|
-
|
|
730
|
+
let order = sortSwitchOrder[sortOrderIndex.value];
|
|
698
731
|
const sortConfig = props.sortConfig;
|
|
732
|
+
const defaultSort = sortConfig.defaultSort;
|
|
733
|
+
|
|
734
|
+
if (!order && defaultSort) {
|
|
735
|
+
// 没有排序时变成默认排序
|
|
736
|
+
order = defaultSort.order;
|
|
737
|
+
sortOrderIndex.value = sortSwitchOrder.indexOf(order);
|
|
738
|
+
sortCol.value = defaultSort.dataIndex as string;
|
|
739
|
+
}
|
|
699
740
|
if (!props.sortRemote || options.force) {
|
|
700
741
|
dataSourceCopy.value = tableSort(col, order, props.dataSource, sortConfig);
|
|
701
742
|
}
|
|
@@ -813,16 +854,16 @@ function setCurrentRow(rowKey: string, option = { silent: false }) {
|
|
|
813
854
|
|
|
814
855
|
/**
|
|
815
856
|
* 设置表头排序状态
|
|
816
|
-
* @param
|
|
817
|
-
* @param
|
|
818
|
-
* @param
|
|
819
|
-
* @param
|
|
820
|
-
* @param
|
|
857
|
+
* @param dataIndex 列字段
|
|
858
|
+
* @param order 正序倒序
|
|
859
|
+
* @param option.sortOption 指定排序参数。同 StkTableColumn 中排序相关字段。建议从columns中find得到。
|
|
860
|
+
* @param option.sort 是否触发排序-默认true
|
|
861
|
+
* @param option.silent 是否禁止触发回调-默认true
|
|
821
862
|
*/
|
|
822
|
-
function setSorter(dataIndex: string, order:
|
|
863
|
+
function setSorter(dataIndex: string, order: Order, option: { sortOption?: SortOption<DT>; silent?: boolean; sort?: boolean } = {}) {
|
|
823
864
|
const newOption = { silent: true, sortOption: null, sort: true, ...option };
|
|
824
865
|
sortCol.value = dataIndex;
|
|
825
|
-
sortOrderIndex.value = sortSwitchOrder.
|
|
866
|
+
sortOrderIndex.value = sortSwitchOrder.indexOf(order);
|
|
826
867
|
|
|
827
868
|
if (newOption.sort && dataSourceCopy.value?.length) {
|
|
828
869
|
// 如果表格有数据,则进行排序
|
|
@@ -59,18 +59,32 @@ export type StkTableColumn<T extends Record<string, any>> = {
|
|
|
59
59
|
__PARENT__?: StkTableColumn<T> | null;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
export type SortOption = Pick<StkTableColumn<
|
|
62
|
+
export type SortOption<T extends Record<string, any>> = Pick<StkTableColumn<T>, 'sorter' | 'dataIndex' | 'sortField' | 'sortType'>;
|
|
63
63
|
|
|
64
|
+
/** 排序状态 */
|
|
64
65
|
export type SortState<T> = {
|
|
65
66
|
dataIndex: T;
|
|
66
67
|
order: null | 'asc' | 'desc';
|
|
67
68
|
sortType?: 'number' | 'string';
|
|
68
69
|
};
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
/** 唯一键 */
|
|
72
|
+
export type UniqKey = string | number;
|
|
73
|
+
export type UniqKeyFun = (param: any) => UniqKey;
|
|
74
|
+
export type UniqKeyProp = UniqKey | UniqKeyFun;
|
|
71
75
|
|
|
72
76
|
/** 排序配置 */
|
|
73
|
-
export type SortConfig = {
|
|
77
|
+
export type SortConfig<T extends Record<string, any>> = {
|
|
74
78
|
/** 空值始终排在列表末尾 */
|
|
75
79
|
emptyToBottom?: boolean;
|
|
80
|
+
/** 默认排序(1.初始化时触发 2.排序方向为null时触发) */
|
|
81
|
+
defaultSort?: {
|
|
82
|
+
dataIndex: keyof T;
|
|
83
|
+
order: Order;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* string排序是否使用 String.prototype.localCompare
|
|
87
|
+
* 默认true (&$&应该false)
|
|
88
|
+
*/
|
|
89
|
+
stringLocaleCompare?: boolean;
|
|
76
90
|
};
|
|
@@ -4,9 +4,9 @@ import { StkTableColumn } from './types';
|
|
|
4
4
|
import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
|
|
5
5
|
import { getColWidth } from './utils';
|
|
6
6
|
|
|
7
|
-
type Options = {
|
|
7
|
+
type Options<T extends Record<string, any>> = {
|
|
8
8
|
props: any;
|
|
9
|
-
|
|
9
|
+
tableHeaders: Ref<StkTableColumn<T>[][]>;
|
|
10
10
|
virtualScroll: Ref<VirtualScrollStore>;
|
|
11
11
|
virtualScrollX: Ref<VirtualScrollXStore>;
|
|
12
12
|
virtualX_on: Ref<boolean>;
|
|
@@ -17,33 +17,52 @@ type Options = {
|
|
|
17
17
|
* @param param0
|
|
18
18
|
* @returns
|
|
19
19
|
*/
|
|
20
|
-
export function useFixedStyle
|
|
20
|
+
export function useFixedStyle<DT extends Record<string, any>>({
|
|
21
|
+
props,
|
|
22
|
+
tableHeaders,
|
|
23
|
+
virtualScroll,
|
|
24
|
+
virtualScrollX,
|
|
25
|
+
virtualX_on,
|
|
26
|
+
virtualX_offsetRight,
|
|
27
|
+
}: Options<DT>) {
|
|
21
28
|
const fixedColumnsPositionStore = computed(() => {
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
/** dataIndex 作为唯一标识 */
|
|
30
|
+
const colKeyStore: Record<string, number> = {};
|
|
31
|
+
/** 没有dataIndex 的多级表头列,使用对象引用做标识 */
|
|
32
|
+
const refStore = new WeakMap<StkTableColumn<DT>, number>();
|
|
33
|
+
tableHeaders.value.forEach(cols => {
|
|
34
|
+
let left = 0;
|
|
35
|
+
/**遍历右侧fixed时,因为left已经遍历过一次了。所以,可以拿到right遍历边界 */
|
|
36
|
+
let rightStartIndex = 0;
|
|
37
|
+
for (let i = 0; i < cols.length; i++) {
|
|
38
|
+
const item = cols[i];
|
|
39
|
+
if (item.fixed === 'left') {
|
|
40
|
+
if (item.dataIndex) {
|
|
41
|
+
colKeyStore[item.dataIndex] = left;
|
|
42
|
+
} else {
|
|
43
|
+
refStore.set(item, left);
|
|
44
|
+
}
|
|
45
|
+
left += getColWidth(item);
|
|
46
|
+
}
|
|
47
|
+
if (!rightStartIndex && item.fixed === 'right') {
|
|
48
|
+
rightStartIndex = i;
|
|
49
|
+
}
|
|
35
50
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
let right = 0;
|
|
52
|
+
for (let i = cols.length - 1; i >= rightStartIndex; i--) {
|
|
53
|
+
const item = cols[i];
|
|
54
|
+
if (item.fixed === 'right') {
|
|
55
|
+
if (item.dataIndex) {
|
|
56
|
+
colKeyStore[item.dataIndex] = right;
|
|
57
|
+
} else {
|
|
58
|
+
refStore.set(item, right);
|
|
59
|
+
}
|
|
60
|
+
right += getColWidth(item);
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
|
-
}
|
|
63
|
+
});
|
|
45
64
|
|
|
46
|
-
return
|
|
65
|
+
return { refStore, colKeyStore };
|
|
47
66
|
});
|
|
48
67
|
/**
|
|
49
68
|
* 固定列的style
|
|
@@ -52,9 +71,10 @@ export function useFixedStyle({ props, tableHeaderLast, virtualScroll, virtualSc
|
|
|
52
71
|
* @param depth 深度。tagType = 1时使用
|
|
53
72
|
*/
|
|
54
73
|
function getFixedStyle(tagType: 1 | 2, col: StkTableColumn<any>, depth = 0): CSSProperties {
|
|
55
|
-
const { fixed
|
|
74
|
+
const { fixed } = col;
|
|
56
75
|
const isFixedLeft = fixed === 'left';
|
|
57
76
|
const style: CSSProperties = {};
|
|
77
|
+
const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
|
|
58
78
|
// TD
|
|
59
79
|
if (Is_Legacy_Mode) {
|
|
60
80
|
style.position = 'relative';
|
|
@@ -83,10 +103,11 @@ export function useFixedStyle({ props, tableHeaderLast, virtualScroll, virtualSc
|
|
|
83
103
|
style.right = `${virtualX_offsetRight.value}px`;
|
|
84
104
|
}
|
|
85
105
|
} else {
|
|
106
|
+
const lr = (col.dataIndex ? colKeyStore[col.dataIndex] : refStore.get(col)) + 'px';
|
|
86
107
|
if (isFixedLeft) {
|
|
87
|
-
style.left =
|
|
108
|
+
style.left = lr;
|
|
88
109
|
} else {
|
|
89
|
-
style.right =
|
|
110
|
+
style.right = lr;
|
|
90
111
|
}
|
|
91
112
|
}
|
|
92
113
|
}
|