Files
leaudit-platform-frontend/docs/docreview-development-standards.md
T
2025-05-30 21:42:44 +08:00

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-4 mt-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;
}

常见问题排查:

  1. 图标显示为方块或问号: 检查是否有CSS规则覆盖了 font-family: 'remixicon'
  2. 只在特定页面不显示: 检查该页面是否使用了样式隔离规则
  3. 首次加载不显示: 确认字体预加载配置正确
  4. 部分图标不显示: 检查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="操作按钮"
>

📋 开发流程规范

组件开发流程

  1. 创建组件TypeScript接口定义
  2. 实现组件逻辑 (.tsx)
  3. 编写组件样式 (.css)
  4. main.css中导入样式
  5. 编写使用示例
  6. 进行测试验证

页面开发流程

  1. routes/下创建路由文件
  2. 定义loader函数处理数据获取
  3. 实现页面组件
  4. 配置metalinks
  5. 添加错误处理
  6. 测试页面功能

🚀 部署和构建规范

环境变量

// 生产环境配置
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编译无错误
  • 样式符合设计系统
  • 组件功能测试完成
  • 代码注释清晰完整

此规范将根据项目发展持续更新和完善。