Skip to content

Commit c4dda42

Browse files
committed
优化表格数据展示
1 parent 8359844 commit c4dda42

File tree

2 files changed

+59
-69
lines changed

2 files changed

+59
-69
lines changed

app/globals.css

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -322,23 +322,6 @@ select:focus-visible {
322322
transition: none;
323323
}
324324

325-
/* DataTable 分类行样式 */
326-
.category-row > td {
327-
background-color: #eff6ff !important;
328-
}
329-
330-
.dark .category-row > td {
331-
background-color: rgba(30, 58, 138, 0.3) !important;
332-
}
333-
334-
.category-row:hover > td {
335-
background-color: #dbeafe !important;
336-
}
337-
338-
.dark .category-row:hover > td {
339-
background-color: rgba(30, 64, 175, 0.4) !important;
340-
}
341-
342325
/* PWA 安装提示动画 */
343326
@keyframes slide-up {
344327
from {

components/management/DataTable.tsx

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import React, { useState, useMemo, useEffect } from 'react';
44
import { Table, Button, Space, Popconfirm } from 'antd';
5-
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
5+
import { EditOutlined, DeleteOutlined, RightOutlined, DownOutlined } from '@ant-design/icons';
66
import type { ColumnsType } from 'antd/es/table';
77
import { Link } from '@/types/link';
88
import { Category } from '@/types/category';
@@ -59,18 +59,19 @@ export const DataTable: React.FC<DataTableProps> = ({
5959
const categories = useAppSelector((state) => state.categories.items);
6060

6161
// 使用外部传入的 selectedRowKeys 或内部状态
62-
const selectedRowKeys = externalSelectedRowKeys !== undefined ? externalSelectedRowKeys : internalSelectedRowKeys;
62+
const selectedRowKeys =
63+
externalSelectedRowKeys !== undefined ? externalSelectedRowKeys : internalSelectedRowKeys;
6364

6465
// 构建树形数据结构
6566
const treeData = useMemo(() => {
6667
const tree: TreeNode[] = [];
6768

6869
// 按分类组织链接
69-
categories.forEach(category => {
70+
categories.forEach((category) => {
7071
const categoryLinks = links
71-
.filter(link => link.category === category.name)
72+
.filter((link) => link.category === category.name)
7273
.sort((a, b) => a.order - b.order)
73-
.map(link => ({
74+
.map((link) => ({
7475
key: link.id,
7576
id: link.id,
7677
name: link.name,
@@ -101,9 +102,9 @@ export const DataTable: React.FC<DataTableProps> = ({
101102

102103
// 添加未分类节点(如果有未分类的链接)
103104
const uncategorizedLinks = links
104-
.filter(link => !link.category || link.category === '')
105+
.filter((link) => !link.category || link.category === '')
105106
.sort((a, b) => a.order - b.order)
106-
.map(link => ({
107+
.map((link) => ({
107108
key: link.id,
108109
id: link.id,
109110
name: link.name,
@@ -136,42 +137,62 @@ export const DataTable: React.FC<DataTableProps> = ({
136137
return tree.sort((a, b) => a.order - b.order);
137138
}, [links, categories]);
138139

139-
// 默认展开所有分类(包括未分类)
140+
// 默认展开第一个分类
140141
useEffect(() => {
141-
const allCategoryKeys = categories.map(cat => `category-${cat.id}`);
142-
// 如果有未分类链接,也展开未分类节点
143-
const hasUncategorized = links.some(link => !link.category || link.category === '');
144-
if (hasUncategorized) {
145-
allCategoryKeys.push('category-uncategorized');
142+
if (categories.length > 0) {
143+
const firstCategoryKey = `category-${categories[0].id}`;
144+
setExpandedRowKeys([firstCategoryKey]);
146145
}
147-
setExpandedRowKeys(allCategoryKeys);
148-
}, [categories, links]);
146+
}, [categories]);
149147

150148
// 表格列定义
151149
const columns: ColumnsType<TreeNode> = [
152150
{
153151
title: '名称',
154152
dataIndex: 'name',
155153
key: 'name',
156-
width: 160,
154+
width: 120,
157155
ellipsis: true,
158-
render: (name: string, record: TreeNode) => (
159-
<span className={record.isCategory ? 'font-semibold text-base' : ''}>
160-
{name}
161-
</span>
162-
),
156+
render: (name: string, record: TreeNode) =>
157+
record.isCategory ? (
158+
<span className="font-semibold">{name}</span>
159+
) : record.icon ? (
160+
<div className="flex items-center">
161+
<div
162+
className="w-6 h-6 rounded border border-gray-300 flex justify-center items-center mr-2"
163+
style={{ background: record.backgroundColor }}
164+
>
165+
<img
166+
src={record.icon}
167+
alt="图标"
168+
className="w-4 h-4 object-contain"
169+
onError={(e) => {
170+
e.currentTarget.style.display = 'none';
171+
}}
172+
/>
173+
</div>
174+
<span> {name} </span>
175+
</div>
176+
) : (
177+
<span> {name} </span>
178+
),
163179
},
164180
{
165181
title: '地址',
166182
dataIndex: 'url',
167183
key: 'url',
168-
width: 200,
184+
width: 180,
169185
ellipsis: true,
170-
render: (url: string, record: TreeNode) =>
186+
render: (url: string, record: TreeNode) =>
171187
record.isCategory ? (
172188
<span className="text-gray-400">-</span>
173189
) : url ? (
174-
<a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:text-blue-700">
190+
<a
191+
href={url}
192+
target="_blank"
193+
rel="noopener noreferrer"
194+
className="text-blue-500 hover:text-blue-700"
195+
>
175196
{url}
176197
</a>
177198
) : null,
@@ -180,21 +201,21 @@ export const DataTable: React.FC<DataTableProps> = ({
180201
title: '描述',
181202
dataIndex: 'description',
182203
key: 'description',
183-
width: 300,
204+
width: 240,
184205
ellipsis: true,
185-
render: (description: string, record: TreeNode) =>
206+
render: (description: string, record: TreeNode) =>
186207
record.isCategory ? (
187208
<span className="text-gray-500">{record.children?.length || 0} 条链接</span>
188209
) : (
189210
description
190211
),
191212
},
192213
{
193-
title: '背景颜色',
214+
title: '背景',
194215
dataIndex: 'backgroundColor',
195216
key: 'backgroundColor',
196217
width: 100,
197-
render: (color: string, record: TreeNode) =>
218+
render: (color: string, record: TreeNode) =>
198219
record.isCategory ? (
199220
<span className="text-gray-400">-</span>
200221
) : (
@@ -210,15 +231,15 @@ export const DataTable: React.FC<DataTableProps> = ({
210231
{
211232
title: '操作',
212233
key: 'action',
213-
width: 150,
234+
width: 120,
214235
fixed: 'right',
215236
render: (_, record: TreeNode) => {
216237
if (record.isCategory) {
217238
// 未分类节点不允许编辑和删除
218239
if (record.id === 'uncategorized') {
219240
return <span className="text-gray-400">-</span>;
220241
}
221-
242+
222243
// 分类节点的操作
223244
const category: Category = {
224245
id: record.id,
@@ -228,7 +249,7 @@ export const DataTable: React.FC<DataTableProps> = ({
228249
createdAt: record.createdAt,
229250
updatedAt: record.updatedAt,
230251
};
231-
252+
232253
return (
233254
<Space size="small">
234255
<Button
@@ -250,19 +271,14 @@ export const DataTable: React.FC<DataTableProps> = ({
250271
cancelText="取消"
251272
okType="danger"
252273
>
253-
<Button
254-
type="link"
255-
danger
256-
icon={<DeleteOutlined />}
257-
size="small"
258-
>
274+
<Button type="link" danger icon={<DeleteOutlined />} size="small">
259275
删除
260276
</Button>
261277
</Popconfirm>
262278
</Space>
263279
);
264280
}
265-
281+
266282
// 链接节点的操作
267283
return (
268284
<Space size="small">
@@ -280,12 +296,7 @@ export const DataTable: React.FC<DataTableProps> = ({
280296
okText="确定"
281297
cancelText="取消"
282298
>
283-
<Button
284-
type="link"
285-
danger
286-
icon={<DeleteOutlined />}
287-
size="small"
288-
>
299+
<Button type="link" danger icon={<DeleteOutlined />} size="small">
289300
删除
290301
</Button>
291302
</Popconfirm>
@@ -300,7 +311,7 @@ export const DataTable: React.FC<DataTableProps> = ({
300311
selectedRowKeys,
301312
onChange: (newSelectedRowKeys: React.Key[]) => {
302313
// 过滤掉分类节点
303-
const linkKeys = newSelectedRowKeys.filter(key => !String(key).startsWith('category-'));
314+
const linkKeys = newSelectedRowKeys.filter((key) => !String(key).startsWith('category-'));
304315
if (onSelectionChange) {
305316
onSelectionChange(linkKeys);
306317
} else {
@@ -321,15 +332,12 @@ export const DataTable: React.FC<DataTableProps> = ({
321332
rowKey="key"
322333
size="middle"
323334
rowSelection={rowSelection}
324-
rowClassName={(record) =>
325-
record.isCategory
326-
? 'category-row'
327-
: ''
328-
}
335+
rowClassName={(record) => (record.isCategory ? 'category-row' : '')}
329336
expandable={{
330337
expandedRowKeys,
338+
indentSize: 0,
331339
onExpandedRowsChange: (keys) => setExpandedRowKeys([...keys]),
332-
defaultExpandAllRows: true,
340+
// defaultExpandAllRows: true,
333341
}}
334342
pagination={{
335343
current: currentPage,
@@ -347,7 +355,6 @@ export const DataTable: React.FC<DataTableProps> = ({
347355
pageSizeOptions: ['10', '20', '50', '100'],
348356
}}
349357
scroll={{ x: 1200 }}
350-
className="[&_.ant-empty]:z-0 [&_.category-row>td]:bg-blue-50! [&_.category-row>td]:dark:bg-blue-900/30! [&_.category-row:hover>td]:bg-blue-100! [&_.category-row:hover>td]:dark:bg-blue-800/40!"
351358
/>
352359
</div>
353360
);

0 commit comments

Comments
 (0)