Skip to content

Commit 5fa73d3

Browse files
committed
refactor: 更新分类管理和记录页面样式以支持暗黑模式
- 在 Title 组件中添加暗黑模式支持,提升视觉一致性。 - 更新分类管理页面中的按钮和表单样式,增强用户交互体验。 - 调整记录页面中的表格和骨架屏样式,确保在暗黑模式下的可读性和视觉效果。
1 parent 865103d commit 5fa73d3

File tree

4 files changed

+182
-107
lines changed

4 files changed

+182
-107
lines changed

src/components/Title/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface Props {
88

99
export default ({ value, children }: Props) => {
1010
return (
11-
<div className="px-6 py-3 bg-white rounded-xl shadow-sm border border-gray-100 mb-2">
11+
<div className="px-6 py-3 bg-white dark:bg-boxdark rounded-xl shadow-sm border border-gray-100 dark:border-strokedark mb-2">
1212
<div className="overflow-auto flex justify-between items-center">
1313
<h2 className="font-semibold text-black dark:text-white text-xl min-w-24">{value}</h2>
1414

src/pages/cate/index.scss

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
1+
/* 仅保留 Ant Design Tree 布局覆盖,其余样式均使用 Tailwind 写在 tsx 中 */
12
.CatePage {
3+
.ant-tree-node-content-wrapper {
4+
background-color: transparent !important;
5+
}
26
.ant-tree-treenode {
37
width: 100% !important;
48
}
5-
69
.ant-tree-node-content-wrapper {
710
display: flex !important;
811
width: 100% !important;
912
flex: 1 !important;
1013
}
11-
1214
.ant-tree-title {
1315
width: 100% !important;
1416
display: block !important;
1517
flex: 1 !important;
1618
}
17-
1819
.ant-tree-switcher {
20+
margin-top: 7px !important;
1921
flex-shrink: 0 !important;
22+
color: #288eff;
23+
24+
svg {
25+
position: relative;
26+
left: 5px;
27+
}
28+
}
29+
.ant-tree-switcher:before {
30+
left: 5px;
31+
z-index: 10;
32+
}
33+
34+
.ant-tree-switcher-leaf-line:before {
35+
border-inline-end: #ebebeb solid 1px !important;
36+
bottom: -15px !important;
37+
}
38+
.ant-tree-switcher-leaf-line:after {
39+
border-bottom: #ebebeb solid 1px !important;
2040
}
21-
}
41+
}

src/pages/cate/index.tsx

Lines changed: 141 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState, useEffect, useRef } from 'react';
22

3-
import { DownOutlined } from '@ant-design/icons';
3+
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
44
import { Form, Input, Button, Tree, Modal, Spin, Dropdown, Card, MenuProps, Popconfirm, message, Radio, Select, Skeleton } from 'antd';
55
import type { DataNode } from 'antd/es/tree';
66

@@ -26,7 +26,6 @@ export default () => {
2626

2727
const getCateList = async () => {
2828
try {
29-
// 如果是第一次加载,使用 initialLoading
3029
if (isFirstLoadRef.current) {
3130
setInitialLoading(true);
3231
} else {
@@ -107,7 +106,6 @@ export default () => {
107106

108107
await getCateList();
109108

110-
// 初始化表单状态
111109
form.resetFields();
112110
setCate({} as Cate);
113111

@@ -130,38 +128,63 @@ export default () => {
130128
setCate({} as Cate);
131129
};
132130

133-
// 将数据转换为树形结构
134131
const toTreeData = (data: Cate[]): DataNode[] =>
135132
data.map((item) => {
136133
const items: MenuProps['items'] = [
137134
{
138135
key: '1',
139-
label: <span onClick={() => addCateData(item.id!)}>新增</span>,
136+
label: (
137+
<span className="flex items-center gap-2 py-1">
138+
<PlusOutlined className="text-md" />
139+
新增
140+
</span>
141+
),
142+
onClick: () => addCateData(item.id!),
140143
},
141144
{
142145
key: '2',
143-
label: <span onClick={() => editCateData(item.id!)}>编辑</span>,
146+
label: (
147+
<span className="flex items-center gap-2 py-1">
148+
<EditOutlined className="text-md" />
149+
编辑
150+
</span>
151+
),
152+
onClick: () => editCateData(item.id!),
144153
},
145154
{
146155
key: '3',
147156
label: (
148-
<Popconfirm title="警告" description="你确定要删除吗" okText="确定" cancelText="取消" onConfirm={() => delCateData(item.id!)}>
149-
<span>删除</span>
157+
<Popconfirm
158+
title="删除确认"
159+
description="确定要删除该分类吗?"
160+
okText="确定"
161+
cancelText="取消"
162+
onConfirm={() => delCateData(item.id!)}
163+
>
164+
<span className="flex items-center gap-2 py-1 text-red-500 hover:text-red-600">
165+
<DeleteOutlined className="text-md" />
166+
删除
167+
</span>
150168
</Popconfirm>
151169
),
152170
},
153171
];
154172

155173
return {
156174
title: (
157-
<div className="group w-full flex justify-between items-center">
158-
<h3>
159-
{item.icon} <span className="ml-2">{item.name}</span>
160-
</h3>
161-
162-
<Dropdown menu={{ items }} arrow>
163-
<Button type="link" size="small">
164-
操作 <DownOutlined />
175+
<div className="group flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 -ml-2.5 transition-colors hover:bg-slate-50 dark:hover:bg-white/5">
176+
<div className="flex min-w-0 flex-1 items-center gap-2">
177+
<span className="text-lg leading-none opacity-80">{item.icon}</span>
178+
<span className="truncate text-slate-600 dark:text-slate-200">{item.name}</span>
179+
</div>
180+
181+
<Dropdown menu={{ items }} trigger={['click']} placement="bottomRight">
182+
<Button
183+
type="text"
184+
size="small"
185+
className="flex shrink-0 items-center gap-1 text-slate-500 hover:bg-slate-100 hover:text-slate-700 dark:text-slate-400 dark:hover:bg-white/10 dark:hover:text-slate-200"
186+
>
187+
操作
165188
</Button>
166189
</Dropdown>
167190
</div>
@@ -181,110 +204,142 @@ export default () => {
181204
})),
182205
];
183206

184-
// 初始加载时显示骨架屏
185207
if (initialLoading) {
186208
return (
187-
<div>
188-
{/* Title 骨架屏 */}
189-
<Card className="[&>.ant-card-body]:!py-2 [&>.ant-card-body]:!px-5 mb-2">
190-
<div className="flex justify-between items-center">
191-
<Skeleton.Input active size="large" style={{ width: 150, height: 32 }} />
192-
<Skeleton.Button active size="large" style={{ width: 120, height: 40 }} />
209+
<div className="space-y-2">
210+
<Card className="!rounded-xl !border-stroke !shadow-sm [&>.ant-card-body]:!p-4 dark:!border-strokedark">
211+
<div className="flex items-center justify-between">
212+
<Skeleton.Input active size="large" className="!h-9 !w-40" />
213+
<Skeleton.Button active size="large" className="!h-10 !w-28" />
193214
</div>
194215
</Card>
195216

196-
{/* 树形结构骨架屏 */}
197-
<Card className={`border-stroke [&>.ant-card-body]:!p-[30px_20px] [&>.ant-card-body]:!pb-6 mt-2 min-h-[calc(100vh-160px)]`}>
198-
{[1, 2, 3, 4, 5, 6].map((item) => (
199-
<div key={item} className="mb-4">
200-
<div className="flex items-center justify-between mb-2">
201-
<Skeleton.Input active size="default" style={{ width: 200, height: 24 }} />
202-
<Skeleton.Button active size="small" style={{ width: 60, height: 24 }} />
203-
</div>
204-
{/* 子项骨架屏 */}
205-
{item <= 3 && (
206-
<div className="ml-6 space-y-2">
207-
{[1, 2, 3].map((child) => (
208-
<div key={child} className="flex items-center justify-between">
209-
<Skeleton.Input active size="small" style={{ width: 150, height: 20 }} />
210-
<Skeleton.Button active size="small" style={{ width: 60, height: 20 }} />
211-
</div>
212-
))}
217+
<Card className="!min-h-[calc(100vh-160px)] !rounded-xl !border-stroke !shadow-sm [&>.ant-card-body]:!p-6 dark:!border-strokedark">
218+
<div className="space-y-5">
219+
{[1, 2, 3, 4, 5, 6].map((item) => (
220+
<div key={item} className="space-y-2">
221+
<div className="flex items-center justify-between">
222+
<Skeleton.Input active className="!h-6 !w-48" />
223+
<Skeleton.Button active size="small" className="!h-6 !w-14" />
213224
</div>
214-
)}
215-
</div>
216-
))}
225+
{item <= 3 && (
226+
<div className="ml-6 space-y-2">
227+
{[1, 2, 3].map((child) => (
228+
<div key={child} className="flex items-center justify-between">
229+
<Skeleton.Input active size="small" className="!h-5 !w-36" />
230+
<Skeleton.Button active size="small" className="!h-5 !w-12" />
231+
</div>
232+
))}
233+
</div>
234+
)}
235+
</div>
236+
))}
237+
</div>
217238
</Card>
218239
</div>
219240
);
220241
}
221242

222243
return (
223-
<div>
244+
<div className="space-y-2">
224245
<Title value="分类管理">
225-
<Button type="primary" size="large" onClick={() => addCateData(0)}>
246+
<Button
247+
type="primary"
248+
size="large"
249+
onClick={() => addCateData(0)}
250+
>
226251
新增分类
227252
</Button>
228253
</Title>
229254

230-
<Card className={`border-stroke [&>.ant-card-body]:!p-[30px_20px] [&>.ant-card-body]:!pb-6 mt-2 min-h-[calc(100vh-160px)]`}>
231-
<Spin spinning={loading}>
232-
<Tree className="CatePage" defaultExpandAll={true} treeData={toTreeData(list)} />
255+
<Card
256+
className={`CatePage !min-h-[calc(100vh-160px)] !rounded-xl !border !border-stroke !bg-white !shadow-sm [&>.ant-card-body]:!p-6 dark:!border-strokedark dark:!bg-boxdark`}
257+
>
258+
<Spin spinning={loading} className="min-h-[280px]">
259+
<Tree
260+
className="!bg-transparent [&_.ant-tree-treenode]:!py-0.5 [&_.ant-tree-indent-unit]:!w-4"
261+
defaultExpandAll
262+
treeData={toTreeData(list)}
263+
showLine={{ showLeafIcon: false }}
264+
blockNode
265+
/>
233266
</Spin>
267+
</Card>
234268

235-
<Modal loading={editLoading} title={isMethod === 'edit' ? '编辑分类' : '新增分类'} open={isModelOpen} onCancel={closeModel} destroyOnClose footer={null}>
236-
<Form form={form} layout="vertical" initialValues={cate} size="large" preserve={false} className="mt-6">
269+
<Modal
270+
open={isModelOpen}
271+
onCancel={closeModel}
272+
footer={null}
273+
title={isMethod === 'edit' ? '编辑分类' : '新增分类'}
274+
loading={editLoading}
275+
className="[&_.ant-modal-content]:!rounded-2xl"
276+
>
277+
<Form
278+
form={form}
279+
layout="vertical"
280+
initialValues={cate}
281+
size="large"
282+
preserve={false}
283+
className="mt-2 [&_.ant-input]:!rounded-lg [&_.ant-select-selector]:!rounded-lg"
284+
>
285+
<div className="grid gap-x-4 sm:grid-cols-2">
237286
<Form.Item label="名称" name="name" rules={[{ required: true, message: '分类名称不能为空' }]}>
238287
<Input placeholder="请输入分类名称" />
239288
</Form.Item>
240-
241289
<Form.Item label="标识" name="mark" rules={[{ required: true, message: '分类标识不能为空' }]}>
242290
<Input placeholder="请输入分类标识" />
243291
</Form.Item>
292+
</div>
244293

245-
<Form.Item label="图标" name="icon">
246-
<Input placeholder="请输入分类图标" />
247-
</Form.Item>
294+
<Form.Item label="图标" name="icon">
295+
<Input placeholder="请输入分类图标(如 emoji 或图标名)" />
296+
</Form.Item>
248297

249-
{isCateShow && (
250-
<Form.Item label="链接" name="url">
251-
<Input placeholder="请输入分类链接" />
252-
</Form.Item>
253-
)}
298+
{isCateShow && (
299+
<Form.Item label="链接" name="url">
300+
<Input placeholder="请输入分类链接" />
301+
</Form.Item>
302+
)}
254303

304+
<div className="grid gap-x-4 sm:grid-cols-2">
255305
<Form.Item label="顺序" name="order">
256-
<Input placeholder="请输入分类顺序(值越小越靠前" />
306+
<Input placeholder="值越小越靠前" />
257307
</Form.Item>
258-
259308
<Form.Item label="级别" name="level">
260309
<Select options={toCascaderOptions(list)} placeholder="请选择分类级别" />
261310
</Form.Item>
311+
</div>
262312

263-
<Form.Item label="模式" name="type">
264-
<Radio.Group
265-
onChange={(e) => {
266-
const type = e.target.value;
267-
268-
if (type === 'nav') {
269-
setIsCateShow(true);
270-
} else {
271-
setIsCateShow(false);
272-
}
273-
}}
274-
>
275-
<Radio value="cate">分类</Radio>
276-
<Radio value="nav">导航</Radio>
277-
</Radio.Group>
278-
</Form.Item>
279-
280-
<Form.Item className="!mb-0 w-full">
281-
<Button type="primary" onClick={submit} loading={btnLoading} className="w-full ml-2">
282-
{isMethod === 'edit' ? '编辑分类' : '新增分类'}
283-
</Button>
284-
</Form.Item>
285-
</Form>
286-
</Modal>
287-
</Card>
313+
<Form.Item label="模式" name="type">
314+
<Radio.Group
315+
className="!flex !gap-4"
316+
onChange={(e) => {
317+
const type = e.target.value;
318+
setIsCateShow(type === 'nav');
319+
}}
320+
>
321+
<Radio value="cate" className="!m-0">
322+
分类
323+
</Radio>
324+
<Radio value="nav" className="!m-0">
325+
导航
326+
</Radio>
327+
</Radio.Group>
328+
</Form.Item>
329+
330+
<Form.Item className="!mb-0">
331+
<Button
332+
type="primary"
333+
onClick={submit}
334+
loading={btnLoading}
335+
className="!h-12 !w-full !rounded-lg !font-medium"
336+
icon={isMethod === 'edit' ? <EditOutlined /> : <PlusOutlined />}
337+
>
338+
{isMethod === 'edit' ? '保存修改' : '新增分类'}
339+
</Button>
340+
</Form.Item>
341+
</Form>
342+
</Modal>
288343
</div>
289344
);
290345
};

0 commit comments

Comments
 (0)