# 中国烟草AI合同及卷宗审核系统 - 开发规范指南 ## 📋 概述 本文档定义了「中国烟草AI合同及卷宗审核系统」的开发规范,包括技术架构、设计风格、代码规范、UI组件等各个方面,确保团队开发的一致性和代码质量。 ## 🏗 技术架构规范 ### 核心技术栈 - **前端框架**: Remix (React) + TypeScript - **构建工具**: Vite - **样式系统**: Tailwind CSS + 自定义CSS - **图标库**: Remixicon (已本地化) - **文档处理**: react-pdf, mammoth, docx-preview - **代码规范**: ESLint + TypeScript - **状态管理**: React Context + useState/useEffect ### 项目结构规范 ``` app/ ├── api/ # API层接口 ├── components/ # 组件 │ ├── ui/ # 通用UI组件 │ ├── layout/ # 布局组件 │ ├── error/ # 错误处理组件 │ └── [feature]/ # 功能特定组件 ├── routes/ # Remix路由页面 ├── styles/ # 样式文件 │ ├── main.css # 主样式 │ └── components/ # 组件样式 ├── types/ # TypeScript类型定义 ├── contexts/ # React Context ├── models/ # 数据模型 └── utils.ts # 工具函数 ``` ## 🎨 设计系统规范 ### 颜色主题 ```css /* 主色调 - 中国烟草企业绿 */ --color-primary: #00684a; /* 主色 */ --color-primary-hover: #005a3f; /* 悬停色 */ --color-primary-light: rgba(0, 104, 74, 0.1); /* 浅色背景 */ /* 状态颜色 */ --color-success: #52c41a; /* 成功绿 */ --color-warning: #faad14; /* 警告橙 */ --color-error: #f5222d; /* 错误红 */ /* 中性色系 */ --color-gray-50: #f8f9fa; /* 最浅灰 */ --color-gray-100: #f1f3f5; --color-gray-200: #e9ecef; --color-gray-300: #dee2e6; --color-gray-400: #ced4da; --color-gray-500: #adb5bd; /* 中性灰 */ --color-gray-600: #868e96; --color-gray-700: #495057; --color-gray-800: #343a40; --color-gray-900: #212529; /* 最深灰 */ ``` ### 字体规范 ```css font-family: [ "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans SC", /* 中文优先 */ "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "sans-serif" ]; ``` ### 间距系统 - 使用Tailwind默认间距: 4px基数 (1, 2, 3, 4, 5, 6...) - 页面容器内边距: `p-5` (20px) - 卡片内边距: `p-4` (16px) - 组件间距: `mb-4` `mt-6` (16px, 24px) ### 圆角规范 - 按钮、卡片: `rounded-md` (6px) - 输入框: `rounded-md` (6px) - 头像: `rounded-full` - 标签: `rounded-md` ### 阴影系统 ```css /* 卡片阴影 */ .card: shadow-sm; /* 默认 */ .card:hover: shadow-md; /* 悬停 */ .sidebar: shadow-[0_0_15px_rgba(0,0,0,0.05)]; /* 侧边栏 */ ``` ## 🧩 组件设计规范 ### 按钮组件 ```tsx // 类型定义 type ButtonType = 'primary' | 'default' | 'danger'; type ButtonSize = 'small' | 'medium' | 'large'; // 样式类 .ant-btn-primary: bg-[#00684a] text-white hover:bg-[#005a3f] .ant-btn-default: bg-white border border-gray-300 text-gray-800 .ant-btn-danger: bg-[#f5222d] text-white hover:bg-[#cf1f29] ``` ### 卡片组件 ```tsx // 基础结构
内容
// 样式规范 .card: bg-white rounded-lg shadow overflow-hidden .card-header: px-5 py-4 border-b border-gray-100 .card-title: text-base font-medium text-gray-900 ``` ### 布局组件 ```tsx // 侧边栏宽度 .sidebar: w-[280px] /* 展开状态 */ .sidebar.collapsed: w-20 /* 收缩状态 */ // 主内容区适配 .main-content: ml-[280px] /* 对应侧边栏宽度 */ .main-content.sidebar-collapsed: ml-20 ``` ## 📝 代码规范 ### TypeScript规范 ```typescript // 接口命名使用PascalCase interface DocumentUI { id: string; name: string; status: ProcessingStatus; } // 类型联合使用字符串字面量 type ProcessingStatus = 'Waiting' | 'Cutting' | 'Extractioning' | 'Evaluationing' | 'Processed'; // 组件Props接口 interface ComponentProps { children: React.ReactNode; className?: string; disabled?: boolean; } ``` ### React组件规范 ```tsx // 函数组件使用function声明 export function ComponentName({ prop1, prop2 }: ComponentProps) { // useState放在顶部 const [state, setState] = useState(initialValue); // useEffect按逻辑分组 useEffect(() => { // 副作用逻辑 }, [dependencies]); // 事件处理函数 const handleClick = (e: React.MouseEvent) => { // 处理逻辑 }; return (
{/* JSX内容 */}
); } ``` ### 文件命名规范 - 组件文件: `PascalCase.tsx` (如: `Button.tsx`) - 路由文件: `kebab-case.tsx` (如: `user-profile.tsx`) - 样式文件: `kebab-case.css` (如: `button.css`) - 工具文件: `camelCase.ts` (如: `utils.ts`) ### 导入顺序规范 ```typescript // 1. React相关 import React, { useState, useEffect } from 'react'; import { Link, useLoaderData } from '@remix-run/react'; // 2. 第三方库 import dayjs from 'dayjs'; // 3. 内部组件 (~/ 别名) import { Card } from '~/components/ui/Card'; import { Button } from '~/components/ui/Button'; // 4. 类型定义 import type { DocumentUI } from '~/types/document'; // 5. 样式文件 import styles from '~/styles/components/component.css?url'; ``` ### CSS类命名规范 ```css /* BEM方法论 + 功能前缀 */ .sidebar-menu-item /* 组件-子元素-状态 */ .sidebar-menu-item.active /* 状态修饰符 */ .ant-btn-primary /* 组件库前缀 */ .text-primary /* 工具类 */ ``` ## 🎯 UI/UX设计规范 ### 交互动效 ```css /* 统一过渡动效 */ .transition-all-ease: transition-all duration-200 ease-in-out; /* 悬停效果 */ .sidebar-menu-item:hover: bg-[rgba(0,104,74,0.05)]; .card:hover: shadow-md; ``` ### 状态指示 ```typescript // 文件处理状态 const statusConfig = { "Waiting": { label: "上传中", icon: "ri-loader-line", color: "blue" }, "Cutting": { label: "切分中", icon: "ri-loader-line", color: "purple" }, "Extractioning": { label: "抽取中", icon: "ri-loader-line", color: "cyan" }, "Evaluationing": { label: "评查中", icon: "ri-loader-line", color: "teal" }, "Processed": { label: "已完成", icon: "ri-check-line", color: "green" } }; ``` ### 图标使用规范 (RemixIcon 本地化) ```tsx // 基本图标使用 // 图标尺寸控制 // 大图标 // 特大图标 // 2倍大小 // 结合样式使用 // 在按钮组件中使用 ``` **图标系统特点:** - **本地化部署**: 字体文件已复制到 `public/fonts/` 目录,无外网依赖 - **预加载优化**: 通过 `` 确保首次访问图标立即显示 - **完整支持**: 包含3000+图标,支持所有RemixIcon官方图标 - **性能优化**: 启用 `font-display: swap` 提供更好的加载体验 - **浏览器兼容**: 支持IE9+到最新浏览器 **⚠️ 重要注意事项 - 避免样式冲突:** 在使用CSS样式隔离(如 `all: unset` 或强制 `font-family: inherit`)时,必须为RemixIcon图标添加例外规则: ```css /* 错误示例 - 会导致图标不显示 */ .my-isolated-container * { font-family: inherit !important; /* 这会覆盖图标字体 */ } /* 正确示例 - 添加图标例外规则 */ .my-isolated-container * { font-family: inherit !important; } .my-isolated-container [class^="ri-"], .my-isolated-container [class*=" ri-"], .my-isolated-container i[class^="ri-"], .my-isolated-container i[class*=" ri-"] { font-family: 'remixicon' !important; font-style: normal !important; font-weight: normal !important; font-variant: normal !important; text-transform: none !important; line-height: 1 !important; -webkit-font-smoothing: antialiased !important; -moz-osx-font-smoothing: grayscale !important; speak: none !important; } ``` **常见问题排查:** 1. **图标显示为方块或问号**: 检查是否有CSS规则覆盖了 `font-family: 'remixicon'` 2. **只在特定页面不显示**: 检查该页面是否使用了样式隔离规则 3. **首次加载不显示**: 确认字体预加载配置正确 4. **部分图标不显示**: 检查CSS选择器优先级和 `!important` 使用 ### 国际化和本地化 - 界面语言: 简体中文为主 - 日期格式: `YYYY年MM月DD日` - 时间格式: `HH:mm:ss` - 数字格式: 使用中文习惯 (如: 万、千) ## 🔧 工具配置规范 ### ESLint配置要点 ```javascript // 启用的规则 - "plugin:react/recommended" - "plugin:react-hooks/recommended" - "plugin:@typescript-eslint/recommended" - "plugin:jsx-a11y/recommended" ``` ### Tailwind配置扩展 ```typescript // tailwind.config.ts theme: { extend: { colors: { primary: { DEFAULT: '#1677ff', // 保持Remix默认,实际使用CSS变量覆盖 // ... 其他色阶 } } } } ``` ## 📊 性能优化规范 ### 组件优化 ```typescript // 使用React.memo对纯组件优化 export const MemoizedComponent = React.memo(Component); // 防抖工具函数使用 import { debounce } from '~/utils'; const debouncedHandler = debounce(handler, 300); ``` ### 资源加载 ```typescript // 样式文件异步加载 import styles from '~/styles/component.css?url'; // 组件懒加载 const LazyComponent = lazy(() => import('~/components/LazyComponent')); ``` ## 🚨 错误处理规范 ### 错误边界 ```tsx // 统一错误处理组件 ``` ### API错误处理 ```typescript // 统一的API响应处理 if (response.error) { console.error('API错误:', response.error); return Response.json( { error: response.error }, { status: response.status || 500 } ); } ``` ## 📱 响应式设计规范 ### 断点使用 - `sm`: 640px+ (移动端横屏) - `md`: 768px+ (平板) - `lg`: 1024px+ (桌面) - `xl`: 1280px+ (大屏) ### 适配策略 ```css /* 移动端优先 */ .content-container: p-5; @screen sm: .content-container: p-6; /* 侧边栏响应式 */ @screen md: .sidebar-toggle: block; ``` ## 🔍 可访问性规范 ### 语义化HTML ```tsx // 使用语义化标签