12 KiB
12 KiB
中国烟草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 # 工具函数
🎨 设计系统规范
颜色主题
/* 主色调 - 中国烟草企业绿 */
--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; /* 最深灰 */
字体规范
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-4mt-6(16px, 24px)
圆角规范
- 按钮、卡片:
rounded-md(6px) - 输入框:
rounded-md(6px) - 头像:
rounded-full - 标签:
rounded-md
阴影系统
/* 卡片阴影 */
.card: shadow-sm; /* 默认 */
.card:hover: shadow-md; /* 悬停 */
.sidebar: shadow-[0_0_15px_rgba(0,0,0,0.05)]; /* 侧边栏 */
🧩 组件设计规范
按钮组件
// 类型定义
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]
卡片组件
// 基础结构
<Card title="标题" icon="ri-icon-name" className="additional-classes">
<div className="card-body">内容</div>
</Card>
// 样式规范
.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
布局组件
// 侧边栏宽度
.sidebar: w-[280px] /* 展开状态 */
.sidebar.collapsed: w-20 /* 收缩状态 */
// 主内容区适配
.main-content: ml-[280px] /* 对应侧边栏宽度 */
.main-content.sidebar-collapsed: ml-20
📝 代码规范
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组件规范
// 函数组件使用function声明
export function ComponentName({ prop1, prop2 }: ComponentProps) {
// useState放在顶部
const [state, setState] = useState<Type>(initialValue);
// useEffect按逻辑分组
useEffect(() => {
// 副作用逻辑
}, [dependencies]);
// 事件处理函数
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
// 处理逻辑
};
return (
<div className="component-container">
{/* JSX内容 */}
</div>
);
}
文件命名规范
- 组件文件:
PascalCase.tsx(如:Button.tsx) - 路由文件:
kebab-case.tsx(如:user-profile.tsx) - 样式文件:
kebab-case.css(如:button.css) - 工具文件:
camelCase.ts(如:utils.ts)
导入顺序规范
// 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类命名规范
/* BEM方法论 + 功能前缀 */
.sidebar-menu-item /* 组件-子元素-状态 */
.sidebar-menu-item.active /* 状态修饰符 */
.ant-btn-primary /* 组件库前缀 */
.text-primary /* 工具类 */
🎯 UI/UX设计规范
交互动效
/* 统一过渡动效 */
.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;
状态指示
// 文件处理状态
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 本地化)
// 基本图标使用
<i className="ri-home-line"></i>
<i className="ri-file-list-3-line"></i>
<i className="ri-user-line"></i>
// 图标尺寸控制
<i className="ri-home-line ri-lg"></i> // 大图标
<i className="ri-home-line ri-xl"></i> // 特大图标
<i className="ri-home-line ri-2x"></i> // 2倍大小
// 结合样式使用
<i className="ri-error-warning-line text-red-500"></i>
<i className="ri-check-line text-green-600"></i>
<i className="ri-information-line text-blue-500"></i>
// 在按钮组件中使用
<Button icon="ri-add-line">添加</Button>
<Button icon="ri-edit-line">编辑</Button>
<Button icon="ri-delete-bin-line">删除</Button>
图标系统特点:
- 本地化部署: 字体文件已复制到
public/fonts/目录,无外网依赖 - 预加载优化: 通过
<link rel="preload">确保首次访问图标立即显示 - 完整支持: 包含3000+图标,支持所有RemixIcon官方图标
- 性能优化: 启用
font-display: swap提供更好的加载体验 - 浏览器兼容: 支持IE9+到最新浏览器
⚠️ 重要注意事项 - 避免样式冲突:
在使用CSS样式隔离(如 all: unset 或强制 font-family: inherit)时,必须为RemixIcon图标添加例外规则:
/* 错误示例 - 会导致图标不显示 */
.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;
}
常见问题排查:
- 图标显示为方块或问号: 检查是否有CSS规则覆盖了
font-family: 'remixicon' - 只在特定页面不显示: 检查该页面是否使用了样式隔离规则
- 首次加载不显示: 确认字体预加载配置正确
- 部分图标不显示: 检查CSS选择器优先级和
!important使用
国际化和本地化
- 界面语言: 简体中文为主
- 日期格式:
YYYY年MM月DD日 - 时间格式:
HH:mm:ss - 数字格式: 使用中文习惯 (如: 万、千)
🔧 工具配置规范
ESLint配置要点
// 启用的规则
- "plugin:react/recommended"
- "plugin:react-hooks/recommended"
- "plugin:@typescript-eslint/recommended"
- "plugin:jsx-a11y/recommended"
Tailwind配置扩展
// tailwind.config.ts
theme: {
extend: {
colors: {
primary: {
DEFAULT: '#1677ff', // 保持Remix默认,实际使用CSS变量覆盖
// ... 其他色阶
}
}
}
}
📊 性能优化规范
组件优化
// 使用React.memo对纯组件优化
export const MemoizedComponent = React.memo(Component);
// 防抖工具函数使用
import { debounce } from '~/utils';
const debouncedHandler = debounce(handler, 300);
资源加载
// 样式文件异步加载
import styles from '~/styles/component.css?url';
// 组件懒加载
const LazyComponent = lazy(() => import('~/components/LazyComponent'));
🚨 错误处理规范
错误边界
// 统一错误处理组件
<AppErrorBoundary
status={500}
statusText="服务器错误"
message="服务器发生了意外错误,请稍后重试"
/>
API错误处理
// 统一的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+ (大屏)
适配策略
/* 移动端优先 */
.content-container: p-5;
@screen sm: .content-container: p-6;
/* 侧边栏响应式 */
@screen md: .sidebar-toggle: block;
🔍 可访问性规范
语义化HTML
// 使用语义化标签
<main className="main-content">
<nav className="breadcrumb" aria-label="页面导航">
<section className="content-section">
键盘导航
// 确保所有交互元素可键盘访问
<button
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
aria-label="操作按钮"
>
📋 开发流程规范
组件开发流程
- 创建组件TypeScript接口定义
- 实现组件逻辑 (
.tsx) - 编写组件样式 (
.css) - 在
main.css中导入样式 - 编写使用示例
- 进行测试验证
页面开发流程
- 在
routes/下创建路由文件 - 定义
loader函数处理数据获取 - 实现页面组件
- 配置
meta和links - 添加错误处理
- 测试页面功能
🚀 部署和构建规范
环境变量
// 生产环境配置
NODE_ENV=production
DATABASE_URL=...
SESSION_SECRET=...
构建优化
// vite.config.ts优化配置
export default defineConfig({
plugins: [remix(), tsconfigPaths()],
build: {
rollupOptions: {
// 代码分割优化
}
}
});
📚 开发检查清单
新组件开发
- TypeScript接口定义完整
- 样式使用设计系统颜色
- 支持必要的props (className, disabled等)
- 添加适当的过渡动效
- 编写组件文档注释
新页面开发
- loader函数处理数据和错误
- meta信息配置完整
- 响应式设计适配
- 错误边界处理
- 面包屑导航配置
代码提交前
- ESLint检查通过
- TypeScript编译无错误
- 样式符合设计系统
- 组件功能测试完成
- 代码注释清晰完整
此规范将根据项目发展持续更新和完善。