tdesign-react
tdesign-react copied to clipboard
[Table] 虚拟滚动问题:fix右列样式没对齐问题 + 滚到下面行的线消失了 + 合并单元格有问题
tdesign-react 版本
1.15.1
重现链接
No response
重现步骤
<Table
rowKey='id'
data={list}
columns={getTableColumns({
abnormalType,
days,
canEdit,
onRemarkEditedCell,
})}
rowspanAndColspan={rowspanAndColspan}
className={styles.commonFullTable}
loading={loading}
empty={<Empty />}
scroll={{ type: 'virtual' }}
lazyLoad
/>
1、右侧fixed的问题
{
title: '备注',
colKey: 'mark',
fixed: 'right',
width: 200,
}
上面:
滚到下面:
2、滚到下面行的线消失了
3、合并列失效
期望结果
三个问题正常展示
实际结果
No response
框架版本
No response
浏览器版本
No response
系统版本
No response
Node版本
No response
补充说明
No response
👋 @tingtingcheng6,感谢给 TDesign 提出了 issue。 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。
问题 1 已修复,预计下个版本发布 https://github.com/Tencent/tdesign-react/pull/3792 问题 2 和 3 无法复现 请提供可复现的在线代码 DEMO
全部 Bug 场景均已可复现...接下来会进行修复并在某个版本发布
完整 DEMO 存档
import React, { useMemo } from 'react';
import { CheckCircleFilledIcon, CloseCircleFilledIcon, ErrorCircleFilledIcon } from 'tdesign-icons-react';
import { Link, Space, Table, Tag } from 'tdesign-react';
import type { TableProps } from 'tdesign-react';
const statusNameListMap = {
0: { label: '正常', theme: 'success', icon: <CheckCircleFilledIcon /> },
1: { label: '异常', theme: 'danger', icon: <CloseCircleFilledIcon /> },
2: { label: '警告', theme: 'warning', icon: <ErrorCircleFilledIcon /> },
};
// 生成大量数据
const generateData = (count: number) => {
const data: any[] = [];
const departments = ['技术部', '产品部', '运营部', '市场部'];
// 计算每个部门的人数
const peoplePerDept = Math.ceil(count / departments.length);
let currentId = 1;
departments.forEach((dept, deptIndex) => {
// 为每个部门生成指定数量的人员
const deptSize =
deptIndex === departments.length - 1
? count - peoplePerDept * (departments.length - 1) // 最后一个部门处理余数
: peoplePerDept;
for (let i = 0; i < deptSize; i++) {
const globalIndex = currentId - 1;
data.push({
id: currentId,
name: `${dept.replace('部', '')}员工${i + 1}`,
department: dept,
email: `user${currentId}@${dept.toLowerCase().replace('部', '')}.com`,
phone: `138${String(globalIndex).padStart(8, '0')}`,
status: globalIndex % 3,
score: Math.floor(Math.random() * 100),
joinDate: `2023-${String((globalIndex % 12) + 1).padStart(2, '0')}-${String((globalIndex % 28) + 1).padStart(
2,
'0',
)}`,
address: `北京市朝阳区${dept}办公楼${i + 1}号`,
project: ['项目A', '项目B', '项目C', '项目D'][deptIndex % 4],
workYears: Math.floor(i / 3) + 1,
salary: (deptIndex + 1) * 8000 + i * 1000 + Math.floor(Math.random() * 3000),
mark: i % 3 === 0 ? `${dept}重要成员${i + 1}` : `${dept}普通成员${i + 1}`,
});
currentId++;
}
});
return data;
};
export default function VirtualScrollIssuesDemo() {
const data = useMemo(() => generateData(500), []);
// 合并单元格逻辑 - 按部门合并
const rowspanAndColspan = useMemo(() => {
const spanMap = new Map();
// 计算每个部门的行数
const departmentCounts = new Map();
data.forEach((item, index) => {
const dept = item.department;
if (!departmentCounts.has(dept)) {
departmentCounts.set(dept, []);
}
departmentCounts.get(dept).push(index);
});
// 设置合并单元格
departmentCounts.forEach((indexes) => {
indexes.forEach((rowIndex, i) => {
if (i === 0) {
// 第一行显示合并的单元格
spanMap.set(`${rowIndex}_department`, {
rowspan: indexes.length,
colspan: 1,
});
} else {
// 其他行隐藏
spanMap.set(`${rowIndex}_department`, {
rowspan: 0,
colspan: 0,
});
}
});
});
return ({ rowIndex, col }) => {
const key = `${rowIndex}_${col.colKey}`;
return spanMap.get(key);
};
}, [data]);
const columns: TableProps['columns'] = [
{
title: 'ID',
colKey: 'id',
width: 80,
fixed: 'left',
},
{
title: '部门',
colKey: 'department',
width: 120,
// 这一列会被合并
},
{
title: '姓名',
colKey: 'name',
width: 120,
fixed: 'left',
},
{
title: '邮箱',
colKey: 'email',
width: 200,
ellipsis: true,
},
{
title: '电话',
colKey: 'phone',
width: 140,
},
{
title: '状态',
colKey: 'status',
width: 120,
cell: ({ row }) => {
const { status } = row;
return (
<Tag
shape="round"
theme={statusNameListMap[status].theme}
variant="light-outline"
icon={statusNameListMap[status].icon}
>
{statusNameListMap[status].label}
</Tag>
);
},
},
{
title: '评分',
colKey: 'score',
width: 100,
},
{
title: '入职日期',
colKey: 'joinDate',
width: 120,
},
{
title: '地址',
colKey: 'address',
width: 250,
ellipsis: true,
},
{
title: '项目',
colKey: 'project',
width: 120,
},
{
title: '工作年限',
colKey: 'workYears',
width: 100,
},
{
title: '薪资',
colKey: 'salary',
width: 120,
},
{
title: '操作',
colKey: 'operation',
width: 150,
fixed: 'right',
cell: () => (
<Space size="small">
<Link theme="primary" size="small">
编辑
</Link>
<Link theme="danger" size="small">
删除
</Link>
</Space>
),
},
{
title: '备注',
colKey: 'mark',
fixed: 'right',
width: 200,
ellipsis: true,
},
];
return (
<div style={{ width: '1000px' }}>
<Table
maxHeight={600}
rowKey="id"
data={data}
columns={columns}
rowspanAndColspan={rowspanAndColspan}
scroll={{ type: 'virtual' }}
bordered
/>
</div>
);
}