stk-table-vue 0.4.6 → 0.4.9
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 +3 -0
- package/lib/stk-table-vue.js +110 -93
- package/lib/style.css +15 -6
- package/package.json +64 -64
- package/src/StkTable/StkTable.vue +42 -38
- package/src/StkTable/style.less +18 -6
- package/src/StkTable/useFixedStyle.ts +3 -3
- package/src/StkTable/useKeyboardArrowScroll.ts +18 -8
- package/src/StkTable/useVirtualScroll.ts +23 -25
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ repo:
|
|
|
13
13
|
## Bug TODO:
|
|
14
14
|
* [x] props.dataSource 为 shallowRef 时,高亮行不生效。(bug:2024.02.21)(resolved:0.2.3)
|
|
15
15
|
* [] 固定列列宽拖动目标。
|
|
16
|
+
* [] 惯性滚动优化。
|
|
16
17
|
|
|
17
18
|
## Feature TODO:
|
|
18
19
|
* [x] 高亮行,单元格。
|
|
@@ -587,6 +588,8 @@ export type SortConfig<T extends Record<string, any>> = {
|
|
|
587
588
|
- 以下情况尝试开启此功能。
|
|
588
589
|
- 在 `customCell` 较多且复杂时。
|
|
589
590
|
- 大量 highlight 动画时。
|
|
591
|
+
### props.autoResize
|
|
592
|
+
* 手动设置为 `props.autoResize=false`。可取消监听的性能消耗。适用于宽度高度不变的表格。
|
|
590
593
|
|
|
591
594
|
## Tips
|
|
592
595
|
### props.fixedMode
|
package/lib/stk-table-vue.js
CHANGED
|
@@ -455,8 +455,6 @@ function useFixedStyle({
|
|
|
455
455
|
if (tagType === TagType.TD && !fixed)
|
|
456
456
|
return null;
|
|
457
457
|
const style = {};
|
|
458
|
-
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
459
|
-
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
460
458
|
const isFixedLeft = fixed === "left";
|
|
461
459
|
if (tagType === TagType.TH) {
|
|
462
460
|
if (isRelativeMode.value) {
|
|
@@ -465,6 +463,8 @@ function useFixedStyle({
|
|
|
465
463
|
style.top = depth * props.rowHeight + "px";
|
|
466
464
|
}
|
|
467
465
|
}
|
|
466
|
+
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
467
|
+
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
468
468
|
if (fixed === "left" || fixed === "right") {
|
|
469
469
|
if (isRelativeMode.value) {
|
|
470
470
|
if (isFixedLeft) {
|
|
@@ -740,7 +740,16 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
|
|
|
740
740
|
setHighlightDimCell
|
|
741
741
|
};
|
|
742
742
|
}
|
|
743
|
-
|
|
743
|
+
var ScrollCodes = /* @__PURE__ */ ((ScrollCodes2) => {
|
|
744
|
+
ScrollCodes2["ArrowUp"] = "ArrowUp";
|
|
745
|
+
ScrollCodes2["ArrowRight"] = "ArrowRight";
|
|
746
|
+
ScrollCodes2["ArrowDown"] = "ArrowDown";
|
|
747
|
+
ScrollCodes2["ArrowLeft"] = "ArrowLeft";
|
|
748
|
+
ScrollCodes2["PageUp"] = "PageUp";
|
|
749
|
+
ScrollCodes2["PageDown"] = "PageDown";
|
|
750
|
+
return ScrollCodes2;
|
|
751
|
+
})(ScrollCodes || {});
|
|
752
|
+
const ScrollCodesValues = Object.values(ScrollCodes);
|
|
744
753
|
function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on }) {
|
|
745
754
|
let isMouseOver = false;
|
|
746
755
|
watch(virtual_on, (val) => {
|
|
@@ -767,7 +776,9 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
|
|
|
767
776
|
(_c = targetElement.value) == null ? void 0 : _c.removeEventListener("mousedown", handleMouseDown);
|
|
768
777
|
}
|
|
769
778
|
function handleKeydown(e) {
|
|
770
|
-
if (!
|
|
779
|
+
if (!virtual_on.value)
|
|
780
|
+
return;
|
|
781
|
+
if (!ScrollCodesValues.includes(e.code))
|
|
771
782
|
return;
|
|
772
783
|
if (!isMouseOver)
|
|
773
784
|
return;
|
|
@@ -777,17 +788,17 @@ function useKeyboardArrowScroll(targetElement, { props, scrollTo, virtualScroll,
|
|
|
777
788
|
const { headless, headerRowHeight } = props;
|
|
778
789
|
const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
|
|
779
790
|
const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
|
|
780
|
-
if (e.code ===
|
|
791
|
+
if (e.code === "ArrowUp") {
|
|
781
792
|
scrollTo(scrollTop - rowHeight, null);
|
|
782
|
-
} else if (e.code ===
|
|
793
|
+
} else if (e.code === "ArrowRight") {
|
|
783
794
|
scrollTo(null, scrollLeft + rowHeight);
|
|
784
|
-
} else if (e.code ===
|
|
795
|
+
} else if (e.code === "ArrowDown") {
|
|
785
796
|
scrollTo(scrollTop + rowHeight, null);
|
|
786
|
-
} else if (e.code ===
|
|
797
|
+
} else if (e.code === "ArrowLeft") {
|
|
787
798
|
scrollTo(null, scrollLeft - rowHeight);
|
|
788
|
-
} else if (e.code ===
|
|
799
|
+
} else if (e.code === "PageUp") {
|
|
789
800
|
scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
|
|
790
|
-
} else if (e.code ===
|
|
801
|
+
} else if (e.code === "PageDown") {
|
|
791
802
|
scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
|
|
792
803
|
}
|
|
793
804
|
}
|
|
@@ -937,6 +948,10 @@ function useVirtualScroll({
|
|
|
937
948
|
const { headerRowHeight } = props;
|
|
938
949
|
return headerRowHeight * tableHeaders.value.length;
|
|
939
950
|
}
|
|
951
|
+
function initVirtualScroll(height) {
|
|
952
|
+
initVirtualScrollY(height);
|
|
953
|
+
initVirtualScrollX();
|
|
954
|
+
}
|
|
940
955
|
function initVirtualScrollY(height) {
|
|
941
956
|
var _a;
|
|
942
957
|
if (height !== void 0 && typeof height !== "number") {
|
|
@@ -954,7 +969,7 @@ function useVirtualScroll({
|
|
|
954
969
|
const headerHeight = getTableHeaderHeight();
|
|
955
970
|
tableHeaderHeight.value = headerHeight;
|
|
956
971
|
if (!headless) {
|
|
957
|
-
const headerToBodyRowHeightCount = Math.floor(headerHeight
|
|
972
|
+
const headerToBodyRowHeightCount = Math.floor(headerHeight / rowHeight);
|
|
958
973
|
pageSize -= headerToBodyRowHeightCount;
|
|
959
974
|
}
|
|
960
975
|
const maxScrollTop = dataSourceCopy.value.length * rowHeight + tableHeaderHeight.value - containerHeight;
|
|
@@ -970,31 +985,21 @@ function useVirtualScroll({
|
|
|
970
985
|
virtualScrollX.value.scrollWidth = scrollWidth || DEFAULT_TABLE_WIDTH;
|
|
971
986
|
updateVirtualScrollX(scrollLeft);
|
|
972
987
|
}
|
|
973
|
-
function initVirtualScroll(height) {
|
|
974
|
-
initVirtualScrollY(height);
|
|
975
|
-
initVirtualScrollX();
|
|
976
|
-
}
|
|
977
988
|
let vue2ScrollYTimeout = null;
|
|
978
989
|
function updateVirtualScrollY(sTop = 0) {
|
|
979
|
-
const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex } = virtualScroll.value;
|
|
990
|
+
const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex, endIndex: oldEndIndex } = virtualScroll.value;
|
|
980
991
|
virtualScroll.value.scrollTop = sTop;
|
|
981
992
|
if (!virtual_on.value) {
|
|
982
993
|
return;
|
|
983
994
|
}
|
|
984
995
|
let startIndex = Math.floor(sTop / rowHeight);
|
|
985
|
-
|
|
986
|
-
startIndex = 0;
|
|
987
|
-
}
|
|
996
|
+
let endIndex = startIndex + pageSize;
|
|
988
997
|
if (props.stripe && startIndex !== 0) {
|
|
989
|
-
|
|
990
|
-
if (scrollRows % 2) {
|
|
998
|
+
if (startIndex % 2) {
|
|
991
999
|
startIndex -= 1;
|
|
992
1000
|
}
|
|
993
1001
|
}
|
|
994
|
-
|
|
995
|
-
if (props.stripe) {
|
|
996
|
-
endIndex += 1;
|
|
997
|
-
}
|
|
1002
|
+
startIndex = Math.max(0, startIndex);
|
|
998
1003
|
endIndex = Math.min(endIndex, dataSourceCopy.value.length);
|
|
999
1004
|
if (startIndex >= endIndex) {
|
|
1000
1005
|
startIndex = endIndex - pageSize;
|
|
@@ -1002,13 +1007,12 @@ function useVirtualScroll({
|
|
|
1002
1007
|
if (vue2ScrollYTimeout) {
|
|
1003
1008
|
window.clearTimeout(vue2ScrollYTimeout);
|
|
1004
1009
|
}
|
|
1010
|
+
if (oldStartIndex === startIndex && oldEndIndex === endIndex) {
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1005
1013
|
const offsetTop = startIndex * rowHeight;
|
|
1006
1014
|
if (!props.optimizeVue2Scroll || sTop <= scrollTop || Math.abs(oldStartIndex - startIndex) >= pageSize) {
|
|
1007
|
-
Object.assign(virtualScroll.value, {
|
|
1008
|
-
startIndex,
|
|
1009
|
-
endIndex,
|
|
1010
|
-
offsetTop
|
|
1011
|
-
});
|
|
1015
|
+
Object.assign(virtualScroll.value, { startIndex, endIndex, offsetTop });
|
|
1012
1016
|
} else {
|
|
1013
1017
|
virtualScroll.value.endIndex = endIndex;
|
|
1014
1018
|
vue2ScrollYTimeout = window.setTimeout(() => {
|
|
@@ -1087,17 +1091,16 @@ function useVirtualScroll({
|
|
|
1087
1091
|
};
|
|
1088
1092
|
}
|
|
1089
1093
|
const _hoisted_1 = ["data-col-key", "draggable", "rowspan", "colspan", "title", "onClick"];
|
|
1090
|
-
const _hoisted_2 = {
|
|
1091
|
-
const _hoisted_3 = {
|
|
1094
|
+
const _hoisted_2 = {
|
|
1092
1095
|
key: 1,
|
|
1093
1096
|
class: "table-header-title"
|
|
1094
1097
|
};
|
|
1095
|
-
const
|
|
1096
|
-
const
|
|
1098
|
+
const _hoisted_3 = { class: "table-header-title" };
|
|
1099
|
+
const _hoisted_4 = {
|
|
1097
1100
|
key: 3,
|
|
1098
1101
|
class: "table-header-sorter"
|
|
1099
1102
|
};
|
|
1100
|
-
const
|
|
1103
|
+
const _hoisted_5 = /* @__PURE__ */ createElementVNode("svg", {
|
|
1101
1104
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1102
1105
|
width: "16px",
|
|
1103
1106
|
height: "16px",
|
|
@@ -1114,31 +1117,23 @@ const _hoisted_6 = /* @__PURE__ */ createElementVNode("svg", {
|
|
|
1114
1117
|
points: "8 10 4.8 14 11.2 14"
|
|
1115
1118
|
})
|
|
1116
1119
|
], -1);
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1120
|
+
const _hoisted_6 = [
|
|
1121
|
+
_hoisted_5
|
|
1119
1122
|
];
|
|
1123
|
+
const _hoisted_7 = ["onMousedown"];
|
|
1120
1124
|
const _hoisted_8 = ["onMousedown"];
|
|
1121
|
-
const _hoisted_9 =
|
|
1125
|
+
const _hoisted_9 = { class: "stk-tbody-main" };
|
|
1122
1126
|
const _hoisted_10 = {
|
|
1123
|
-
key: 1,
|
|
1124
|
-
class: "virtual-top"
|
|
1125
|
-
};
|
|
1126
|
-
const _hoisted_11 = {
|
|
1127
1127
|
key: 0,
|
|
1128
|
-
class: "
|
|
1128
|
+
class: "vt-x-left"
|
|
1129
1129
|
};
|
|
1130
|
-
const
|
|
1131
|
-
const
|
|
1132
|
-
const _hoisted_14 = {
|
|
1130
|
+
const _hoisted_11 = ["id", "data-row-key", "onClick", "onDblclick", "onContextmenu", "onMouseover"];
|
|
1131
|
+
const _hoisted_12 = {
|
|
1133
1132
|
key: 0,
|
|
1134
|
-
class: "
|
|
1135
|
-
};
|
|
1136
|
-
const _hoisted_15 = ["data-index", "onClick", "onMouseenter", "onMouseleave", "onMouseover"];
|
|
1137
|
-
const _hoisted_16 = ["title"];
|
|
1138
|
-
const _hoisted_17 = {
|
|
1139
|
-
key: 2,
|
|
1140
|
-
class: "virtual-bottom"
|
|
1133
|
+
class: "vt-x-left"
|
|
1141
1134
|
};
|
|
1135
|
+
const _hoisted_13 = ["data-index", "onClick", "onMouseenter", "onMouseleave", "onMouseover"];
|
|
1136
|
+
const _hoisted_14 = ["title"];
|
|
1142
1137
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
1143
1138
|
__name: "StkTable",
|
|
1144
1139
|
props: {
|
|
@@ -1283,6 +1278,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1283
1278
|
});
|
|
1284
1279
|
}
|
|
1285
1280
|
);
|
|
1281
|
+
watch(
|
|
1282
|
+
() => props.virtual,
|
|
1283
|
+
() => {
|
|
1284
|
+
nextTick(() => {
|
|
1285
|
+
initVirtualScrollY();
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
);
|
|
1286
1289
|
watch(
|
|
1287
1290
|
() => props.virtualX,
|
|
1288
1291
|
() => {
|
|
@@ -1466,9 +1469,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1466
1469
|
const sortConfig = props.sortConfig;
|
|
1467
1470
|
const defaultSort = sortConfig.defaultSort;
|
|
1468
1471
|
if (!order && defaultSort) {
|
|
1469
|
-
|
|
1472
|
+
if (!defaultSort.dataIndex) {
|
|
1473
|
+
console.error("sortConfig.defaultSort.dataIndex is required");
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
order = defaultSort.order || "desc";
|
|
1470
1477
|
sortOrderIndex.value = sortSwitchOrder.indexOf(order);
|
|
1471
1478
|
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;
|
|
1472
1488
|
}
|
|
1473
1489
|
if (!props.sortRemote || options.force) {
|
|
1474
1490
|
dataSourceCopy.value = tableSort(col, order, props.dataSource, sortConfig);
|
|
@@ -1580,15 +1596,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1580
1596
|
function setCurrentRow(rowKey, option = { silent: false }) {
|
|
1581
1597
|
if (!dataSourceCopy.value.length)
|
|
1582
1598
|
return;
|
|
1583
|
-
|
|
1584
|
-
|
|
1599
|
+
const row = dataSourceCopy.value.find((it) => rowKeyGen(it) === rowKey);
|
|
1600
|
+
if (!row) {
|
|
1601
|
+
console.warn("setCurrentRow failed.rowKey:", rowKey);
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
currentRow.value = row;
|
|
1605
|
+
currentRowKey.value = rowKey;
|
|
1585
1606
|
if (!option.silent) {
|
|
1586
1607
|
emits(
|
|
1587
1608
|
"current-change",
|
|
1588
1609
|
/** no Event */
|
|
1589
1610
|
null,
|
|
1590
1611
|
currentRow.value,
|
|
1591
|
-
{ select:
|
|
1612
|
+
{ select: true }
|
|
1592
1613
|
);
|
|
1593
1614
|
}
|
|
1594
1615
|
}
|
|
@@ -1661,6 +1682,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1661
1682
|
class: normalizeClass(["stk-table", {
|
|
1662
1683
|
virtual: _ctx.virtual,
|
|
1663
1684
|
"virtual-x": _ctx.virtualX,
|
|
1685
|
+
"vt-on": unref(virtual_on),
|
|
1664
1686
|
dark: _ctx.theme === "dark",
|
|
1665
1687
|
headless: _ctx.headless,
|
|
1666
1688
|
"is-col-resizing": unref(isColResizing),
|
|
@@ -1710,11 +1732,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1710
1732
|
}, [
|
|
1711
1733
|
unref(virtualX_on) ? (openBlock(), createElementBlock("th", {
|
|
1712
1734
|
key: 0,
|
|
1713
|
-
class: "
|
|
1714
|
-
style: normalizeStyle({
|
|
1715
|
-
minWidth: unref(virtualScrollX).offsetLeft + "px",
|
|
1716
|
-
width: unref(virtualScrollX).offsetLeft + "px"
|
|
1717
|
-
})
|
|
1735
|
+
class: "vt-x-left",
|
|
1736
|
+
style: normalizeStyle(`min-width:${unref(virtualScrollX).offsetLeft}px;width:${unref(virtualScrollX).offsetLeft}px`)
|
|
1718
1737
|
}, null, 4)) : createCommentVNode("", true),
|
|
1719
1738
|
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_on) && rowIndex === tableHeaders.value.length - 1 ? unref(virtualX_columnPart) : row, (col, colIndex) => {
|
|
1720
1739
|
return openBlock(), createElementBlock("th", {
|
|
@@ -1742,65 +1761,64 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1742
1761
|
onDragover: _cache[2] || (_cache[2] = //@ts-ignore
|
|
1743
1762
|
(...args) => unref(onThDragOver) && unref(onThDragOver)(...args))
|
|
1744
1763
|
}, [
|
|
1745
|
-
createElementVNode("div",
|
|
1764
|
+
createElementVNode("div", {
|
|
1765
|
+
class: "table-header-cell-wrapper",
|
|
1766
|
+
style: normalizeStyle(`--row-span:${unref(virtualX_on) ? 1 : col.rowSpan}`)
|
|
1767
|
+
}, [
|
|
1746
1768
|
col.customHeaderCell ? (openBlock(), createBlock(resolveDynamicComponent(col.customHeaderCell), {
|
|
1747
1769
|
key: 0,
|
|
1748
1770
|
col,
|
|
1749
1771
|
colIndex,
|
|
1750
1772
|
rowIndex
|
|
1751
|
-
}, null, 8, ["col", "colIndex", "rowIndex"])) : col.type === "seq" ? (openBlock(), createElementBlock("span",
|
|
1773
|
+
}, null, 8, ["col", "colIndex", "rowIndex"])) : col.type === "seq" ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(col.title), 1)) : renderSlot(_ctx.$slots, "tableHeader", {
|
|
1752
1774
|
key: 2,
|
|
1753
1775
|
col
|
|
1754
1776
|
}, () => [
|
|
1755
|
-
createElementVNode("span",
|
|
1777
|
+
createElementVNode("span", _hoisted_3, toDisplayString(col.title), 1)
|
|
1756
1778
|
]),
|
|
1757
|
-
col.sorter ? (openBlock(), createElementBlock("span",
|
|
1779
|
+
col.sorter ? (openBlock(), createElementBlock("span", _hoisted_4, _hoisted_6)) : createCommentVNode("", true),
|
|
1758
1780
|
_ctx.colResizable && colIndex > 0 ? (openBlock(), createElementBlock("div", {
|
|
1759
1781
|
key: 4,
|
|
1760
1782
|
class: "table-header-resizer left",
|
|
1761
1783
|
onMousedown: (e) => unref(onThResizeMouseDown)(e, col, true)
|
|
1762
|
-
}, null, 40,
|
|
1784
|
+
}, null, 40, _hoisted_7)) : createCommentVNode("", true),
|
|
1763
1785
|
_ctx.colResizable ? (openBlock(), createElementBlock("div", {
|
|
1764
1786
|
key: 5,
|
|
1765
1787
|
class: "table-header-resizer right",
|
|
1766
1788
|
onMousedown: (e) => unref(onThResizeMouseDown)(e, col)
|
|
1767
|
-
}, null, 40,
|
|
1768
|
-
])
|
|
1789
|
+
}, null, 40, _hoisted_8)) : createCommentVNode("", true)
|
|
1790
|
+
], 4)
|
|
1769
1791
|
], 46, _hoisted_1);
|
|
1770
1792
|
}), 128)),
|
|
1771
1793
|
unref(virtualX_on) ? (openBlock(), createElementBlock("th", {
|
|
1772
1794
|
key: 1,
|
|
1773
|
-
class: "
|
|
1774
|
-
style: normalizeStyle({
|
|
1775
|
-
minWidth: unref(virtualX_offsetRight) + "px",
|
|
1776
|
-
width: unref(virtualX_offsetRight) + "px"
|
|
1777
|
-
})
|
|
1795
|
+
class: "vt-x-right",
|
|
1796
|
+
style: normalizeStyle(`min-width:${unref(virtualX_offsetRight)}px;width:${unref(virtualX_offsetRight)}px`)
|
|
1778
1797
|
}, null, 4)) : createCommentVNode("", true)
|
|
1779
1798
|
], 32);
|
|
1780
1799
|
}), 128))
|
|
1781
1800
|
], 512)) : createCommentVNode("", true),
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1801
|
+
createElementVNode("tbody", _hoisted_9, [
|
|
1802
|
+
unref(virtual_on) ? (openBlock(), createElementBlock("tr", {
|
|
1803
|
+
key: 0,
|
|
1804
|
+
style: normalizeStyle(`height:${unref(virtualScroll).offsetTop}px`),
|
|
1785
1805
|
class: "padding-top-tr"
|
|
1786
1806
|
}, [
|
|
1787
|
-
unref(virtualX_on) && _ctx.fixedMode && _ctx.headless ? (openBlock(), createElementBlock("td",
|
|
1807
|
+
unref(virtualX_on) && _ctx.fixedMode && _ctx.headless ? (openBlock(), createElementBlock("td", _hoisted_10)) : createCommentVNode("", true),
|
|
1788
1808
|
_ctx.fixedMode && _ctx.headless ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(unref(virtualX_columnPart), (col) => {
|
|
1789
1809
|
return openBlock(), createElementBlock("td", {
|
|
1790
1810
|
key: col.dataIndex,
|
|
1791
1811
|
style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen.value(col)))
|
|
1792
1812
|
}, null, 4);
|
|
1793
1813
|
}), 128)) : createCommentVNode("", true)
|
|
1794
|
-
], 4)
|
|
1795
|
-
])) : createCommentVNode("", true),
|
|
1796
|
-
createElementVNode("tbody", _hoisted_12, [
|
|
1814
|
+
], 4)) : createCommentVNode("", true),
|
|
1797
1815
|
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtual_dataSourcePart), (row, rowIndex) => {
|
|
1798
1816
|
return openBlock(), createElementBlock("tr", {
|
|
1799
1817
|
id: unref(stkTableId) + "-" + (_ctx.rowKey ? rowKeyGen(row) : rowIndex),
|
|
1800
1818
|
key: _ctx.rowKey ? rowKeyGen(row) : rowIndex,
|
|
1801
1819
|
"data-row-key": _ctx.rowKey ? rowKeyGen(row) : rowIndex,
|
|
1802
1820
|
class: normalizeClass({
|
|
1803
|
-
active: _ctx.rowKey ? rowKeyGen(row) ===
|
|
1821
|
+
active: _ctx.rowKey ? rowKeyGen(row) === currentRowKey.value : row === currentRow.value,
|
|
1804
1822
|
hover: props.showTrHoverClass && (_ctx.rowKey ? rowKeyGen(row) === currentHoverRowKey.value : row === currentHoverRowKey.value),
|
|
1805
1823
|
[_ctx.rowClassName(row, rowIndex)]: true
|
|
1806
1824
|
}),
|
|
@@ -1809,7 +1827,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1809
1827
|
onContextmenu: (e) => onRowMenu(e, row),
|
|
1810
1828
|
onMouseover: (e) => onTrMouseOver(e, row)
|
|
1811
1829
|
}, [
|
|
1812
|
-
unref(virtualX_on) ? (openBlock(), createElementBlock("td",
|
|
1830
|
+
unref(virtualX_on) ? (openBlock(), createElementBlock("td", _hoisted_12)) : createCommentVNode("", true),
|
|
1813
1831
|
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_columnPart), (col, colIndex) => {
|
|
1814
1832
|
return openBlock(), createElementBlock("td", {
|
|
1815
1833
|
key: col.dataIndex,
|
|
@@ -1838,17 +1856,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1838
1856
|
], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
1839
1857
|
createTextVNode(toDisplayString((row == null ? void 0 : row[col.dataIndex]) ?? getEmptyCellText.value(col, row)), 1)
|
|
1840
1858
|
], 64))
|
|
1841
|
-
], 8,
|
|
1842
|
-
], 46,
|
|
1859
|
+
], 8, _hoisted_14))
|
|
1860
|
+
], 46, _hoisted_13);
|
|
1843
1861
|
}), 128))
|
|
1844
|
-
], 42,
|
|
1845
|
-
}), 128))
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
])) : createCommentVNode("", true)
|
|
1862
|
+
], 42, _hoisted_11);
|
|
1863
|
+
}), 128)),
|
|
1864
|
+
unref(virtual_on) ? (openBlock(), createElementBlock("tr", {
|
|
1865
|
+
key: 1,
|
|
1866
|
+
style: normalizeStyle(`height: ${unref(virtual_offsetBottom)}px`)
|
|
1867
|
+
}, null, 4)) : createCommentVNode("", true)
|
|
1868
|
+
])
|
|
1852
1869
|
], 6),
|
|
1853
1870
|
(!dataSourceCopy.value || !dataSourceCopy.value.length) && _ctx.showNoData ? (openBlock(), createElementBlock("div", {
|
|
1854
1871
|
key: 1,
|
package/lib/style.css
CHANGED
|
@@ -91,13 +91,22 @@
|
|
|
91
91
|
.stk-table.border-body-v tbody{
|
|
92
92
|
--bg-border-bottom:linear-gradient(transparent, transparent);
|
|
93
93
|
}
|
|
94
|
-
.stk-table.stripe tbody tr:nth-child(even){
|
|
94
|
+
.stk-table.stripe .stk-tbody-main tr:nth-child(even){
|
|
95
95
|
background-color:var(--stripe-bgc);
|
|
96
96
|
}
|
|
97
|
-
.stk-table.
|
|
97
|
+
.stk-table.stripe.vt-on .stk-tbody-main tr:nth-child(odd){
|
|
98
|
+
background-color:var(--stripe-bgc);
|
|
99
|
+
}
|
|
100
|
+
.stk-table.stripe.row-hover .stk-tbody-main tr:hover{
|
|
101
|
+
background-color:var(--tr-hover-bgc);
|
|
102
|
+
}
|
|
103
|
+
.stk-table.stripe.row-active .stk-tbody-main tr.active{
|
|
104
|
+
background-color:var(--tr-active-bgc);
|
|
105
|
+
}
|
|
106
|
+
.stk-table.row-hover .stk-tbody-main tr:hover{
|
|
98
107
|
background-color:var(--tr-hover-bgc);
|
|
99
108
|
}
|
|
100
|
-
.stk-table.row-active tbody tr.active{
|
|
109
|
+
.stk-table.row-active .stk-tbody-main tr.active{
|
|
101
110
|
background-color:var(--tr-active-bgc);
|
|
102
111
|
}
|
|
103
112
|
.stk-table.cell-hover tbody td:hover{
|
|
@@ -120,7 +129,7 @@
|
|
|
120
129
|
}
|
|
121
130
|
.stk-table.virtual .table-header-cell-wrapper{
|
|
122
131
|
overflow:hidden;
|
|
123
|
-
max-height:var(--header-row-height);
|
|
132
|
+
max-height:calc(var(--header-row-height) * var(--row-span));
|
|
124
133
|
}
|
|
125
134
|
.stk-table.virtual tbody td{
|
|
126
135
|
height:var(--row-height);
|
|
@@ -187,8 +196,8 @@
|
|
|
187
196
|
background-color:var(--td-bgc);
|
|
188
197
|
height:var(--row-height);
|
|
189
198
|
}
|
|
190
|
-
.stk-table .
|
|
191
|
-
.stk-table .
|
|
199
|
+
.stk-table .vt-x-left,
|
|
200
|
+
.stk-table .vt-x-right{
|
|
192
201
|
padding:0;
|
|
193
202
|
background:none;
|
|
194
203
|
pointer-events:none;
|
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "stk-table-vue",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Simple realtime virtual table for vue3 and vue2.7",
|
|
5
|
-
"main": "./lib/stk-table-vue.js",
|
|
6
|
-
"types": "./lib/src/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
|
-
"vue2",
|
|
21
|
-
"vue3",
|
|
22
|
-
"highlight",
|
|
23
|
-
"sticky",
|
|
24
|
-
"virtual",
|
|
25
|
-
"table",
|
|
26
|
-
"list"
|
|
27
|
-
],
|
|
28
|
-
"files": [
|
|
29
|
-
"lib",
|
|
30
|
-
"src"
|
|
31
|
-
],
|
|
32
|
-
"author": "japlus",
|
|
33
|
-
"repository": {
|
|
34
|
-
"type": "git",
|
|
35
|
-
"url": "https://github.com/ja-plus/stk-table-vue"
|
|
36
|
-
},
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@types/d3-interpolate": "^3.0.4",
|
|
40
|
-
"@types/node": "^20.12.10",
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
42
|
-
"@typescript-eslint/parser": "^7.7.0",
|
|
43
|
-
"@vitejs/plugin-vue": "^5.0.4",
|
|
44
|
-
"@vue/test-utils": "2.4.4",
|
|
45
|
-
"eslint": "^8.57.0",
|
|
46
|
-
"eslint-config-prettier": "^9.1.0",
|
|
47
|
-
"eslint-plugin-html": "^8.1.0",
|
|
48
|
-
"eslint-plugin-prettier": "^5.1.3",
|
|
49
|
-
"eslint-plugin-vue": "^9.25.0",
|
|
50
|
-
"happy-dom": "^12.10.3",
|
|
51
|
-
"less": "^4.2.0",
|
|
52
|
-
"postcss-discard-comments": "^6.0.2",
|
|
53
|
-
"postcss-preset-env": "^9.5.11",
|
|
54
|
-
"prettier": "^3.2.5",
|
|
55
|
-
"typescript": "^5.4.5",
|
|
56
|
-
"vite": "^5.2.11",
|
|
57
|
-
"vite-plugin-dts": "^3.9.1",
|
|
58
|
-
"vitest": "^1.6.0",
|
|
59
|
-
"vue": "^3.4.26",
|
|
60
|
-
"vue-eslint-parser": "^9.4.2"
|
|
61
|
-
},
|
|
62
|
-
"dependencies": {
|
|
63
|
-
"d3-interpolate": "^3.0.1"
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "stk-table-vue",
|
|
3
|
+
"version": "0.4.9",
|
|
4
|
+
"description": "Simple realtime virtual table for vue3 and vue2.7",
|
|
5
|
+
"main": "./lib/stk-table-vue.js",
|
|
6
|
+
"types": "./lib/src/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
|
+
"vue2",
|
|
21
|
+
"vue3",
|
|
22
|
+
"highlight",
|
|
23
|
+
"sticky",
|
|
24
|
+
"virtual",
|
|
25
|
+
"table",
|
|
26
|
+
"list"
|
|
27
|
+
],
|
|
28
|
+
"files": [
|
|
29
|
+
"lib",
|
|
30
|
+
"src"
|
|
31
|
+
],
|
|
32
|
+
"author": "japlus",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/ja-plus/stk-table-vue"
|
|
36
|
+
},
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/d3-interpolate": "^3.0.4",
|
|
40
|
+
"@types/node": "^20.12.10",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
42
|
+
"@typescript-eslint/parser": "^7.7.0",
|
|
43
|
+
"@vitejs/plugin-vue": "^5.0.4",
|
|
44
|
+
"@vue/test-utils": "2.4.4",
|
|
45
|
+
"eslint": "^8.57.0",
|
|
46
|
+
"eslint-config-prettier": "^9.1.0",
|
|
47
|
+
"eslint-plugin-html": "^8.1.0",
|
|
48
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
49
|
+
"eslint-plugin-vue": "^9.25.0",
|
|
50
|
+
"happy-dom": "^12.10.3",
|
|
51
|
+
"less": "^4.2.0",
|
|
52
|
+
"postcss-discard-comments": "^6.0.2",
|
|
53
|
+
"postcss-preset-env": "^9.5.11",
|
|
54
|
+
"prettier": "^3.2.5",
|
|
55
|
+
"typescript": "^5.4.5",
|
|
56
|
+
"vite": "^5.2.11",
|
|
57
|
+
"vite-plugin-dts": "^3.9.1",
|
|
58
|
+
"vitest": "^1.6.0",
|
|
59
|
+
"vue": "^3.4.26",
|
|
60
|
+
"vue-eslint-parser": "^9.4.2"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"d3-interpolate": "^3.0.1"
|
|
64
|
+
}
|
|
65
65
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!-- eslint-disable vue/attribute-hyphenation -->
|
|
1
2
|
<template>
|
|
2
3
|
<div
|
|
3
4
|
ref="tableContainerRef"
|
|
@@ -5,6 +6,7 @@
|
|
|
5
6
|
:class="{
|
|
6
7
|
virtual,
|
|
7
8
|
'virtual-x': virtualX,
|
|
9
|
+
'vt-on': virtual_on,
|
|
8
10
|
dark: theme === 'dark',
|
|
9
11
|
headless,
|
|
10
12
|
'is-col-resizing': isColResizing,
|
|
@@ -52,11 +54,8 @@
|
|
|
52
54
|
<!-- 这个th用于横向虚拟滚动表格左边距,width、maxWidth 用于兼容低版本浏览器 -->
|
|
53
55
|
<th
|
|
54
56
|
v-if="virtualX_on"
|
|
55
|
-
class="
|
|
56
|
-
:style="{
|
|
57
|
-
minWidth: virtualScrollX.offsetLeft + 'px',
|
|
58
|
-
width: virtualScrollX.offsetLeft + 'px',
|
|
59
|
-
}"
|
|
57
|
+
class="vt-x-left"
|
|
58
|
+
:style="`min-width:${virtualScrollX.offsetLeft}px;width:${virtualScrollX.offsetLeft}px`"
|
|
60
59
|
></th>
|
|
61
60
|
<!-- v for中最后一行才用 切割。TODO:不支持多级表头虚拟横向滚动 -->
|
|
62
61
|
<th
|
|
@@ -84,7 +83,7 @@
|
|
|
84
83
|
@drop="onThDrop"
|
|
85
84
|
@dragover="onThDragOver"
|
|
86
85
|
>
|
|
87
|
-
<div class="table-header-cell-wrapper">
|
|
86
|
+
<div class="table-header-cell-wrapper" :style="`--row-span:${virtualX_on ? 1 : col.rowSpan}`">
|
|
88
87
|
<component :is="col.customHeaderCell" v-if="col.customHeaderCell" :col="col" :colIndex="colIndex" :rowIndex="rowIndex" />
|
|
89
88
|
<template v-else-if="col.type === 'seq'">
|
|
90
89
|
<span class="table-header-title">{{ col.title }}</span>
|
|
@@ -116,46 +115,28 @@
|
|
|
116
115
|
</div>
|
|
117
116
|
</th>
|
|
118
117
|
<!-- 这个th用于横向虚拟滚动表格右边距 width、maxWidth 用于兼容低版本浏览器-->
|
|
119
|
-
<th
|
|
120
|
-
v-if="virtualX_on"
|
|
121
|
-
class="virtual-x-right"
|
|
122
|
-
:style="{
|
|
123
|
-
minWidth: virtualX_offsetRight + 'px',
|
|
124
|
-
width: virtualX_offsetRight + 'px',
|
|
125
|
-
}"
|
|
126
|
-
></th>
|
|
118
|
+
<th v-if="virtualX_on" class="vt-x-right" :style="`min-width:${virtualX_offsetRight}px;width:${virtualX_offsetRight}px`"></th>
|
|
127
119
|
</tr>
|
|
128
120
|
</thead>
|
|
129
121
|
|
|
130
122
|
<!-- 用于虚拟滚动表格内容定位 @deprecated 有兼容问题-->
|
|
131
|
-
<!-- <tbody v-if="virtual_on" :style="{ height: `${virtualScroll.offsetTop}px` }">
|
|
132
|
-
<!==这个tr兼容火狐==>
|
|
133
|
-
<tr></tr>
|
|
134
|
-
</tbody> -->
|
|
135
|
-
<!-- <td
|
|
136
|
-
v-for="col in virtualX_on ? virtualX_columnPart : tableHeaderLast"
|
|
137
|
-
:key="col.dataIndex"
|
|
138
|
-
class="perch-td top"
|
|
139
|
-
></td> -->
|
|
123
|
+
<!-- <tbody v-if="virtual_on" :style="{ height: `${virtualScroll.offsetTop}px` }"></tbody> -->
|
|
140
124
|
<!-- <tbody :style="{ transform: `translateY(${virtualScroll.offsetTop}px)` }"> -->
|
|
141
|
-
<tbody
|
|
142
|
-
|
|
143
|
-
<tr :style="{ height: `${virtualScroll.offsetTop}px` }" class="padding-top-tr">
|
|
125
|
+
<tbody class="stk-tbody-main">
|
|
126
|
+
<tr v-if="virtual_on" :style="`height:${virtualScroll.offsetTop}px`" class="padding-top-tr">
|
|
144
127
|
<!--这个td用于配合虚拟滚动的th对应,防止列错位-->
|
|
145
|
-
<td v-if="virtualX_on && fixedMode && headless" class="
|
|
128
|
+
<td v-if="virtualX_on && fixedMode && headless" class="vt-x-left"></td>
|
|
146
129
|
<template v-if="fixedMode && headless">
|
|
147
130
|
<td v-for="col in virtualX_columnPart" :key="col.dataIndex" :style="cellStyleMap[TagType.TD].get(colKeyGen(col))"></td>
|
|
148
131
|
</template>
|
|
149
132
|
</tr>
|
|
150
|
-
</tbody>
|
|
151
|
-
<tbody class="stk-tbody-main">
|
|
152
133
|
<tr
|
|
153
134
|
v-for="(row, rowIndex) in virtual_dataSourcePart"
|
|
154
135
|
:id="stkTableId + '-' + (rowKey ? rowKeyGen(row) : rowIndex)"
|
|
155
136
|
:key="rowKey ? rowKeyGen(row) : rowIndex"
|
|
156
137
|
:data-row-key="rowKey ? rowKeyGen(row) : rowIndex"
|
|
157
138
|
:class="{
|
|
158
|
-
active: rowKey ? rowKeyGen(row) ===
|
|
139
|
+
active: rowKey ? rowKeyGen(row) === currentRowKey : row === currentRow,
|
|
159
140
|
hover: props.showTrHoverClass && (rowKey ? rowKeyGen(row) === currentHoverRowKey : row === currentHoverRowKey),
|
|
160
141
|
[rowClassName(row, rowIndex)]: true,
|
|
161
142
|
}"
|
|
@@ -165,7 +146,7 @@
|
|
|
165
146
|
@mouseover="e => onTrMouseOver(e, row)"
|
|
166
147
|
>
|
|
167
148
|
<!--这个td用于配合虚拟滚动的th对应,防止列错位-->
|
|
168
|
-
<td v-if="virtualX_on" class="
|
|
149
|
+
<td v-if="virtualX_on" class="vt-x-left"></td>
|
|
169
150
|
<td
|
|
170
151
|
v-for="(col, colIndex) in virtualX_columnPart"
|
|
171
152
|
:key="col.dataIndex"
|
|
@@ -196,9 +177,7 @@
|
|
|
196
177
|
</div>
|
|
197
178
|
</td>
|
|
198
179
|
</tr>
|
|
199
|
-
|
|
200
|
-
<tbody v-if="virtual_on" class="virtual-bottom">
|
|
201
|
-
<tr :style="{ height: `${virtual_offsetBottom}px` }"></tr>
|
|
180
|
+
<tr v-if="virtual_on" :style="`height: ${virtual_offsetBottom}px`"></tr>
|
|
202
181
|
</tbody>
|
|
203
182
|
</table>
|
|
204
183
|
<div v-if="(!dataSourceCopy || !dataSourceCopy.length) && showNoData" class="stk-table-no-data" :class="{ 'no-data-full': noDataFull }">
|
|
@@ -633,6 +612,14 @@ watch(
|
|
|
633
612
|
});
|
|
634
613
|
},
|
|
635
614
|
);
|
|
615
|
+
watch(
|
|
616
|
+
() => props.virtual,
|
|
617
|
+
() => {
|
|
618
|
+
nextTick(() => {
|
|
619
|
+
initVirtualScrollY();
|
|
620
|
+
});
|
|
621
|
+
},
|
|
622
|
+
);
|
|
636
623
|
watch(
|
|
637
624
|
() => props.virtualX,
|
|
638
625
|
() => {
|
|
@@ -869,10 +856,22 @@ function onColumnSort(col?: StkTableColumn<DT>, click = true, options: { force?:
|
|
|
869
856
|
const defaultSort = sortConfig.defaultSort;
|
|
870
857
|
|
|
871
858
|
if (!order && defaultSort) {
|
|
859
|
+
if (!defaultSort.dataIndex) {
|
|
860
|
+
console.error('sortConfig.defaultSort.dataIndex is required');
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
872
863
|
// 没有排序时变成默认排序
|
|
873
|
-
order = defaultSort.order;
|
|
864
|
+
order = defaultSort.order || 'desc';
|
|
874
865
|
sortOrderIndex.value = sortSwitchOrder.indexOf(order);
|
|
875
866
|
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;
|
|
876
875
|
}
|
|
877
876
|
if (!props.sortRemote || options.force) {
|
|
878
877
|
dataSourceCopy.value = tableSort(col, order, props.dataSource, sortConfig);
|
|
@@ -1036,10 +1035,15 @@ function onTrMouseOver(_e: MouseEvent, row: DT) {
|
|
|
1036
1035
|
*/
|
|
1037
1036
|
function setCurrentRow(rowKey: string, option = { silent: false }) {
|
|
1038
1037
|
if (!dataSourceCopy.value.length) return;
|
|
1039
|
-
|
|
1040
|
-
|
|
1038
|
+
const row = dataSourceCopy.value.find(it => rowKeyGen(it) === rowKey);
|
|
1039
|
+
if (!row) {
|
|
1040
|
+
console.warn('setCurrentRow failed.rowKey:', rowKey);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
currentRow.value = row;
|
|
1044
|
+
currentRowKey.value = rowKey;
|
|
1041
1045
|
if (!option.silent) {
|
|
1042
|
-
emits('current-change', /** no Event */ null, currentRow.value, { select:
|
|
1046
|
+
emits('current-change', /** no Event */ null, currentRow.value, { select: true });
|
|
1043
1047
|
}
|
|
1044
1048
|
}
|
|
1045
1049
|
|
package/src/StkTable/style.less
CHANGED
|
@@ -135,18 +135,30 @@
|
|
|
135
135
|
|
|
136
136
|
/* 斑马纹*/
|
|
137
137
|
&.stripe {
|
|
138
|
+
.stk-tbody-main tr:nth-child(even) {
|
|
139
|
+
background-color: var(--stripe-bgc);
|
|
140
|
+
}
|
|
138
141
|
|
|
139
|
-
tbody tr:nth-child(
|
|
142
|
+
&.vt-on .stk-tbody-main tr:nth-child(odd) {
|
|
140
143
|
background-color: var(--stripe-bgc);
|
|
141
144
|
}
|
|
145
|
+
|
|
146
|
+
&.row-hover .stk-tbody-main tr:hover {
|
|
147
|
+
background-color: var(--tr-hover-bgc);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
&.row-active .stk-tbody-main tr.active {
|
|
151
|
+
background-color: var(--tr-active-bgc);
|
|
152
|
+
}
|
|
142
153
|
}
|
|
143
154
|
|
|
144
|
-
|
|
155
|
+
|
|
156
|
+
&.row-hover .stk-tbody-main tr:hover {
|
|
145
157
|
background-color: var(--tr-hover-bgc);
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
|
|
149
|
-
&.row-active tbody tr.active {
|
|
161
|
+
&.row-active .stk-tbody-main tr.active {
|
|
150
162
|
background-color: var(--tr-active-bgc);
|
|
151
163
|
}
|
|
152
164
|
|
|
@@ -183,7 +195,7 @@
|
|
|
183
195
|
/* 为不影响布局,表头行高要定死*/
|
|
184
196
|
.table-header-cell-wrapper {
|
|
185
197
|
overflow: hidden;
|
|
186
|
-
max-height: var(--header-row-height);
|
|
198
|
+
max-height: calc(var(--header-row-height) * var(--row-span));
|
|
187
199
|
}
|
|
188
200
|
|
|
189
201
|
tbody td {
|
|
@@ -279,8 +291,8 @@
|
|
|
279
291
|
}
|
|
280
292
|
|
|
281
293
|
|
|
282
|
-
.
|
|
283
|
-
.
|
|
294
|
+
.vt-x-left,
|
|
295
|
+
.vt-x-right {
|
|
284
296
|
padding: 0;
|
|
285
297
|
background: none;
|
|
286
298
|
pointer-events: none;
|
|
@@ -37,9 +37,6 @@ export function useFixedStyle<DT extends Record<string, any>>({
|
|
|
37
37
|
|
|
38
38
|
const style: CSSProperties = {};
|
|
39
39
|
|
|
40
|
-
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
41
|
-
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
42
|
-
|
|
43
40
|
const isFixedLeft = fixed === 'left';
|
|
44
41
|
if (tagType === TagType.TH) {
|
|
45
42
|
// TH
|
|
@@ -50,6 +47,9 @@ export function useFixedStyle<DT extends Record<string, any>>({
|
|
|
50
47
|
}
|
|
51
48
|
}
|
|
52
49
|
|
|
50
|
+
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
51
|
+
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
52
|
+
|
|
53
53
|
if (fixed === 'left' || fixed === 'right') {
|
|
54
54
|
if (isRelativeMode.value) {
|
|
55
55
|
if (isFixedLeft) {
|
|
@@ -3,7 +3,16 @@ import { StkTableColumn } from './types';
|
|
|
3
3
|
import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
|
|
4
4
|
|
|
5
5
|
/** 翻页按键 */
|
|
6
|
-
|
|
6
|
+
enum ScrollCodes {
|
|
7
|
+
ArrowUp = 'ArrowUp',
|
|
8
|
+
ArrowRight = 'ArrowRight',
|
|
9
|
+
ArrowDown = 'ArrowDown',
|
|
10
|
+
ArrowLeft = 'ArrowLeft',
|
|
11
|
+
PageUp = 'PageUp',
|
|
12
|
+
PageDown = 'PageDown',
|
|
13
|
+
}
|
|
14
|
+
/** 所有翻页按键数组 */
|
|
15
|
+
const ScrollCodesValues = Object.values(ScrollCodes);
|
|
7
16
|
|
|
8
17
|
type Options<DT extends Record<string, any>> = {
|
|
9
18
|
props: any;
|
|
@@ -52,7 +61,8 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
|
|
|
52
61
|
|
|
53
62
|
/** 键盘按下事件 */
|
|
54
63
|
function handleKeydown(e: KeyboardEvent) {
|
|
55
|
-
if (!
|
|
64
|
+
if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
|
|
65
|
+
if (!ScrollCodesValues.includes(e.code as any)) return;
|
|
56
66
|
if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
|
|
57
67
|
e.preventDefault(); // 不触发键盘默认的箭头事件
|
|
58
68
|
|
|
@@ -65,17 +75,17 @@ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
|
|
|
65
75
|
/** 表体的page */
|
|
66
76
|
const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
|
|
67
77
|
|
|
68
|
-
if (e.code ===
|
|
78
|
+
if (e.code === ScrollCodes.ArrowUp) {
|
|
69
79
|
scrollTo(scrollTop - rowHeight, null);
|
|
70
|
-
} else if (e.code ===
|
|
80
|
+
} else if (e.code === ScrollCodes.ArrowRight) {
|
|
71
81
|
scrollTo(null, scrollLeft + rowHeight);
|
|
72
|
-
} else if (e.code ===
|
|
82
|
+
} else if (e.code === ScrollCodes.ArrowDown) {
|
|
73
83
|
scrollTo(scrollTop + rowHeight, null);
|
|
74
|
-
} else if (e.code ===
|
|
84
|
+
} else if (e.code === ScrollCodes.ArrowLeft) {
|
|
75
85
|
scrollTo(null, scrollLeft - rowHeight);
|
|
76
|
-
} else if (e.code ===
|
|
86
|
+
} else if (e.code === ScrollCodes.PageUp) {
|
|
77
87
|
scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
|
|
78
|
-
} else if (e.code ===
|
|
88
|
+
} else if (e.code === ScrollCodes.PageDown) {
|
|
79
89
|
scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
|
|
80
90
|
}
|
|
81
91
|
}
|
|
@@ -163,6 +163,15 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
163
163
|
// return theadRef.value?.offsetHeight || 0;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
/**
|
|
167
|
+
* 初始化虚拟滚动参数
|
|
168
|
+
* @param {number} [height] 虚拟滚动的高度
|
|
169
|
+
*/
|
|
170
|
+
function initVirtualScroll(height?: number) {
|
|
171
|
+
initVirtualScrollY(height);
|
|
172
|
+
initVirtualScrollX();
|
|
173
|
+
}
|
|
174
|
+
|
|
166
175
|
/**
|
|
167
176
|
* 初始化Y虚拟滚动参数
|
|
168
177
|
* @param {number} [height] 虚拟滚动的高度
|
|
@@ -184,7 +193,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
184
193
|
tableHeaderHeight.value = headerHeight;
|
|
185
194
|
if (!headless) {
|
|
186
195
|
/** 表头高度占几行表体高度数 */
|
|
187
|
-
const headerToBodyRowHeightCount = Math.floor(headerHeight
|
|
196
|
+
const headerToBodyRowHeightCount = Math.floor(headerHeight / rowHeight);
|
|
188
197
|
pageSize -= headerToBodyRowHeightCount; //减去表头行数
|
|
189
198
|
}
|
|
190
199
|
/** 最大的scrollTop */
|
|
@@ -203,20 +212,12 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
203
212
|
virtualScrollX.value.scrollWidth = scrollWidth || DEFAULT_TABLE_WIDTH;
|
|
204
213
|
updateVirtualScrollX(scrollLeft);
|
|
205
214
|
}
|
|
206
|
-
/**
|
|
207
|
-
* 初始化虚拟滚动参数
|
|
208
|
-
* @param {number} [height] 虚拟滚动的高度
|
|
209
|
-
*/
|
|
210
|
-
function initVirtualScroll(height?: number) {
|
|
211
|
-
initVirtualScrollY(height);
|
|
212
|
-
initVirtualScrollX();
|
|
213
|
-
}
|
|
214
215
|
|
|
215
216
|
let vue2ScrollYTimeout: null | number = null;
|
|
216
217
|
|
|
217
218
|
/** 通过滚动条位置,计算虚拟滚动的参数 */
|
|
218
219
|
function updateVirtualScrollY(sTop = 0) {
|
|
219
|
-
const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex } = virtualScroll.value;
|
|
220
|
+
const { rowHeight, pageSize, scrollTop, startIndex: oldStartIndex, endIndex: oldEndIndex } = virtualScroll.value;
|
|
220
221
|
// 先更新滚动条位置记录,其他地方有依赖。(stripe 时ArrowUp/Down滚动依赖)
|
|
221
222
|
virtualScroll.value.scrollTop = sTop;
|
|
222
223
|
|
|
@@ -226,22 +227,18 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
let startIndex = Math.floor(sTop / rowHeight);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
230
|
+
let endIndex = startIndex + pageSize;
|
|
231
|
+
|
|
232
232
|
if (props.stripe && startIndex !== 0) {
|
|
233
|
-
const scrollRows = Math.abs(oldStartIndex - startIndex);
|
|
234
233
|
// 斑马纹情况下,每滚动偶数行才加载。防止斑马纹错位。
|
|
235
|
-
if (
|
|
234
|
+
if (startIndex % 2) {
|
|
236
235
|
startIndex -= 1; // 奇数-1变成偶数
|
|
237
236
|
}
|
|
238
237
|
}
|
|
239
|
-
let endIndex = startIndex + pageSize;
|
|
240
|
-
if (props.stripe) {
|
|
241
|
-
endIndex += 1; // 斑马纹下多渲染一些
|
|
242
|
-
}
|
|
243
238
|
|
|
244
|
-
|
|
239
|
+
startIndex = Math.max(0, startIndex);
|
|
240
|
+
|
|
241
|
+
// 溢出修正
|
|
245
242
|
endIndex = Math.min(endIndex, dataSourceCopy.value.length);
|
|
246
243
|
|
|
247
244
|
if (startIndex >= endIndex) {
|
|
@@ -253,6 +250,11 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
253
250
|
window.clearTimeout(vue2ScrollYTimeout);
|
|
254
251
|
}
|
|
255
252
|
|
|
253
|
+
if (oldStartIndex === startIndex && oldEndIndex === endIndex) {
|
|
254
|
+
// 没有变化,不需要更新
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
256
258
|
const offsetTop = startIndex * rowHeight; // startIndex之前的高度
|
|
257
259
|
|
|
258
260
|
/**
|
|
@@ -260,11 +262,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
260
262
|
*/
|
|
261
263
|
if (!props.optimizeVue2Scroll || sTop <= scrollTop || Math.abs(oldStartIndex - startIndex) >= pageSize) {
|
|
262
264
|
// 向上滚动
|
|
263
|
-
Object.assign(virtualScroll.value, {
|
|
264
|
-
startIndex,
|
|
265
|
-
endIndex,
|
|
266
|
-
offsetTop,
|
|
267
|
-
});
|
|
265
|
+
Object.assign(virtualScroll.value, { startIndex, endIndex, offsetTop });
|
|
268
266
|
} else {
|
|
269
267
|
// vue2向下滚动优化
|
|
270
268
|
virtualScroll.value.endIndex = endIndex;
|