Files
color_full/docs/project-overview.md
qichi.liang c58ca26969 企业级重构:四层模块化架构 + RBAC授权 + 安全加固 + 颜色引擎/配方推演增强
架构
- 后端从 flat routes/ 重构为 modules/<domain>/ 模块化结构(8个模块)
- 四层架构:Route -> Service -> Repository -> Prisma
- 新增 shared/ 基础设施(AppError 异常体系、ALS 上下文、prom-client 指标)
- 前端 Toast/Skeleton/Alert 组件基建 + formulaService 模板

安全
- JWT 签名算法修复(HS256 用 createHmac 而非 createHash)
- 密码哈希 async scrypt + timingSafeEqual
- API Key 从 localStorage 迁移至服务端 runtime/config.json
- Helmet 安全头 + rate-limit 全局限流 100 req/min
- 全局 auth preHandler + RBAC + Ownership 中间件

颜色引擎
- 色匹配切换为 cube 粗筛 + CIEDE2000 精排
- PantoneColor 表 + 种子数据 + 搜索端点
- AI 配色 Prompt 注入成分库 colorant 列表

配方推演
- 本地优化引擎(同 category 替换 + 成本排序)
- baseFormulaId 支持 + Pareto 散点图

文档
- ADR-0003 四层架构、ADR-0004 RBAC 授权模型
- 更新 ADR-0001/0002
- api-reference.md(29端点)、project-overview.md

部署
- Dockerfile * 2 + nginx.conf + docker-compose.prod.yml
- 健康探针 + 优雅关闭 + pg_dump 备份脚本
- ESLint + Prettier + tsconfig strict
2026-05-21 17:29:52 +08:00

24 KiB
Raw Blame History

配方研发智能平台 — 项目全貌

最后更新 2026-05-21 | 版本 v0.1.0 | 企业级重构后


1. 项目是什么

AI 驱动的化妆品配方研发智能平台(纯 Web 端)。面向化妆品研发工程师,提供四大核心能力:

能力 说明
颜色管理 CIELAB 色空间 + Display P3 广色域渲染 + AI 配色推荐
可视化配方调整 拖拽交互 + 实时 AI 预测反馈 + ECharts 图表
配方记录管理 结构化存储 + 版本管理 + 自然语言搜索
配方推演 多方案并行优化 + Pareto 前沿 + 成本/功效约束

2. 目录全貌

color_full/
│
├── CONTEXT.md                          # 领域词汇表(纯业务术语)
├── README.md
├── AGENTS.md                           # Agent 配置
│
├── docs/
│   ├── adr/
│   │   ├── 0001-architecture-stack.md       # 技术栈选型React/Fastify/Prisma/...
│   │   ├── 0002-ai-api-strategy.md          # AI 外部 API 调用策略
│   │   ├── 0003-four-layer-module-architecture.md  # 后端四层模块化架构
│   │   └── 0004-rbac-ownership-authorization.md    # RBAC + 资源级 Ownership
│   ├── api-reference.md                      # API 接口文档29 端点)
│   ├── project-overview.md                   # 本文件
│   └── agents/                               # Agent skills 配置
│
├── backend/                                  # 后端Fastify + TypeScript
│   ├── Dockerfile
│   ├── package.json
│   ├── tsconfig.json                         # strict + noUncheckedIndexedAccess
│   ├── vitest.config.ts
│   ├── eslint.config.js
│   ├── .prettierrc
│   ├── .env.example                          # 环境变量模板
│   ├── runtime/
│   │   └── config.json                       # 运行时 AI Key 持久化
│   ├── scripts/
│   │   └── generate-openapi.ts               # OpenAPI spec 生成
│   ├── prisma/
│   │   ├── schema.prisma                     # 数据模型定义10 个模型)
│   │   ├── seed.ts
│   │   └── migrations/
│   └── src/
│       ├── app.ts                            # ★ 应用入口:插件注册 + 全局中间件
│       ├── server.ts                         # ★ 启动 + 优雅关闭
│       ├── lib/                               # 工具库
│       │   ├── prisma.ts                     # Prisma 客户端
│       │   ├── configStore.ts                # 服务器端配置持久化
│       │   ├── validate.ts                   # Zod → Fastify 校验桥接
│       │   └── swagger.ts                    # Zod → JSON Schema 转换
│       ├── shared/                            # ★ 跨模块共享基础设施
│       │   ├── errors/
│       │   │   ├── app-error.ts              # AppError 6 子类体系
│       │   │   └── codes.ts                  # 30+ 错误码常量
│       │   ├── logging/
│       │   │   └── context.ts                # AsyncLocalStorage 请求上下文
│       │   ├── middleware/
│       │   │   ├── rbac.ts                   # requireRole('admin')
│       │   │   └── ownership.ts              # requireFormulaOwnership()
│       │   ├── metrics/
│       │   │   └── metrics.ts                # prom-client 5 指标
│       │   └── audit/
│       │       └── audit.service.ts          # 结构化审计日志
│       ├── services/                          # 核心服务
│       │   └── ai/
│       │       ├── index.ts                  # ★ AIServiceProvider 抽象 + 缓存 + 限流 + 回退)
│       │       ├── cache.ts                  # LRUCache
│       │       ├── rate-limiter.ts           # Token Bucket
│       │       ├── audit.ts                  # AI 调用审计记录
│       │       ├── providers/
│       │       │   ├── types.ts              # AIProvider 接口
│       │       │   ├── openai.ts             # OpenAI (GPT-4o)
│       │       │   └── deepseek.ts           # DeepSeek (deepseek-chat)
│       │       └── templates/
│       │           └── index.ts              # 5 个 Prompt 模板
│       ├── modules/                           # ★ 业务模块(四层架构)
│       │   ├── auth/                         # 认证(注册/登录/JWT
│       │   ├── ingredients/                  # 成分目录route + service + repository + test
│       │   ├── formulas/                     # 配方记录route + service + repository + test
│       │   ├── color/                        # 颜色引擎(推荐/匹配/保存)
│       │   ├── ai/                           # AI 推演(预测/探索/提取/搜索, SSE 流)
│       │   ├── projects/                     # 项目管理
│       │   ├── config/                       # 配置管理AI Key/admin only
│       │   └── health/                       # 健康检查live/ready + /metrics
│       └── generated/                        # Prisma 自动生成
│
├── frontend/                                 # 前端React 19 + Vite 8 + TypeScript
│   ├── Dockerfile
│   ├── package.json
│   ├── vite.config.ts
│   ├── vitest.config.ts
│   ├── eslint.config.js
│   ├── tsconfig.json / tsconfig.app.json / tsconfig.node.json
│   ├── index.html
│   ├── nginx.conf                            # 生产 Nginx 配置
│   ├── scripts/
│   │   └── generate-types.ts                 # OpenAPI → TypeScript 类型生成
│   └── src/
│       ├── main.tsx                          # ★ 入口ToastProvider + QueryClient + Router
│       ├── App.tsx
│       ├── router.tsx                        # React Router v7 配置
│       ├── index.css                         # Tailwind CSS 4 入口
│       ├── lib/
│       │   ├── api.ts                        # apiFetch 封装 + Auth header
│       │   ├── queryClient.ts                # TanStack Query 配置
│       │   └── color/                        # 色彩科学工具
│       │       ├── convert.ts                # 色空间转换Lab/Hex/RGB/LCH/P3
│       │       ├── deltaE.ts                 # ΔE 2000/CMC/76 计算
│       │       ├── types.ts                  # 颜色类型定义
│       │       └── color.test.ts             # 颜色工具测试
│       ├── shared/                           # ★ 共享 UI 基建
│       │   ├── components/
│       │   │   ├── Toast.tsx                 # Toast 通知系统Provider + Hook
│       │   │   ├── Skeleton.tsx              # 骨架屏(单行/多行/页面级)
│       │   │   └── Alert.tsx                 # 警告提示4 种变体)
│       │   └── services/
│       │       └── api.ts                    # 统一 API 客户端(带 Auth Token
│       ├── modules/                          # 前端模块
│       │   └── formulas/
│       │       └── formulas.service.ts       # 配方 Service 层TanStack Query 就绪)
│       ├── pages/                            # 页面组件14 个)
│       │   ├── DashboardPage.tsx             # 仪表盘
│       │   ├── FormulaListPage.tsx           # 配方列表
│       │   ├── FormulaDetailPage.tsx         # 配方详情(含可视化编辑器)
│       │   ├── FormulaEditorPage.tsx         # 配方编辑器
│       │   ├── FormulaExplorerPage.tsx       # 配方推演
│       │   ├── VersionHistoryPage.tsx        # 版本历史
│       │   ├── VersionComparePage.tsx        # 版本对比
│       │   ├── ColorLabPage.tsx              # 颜色实验室
│       │   ├── IngredientsPage.tsx           # 成分目录
│       │   ├── ProjectsPage.tsx              # 项目管理
│       │   ├── SettingsPage.tsx              # 设置(外观 + AI 配置)
│       │   ├── SearchPage.tsx                # AI 搜索
│       │   ├── LoginPage.tsx                 # 登录
│       │   └── RegisterPage.tsx              # 注册
│       ├── components/                       # 共享组件
│       │   ├── AuthGuard.tsx                 # 路由守卫
│       │   ├── ErrorBoundary.tsx             # 错误边界
│       │   ├── ColorWheel.tsx                # 色轮 Canvas
│       │   ├── EyedropperPanel.tsx           # 取色棒
│       │   ├── ColorRecommendPanel.tsx        # AI 配色推荐弹窗
│       │   └── FormulaVisualEditor.tsx       # 配方可视化编辑器
│       ├── layouts/
│       │   └── AppLayout.tsx                 # 主布局(侧栏 + 顶栏)
│       ├── hooks/
│       │   └── useAIPredict.ts               # AI 预测 Hook
│       └── stores/
│           ├── authStore.ts                  # 认证状态Zustand
│           └── themeStore.ts                 # 主题状态Zustand
│
├── docker/
│   └── Dockerfile.pgvector                   # PostgreSQL + pgvector 镜像
├── docker-compose.yml                        # 开发环境PostgreSQL + MinIO[可选]
├── docker-compose.prod.yml                   # 生产环境Traefik + PostgreSQL + Backend + Frontend
└── scripts/
    ├── backup-db.sh                          # pg_dump 备份脚本7 天留存)
    └── init-db.sh                            # 数据库初始化

3. 架构全景

3.1 后端:四层模块化

HTTP Request
    │
    ▼
┌──────────────────────────────────────────────┐
│  app.ts (Fastify)                            │
│  ├── Helmet + CORS + RateLimit               │
│  ├── global preHandler: JWT verify           │
│  ├── global setErrorHandler: AppError → HTTP │
│  └── /docs (Swagger UI) + /api/* routes      │
└────────────┬─────────────────────────────────┘
             │
    ┌────────▼────────┐
    │  Route Layer    │  ← 参数提取 (req → 纯数据) + Zod 校验
    │  *.route.ts      │     preHandler: requireRole() / requireFormulaOwnership()
    └────────┬────────┘
             │
    ┌────────▼────────┐
    │  Service Layer  │  ← 纯业务逻辑 + 审计埋点 + 百分比验证
    │  *.service.ts    │     依赖 Repository + AuditService
    └────────┬────────┘
             │
    ┌────────▼────────┐
    │  Repository     │  ← Prisma 查询封装 + 事务管理
    │  Layer          │     每个模块独立 Repository
    │  *.repository.ts│
    └────────┬────────┘
             │
    ┌────────▼────────┐
    │  Prisma ORM     │
    │  PostgreSQL     │
    │  + pgvector     │
    └─────────────────┘

3.2 横切关注点注入矩阵

关注点 注入方式 注入位置
请求 ID genReqId: () => randomUUID() app.ts 构造
认证 addHook('preHandler') → verifyToken → set userId app.ts 全局
授权 { preHandler: [requireRole(), requireFormulaOwnership()] } Route 注册
输入校验 validateOrReply(zodSchema, data, reply) Route handler
错误处理 setErrorHandler(error, request, reply) → AppError 子类匹配 app.ts 全局
结构化日志 request.log.child({ requestId }) app.ts onRequest
审计日志 auditService.log({ action, resource, userId }) Service 层显式调
API 文档 @fastify/swagger + routeSchema() Route 注册
Prometheus app_errors_total.inc() / /api/metrics 端点 全局 handler + health 模块
HTTP 安全 @fastify/helmet + @fastify/rate-limit app.ts 插件注册

3.3 前端:渐进式分层

React Router
    │
    ▼
┌──────────────────────────┐
│  Page 组件               │  ← UI 渲染 + 调用 Hooks
│  (pages/)                │
└────────────┬─────────────┘
             │
    ┌────────▼────────────┐
    │  Hooks               │  ← useQuery / useMutation (TanStack Query)
    │  + 页面级 State      │     useReducer / useState
    └────────┬────────────┘
             │
    ┌────────▼────────────┐
    │  Service 层          │  ← API 调用封装 (apiFetch)
    │  (modules/*.service) │     类型安全的请求/响应
    └────────┬────────────┘
             │
    ┌────────▼────────────┐
    │  共享 UI 基建        │
    │  - ToastProvider     │
    │  - Skeleton          │
    │  - Alert             │
    │  - ErrorBoundary     │
    └──────────────────────┘

"当前状态:后端四层已全部落地,前端仅 formulaService 完成模板,其余 page 仍使用 apiFetch 直调。这是待完成的迁移动脉。"


4. 数据模型

User ────1:N──→ Formula ────1:N──→ FormulaVersion ────1:N──→ Phase
  │                │                     │                        │
  │                │                     │                  1:N   │
  │                │                     │                 FormulaIngredient ────N:1──→ Ingredient
  │                │                     │
  │           1:N  │                1:N  │
  ├─────→ ColorFormula           Phase (via formulaId on Phase)
  │
  └─────→ Project ────1:N──→ Formula
核心字段 说明
users username(unique), passwordHash(scrypt), role(engineer/admin) 用户
projects name, description, createdBy 项目
formulas name, description, currentVersion, projectId, embedding(vector) 配方
formula_versions formulaId, versionNumber(unique pair), snapshotData(JSON), createdBy 版本快照
phases name, formulaId(→FormulaVersion), sortOrder 工艺阶段
formula_ingredients formulaVersionId, phaseId, ingredientId, percentage, processNotes 成分关联
ingredients inciName, chineseName, functionCategory(12枚举), supplier, unitPrice 原料
color_formulas name, targetLab(JSON), actualLab(JSON), deltaE, colorantComposition(JSON) 颜色配方
ai_audit_logs capability, modelName, promptHash, tokensUsed, durationMs AI 调用审计

5. 安全架构

5.1 认证流程

POST /api/auth/register
  用户名 + 密码 → scrypt 异步哈希 → 存入 users.passwordHash
  返回 JWT Token (HS256, 24h)

POST /api/auth/login
  用户名 + 密码 → scrypt 异步比对 (timingSafeEqual)
  返回 JWT Token

每个业务请求:
  Authorization: Bearer <token>
    → preHandler: 解码验证 → 查 DB 确认用户存在 → set request.userId

5.2 授权矩阵

操作 admin engineer
管理 AI 配置
增删改成份目录
创建配方
编辑/删除自己的配方
编辑/删除他人的配方
颜色引擎 / AI 推演
管理项目

5.3 安全层

工具 作用
HTTP 头 @fastify/helmet CSP/HSTS/X-Frame 等安全头
CORS @fastify/cors 仅允许 localhost:5173
速率限制 @fastify/rate-limit 全局 100 req/min
密码 scrypt(salt=16, output=64) + timingSafeEqual 抗彩虹表 + 防时序攻击
Token JWT HMAC-SHA256 (HS256) 正确实现,非 SHA256 裸哈希
API Key runtime/config.json 服务器端存储 不从 localStorage 传输

6. 可观测性

6.1 健康探针

端点 用途 实现
/api/health 基础存活 返回 timestamp
/api/health/live K8s liveness SELECT 1 检测 DB 连接,失败 503
/api/health/ready K8s readiness SIGTERM 后返回 503
/api/metrics Prometheus scrape 5 个指标

6.2 Prometheus 指标

指标 类型 标签
http_requests_total Counter method, path, status
http_request_duration_ms Histogram method, path
app_errors_total Counter category, module, code
ai_requests_total Counter capability, provider, status
ai_request_duration_ms Histogram capability

6.3 日志

  • 框架: pino结构化 JSON
  • 上下文: 每个请求自动注入 requestId
  • 审计: auditService.log(){ audit: true, action, resource, resourceId, userId }
  • 格式: 开发 pino-pretty,生产纯 JSON → Loki/ELK

7. 部署架构

7.1 开发环境

docker compose up          # PostgreSQL (pgvector)
pnpm dev                   # backend (3001) + frontend (5173)

MinIO 可选:docker compose --profile full up

7.2 生产环境

┌────────────────────────────────────────────┐
│  Traefik (80/443)                          │
│  ├── /api/*  → backend:3001               │
│  └── /*      → frontend:80                │
├────────────────────────────────────────────┤
│  Backend (Fastify, port 3001)              │
│  ├── /api/* 业务路由                       │
│  ├── /docs   Swagger UI                   │
│  ├── /api/health/live  liveness probe     │
│  ├── /api/health/ready  readiness probe   │
│  └── /api/metrics  Prometheus scrape      │
├────────────────────────────────────────────┤
│  Frontend (Nginx, port 80)                │
│  ├── SPA static files                     │
│  └── /api/* → backend proxy              │
├────────────────────────────────────────────┤
│  PostgreSQL (pgvector)                     │
└────────────────────────────────────────────┘
docker compose -f docker-compose.prod.yml up -d

7.3 备份

# 手动备份
./scripts/backup-db.sh

# crontab 每日备份
0 2 * * * /opt/colorfull/scripts/backup-db.sh >> /var/log/colorfull-backup.log 2>&1

8. 质量保障

8.1 TypeScript 严格度

开关 后端 前端
strict: true
noUncheckedIndexedAccess
noUnusedLocals
noUnusedParameters
skipLibCheck

8.2 代码规范

工具 后端 前端
ESLint ✓ (typescript-eslint)
Prettier ✓ (semi=false, singleQuote, trailingComma=all)
状态 lint 零错误

8.3 测试

后端 前端
单元测试 待补Service 层) lib/color/color.test.ts(色空间转换)
集成测试 ingredients.test.ts + formulas.test.ts26 用例) 待补React Testing Library
E2E 待补Playwright
运行 pnpm test (vitest) pnpm test (vitest)

8.4 命令速查

# 后端
cd backend
pnpm dev               # 启动开发服务器 (tsx watch)
pnpm build             # TypeScript 编译
pnpm test              # 运行 26 个集成测试
pnpm lint              # ESLint 检查
pnpm format            # Prettier 格式化
pnpm db:migrate        # 数据库迁移
pnpm db:seed           # 种子数据
pnpm api:gen           # 生成 OpenAPI spec

# 前端
cd frontend
pnpm dev               # 启动 Vite 开发服务器
pnpm build             # 生产构建
pnpm lint              # ESLint
pnpm api:gen           # 从 OpenAPI spec 生成 TypeScript 类型

9. API 速览

模块 端点 方法 认证 说明
health /api/health GET 基础存活
health /api/health/live GET DB 检查
health /api/health/ready GET 就绪检查
health /api/metrics GET Prometheus
auth /api/auth/register POST 注册
auth /api/auth/login POST 登录
auth /api/auth/me GET 当前用户
ingredients /api/ingredients GET/POST 列表/创建
ingredients /api/ingredients/:id GET/PUT/DEL 详情/更新/删除
formulas /api/formulas GET/POST 列表/创建
formulas /api/formulas/:id GET/PUT/DEL 详情/更新/删除
formulas /api/formulas/:id/composition PUT 更新成分(新版本)
color /api/color/recommend POST AI 配色推荐
color /api/color/formulas/match GET 颜色配方匹配
color /api/color/formulas POST 保存颜色配方
ai /api/ai/predict-formula POST 预测指标(SSE)
ai /api/ai/explore-formula POST 配方推演(SSE)
ai /api/ai/extract-formula POST 提取配方文本
ai /api/ai/search GET NL 搜索
projects /api/projects GET/POST 列表/创建
projects /api/projects/:id PUT/DEL 更新/删除
config /api/config GET/PUT 查看/更新配置(admin)
config /api/config/test POST 测试 AI 连接(admin)

10. 待完成清单

优先级 项目 状态
P1 前端页面逐批迁移到 Service 层 + TanStack Query 仅 formulaService 完成
P1 前端集成 shadcn/ui 组件(替换手动创建的 Toast/Skeleton/Alert Tailwind 4 兼容性问题待解决
P2 后端 Service 层单元测试mock Repository 待开始
P2 后端 Testcontainers 集成测试框架 待开始
P2 Playwright E2E 关键流程测试 待开始
P2 Husky pre-commit hooks后端 + 前端) 待配置
P3 CI/CD 流水线GitHub Actions / GitLab CI 待配置
P3 前端 OpenAPI 类型生成流水线验证 脚本已就绪,待端到端跑通
P3 Admin 用户管理 UI 直接操作 DB

11. 相关文档索引

文档 路径 内容
领域词汇 CONTEXT.md 纯业务术语定义
技术栈 ADR docs/adr/0001-architecture-stack.md 为什么选 React/Fastify/Prisma 等
AI 策略 ADR docs/adr/0002-ai-api-strategy.md 为什么用外部 LLM API
架构 ADR docs/adr/0003-four-layer-module-architecture.md 为什么四层模块化
授权 ADR docs/adr/0004-rbac-ownership-authorization.md 为什么 RBAC + Ownership
API 文档 docs/api-reference.md 29 个接口完整说明
PRD .scratch/formula-rd-platform/PRD.md 产品需求