|
1 | | -import React, { useState, useEffect, useRef } from 'react'; |
| 1 | +import React, { useState } from 'react'; |
2 | 2 | import { Table, Checkbox, Space, Tag } from 'tdesign-react'; |
3 | 3 | import { ErrorCircleFilledIcon, CheckCircleFilledIcon, CloseCircleFilledIcon } from 'tdesign-icons-react'; |
4 | 4 |
|
@@ -45,107 +45,14 @@ export default function TableExample() { |
45 | 45 | const [fixedLeftCol, setFixedLeftCol] = useState(false); |
46 | 46 | const [fixedRightCol, setFixedRightCol] = useState(false); |
47 | 47 | const [headerAffixedTop, setHeaderAffixedTop] = useState(false); |
48 | | - const [stickyMultiHeader, setStickyMultiHeader] = useState(true); |
49 | 48 | const [sort, setSort] = useState<TableSort>({ sortBy: 'default', descending: false }); |
50 | | - const tableContainerRef = useRef<HTMLDivElement>(null); |
51 | 49 |
|
52 | 50 | const onSortChange: TableProps['onSortChange'] = (sortInfo, context) => { |
53 | 51 | setSort(sortInfo); |
54 | 52 | setData([...context.currentDataSource]); |
55 | 53 | console.log(context); |
56 | 54 | }; |
57 | 55 |
|
58 | | - // 多级表头粘性定位逻辑 |
59 | | - useEffect(() => { |
60 | | - if (!stickyMultiHeader || !tableContainerRef.current) return; |
61 | | - |
62 | | - const tableContainer = tableContainerRef.current; |
63 | | - const tableContent = tableContainer.querySelector('.t-table__content') as HTMLElement; |
64 | | - |
65 | | - if (!tableContent) return; |
66 | | - |
67 | | - const handleScroll = () => { |
68 | | - const scrollLeft = tableContent.scrollLeft; |
69 | | - const thead = tableContainer.querySelector('.t-table__header--multiple') as HTMLElement; |
70 | | - |
71 | | - if (!thead) return; |
72 | | - |
73 | | - // 获取所有顶级表头单元格(有colspan的) |
74 | | - const topLevelHeaders = thead.querySelectorAll('tr:first-child th[colspan]') as NodeListOf<HTMLElement>; |
75 | | - |
76 | | - let accumulatedWidth = 0; |
77 | | - |
78 | | - topLevelHeaders.forEach((header) => { |
79 | | - const colKey = header.getAttribute('data-colkey'); |
80 | | - if (!colKey) return; |
81 | | - |
82 | | - const cellInner = header.querySelector('.t-table__th-cell-inner') as HTMLElement; |
83 | | - if (!cellInner) return; |
84 | | - |
85 | | - // 获取表头相对于表格容器的位置 |
86 | | - const headerLeft = header.offsetLeft; |
87 | | - const headerWidth = header.offsetWidth; |
88 | | - const headerRight = headerLeft + headerWidth; |
89 | | - |
90 | | - // 判断是否需要粘性定位:表头的左边已经滚动出视野,但右边还在视野内 |
91 | | - const shouldStick = scrollLeft > headerLeft && scrollLeft < headerRight; |
92 | | - |
93 | | - if (shouldStick) { |
94 | | - // 计算粘性位置,确保不超出表头边界 |
95 | | - const maxLeft = headerWidth - 120; // 预留最小显示宽度 |
96 | | - const stickyLeft = Math.min(scrollLeft - headerLeft, maxLeft); |
97 | | - |
98 | | - console.log('shouldStick', headerLeft, headerRight, scrollLeft, stickyLeft); |
99 | | - // 应用粘性样式 |
100 | | - cellInner.style.position = 'relative'; |
101 | | - cellInner.style.left = `${stickyLeft}px`; |
102 | | - cellInner.style.zIndex = '10'; |
103 | | - } else { |
104 | | - // 移除粘性样式 |
105 | | - cellInner.style.position = ''; |
106 | | - cellInner.style.left = ''; |
107 | | - cellInner.style.zIndex = ''; |
108 | | - } |
109 | | - }); |
110 | | - }; |
111 | | - |
112 | | - // 节流处理 |
113 | | - let ticking = false; |
114 | | - const throttledScroll = () => { |
115 | | - if (!ticking) { |
116 | | - requestAnimationFrame(() => { |
117 | | - handleScroll(); |
118 | | - ticking = false; |
119 | | - }); |
120 | | - ticking = true; |
121 | | - } |
122 | | - }; |
123 | | - |
124 | | - tableContent.addEventListener('scroll', throttledScroll); |
125 | | - |
126 | | - // 初始化执行 |
127 | | - handleScroll(); |
128 | | - |
129 | | - return () => { |
130 | | - tableContent.removeEventListener('scroll', throttledScroll); |
131 | | - |
132 | | - // 清理样式 |
133 | | - const thead = tableContainer.querySelector('.t-table__header--multiple') as HTMLElement; |
134 | | - if (thead) { |
135 | | - const cellInners = thead.querySelectorAll('.t-table__th-cell-inner') as NodeListOf<HTMLElement>; |
136 | | - cellInners.forEach((cellInner) => { |
137 | | - cellInner.style.position = ''; |
138 | | - cellInner.style.left = ''; |
139 | | - cellInner.style.zIndex = ''; |
140 | | - cellInner.style.backgroundColor = ''; |
141 | | - cellInner.style.boxShadow = ''; |
142 | | - cellInner.style.borderRight = ''; |
143 | | - cellInner.style.minWidth = ''; |
144 | | - }); |
145 | | - } |
146 | | - }; |
147 | | - }, [stickyMultiHeader]); |
148 | | - |
149 | 56 | const columns: TableProps['columns'] = [ |
150 | 57 | { |
151 | 58 | title: '申请人', |
@@ -279,44 +186,39 @@ export default function TableExample() { |
279 | 186 | }, |
280 | 187 | ]; |
281 | 188 | return ( |
282 | | - <div ref={tableContainerRef}> |
283 | | - <Space direction="vertical" size="large" style={{ width: '100%' }}> |
284 | | - {/* <!-- 按钮操作区域 --> */} |
285 | | - <Space> |
286 | | - <Checkbox checked={bordered} onChange={setBordered}> |
287 | | - 显示表格边框 |
288 | | - </Checkbox> |
289 | | - <Checkbox checked={fixedHeader} onChange={setFixedHeader}> |
290 | | - 显示固定表头 |
291 | | - </Checkbox> |
292 | | - <Checkbox checked={fixedLeftCol} onChange={setFixedLeftCol}> |
293 | | - 固定左侧列 |
294 | | - </Checkbox> |
295 | | - <Checkbox checked={fixedRightCol} onChange={setFixedRightCol}> |
296 | | - 固定右侧列 |
297 | | - </Checkbox> |
298 | | - <Checkbox checked={headerAffixedTop} onChange={setHeaderAffixedTop}> |
299 | | - 表头吸顶 |
300 | | - </Checkbox> |
301 | | - <Checkbox checked={stickyMultiHeader} onChange={setStickyMultiHeader}> |
302 | | - 多级表头粘性定位 |
303 | | - </Checkbox> |
304 | | - </Space> |
305 | | - |
306 | | - <Table |
307 | | - data={data} |
308 | | - bordered={bordered} |
309 | | - columns={columns} |
310 | | - rowKey="index" |
311 | | - maxHeight={fixedHeader ? 380 : undefined} |
312 | | - headerAffixProps={{ offsetTop: 0 }} |
313 | | - headerAffixedTop={headerAffixedTop} |
314 | | - columnController={{ displayType: 'auto-width' }} |
315 | | - sort={sort} |
316 | | - onSortChange={onSortChange} |
317 | | - lazyLoad |
318 | | - /> |
| 189 | + <Space direction="vertical" size="large" style={{ width: '100%' }}> |
| 190 | + {/* <!-- 按钮操作区域 --> */} |
| 191 | + <Space> |
| 192 | + <Checkbox checked={bordered} onChange={setBordered}> |
| 193 | + 显示表格边框 |
| 194 | + </Checkbox> |
| 195 | + <Checkbox checked={fixedHeader} onChange={setFixedHeader}> |
| 196 | + 显示固定表头 |
| 197 | + </Checkbox> |
| 198 | + <Checkbox checked={fixedLeftCol} onChange={setFixedLeftCol}> |
| 199 | + 固定左侧列 |
| 200 | + </Checkbox> |
| 201 | + <Checkbox checked={fixedRightCol} onChange={setFixedRightCol}> |
| 202 | + 固定右侧列 |
| 203 | + </Checkbox> |
| 204 | + <Checkbox checked={headerAffixedTop} onChange={setHeaderAffixedTop}> |
| 205 | + 表头吸顶 |
| 206 | + </Checkbox> |
319 | 207 | </Space> |
320 | | - </div> |
| 208 | + |
| 209 | + <Table |
| 210 | + data={data} |
| 211 | + bordered={bordered} |
| 212 | + columns={columns} |
| 213 | + rowKey="index" |
| 214 | + maxHeight={fixedHeader ? 380 : undefined} |
| 215 | + headerAffixProps={{ offsetTop: 0 }} |
| 216 | + headerAffixedTop={headerAffixedTop} |
| 217 | + columnController={{ displayType: 'auto-width' }} |
| 218 | + sort={sort} |
| 219 | + onSortChange={onSortChange} |
| 220 | + lazyLoad |
| 221 | + /> |
| 222 | + </Space> |
321 | 223 | ); |
322 | 224 | } |
0 commit comments