Skip to content

Commit c8b1a6a

Browse files
author
Tenny
committed
重构 Table
Signed-off-by: Tenny <tenny.shu@foxmail.com>
1 parent 3e10b1b commit c8b1a6a

File tree

1 file changed

+101
-25
lines changed

1 file changed

+101
-25
lines changed

src/components/table/Table.vue

Lines changed: 101 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import { defineComponent, h, PropType, ref, toRaw, watch } from 'vue';
3-
import type { VNode } from 'vue';
4-
import { random } from 'ph-utils';
3+
import type { VNode, CSSProperties } from 'vue';
4+
import { isBlank, random } from 'ph-utils';
55
import { format } from 'ph-utils/date';
66
77
export interface ColumnOption {
@@ -27,10 +27,9 @@ export interface ColumnOption {
2727
titleColspan?: number;
2828
/** th rowspan */
2929
titleRowspan?: number;
30-
/** 设置可选择 */
31-
type?: 'radio' | 'checkbox';
32-
/** 为 radio,checkbox 设置是否禁用 */
33-
disabled?: (row: any) => boolean;
30+
id?: string;
31+
style?: CSSProperties;
32+
className?: string;
3433
}
3534
3635
export interface DataSortState {
@@ -51,44 +50,115 @@ type SorterFnOption = (
5150
5251
type RowKeyOption = (row: any) => any;
5352
54-
/** 通过配置的 columns 计算表头跨行,跨列 */
55-
function calculateSpan(headers: ColumnOption[], level = 0): ColumnOption[] {
56-
if (!Array.isArray(headers)) {
57-
return [];
53+
function getLeftStart(id: string, left: [string, number][]) {
54+
let start = 0;
55+
const len = left.length;
56+
let isFirst = false;
57+
for (let i = 0; i < len; i++) {
58+
const item = left[i];
59+
if (item[0] === id) {
60+
if (i === 0) {
61+
isFirst = true;
62+
}
63+
break;
64+
}
65+
start += item[1];
66+
}
67+
return { start, isFirst };
68+
}
69+
70+
function getRightStart(id: string, right: [string, number][]) {
71+
let start = 0;
72+
let isFirst = false;
73+
const len = right.length;
74+
for (let i = len - 1; i >= 0; i--) {
75+
const item = right[i];
76+
if (item[0] === id) {
77+
if (i === len - 1) {
78+
isFirst = true;
79+
}
80+
break;
81+
}
82+
start += item[1];
5883
}
84+
return { start, isFirst };
85+
}
86+
87+
function getCommonStyle(
88+
column: ColumnOption,
89+
fl: [string, number][],
90+
fr: [string, number][],
91+
): CSSProperties {
92+
const res: CSSProperties = { ...column.style };
93+
if (column.width != null) {
94+
if (typeof column.width === 'number') {
95+
res.width = `${column.width}px`;
96+
} else {
97+
res.width = column.width;
98+
}
99+
}
100+
return res;
101+
}
59102
60-
const spans = headers.map((header) => {
103+
/** 通过配置的 columns 计算表头跨行,跨列 */
104+
function calculateSpan(
105+
headers: ColumnOption[],
106+
level = 0,
107+
leftFixed: [string, number][],
108+
rightFixed: [string, number][],
109+
): ColumnOption[] {
110+
const tmpCols = [];
111+
for (let i = 0, len = headers.length; i < len; i++) {
112+
const header = headers[i];
113+
if (header.id == null) {
114+
header.id = header.key || header.title;
115+
}
116+
if (isBlank(header.id)) {
117+
header.id = random(6) as string;
118+
}
119+
if (header.fixed != null) {
120+
const widNum = parseInt(`${header.width || 0}`);
121+
if (header.fixed === 'left') {
122+
leftFixed.push([header.id as string, widNum]);
123+
} else if (header.fixed === 'right') {
124+
rightFixed.push([header.id as string, widNum]);
125+
}
126+
}
61127
// 如果有子级元素,递归计算
62128
if (header.children != null) {
63129
let titleColspan = header.titleColspan;
64-
const childrenSpans = calculateSpan(header.children, level + 1);
130+
const childrenSpans = calculateSpan(
131+
header.children,
132+
level + 1,
133+
leftFixed,
134+
rightFixed,
135+
);
65136
if (titleColspan == null) {
66137
titleColspan = childrenSpans.reduce(
67138
(sum, childSpan) => sum + (childSpan.titleColspan || 0),
68139
0,
69140
);
70141
}
71-
return {
142+
tmpCols.push({
72143
...header,
73144
titleColspan: titleColspan,
74145
titleRowspan: header.titleRowspan || 1,
75146
children: childrenSpans,
76-
};
147+
});
77148
} else {
78149
let titleRowspan = header.titleRowspan;
79150
if (titleRowspan == null) {
80151
titleRowspan = getMaxDepth(headers);
81152
}
82153
// 如果元素没有子级,意味着它占满从当前层级到最底层的所有行
83-
return {
154+
tmpCols.push({
84155
...header,
85156
titleColspan: header.titleColspan || 1,
86157
titleRowspan: titleRowspan,
87-
};
158+
});
88159
}
89-
});
90-
91-
return spans;
160+
}
161+
return tmpCols;
92162
}
93163
94164
// 递归获取最深的层级数
@@ -164,8 +234,18 @@ export default defineComponent({
164234
order: '',
165235
});
166236
const sourceData = ref(props.data);
167-
const parsedColumns = calculateSpan(props.columns, 0);
168-
237+
/** 缓存列样式, 避免每次遍历列都重新计算 */
238+
const globalColStyles: Record<string, CSSProperties> = {};
239+
/** 左边固定列 */
240+
const fixedLeft: [string, number][] = [];
241+
/** 右边固定列 */
242+
const fixedRight: [string, number][] = [];
243+
const parsedColumns = calculateSpan(
244+
props.columns,
245+
0,
246+
fixedLeft,
247+
fixedRight,
248+
);
169249
watch(
170250
() => props.data,
171251
() => {
@@ -256,10 +336,6 @@ export default defineComponent({
256336
}
257337
}
258338
259-
if (column.type != null && column.width == null) {
260-
column.width = 40;
261-
}
262-
263339
if (column.width) {
264340
let colWidth: string = column.width as string;
265341
if (typeof column.width === 'number') {

0 commit comments

Comments
 (0)