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/lib/src/StkTable/StkTable.vue.d.ts +697 -695
- package/lib/src/StkTable/const.d.ts +2 -0
- package/lib/stk-table-vue.js +2379 -2374
- package/lib/style.css +395 -395
- package/package.json +3 -3
- package/src/StkTable/StkTable.vue +107 -91
- package/src/StkTable/const.ts +3 -0
- package/src/StkTable/style.less +1 -3
- package/src/StkTable/useColResize.ts +7 -4
- package/src/StkTable/useFixedCol.ts +21 -15
- package/src/StkTable/useFixedStyle.ts +5 -6
- package/src/StkTable/useGetFixedColPosition.ts +4 -3
- package/src/StkTable/useKeyboardArrowScroll.ts +9 -3
- package/src/StkTable/useThDrag.ts +1 -1
- package/src/StkTable/useTrDrag.ts +2 -2
- package/src/StkTable/useVirtualScroll.ts +14 -16
- package/src/StkTable/utils/constRefUtils.ts +1 -1
- package/src/StkTable/utils/index.ts +4 -4
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stk-table-vue",
|
|
3
|
-
"version": "0.6.
|
|
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@
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
685
|
-
|
|
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
|
|
684
|
+
return col => (col as any)[colKey];
|
|
688
685
|
}
|
|
689
686
|
});
|
|
690
687
|
|
|
691
|
-
/** 空单元格占位字符 */
|
|
692
688
|
const getEmptyCellText = computed(() => {
|
|
693
|
-
|
|
694
|
-
|
|
689
|
+
const { emptyCellText } = props;
|
|
690
|
+
if (typeof emptyCellText === 'string') {
|
|
691
|
+
return () => emptyCellText;
|
|
695
692
|
} else {
|
|
696
|
-
return (col: StkTableColumn<DT>, row: DT) =>
|
|
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 =
|
|
817
|
+
dataSourceCopy.value = val.slice(); // 浅拷贝
|
|
821
818
|
// 数据长度没变则不计算虚拟滚动
|
|
822
819
|
if (needInitVirtualScrollY) {
|
|
823
820
|
// 表格渲染后再执行。initVirtualScrollY 中有获取dom的操作。
|
|
824
821
|
nextTick(() => initVirtualScrollY());
|
|
825
822
|
}
|
|
826
|
-
|
|
827
|
-
if (
|
|
823
|
+
const sortColValue = sortCol.value;
|
|
824
|
+
if (sortColValue) {
|
|
828
825
|
// 排序
|
|
829
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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) +
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
-
//
|
|
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:
|
|
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
|
|
1065
|
-
if (!
|
|
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
|
-
|
|
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 =
|
|
1057
|
+
sortCol.value = defaultColKey as string;
|
|
1072
1058
|
col = null;
|
|
1073
1059
|
for (const row of tableHeaders.value) {
|
|
1074
|
-
const c = row.find(item =>
|
|
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
|
-
|
|
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,
|
|
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 =>
|
|
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 =
|
|
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 =
|
|
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);
|
package/src/StkTable/const.ts
CHANGED
package/src/StkTable/style.less
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
--td-bgc: #fff;
|
|
18
18
|
--td-hover-color: #71a2fd;
|
|
19
19
|
--td-active-color: #386ccc;
|
|
20
|
-
--th-bgc: #
|
|
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 =>
|
|
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
|
|
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',
|
|
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.
|
|
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
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
+
const getFixedColPositionValue = getFixedColPosition.value;
|
|
87
|
+
let clientWidth, scrollLeft;
|
|
80
88
|
|
|
81
89
|
if (virtualScrollX?.value) {
|
|
82
|
-
const { containerWidth: cw,
|
|
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,
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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) {
|