Files
makemd/docs/03_Frontend/UI_Components.md
wurenzhi 72cd7f6f45 chore: 清理归档文件和文档模板
删除不再需要的归档文件和过时的文档模板,包括多个README、安全策略、前端集成蓝图等文件,同时移除了未使用的业务文档和项目结构文件。

优化项目结构,移除冗余文件,保持代码库整洁。主要删除archive/handover目录下的多个文件及doc目录下的部分文档模板。
2026-03-18 01:21:15 +08:00

494 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UI Components (Crawlful Hub)
> **定位**Crawlful Hub 前端 UI 组件规范 - 基于 Ant Design 5.x 的组件库使用指南。
> **更新日期**: 2026-03-18
---
## 1. 设计系统
### 1.1 色彩规范
```typescript
// 主色调
const colors = {
primary: '#1890ff', // 主色
success: '#52c41a', // 成功
warning: '#faad14', // 警告
error: '#f5222d', // 错误
info: '#1890ff', // 信息
};
// 中性色
const neutral = {
textPrimary: 'rgba(0, 0, 0, 0.85)',
textSecondary: 'rgba(0, 0, 0, 0.65)',
textDisabled: 'rgba(0, 0, 0, 0.25)',
border: '#d9d9d9',
background: '#f5f5f5',
};
```
### 1.2 字体规范
```typescript
const typography = {
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial',
fontSize: {
small: '12px',
base: '14px',
medium: '16px',
large: '20px',
xlarge: '24px',
},
};
```
---
## 2. 基础组件
### 2.1 按钮 (Button)
**使用场景**
- 主操作:蓝色主按钮
- 次操作:默认按钮
- 危险操作:红色按钮
- 文字链接:链接按钮
**示例**
```tsx
import { Button, Space } from 'antd';
// 主操作
<Button type="primary"></Button>
// 次操作
<Button></Button>
// 危险操作
<Button type="primary" danger></Button>
// 图标按钮
<Button icon={<PlusOutlined />}></Button>
// 加载状态
<Button loading></Button>
```
### 2.2 表单 (Form)
**使用场景**
- 商品创建/编辑
- 订单审核
- 用户设置
**示例**
```tsx
import { Form, Input, Select, Button } from 'antd';
const ProductForm: React.FC = () => {
const [form] = Form.useForm();
const onFinish = (values: any) => {
console.log(values);
};
return (
<Form form={form} onFinish={onFinish} layout="vertical">
<Form.Item
name="title"
label="商品名称"
rules={[{ required: true }]}
>
<Input placeholder="请输入商品名称" />
</Form.Item>
<Form.Item name="platform" label="平台">
<Select>
<Select.Option value="AMAZON">Amazon</Select.Option>
<Select.Option value="EBAY">eBay</Select.Option>
<Select.Option value="SHOPIFY">Shopify</Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit"></Button>
</Form.Item>
</Form>
);
};
```
### 2.3 表格 (Table)
**使用场景**
- 商品列表
- 订单列表
- 交易流水
**示例**
```tsx
import { Table, Tag } from 'antd';
const ProductTable: React.FC = () => {
const columns = [
{
title: '商品名称',
dataIndex: 'title',
key: 'title',
},
{
title: '平台',
dataIndex: 'platform',
key: 'platform',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const colorMap: Record<string, string> = {
DRAFTED: 'default',
PENDING_REVIEW: 'processing',
APPROVED: 'success',
REJECTED: 'error',
};
return <Tag color={colorMap[status]}>{status}</Tag>;
},
},
{
title: '售价',
dataIndex: 'sellingPrice',
key: 'sellingPrice',
render: (price: number) => `$${price.toFixed(2)}`,
},
{
title: '操作',
key: 'action',
render: (_, record) => (
<Space>
<Button type="link"></Button>
<Button type="link"></Button>
</Space>
),
},
];
return (
<Table
columns={columns}
dataSource={products}
rowKey="id"
pagination={{ pageSize: 20 }}
/>
);
};
```
### 2.4 卡片 (Card)
**使用场景**
- 仪表盘统计卡片
- 商品信息展示
- 订单概要
**示例**
```tsx
import { Card, Statistic } from 'antd';
import { ArrowUpOutlined } from '@ant-design/icons';
// 统计卡片
<Card>
<Statistic
title="本月营收"
value={112893}
precision={2}
valueStyle={{ color: '#3f8600' }}
prefix="$"
suffix={<ArrowUpOutlined />}
/>
</Card>
// 带标题的卡片
<Card title="商品信息" extra={<a href="#"></a>}>
<p>商品名称: Product Name</p>
<p>平台: Amazon</p>
<p>状态: 已上架</p>
</Card>
```
---
## 3. 业务组件
### 3.1 状态徽章 (StatusBadge)
**组件定义**
```tsx
import { Badge } from 'antd';
interface StatusBadgeProps {
status: string;
type: 'product' | 'order' | 'payment';
}
const statusMap: Record<string, Record<string, { color: string; text: string }>> = {
product: {
DRAFTED: { color: 'default', text: '草稿' },
PENDING_REVIEW: { color: 'processing', text: '待审核' },
APPROVED: { color: 'success', text: '已通过' },
REJECTED: { color: 'error', text: '已拒绝' },
LISTED: { color: 'success', text: '已上架' },
DELISTED: { color: 'default', text: '已下架' },
},
order: {
PULLED: { color: 'default', text: '已拉取' },
PENDING_REVIEW: { color: 'processing', text: '待审核' },
CONFIRMED: { color: 'success', text: '已确认' },
SHIPPED: { color: 'blue', text: '已发货' },
DELIVERED: { color: 'success', text: '已送达' },
},
payment: {
PENDING: { color: 'warning', text: '待支付' },
COMPLETED: { color: 'success', text: '已完成' },
FAILED: { color: 'error', text: '失败' },
REFUNDED: { color: 'default', text: '已退款' },
},
};
export const StatusBadge: React.FC<StatusBadgeProps> = ({ status, type }) => {
const config = statusMap[type]?.[status] || { color: 'default', text: status };
return <Badge status={config.color as any} text={config.text} />;
};
```
### 3.2 筛选面板 (FilterPanel)
**组件定义**
```tsx
import { Form, Input, Select, DatePicker, Button, Space } from 'antd';
interface FilterPanelProps {
onFilter: (values: any) => void;
onReset: () => void;
}
export const FilterPanel: React.FC<FilterPanelProps> = ({ onFilter, onReset }) => {
const [form] = Form.useForm();
return (
<Form form={form} layout="inline" onFinish={onFilter}>
<Form.Item name="keyword" label="关键词">
<Input placeholder="搜索..." allowClear />
</Form.Item>
<Form.Item name="platform" label="平台">
<Select allowClear style={{ width: 120 }}>
<Select.Option value="AMAZON">Amazon</Select.Option>
<Select.Option value="EBAY">eBay</Select.Option>
<Select.Option value="SHOPIFY">Shopify</Select.Option>
</Select>
</Form.Item>
<Form.Item name="dateRange" label="日期">
<DatePicker.RangePicker />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit"></Button>
<Button onClick={() => { form.resetFields(); onReset(); }}></Button>
</Space>
</Form.Item>
</Form>
);
};
```
### 3.3 数据表格 (DataTable)
**组件定义**
```tsx
import { Table, TableProps } from 'antd';
interface DataTableProps<T> extends TableProps<T> {
loading?: boolean;
pagination?: {
current: number;
pageSize: number;
total: number;
};
onPageChange?: (page: number, pageSize: number) => void;
}
export function DataTable<T extends object>({
loading,
pagination,
onPageChange,
...tableProps
}: DataTableProps<T>) {
return (
<Table<T>
{...tableProps}
loading={loading}
pagination={pagination ? {
...pagination,
showSizeChanger: true,
showTotal: (total) => `${total}`,
onChange: onPageChange,
} : false}
scroll={{ x: 'max-content' }}
/>
);
}
```
---
## 4. 图表组件
### 4.1 利润趋势图
**使用 Ant Design Charts**
```tsx
import { Line } from '@ant-design/charts';
const ProfitChart: React.FC = () => {
const data = [
{ date: '2026-03-01', profit: 1000 },
{ date: '2026-03-02', profit: 1200 },
{ date: '2026-03-03', profit: 900 },
// ...
];
const config = {
data,
xField: 'date',
yField: 'profit',
smooth: true,
point: {
size: 5,
shape: 'diamond',
},
label: {
style: {
fill: '#aaa',
},
},
};
return <Line {...config} />;
};
```
### 4.2 订单分布图
```tsx
import { Pie } from '@ant-design/charts';
const OrderDistributionChart: React.FC = () => {
const data = [
{ type: 'Amazon', value: 400 },
{ type: 'eBay', value: 300 },
{ type: 'Shopify', value: 300 },
];
const config = {
data,
angleField: 'value',
colorField: 'type',
radius: 0.8,
label: {
type: 'outer',
},
};
return <Pie {...config} />;
};
```
---
## 5. 布局组件
### 5.1 主布局 (MainLayout)
```tsx
import { Layout, Menu } from 'antd';
import { Outlet, useNavigate } from 'react-router-dom';
const { Header, Sider, Content } = Layout;
const MainLayout: React.FC = () => {
const navigate = useNavigate();
const menuItems = [
{ key: '/', label: '仪表盘', icon: <DashboardOutlined /> },
{ key: '/products', label: '商品管理', icon: <ShoppingOutlined /> },
{ key: '/orders', label: '订单管理', icon: <FileTextOutlined /> },
{ key: '/finance', label: '财务管理', icon: <DollarOutlined /> },
{ key: '/inventory', label: '库存管理', icon: <InboxOutlined /> },
{ key: '/marketing', label: '营销广告', icon: <BarChartOutlined /> },
{ key: '/suppliers', label: '供应商', icon: <TeamOutlined /> },
{ key: '/reports', label: '报表分析', icon: <PieChartOutlined /> },
{ key: '/settings', label: '系统设置', icon: <SettingOutlined /> },
];
return (
<Layout style={{ minHeight: '100vh' }}>
<Sider theme="light">
<div style={{ height: 64, padding: 16 }}>Crawlful Hub</div>
<Menu
mode="inline"
items={menuItems}
onClick={({ key }) => navigate(key)}
/>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: '0 24px' }}>
{/* Header content */}
</Header>
<Content style={{ margin: 24, padding: 24, background: '#fff' }}>
<Outlet />
</Content>
</Layout>
</Layout>
);
};
```
---
## 6. 表单校验规则
```typescript
// utils/validators.ts
export const validators = {
required: (message: string) => ({ required: true, message }),
email: { type: 'email', message: '请输入有效的邮箱地址' },
price: (min: number = 0) => ({
validator: (_: any, value: number) => {
if (value >= min) return Promise.resolve();
return Promise.reject(new Error(`价格不能低于 ${min}`));
},
}),
url: { type: 'url', message: '请输入有效的URL' },
};
```
---
## 7. 相关文档
- [Frontend Design](./Frontend_Design.md)
- [Pages Flow](./Pages_Flow.md)
- [Ant Design 官方文档](https://ant.design/)
---
*本文档基于 Ant Design 5.x最后更新: 2026-03-18*