# 组件设计文档 ## 1. 组件分类 ### 1.1 按功能分类 #### 布局组件 (components/Layout/) - **Layout.jsx**: 主布局容器 - **Header.jsx**: 顶部导航栏 - **Sidebar.jsx**: 侧边栏菜单 #### 通用组件 (components/Common/) - **Button.jsx**: 按钮组件 - **Input.jsx**: 输入框组件 - **Select.jsx**: 下拉选择框组件 - **DatePicker.jsx**: 日期选择器组件 - **Table.jsx**: 表格组件 - **Modal.jsx**: 弹窗组件 - **Form.jsx**: 表单组件 - **Card.jsx**: 卡片组件 - **Tag.jsx**: 标签组件 - **Badge.jsx**: 徽章组件 - **Tooltip.jsx**: 提示框组件 #### 业务组件 (components/Business/) - **ProjectCard.jsx**: 项目卡片 - **StatCard.jsx**: 统计卡片 - **UserAvatar.jsx**: 用户头像 - **ProgressBar.jsx**: 进度条 - **StatusTag.jsx**: 状态标签 - **AmountDisplay.jsx**: 金额显示 - **DateRangePicker.jsx**: 日期范围选择器 ## 2. 组件设计规范 ### 2.1 Props命名规范 #### 2.1.1 布尔类型 - 使用 `is` 或 `has` 前缀 - 示例: `isLoading`, `hasPermission`, `isVisible`, `isRequired` #### 2.1.2 事件处理 - 使用 `on` 前缀 - 示例: `onClick`, `onChange`, `onSubmit`, `onCancel` #### 2.1.3 渲染内容 - 使用 `render` 前缀或作为 `children` - 示例: `renderHeader`, `renderFooter`, `children` ### 2.2 组件Props定义模板 ```jsx import React from 'react'; import PropTypes from 'prop-types'; /** * 按钮组件 * @param {string} type - 按钮类型:primary/default/danger * @param {boolean} loading - 是否加载中 * @param {boolean} disabled - 是否禁用 * @param {function} onClick - 点击事件 * @param {node} children - 子元素 */ const Button = ({ type = 'default', loading = false, disabled = false, onClick, children, className, ...rest }) => { return ( ); }; Button.propTypes = { type: PropTypes.oneOf(['primary', 'default', 'danger']), loading: PropTypes.bool, disabled: PropTypes.bool, onClick: PropTypes.func, children: PropTypes.node, className: PropTypes.string, }; export default Button; ``` ## 3. 核心组件设计 ### 3.1 Button(按钮组件) ```jsx /** * 按钮组件 */ const Button = ({ type = 'default', size = 'medium', icon, loading = false, disabled = false, block = false, ghost = false, danger = false, onClick, children, ...props }) => { const handleClick = (e) => { if (!loading && !disabled && onClick) { onClick(e); } }; return ( ); }; ``` **Props说明:** - `type`: 按钮类型 (default/primary/danger) - `size`: 按钮大小 (small/medium/large) - `icon`: 图标 - `loading`: 加载状态 - `disabled`: 禁用状态 - `block`: 块级按钮 - `ghost`: 幽灵按钮 - `danger`: 危险按钮 ### 3.2 Table(表格组件) ```jsx /** * 表格组件 */ const Table = ({ columns, dataSource, loading = false, pagination, rowKey = 'id', rowSelection, onRow, scroll, ...props }) => { return ( ); }; ``` **Props说明:** - `columns`: 列配置 - `dataSource`: 数据源 - `loading`: 加载状态 - `pagination`: 分页配置 - `rowKey`: 行key - `rowSelection`: 行选择配置 - `scroll`: 滚动配置 ### 3.3 Form(表单组件) ```jsx /** * 表单组件 */ const Form = ({ form, initialValues, onFinish, onFinishFailed, layout = 'vertical', children, ...props }) => { const [formInstance] = Form.useForm(); const currentForm = form || formInstance; return ( {children} ); }; ``` ### 3.4 Modal(弹窗组件) ```jsx /** * 弹窗组件 */ const Modal = ({ visible, title, onOk, onCancel, okText = '确定', cancelText = '取消', confirmLoading = false, width = 520, children, ...props }) => { return ( {children} ); }; ``` ### 3.5 Card(卡片组件) ```jsx /** * 卡片组件 */ const Card = ({ title, extra, bordered = true, hoverable = false, loading = false, children, className, ...props }) => { return ( {children} ); }; ``` ### 3.6 Tag(标签组件) ```jsx /** * 标签组件 */ const Tag = ({ type = 'default', color, children, ...props }) => { const colorMap = { new: 'blue', inProgress: 'green', completed: 'default', paused: 'orange', cancelled: 'red', admin: 'red', market: 'blue', other: 'cyan', }; return ( {children} ); }; ``` ## 4. 业务组件设计 ### 4.1 ProjectCard(项目卡片) ```jsx /** * 项目卡片组件 */ const ProjectCard = ({ project, onView, onEdit, onDelete, showActions = true, }) => { const { hasRole } = usePermission(); return ( {project.name} {project.engineering_type} } extra={ {project.project_no} } className="project-card" >
合同金额:
项目负责人: {project.project_leader}
签订日期: {project.signing_date}
{showActions && (
{hasRole(['admin']) || project.created_by === getCurrentUserId() ? ( <> ) : null}
)}
); }; ``` ### 4.2 StatCard(统计卡片) ```jsx /** * 统计卡片组件 */ const StatCard = ({ title, value, icon, color, prefix, suffix }) => { return (
{title}
{prefix && {prefix}} {typeof value === 'number' ? value.toLocaleString() : value} {suffix && {suffix}}
{icon && (
{icon}
)}
); }; ``` **Props说明:** - `title`: 标题 - `value`: 数值 - `icon`: 图标 - `color`: 颜色 (blue/green/orange/red/cyan) - `prefix`: 前缀(如¥) - `suffix`: 后缀(如%) ### 4.3 StatusTag(状态标签) ```jsx /** * 状态标签组件 */ const StatusTag = ({ status, type = 'project' }) => { const statusMap = { project: { new: { text: '新建', color: 'blue' }, inProgress: { text: '进行中', color: 'green' }, completed: { text: '已完成', color: 'default' }, paused: { text: '已暂停', color: 'orange' }, cancelled: { text: '已取消', color: 'red' }, }, user: { active: { text: '正常', color: 'green' }, inactive: { text: '禁用', color: 'default' }, }, }; const statusInfo = statusMap[type]?.[status] || { text: status, color: 'default' }; return {statusInfo.text}; }; ``` ### 4.4 AmountDisplay(金额显示) ```jsx /** * 金额显示组件 */ const AmountDisplay = ({ value, unit = '万元', precision = 2 }) => { const formatAmount = (val) => { if (val === null || val === undefined) return '-'; return val.toFixed(precision); }; return ( {formatAmount(value)} {unit} ); }; ``` ### 4.5 ProgressBar(进度条) ```jsx /** * 进度条组件 */ const ProgressBar = ({ percent, status = 'active', showText = true }) => { return (
); }; ``` ### 4.6 DateRangePicker(日期范围选择器) ```jsx /** * 日期范围选择器组件 */ const DateRangePicker = ({ value, onChange, placeholder }) => { const { RangePicker } = DatePicker; return ( ); }; ``` ## 5. 高阶组件 ### 5.1 withAuth(认证高阶组件) ```jsx /** * 认证高阶组件 */ const withAuth = (WrappedComponent, requiredRoles = []) => { return (props) => { const { user, isAuthenticated } = useAuth(); if (!isAuthenticated) { return ; } if (requiredRoles.length > 0 && !requiredRoles.includes(user?.role)) { return ; } return ; }; }; ``` ### 5.2 withLoading(加载状态高阶组件) ```jsx /** * 加载状态高阶组件 */ const withLoading = (WrappedComponent) => { return ({ loading, ...props }) => { if (loading) { return ; } return ; }; }; ``` ## 6. 组件复用策略 ### 6.1 通过Props自定义 - 提供灵活的Props接口 - 支持自定义样式和类名 - 支持自定义渲染内容 ### 6.2 通过插槽模式 - 使用 `children` 传递内容 - 使用 `render` 属性传递渲染函数 ### 6.3 通过组合模式 - 将复杂组件拆分为多个小组件 - 通过组合实现复杂功能 ## 7. 组件性能优化 ### 7.1 React.memo ```jsx const MemoComponent = React.memo(({ data }) => { return
{data}
; }); ``` ### 7.2 useMemo ```jsx const expensiveValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]); ``` ### 7.3 useCallback ```jsx const handleClick = useCallback(() => { doSomething(a, b); }, [a, b]); ``` ### 7.4 虚拟滚动 对于大数据量的列表,使用虚拟滚动: ```jsx import { List } from 'react-virtualized'; (
{data[index]}
)} /> ``` ## 8. 组件测试 ### 8.1 单元测试示例 ```jsx import { render, screen, fireEvent } from '@testing-library/react'; import Button from './Button'; describe('Button Component', () => { test('renders button with children', () => { render(); expect(screen.getByText('Click me')).toBeInTheDocument(); }); test('calls onClick when clicked', () => { const handleClick = jest.fn(); render(); fireEvent.click(screen.getByText('Click')); expect(handleClick).toHaveBeenCalledTimes(1); }); test('shows loading state', () => { render(); expect(screen.getByText('Click')).toBeDisabled(); }); }); ``` ## 9. 组件文档 ### 9.1 Storybook(可选) 使用Storybook进行组件文档和展示: ```jsx // stories/Button.stories.jsx import Button from '../components/Common/Button'; export default { title: 'Components/Button', component: Button, }; const Template = (args) =>