Files
lingxi/docs/评估/_调研/sucaigongfang-调研报告.md
T
Stev_Wang 6096568621 docs: 新增双项目整合评估、调研报告与技术栈架构定稿
- 新增双项目整合可行性评估 V0.1 rev.2:覆盖度矩阵、方案对比、目标架构、工作量/TCO、风险与决策清单
- 新增 dewu/sucaigongfang 两份调研报告(内部资料,平台敏感值已脱敏)
- 新增技术栈与架构定稿 V1.0:Node 24.15.0 / pnpm 11.4.0 / Prisma 7.10.1 / PostgreSQL 18 / Redis 7
- 更新 README 文档索引与仓库结构
2026-10-30 14:13:00 +08:00

82 KiB
Raw Blame History

sucaigongfang 调研报告

调研对象:参考项目/sucaigongfang/(「素材工坊」图片素材自动化生产系统,v1.0.0,git main @ d1b01fa,2026-09-26) 调研方式:只读代码勘察 + 文档比对,以代码为准。未执行 pnpm install / 构建 / 迁移 / 长任务。 对照文档:docs/PRD/平台电商素材生产平台_PRD_V0.1.md 的 1.1(P-01~P-07)与 1.2(功能框架)。 口径约定:LOC/文件数均不含 node_modules、dist、.cache、.npm-cache、uploads 内二进制。


0. 结论速览

一句话定位:素材工坊是一套面向信息流广告投放(电商唤端 + 券商)的图片素材批量生产线——设计师上传 PSD 模板、优化师上传商品图并填写字段,系统按「模板 × 商品图」交叉批量合成图片,自动命名、打包、通知,并配套完整的账号/权限/客户/配置/任务治理体系。

架构形态:pnpm workspace 双包。后端 Express 5 + Sequelize 6 + PostgreSQL + Redis/BullMQ + ag-psd/@napi-rs/canvas/sharp/fontkit 渲染 + @imgly/background-removal-node(ONNX) 抠图 + ws 实时推送;前端 React 19 + Arco Design + Tailwind 4 + zustand + axios + react-router 7 + Vite 8。API 与 BullMQ Worker 同进程(backend/src/app.ts:65-66、app.ts:402),单容器部署,文件存储为本地磁盘(backend/uploads,854MB/775 文件在本机副本)。

成熟度:

维度 结论 证据
版本/形态 v1.0.0,可部署的生产态(容器化 + 1Panel 反代 + 回滚脚本) package.json:1-3、deploy/docker-compose.yml:1-40、deploy/deploy.sh:1-30
提交活跃度 249 commits,2026-03-23 → 2026-09-26;3 月 85 / 4 月 33 / 9 月 131(5–8 月空档) git log --format='%ad' --date=format:'%Y-%m'
代码规模 后端 src 30,835 行 / 137 文件;前端 src 32,797 行 / 74 文件;测试 2,078 行 见 §6 口径命令
测试 node:test 175 个用例 / 14 文件,全部纯函数,无 DB/HTTP 集成测试、无 E2E backend/tests/*.test.ts、package.json:24
质量门禁 本地 CI 6 步硬卡:prettier/eslint/单测/前端设计 token 静态校验/tsc/构建 deploy/ci-local.sh:24-45
部署 前后端双镜像 + host/bridge 网络 + Node 24-slim + nginx 反代 /api /uploads /ws backend/Dockerfile、frontend/Dockerfile、frontend/nginx.conf.template:20-40
文档 docs/ 33 篇 md + 4 份方舟 PDF,但 docs/ 整个目录被 .gitignore 忽略(110 个文件 0 入库) .gitignore:122、git ls-files docs = 0

结论表(能力域 → 复用结论)

能力域 复用结论 关键原因 粗估人日
后端工程地基(Express/Sequelize/PG/迁移/日志/健康检查) 直接复用 结构规整;umzug 迁移已落地;日志/健康检查/进程兜底齐全 3–5
认证与账号安全(JWT/强制改密/口令策略/登录限流/口令审计) 直接复用 服务端强制、令牌版本失效、一次性随机口令,安全设计超标 2–3
RBAC 角色权限 + 客户级数据范围 直接复用 权限 key 目录 + fail-closed 客户范围双层 3–4
系统配置框架(40 项 / 10 模块 / L1-L3 / 审计 / 专用控件) 直接复用 声明式注册表,是「加配置不写迁移」的成熟范式 3–5
模板/分类/标签/规格管理 改造复用 结构可留,需加平台维度与 Logo/促销/展示方式资产 8–10
PSD 解析与渲染引擎 改造复用 核心资产(1773 行合成器),但只支持单一商品图入参 12–18
抠图(白底判定 + ONNX + 降级告警) 直接复用 失败会标 low_quality_warning,不静默交付 2–3
批量任务/队列/进度/暂停恢复取消重试/收尾 直接复用 BullMQ + DB 计数 + WS 推送 + 失败口径分轮次,工程细节成熟 6–8
命名规则引擎(变量模板/客户级/批次快照) 直接复用 变量域与 PRD「自定义字段组合」高度一致 3–4
导出 / ZIP 打包 / 下载 直接复用 CSV 导出 + BullMQ 异步打包 + 选集下载 3–4
通知 / 站内信 / WebSocket 改造复用 通知模板可配;缺独立通知中心页(仅文档) 3–4
任务事件 / 失败目录 / 时间线 / 任务日志 直接复用 事件目录 + 失败目录 + 90 天保留期,是统一平台的可观测底座 3–4
文件存储 / 缩略图 / 清理 改造复用 纯本地磁盘、无 OSS,需加存储适配层 4–6
前端设计体系 / 布局 / 守卫 / 共享组件 改造复用 token 单点 + 自动校验;但菜单与权限映射硬编码 5–7
素材制作页(2625 行) 服务端重写 需按「平台 → 选品 → 展示方式/Logo/促销」重构 10–15
首页 Dashboard 服务端重写 指标口径(单套成本/模板占比/提审通过率)全部变化 3–5
AI 生图 服务端重写 仅验证到 M2-0,无产品代码;分支实现已声明作废 20–30
数据字典 / 枚举 服务端重写 仅文档;分支实现未合并且已停用 3–4
多平台 / 平台切换 新建 系统内没有平台概念(得物仅作示例客户名) 5–8
选品 / 原始物料获取 新建(另一项目迁移) 该能力在 dewu-material-Downloader(Electron),本系统无爬取代码 15–25
视频素材 AI 生产 新建 完全空白,无 ffmpeg/视频依赖 40+
提审 新建 完全空白 8–12
投放配置(DP/承接页) 新建 完全空白 8–12

粗估口径:按「熟悉本仓库的 1 名全栈 + 1 名前端」并行估算,仅作量级参考,需与研发负责人校准。可复用/改造部分合计约 60–85 人日;加上制作页与首页重写(13–20 人日),图片产线地基落地约 75–105 人日;再叠加 AI 生图(20–30)、多平台(5–8)、数据字典(3–4)、选品抓取(15–25)、提审(8–12)、投放配置(8–12)≈ 134–196 人日,计入约 20% 的联调/迁移余量后,统一平台 MVP(不含视频深水区)总量级约 165–235 人日。


1. 项目定位与业务链路

1.1 解决什么问题、给谁用

原 PRD 写得很直白:信息流优化师在电商 APP 唤端项目中面临素材产能不足,需要「设计师上传 PSD 模板 → 优化师一键替换产品图生成素材 → 支持批量」(docs/PRD.md:5-14)。用户角色只有三类:管理员 / 设计师 / 优化师(docs/PRD.md:16-22、docs/用户使用手册.md:38-44)。

因此本系统的真实定位是:

  • 面向「素材生产」而不是「素材投放」:产出到「按命名规则落盘 + ZIP 打包下载」为止,不涉及账户搭建、DP、承接页、提审。
  • 单客户 = 单个广告主/品牌方(如「得物」「华泰证券」):clients 表是业务归属维度,不是多租户(同一套部署、同一个库,靠 user_clients + created_by 做数据范围收敛)。
  • 设计师与优化师的协作边界被固化成「模板」:模板承载图层契约,优化师只填字段和传商品图。

补充一个容易被忽略的事实:本系统同时服务电商(得物)与券商(华泰证券等)两个行业,AI 方向的全部验证文档都以券商素材为样本(免责声明、收益暗示、合规红线)。这与本次新 PRD 只聚焦「平台电商(得物/唯品会)」不同——行业假设不一致,AI 侧结论不能整体平移。

1.2 主链路(代码实证)

① 管理员:建客户 → 建用户并绑定客户/角色 →(可选)配置客户级命名规则
② 设计师:上传 PSD → 系统解析图层(ag-psd)→ 逐图层绑定「图片替换/文本替换/剪贴蒙版」
          → 预览图生成 → 归属客户/分类/标签/规格
③ 优化师:素材制作页选模板(可多选)→ 上传商品图(≤100 张)→ 按文件名识别商品ID/名称/品牌
          → 表格可编辑 → 选生产参数(抠图/尺寸限制/JPG/缩放/字号)→ 二次确认提交
④ 系统:建批次(N 模板 × M 商品图 交叉)→ 写命名快照 + 预渲染文件名 → 入 BullMQ
⑤ Worker:白底图自动抠图 → MaterialComposer 合成 → 写 materials → 更新批次统计 → WS 推送
⑥ 收尾:批次完成 → 站内信通知 → 自动/手动触发 ZIP 打包 → 下载交付
⑦ 管理:任务列表 / 任务详情抽屉 / 时间线 / 任务日志(跨用户只读)/ CSV 导出

主链路的关键代码:productionBatchController.ts:646(建批次)、workers.ts:70-412(素材 Worker)、materialComposer.ts:143(合成入口)、workers.ts:764(ZIP Worker)。

1.3 与 PRD 1.1 的问题对应关系(P-01~P-07)

编号 PRD 问题 本系统覆盖度 说明
P-01 原始物料:详情页图片人工下载、分散存放 ❌ 0 无选品/抓取/物料库;商品图靠本地上传。该能力在另一个参考项目 dewu-material-Downloader(Electron 桌面端)
P-02 图片制作:三规格 × 四层信息全靠人工排版 🟡 部分覆盖 已覆盖「基础框架模板 + 商品展示(单图)+ 产品信息(文本层)」,但缺 AI 模特/脚模、Logo 组合、促销信息叠加;规格是通用 (w,h) 实体,非固定的三档
P-03 视频制作依赖实拍与个人经验 ❌ 0 全仓库无视频/ffmpeg 依赖与代码
P-04 命名提审:手工改名、进度散落 🟡 命名全覆盖、提审 0 命名引擎(变量模板 + 客户级 + 快照 + 重试同名)非常成熟;无提审清单/状态机
P-05 账户搭建:DP、承接页逐条复制 ❌ 0 无任何 DP/承接页/链接配置能力
P-06 多平台:资源与口径不统一 ❌ 0 系统无「平台」维度;得物 只出现在通知模板的示例文案里(utils/notificationTemplates.ts:97)
P-07 资产管理:模板、脚本散落 🟡 模板资产强、其余缺 模板/分类/标签/规格/批次模板完整;Logo(仅标签 logo 字段,未进合成)、展示方式、脚本无

覆盖率小结:PRD 七类问题里,本系统实质回答的是 P-02(约一半)+ P-04(一半)+ P-07(约一半),其余四类需要新建或从另一项目迁移。


2. 功能模块清单(全量)

逐项核对方式:以 backend/src/app.ts:147-164 的 17 个 *Routes 挂载 + frontend/src/App.tsx:100-120 的路由表为准,辅以 routes/*.ts 内逐条 router.<verb>。 接口规模:约 113 个业务接口(按 routes/*.ts 的 router.get/post/put/delete 计数)+ /api/health + /api/queue-health + /uploads 静态 + /ws。

模块 前端路由 / 页面 后端 API 前缀 核心功能点 实现状态 关键文件:行
登录与账号安全 /login、/first-login-password /api/auth JWT 登录、IP+用户名双维限流、首次登录强制改密、口令有效期三态策略、改密后旧令牌立即失效 完整 routes/authRoutes.ts:14-28、middlewares/auth.ts:18-32、utils/passwordPolicy.ts
用户管理 /system/users /api/users CRUD、重置密码(一次性随机口令仅显示一次)、角色分配、口令审计、最近登录、密码状态 完整 routes/userRoutes.ts:16-33、controllers/userController.ts
角色与权限 /system/roles /api/roles 角色 CRUD、权限勾选、启用/禁用、isAdmin 超管;前端菜单+路由双守卫 完整 utils/permissions.ts:4-20、components/PermissionGuard.tsx:8-21、AdminLayout.tsx:85-98
客户与数据范围 /system/clients /api/clients 客户 CRUD、用户↔客户多对多绑定、client_scope_mode 受限模式、客户级命名规则 Tab 完整 models/Client.ts:79、models/UserClient.ts、utils/clientScopeCore.ts:12-22
模板分类 /templates/categories /api/categories 树形分类(父子自关联)、客户归属、CRUD 完整 routes/categoryRoutes.ts:19-24、models/TemplateCategory.ts:81
模板标签 /templates/tags /api/tags 标签 CRUD、颜色、客户归属、logo 上传(后端有接口,前端未接线) BETA routes/tagRoutes.ts:20-25、controllers/tagController.ts:21-37
规格管理 /templates/specifications /api/specifications 规格 CRUD;名称由 (w,h) 派生(横版 1280×720),唯一性从名称迁到尺寸 完整 utils/specificationName.ts:46-57、migrations/20260924000001-specification-name-derivation.ts
模板管理 /templates/list、/upload、/:id/edit /api/templates PSD 上传/解析/预览、图层绑定、按客户字段池自动匹配、复制模板、批量删除/改分类/加标签、字体列表 完整 routes/templateRoutes.ts:17-50、controllers/templateController.ts:178
素材制作(核心页) /material-maker /api/materials/*、/api/batches/* 模板筛选/搜索/最近使用/批次模板、商品图批量上传与文件名识别、字段表格可编辑、生产参数、提交前二次确认、悬停预览 完整 pages/Production.tsx:207-364、productionBatchRoutes.ts:12-66
生产任务列表 /tasks /api/batches 卡片/表格双视图、状态页签与 facet 计数、详情抽屉、暂停/恢复/取消/重试/补跑失败项/重置卡死、选集下载、批量操作 完整 pages/Tasks.tsx:467-700、components/BatchDetailDrawer.tsx
批次模板(组合) 制作页内保存/选用 /api/batch-templates 把「多模板组合」存为可复用快捷模板,支持私有/共享、客户归属 完整 routes/batchTemplateRoutes.ts:12-24、controllers/batchTemplateController.ts:16
任务日志(管理端) /system/task-logs /api/admin/batches 跨用户只读看板、事件流/时间线、失败分类、CSV 导出、执行人筛选 完整 routes/taskLogRoutes.ts:28-49、components/TaskLogBoard.tsx
命名规则 客户弹窗「命名规则」Tab、制作页识别列 /api/naming 商品图识别模板、字段/别名/必填/可编辑、素材命名模板、ZIP 命名模板、实时预览与校验 完整 utils/namingConfig.ts:240-328、components/NamingConfigEditor.tsx
导出 / 打包 / 下载 /tasks 内按钮 /api/batches/export、/:id/tasks/download、/:id/package-zip CSV 导出(BOM 防乱码、上限 1 万条)、选中子任务 ZIP、整批 ZIP(BullMQ 异步 + 状态机) 完整 productionBatchController.ts:1249、:2005、:2269、workers.ts:764
通知(站内信) 顶栏铃铛下拉 /api/notifications 列表/未读数/标记已读/全读/删除;三类触发(批次完成/失败/ZIP 就绪);标题与内容模板可在系统配置里改 完整(无独立页面) routes/notificationRoutes.ts:8-20、AdminLayout.tsx:126-133、utils/notificationTemplates.ts:130
通知中心独立页 — — 需求文档中的独立页面:筛选、批量已读/清空、下载关联 仅文档 docs/通知中心页面需求.md:1-80
首页 Dashboard / /api/stats/dashboard 5 张指标卡(模板数量 / 素材生产量 / 生产任务量 / 模板使用率 / 失败率,统一「本周 vs 上周」环比)、今日任务、待我处理(失败/暂停/进行中)、最近任务、快捷入口 完整 pages/Home.tsx:60-140、:367-443、controllers/statsController.ts:52-80
系统配置 /system/config /api/system/configs 10 模块 40 项配置、L1/L2/L3 生效级别、类型与范围校验、审计留痕、两个专用控件(命名规则/通知模板)、运行环境只读面板 完整 utils/systemConfigRegistry.ts:192、controllers/systemConfigController.ts、pages/SystemConfig.tsx
存储管理 / 清理 系统配置 → 存储 /api/system/storage 分类用量统计、先预览后清理、默认只删孤儿文件、保护模板资产、定时清理(默认关) 完整 utils/storageCleanup.ts:18-40、utils/storageCleanupScheduler.ts
文件服务 /uploads/* — JWT 鉴权(header 或 ?token=)、按需缩略图 ?w=320/640 落盘缓存、失败回退原图 完整 app.ts:139-144、middlewares/uploadAuth.ts、middlewares/uploadThumbnail.ts:9
实时进度 /ws?token= WS /ws 批次整行快照推送、300ms 按批次节流、心跳、鉴权失败码 4401、前端降级轮询 完整 utils/realtime.ts:31-40、hooks/useRealtimeBatches.ts
素材历史记录 —(history 路由被注释) /api/materials 分页查询、详情、重生成(复用生产链路入队) BETA:后端就绪,前端未接线 App.tsx:118-120、materialRoutes.ts:28-34
数据字典 / 枚举 — — 「字典类型 → 字典项」两层、系统管理入口、code/label 分离、供 AI 提示词消费 仅文档(分支 backup/ai-asset-m1 有 625 行后端 + 999 行前端实现,未合并) docs/数据字典与枚举管理评估.md:1-40、分支 controllers/dictionaryController.ts
合规词库 / 免责声明校验 — — 禁用词扫描、免责声明逐字比对、AI 成品复核闸门 仅文档/分支(未合并) 分支 controllers/complianceController.ts、utils/disclaimerCheck.ts
AI 生图(M2 路线) — — 9 要素表单 → 提示词合成 → Seedream 出图 → 程序保证免责声明/logo → VLM 文字逐字校验 → 挑图 仅验证(M2-0),无产品代码 tools/ai-image-validation/README.md:3、docs/AI生图-M2-0验证记录.md:8-11
AI 素材生成(M1 路线) —(分支) —(分支 /api/ai/*) 图片模板上传 → VLM 反推 → 人工框选绑定 → 冻结契约 → SchemaRenderer 出图 + AI 底图 实验/已作废:53 commits、约 3.1 万行新代码,但最新方案明确「整体作废,不参考、不复用」 git log backup/ai-asset-m1、docs/AI生图相关功能-实现方案.md:6
视频素材 — — — 不存在 —
提审 — — — 不存在 —
投放配置(DP/承接页) — — — 不存在 —
多平台切换 — — — 不存在 —
队列/依赖健康检查 — /api/health、/api/queue-health DB/Redis 真实探活(失败 503)、队列积压/Worker 状态/WS 在线数/清理状态 完整 app.ts:175-237

说明:「历史上传记录」与「生产任务列表」是两件事。生产记录(批次)已完整实现(/tasks);素材级历史(materials 表)只有 API、没有页面,history 路由在 App.tsx:118-120 被注释为「等待迁移」。


3. 技术栈与架构

3.1 版本清单(以 package.json 实际声明为准)

层 技术 版本 备注
后端运行时 Node.js 24(.nvmrc) 镜像 node:24-slim
Web 框架 Express ^5.2.1 5.x,路由级中间件
ORM / DB Sequelize / pg ^6.37.8 / ^8.20.0 PostgreSQL 18(生产由 1Panel 管理)
迁移 umzug + SequelizeStorage ^3.8.3 账本表 SequelizeMeta(utils/migrator.ts:26)
队列 BullMQ / ioredis ^5.71.0 / ^5.10.1 2 个队列:material-generation、zip-packaging;项目级键前缀 sucaigongfang
PSD 解析 ag-psd ^30.1.0 initializeCanvas 接 @napi-rs/canvas
画布 / 图像 @napi-rs/canvas / sharp ^0.1.97 / 0.32.6(锁定) sharp 锁版本,PNG 量化行为依赖该版本
字体 fontkit ^2.0.4 读字体名 + GlobalFonts 注册
抠图 @imgly/background-removal-node ^1.4.5 内含 onnxruntime-node(medium 模型)
上传 multer ^2.1.1 按请求构造实例以支持热改限制(utils/configurableUpload.ts)
打包 archiver ^7.0.1 ZIP level 9
实时 ws ^8.21.3 复用同一 http.Server
鉴权 jsonwebtoken / bcrypt ^9.0.3 / ^6.0.0 JWT 带口令版本号 pwdv
前端框架 React / react-router-dom ^19.2.4 / ^7.13.1 路由级 lazy 分包
UI @arco-design/web-react ^2.66.12 全站指定 Arco + 自定义 token 层
样式 Tailwind CSS / tw-animate-css ^4.2.2 / ^1.4.0 Tailwind 4 + styles/ token 双轨
状态 zustand ^5.0.12 只有 2 个 store(auth / appConfig)
HTTP axios ^1.13.6 单一 services/api.ts(1223 行,113 个方法)
图表 recharts ^3.8.1 首页趋势
图标 lucide-react ^1.7.0 全站图标
构建 Vite / TypeScript ^8.0.1 / ~5.9.3 前端 tsc -b && vite build

依赖证据:backend/package.json:29-47、frontend/package.json:20-45。

3.2 架构分层与请求链路

┌──────────────────────────── 浏览器(React 19 SPA)────────────────────────────┐
│ pages(16) ─ components(24) ─ services/api.ts(113 方法) ─ zustand(auth/appConfig) │
│ styles/tokens.ts(字号/颜色) + theme.ts(Arco ConfigProvider) + Tailwind 4          │
└───────────────┬───────────────────────────────────────────────┬─────────────────┘
                │ /api/*  (nginx → backend:8300)                 │ /ws?token=  /uploads?w=
┌───────────────▼───────────────────────────────────────────────▼─────────────────┐
│ Express 5 (单进程,API + Worker 同进程)                                          │
│ 中间件链: 请求日志 → CORS 白名单 → body → normalizeQuery → /uploads(鉴权+缩略图+static) │
│           → 17 个 Router(登录校验在 router 内;10 个涉及客户数据的再挂 attachClientScope)│
│ 兜底: multer 错误 → JSON 400;uncaughtException → exit(1) 交给容器重启             │
│ 业务: controllers(17, 9.7k 行) → utils(55, 14.2k 行) → models(20, 2.7k 行)        │
│ 异步: BullMQ(material 2 并发 / zip 1 并发,可页面热调 L3) ──► workers(43.8k 行)     │
│ 实时: realtime.ts 进程内 pub(批内 300ms 节流)──► ws 推送                          │
│ 观测: taskEvents(事件目录) / failureCatalog(失败目录) / taskMonitor(超时卡住巡检)     │
└───────┬──────────────────────┬───────────────────────┬──────────────────────────┘
        │ PostgreSQL(19 表)    │ Redis(2 队列 + 项目前缀) │ 本地磁盘 backend/uploads(~732MB)

三个关键架构决策(都可直接继承):

  1. API 与 Worker 同进程:换来「实时推送零跨进程成本 + 部署极简」,代价是无法按 CPU/内存独立扩缩容,且 uncaughtException 会同时打断 API(app.ts:64-78 注释明确承认)。
  2. ���批次节流推整行快照(realtime.ts:20-40):不做增量、不做 diff,漏收一条下一条即纠正;300ms 合并 + 发送时重读库。
  3. 配置生效级别 L1/L2/L3(systemConfigRegistry.ts:33-45):L1 请求级热生效、L2 新任务生效(批次快照)、L3 需重建运行时(由 app.ts:276-299 注册 applier)。这是统一平台最值得整套照搬的机制之一。

3.3 构建与部署

  • 镜像:后端多阶段 node:24-slim + pnpm build(backend/Dockerfile);前端 builder → nginx:1.27-alpine,构建期注入 VITE_API_BASE_URL,BUILD_INFO.txt 做制品溯源(frontend/Dockerfile:20-66)。
  • 网络:backend 用 host 网络(监听宿主 8300),frontend 用 bridge + 端口映射(3300),容器内 nginx 经 host.docker.internal 反代后端(deploy/docker-compose.yml:1-40)。
  • 反代:SPA history 回退、/api /uploads /ws 转发、WS 必须 map $http_upgrade、client_max_body_size 200M、安全响应头(frontend/nginx.conf.template:20-80)。
  • CI:deploy/ci-local.sh 6 步硬卡(格式 → lint → 单测 → 前端静态校验 → tsc → 构建),构建镜像前必须全绿。
  • 发布:build.sh(本地构建推送,linux/amd64 固定)→ deploy.sh(服务器拉镜像,先备份 DB 再部署,健康校验)→ rollback.sh。DB 备份脚本 backup-db.sh。
  • 宿主机依赖:PostgreSQL 18 / Redis 8.6.1 / OpenResty / SSL 均由 1Panel 管理,本项目不负责(deploy/docker-compose.yml:3-8)。

4. 数据模型与持久化

4.1 模型逐表清单(19 张表)

建表顺序由 utils/schemaFromModels.ts:30-56 的 MIGRATION_MODELS 固化(必须先满足外键依赖)。所有表均 underscore 列名、timestamps。

# 表名 关键字段 关系 / 用途
1 roles name, description, status(enum enabled/disabled), permissions(JSON), isAdmin, deleted_at 角色;isAdmin=true 直接映射全部权限
2 users username, password(bcrypt), role(legacy: admin/designer/optimizer), role_id, nickname, last_login_at, must_change_password, password_changed_at, password_version, client_scope_mode(all/restricted), deleted_at 账号;口令版本 + 客户范围模式都在行上
3 clients name, remark, naming_config(JSONB), deleted_at 客户(=广告主/品牌),客户级配置的载体
4 user_clients user_id, client_id 用户↔客户多对多,仅 restricted 模式生效
5 template_categories name, parent_id, customer_id 树形分类(自关联)
6 template_specifications name, width, height, orientation, description 规格;(width,height) 唯一,名称派生
7 template_tags name, color, logo_path, customer_id 标签(多值、带颜色、客户级)
8 templates name, client_id, orientation, category_id, specification_id, psd_file_path, preview_image_path, layer_config(JSON), created_by 模板主表;layer_config 是图层契约
9 template_tag_relations template_id, tag_id 模板↔标签中间表(另有 tagsFilter 别名专用于筛选,associations.ts:67-74)
10 materials template_id, product_image_path, output_image_path, product_id, material_number, output_filename, extra_fields(JSONB), created_by, batch_id, batch_task_id, status, error_message, retry_count, low_quality_warning 单张产出物;low_quality_warning 记录「抠图降级/压缩不足」
11 production_batches batch_number, task_type(single/batch), status, priority, client_id, created_by, template_ids(INT[]), total/success/failed_count, estimated/actual_duration, zip_file_path, zip_status, started_at, completed_at, auto_cutout/size_limit/force_jpg/jpg_quality/png_colours/scale_mode/font_size, naming_snapshot(JSONB) 批次;生产参数与命名规则在创建时快照(L2 语义)
12 batch_templates name, description, template_ids(INT[]), client_id, created_by, is_shared, deleted_at 模板组合快捷方式
13 batch_tasks batch_id, template_id, product_image_path, product_id, product_name, brand_name, extra_fields(JSONB), planned_filename, status(pending/processing/completed/failed), error_code, error_message, retry_count, started_at, completed_at 子任务;planned_filename 建单时预渲染(保证重试同名)
14 notifications user_id, type, title, content, batch_id, is_read 站内信
15 sequence_numbers date, current_seq 每日批次号自增(YYMMDD + 3 位)
16 system_configs config_key, config_value(JSONB), value_type, updated_by 只存「用户改过的值」,默认值在注册表
17 system_config_audits config_key, old_value, new_value, operator 配置变更审计(完整存明文,没有脱敏)
18 user_audits action, target_username, operator_name, detail 口令/账号审计(刻意不建外键,审计要比被审计者活得久)
19 task_events batch_id, batch_number, batch_task_id, level(batch/task), event_type, status_from/to, failure_code/message, detail, metadata(JSONB), actor/creator/client 快照 任务事件流;快照冗余 + 90 天保留期

关系总图由 models/associations.ts:17-236 统一定义;删除策略:batch_tasks CASCADE 于批次,notifications CASCADE 于用户、SET NULL 于批次。

4.2 迁移机制

  • umzug 迁移,不是 sequelize.sync:DBSync.sync() 启动即 runMigrations()(utils/dbSync.ts:24-40),账本 SequelizeMeta,迁移文件名去扩展名做身份(避免 ts/js 双执行,migrator.ts:56-63)。
  • 11 个迁移 / 778 行(backend/src/migrations/),全部幂等、带 down。初始迁移复用模型定义生成 DDL(schemaFromModels.createSchemaFromModels),避免模型与 DDL 两份漂移。
  • 为什么不 alter:实测开发库累积到「1112 个唯一约束 / 1154 个索引 / 18MB」,每次启动 ACCESS EXCLUSIVE 锁(utils/migrator.ts:8-23)。
  • 初始化脚本:scripts/init-admin.ts(管理员引导,口令来自 ADMIN_INITIAL_PASSWORD,无内置口令)、scripts/migrate.ts(migrate/status/baseline/rollback)、scripts/backfill-password-flags.ts、scripts/clean-data.ts、scripts/clear-queue.ts、scripts/redis-namespace.ts。
  • 枚举/字典:没有独立字典表。规格是专表;状态/类型用 TS 字面量联合类型 + 目录文件(failureCatalog.ts、taskEventCatalog.ts);字典化只做到文档层(见 §2 数据字典行)。

4.3 文件存储

目录 用途 是否受保护 证据
uploads/psd 模板 PSD 源文件 ✅ 永不清理 storageCleanup.ts:65
uploads/preview PSD 解析后的预览 PNG(无损,平均 829KB,最大 2.37MB) ✅ imageThumbnail.ts:22-32
uploads/product/<date> 商品原图 + 抠图中间产物 ❌ 可清理 workers.ts:203
uploads/output/<date> 生成素材 ❌ 可清理 workers.ts:234
uploads/zip/<date> ZIP 交付包 ❌ 可清理(有保留天数) workers.ts:830-840
uploads/tag-logos 标签 logo ✅ tagController.ts:24
uploads/temp 上传临时区 ❌ 可清理 storageCleanup.ts:36-40
uploads/thumb/<w> 按需缩略图缓存(WebP q80) ✅(随源删除 + 孤儿清扫) imageThumbnail.ts:40-60
  • 对外 URL 规则:/uploads/<相对路径>,JWT 鉴权(Authorization 头或 <img> 场景 ?token=),追加 ?w=320|640 返回 WebP 缩略图,失败静默回退原图(middlewares/uploadThumbnail.ts:9-30)。
  • 容量与清理:代码注释记录实测 732MB(psd 417M / output 146M / product 62M / zip 59M / preview 47M);本机副本 854MB / 775 文件。清理策略为「先预览、只删文件、绝不碰模板资产、默认只删孤儿」(storageCleanup.ts:16-40),可配保留天数 + 定时清理(默认关)。
  • 路径安全:所有客户端传入的相对路径必须过 resolveUploadPath(../绝对路径/NUL 全拒绝),历史上曾有任意文件读取漏洞(utils/uploadPath.ts:1-20)。

4.4 Redis 用途与任务状态机

  • Redis 只做 BullMQ:2 个队列(material-generation / zip-packaging)、项目级键前缀 sucaigongfang、可配 db(REDIS_DB 真正生效)。限流用进程内存(非 Redis),因此水平扩容会失效(middlewares/rateLimit.ts:11-18 自述待改)。
  • 批次状态机(models/ProductionBatch.ts:12): pending → processing → completed | failed,旁支 paused(可 resume)与 cancelled(不可被收尾覆盖)。
  • 结束态判定唯一来源 utils/batchStatus.ts:completed|failed 才算结束;failed_count>0 即 failed;cancelled 不允许被收尾改写(batchStatus.ts:12-80)。
  • 子任务状态:pending → processing → completed|failed;BullMQ attempts=3 时中间轮次保持 processing,只有最终失败才计入 failed_count(workers.ts:324-401,这是踩过「失败数按尝试次数累加 → 进度 300%」坑后的修正)。
  • ZIP 状态:none → generating → ready|failed(ProductionBatch.ts:24)。

5. 关键机制

5.1 PSD 模板:上传 → 解析 → 图层约定 → 渲染合成

① 解析(utils/psdParser.ts)

  • readPsd(buffer) + initializeCanvas(@napi-rs/canvas);递归 children 提取图层(psdParser.ts:104-161)。
  • 只识别 3 类前缀:image_replacement_(产品图替换)、text_replacement_(文本替换)、clipping_mask_(剪贴蒙版容器)(psdParser.ts:123-147)。
  • 预览图:psd.canvas → sharp().png() 原尺寸无损落盘(psdParser.ts:170-236)。

② 图层契约(models/Template.ts:10-34)

LayerConfig {
  imageReplacements: [{ layerName, type, description,
                        linkedContentLayer?, linkedClippingMask?,   // 剪贴蒙版双向关联
                        scaleMode?: 'fill'|'contain'|'stretch' }]
  textReplacements:  [{ layerName, field(deprecated), textTemplate?, hideWhenEmpty?,
                        description, font?, fontSize? }]
}

③ 文本图层 ↔ 客户字段匹配(utils/layerFieldMatcher.ts:1-20,四层优先级)

  1. placeholder:图层名直接写模板,如 text_replacement_标题-{品牌名称}{商品名称}(零配置,推荐给设计师);
  2. key:去掉前缀等于字段名(text_replacement_商品名称);
  3. alias:等于字段别名(spmc/title/sku/pp,不区分大小写);
  4. fuzzy:含「标题/名称/title」等关键词兜底;
  5. 未命中返回 null,不猜测(避免把静态文案层错绑成商品名)。

④ 渲染合成(utils/materialComposer.ts,1773 行,本仓库最核心资产)

  • 入口 compose(psdPath, layerConfig, productImagePath, outputPath, fields, forceJpg, sizeLimit, cutoutFailed, renderOptions)(materialComposer.ts:143)。
  • 流程:readPsd 全量图层 → 先渲染「非替换图层」到临时画布(用于取真实背景色)→ 以 PSD 合成 canvas 为底 → 处理替换图层(剪贴蒙版/真实背景/叠加/仅替换 四条分支)→ 输出编码。
  • 支持:图层不透明度、15 种混合模式(multiply/screen/overlay/…/luminosity,materialComposer.ts:427-477)、隐藏图层跳过、剪贴蒙版 alpha 与形状蒙版、scaleMode 三档(fill/contain/stretch)。
  • 文本渲染:buildCanvasFont 按 CSS 规则构造字体简写(踩过引号不成对导致 @napi-rs/canvas Rust 层 panic → SIGABRT → 容器反复重启的坑,materialComposer.ts:100-125);默认字体栈把项目内置中文字体放在最前,避免 node:24-slim 无中日韩字形时渲染成「豆腐块而任务仍报成功」。
  • 输出约束:JPG 用二分搜索质量逼近大小上限;PNG 因 sharp 0.32.6 的 quality 无效,改为调色板 colours 逐级减半(materialComposer.ts:258-357);压不下去时返回 lowQualityWarning 而不是假报成功。
  • 已知限制(对 PRD P-02 致命):所有 imageReplacements 图层共用同一个 productImageBuffer(materialComposer.ts:222-236、516-620),即「同一张商品图贴到多个位置」。不支持按图层注入不同资产(Logo/促销图/AI 模特/脚模),type 字段除 clipping_mask 外被忽略。

5.2 图片生成流水线(当前唯一真正可跑的产线)

上传商品图(≤100) → 按客户命名模板识别文件名(latin1→utf8 乱码修复)
  → 前端可编辑表格(商品图/商品ID/商品名称/品牌) → 校验必填(商品ID)
  → POST /api/batches(事务内建批次+子任务;命名快照;预渲染 planned_filename)
  → 事务外入队(失败不回滚,可用「重试」补救)
  → Worker:白底判定(ImageTypeDetector) → 是白底则 imgly 抠图
           → 抠图失败/产物缺失 ⇒ 回退原图 + cutoutFailed=true(写 low_quality_warning)
  → MaterialComposer.compose → 写 materials → 更新批次计数 → publishBatchUpdate(WS)
  → checkBatchCompletion → 有失败项=skipped failed / 全成功=completed
  → 站内信(成功/失败模板可配)+ 自动 ZIP 打包 → 下载

关键点:

  • 交叉批量:totalTasks = templateIds.length * products.length,双层循环(productionBatchController.ts:839-840、:888-890、:948-950)。
  • 抠图是「条件触发 + 可降级 + 有痕迹」:仅白底图抠(workers.ts:193-230),失败标记低质量而不是静默成功——这是全项目「不静默交付」原则的典型。
  • 并发与内存:素材 Worker 默认 2 并发(可页面 L3 热改 1–4),因为 API 与 Worker 同进程,抠图峰值可能吃掉数 GB(workers.ts:52-66)。
  • 任务监控:超时任务、ZIP 卡住由 taskMonitor.ts 巡检(默认 30 分钟 / 10 分钟,可配),恢复卡死批次。
  • 重试语义:BullMQ 自动重试 3 次 + 手动「重试失败项/继续执行」,planned_filename 保证重试同名不产生重复文件。

5.3 AI 生图:M0 / M1 / M2 三条线的真实结论

一句话:AI 能力目前全部停留在「验证工作台 + 文档」,main 分支没有任何 AI 产品代码;另有一条已声明作废的 M1 实现分支。

证据基线:grep -rniE "seedream|volc|方舟|ai.?image|aigc" backend/src frontend/src 零命中;docs/AI生图相关功能-实现方案.md:4 明确写「基线:main 分支现状(没有任何 AI 代码)+ 从零新写」。

M0 · VLM 反推 / 图层分离可行性(tools/vlm-lab/,10,469 行,已入库)

  • 模型:A=doubao-seed-2-1-pro-260915、B=qwen3.8-max-0902;34 条原始记录。
  • 结论(docs/AI素材生成-M0验证记录.md:10-30):坐标精度 IoU 几何 0.968/0.982、文字 0.819/0.833(达标);坐标格式可被提示词控制(11/11 遵从归一化);json_schema 严格模式 100% 合法;图层分离真实跑通 96s 返回 12 图层;免责声明可逐字锁定。
  • 未达标:换文案鲁棒性(溢出率 16.7%,未达 ≤5%)、单张耗时(86–110s,关思考后 31.3s 达标)。对策是字段加 maxChars,不是放宽阈值。
  • 状态:验证完成,未产品化。

M1 · 图片模板(非 PSD)契约 + 冻结 + Schema 渲染(分支 backup/ai-asset-m1-20260923-1451)

  • 规模:53 个提交,相对 main 净增约 4.8 万行;其中新增文件 后端 ~19,455 行 / 前端 ~11,928 行(aiTemplateController 1341、schemaRenderer 2748、layerMerge 1200、imageTemplateRenderer 774、aiProvider 547…),分支整体约 10 万行。
  • 目标(docs/AI素材生成-M1正式开发方案与计划.md:16-25):设计师传普通图片 → VLM 反推 → 人工框选确认 → 冻结契约 → 优化师填文案出图(≤5 分钟 + ≤3 分钟)。
  • 已实现多条产品链路(合规闸门、警示语逐字比对、擦除遮罩、自由改图、品牌资产逐像素贴回等,见 git log main..branch)。
  • 但已被最新方案整体否决:docs/AI生图相关功能-实现方案.md:6 写明「M1 的文档与代码整体作废,不参考、不复用」,原因是需求方改口径为「生成图即成品,不套模板、不做契约/冻结/图层绑定」。
  • 状态:实验分支,不可作为交付物(但不排除局部算法/经验可借鉴,如擦除遮罩、文字校验、合规词库)。

M2 · Seedream 表单式生图(tools/ai-image-validation/,2,122 行,已入库)

  • 模型:doubao-seedream-5-0-pro-260628 / doubao-seedream-5-0-flash-260915(lib/config.mjs:27-31);读图校验用 doubao-seed-2-1-pro 或 qwen3.8-max 交叉验证。
  • 实测(34 张真实生成,34/34 成功;docs/AI生图-M2-0验证记录.md:46-66):
验证项 结论
中文文字逐字正确率 ✅ 凡提示词写明文案的全部逐字正确(含中英数混排、6 卡片 9 处文案)
background=transparent ✅ 成立(四角 alpha=0,全透明 70–78%),但输出有 20–28% 半透明像素,贴回不能硬阈值抠图
多图参考融合(≤10 张) ✅ 真融合(背景取风格图、主体取主体图)
flash vs pro ✅ 文字/透明底打平,输出 token 相同(16428/张),flash 快约 3 倍(19–25s vs 55–76s)→ 建议默认 flash
文字校验闸门 ⚠️ 机制有效(5 个真错字样本全拦住、0 漏检;读图失败返回 unchecked 而非 passed),但「漏检率为 0」不应作为上线门槛
账号级限流 ⚠️ 真实存在(撞过 429 RPM limit exceeded),产品化必须自己排队(工作台用 12s 串行节流)
  • 产品化差距:M2-A 之后才写 backend/ 代码(tools/ai-image-validation/README.md:3-5),当前零集成:没有 ai 配置模块、没有 AI 数据表、没有 AI 队列、没有前端页面。
  • 成本:待确认。M2-0 明确写「flash 单张价格待补,需把价格做成可配置项用于成本预估」(docs/AI生图-M2-0验证记录.md:134-135)。可确定的是:flash 单张 19–25s、输出 16,428 token/张;文字校验是每张一次额外 VLM 调用,会让耗时与费用接近翻倍(docs/AI生图相关功能-实现方案.md:522)。
  • 密钥约束:AI API Key 不能放系统配置——ConfigValueType 没有 secret 类型,且 SystemConfigAudit 完整存 oldValue/newValue 不脱敏,Key 会长期明文留痕(docs/AI素材生成-与现有系统整合方案.md:122-155)。必须走 .env 或先补 secret 机制。

AI 成熟度判定:M0 验证完成 → M1 实现完成但作废 → M2 验证完成(M2-0),产品代码未开始。统一平台若排 AI 生图,必须按「从零新建」估算,不能按「接入现有能力」估算。

5.4 命名规范引擎(PRD P-04 的直接答案)

  • 变量体系(backend/src/types/naming.ts:19-40):系统变量 11 个(用户昵称/客户名称/模板名称/横竖版/任务编号/批次号/序号/素材序号/日期/时间/扩展名)+ 客户自定义字段(可映射 productId/productName/brandName 三个语义字段,其余落 extra_fields JSONB)。
  • 默认模板(utils/namingConfig.ts:28-72):
    • 商品图识别:['交易-sp{商品ID}-{商品名称}', '交易-sp{商品ID}']
    • 素材命名:交易-sp{商品ID}-{横竖版}-{品牌名称}-{用户昵称}-{任务编号}-{序号}.{扩展名}
    • ZIP:{客户名称}图片素材-{任务编号}
  • 三层兜底:客户配置 → 客户配置不命中回落到旧 FilenameParser 宽松解析 → 仍失败用 renderFallbacks(商品ID/品牌默认 unknown)(namingConfig.ts:352-403)。
  • 校验很实:字段名不得与系统变量重名、别名不得跨字段重复、识别模板必须能编译且字段已定义、命名模板不得引用未知变量(namingConfig.ts:240-328)。前端 NamingConfigEditor.tsx(765 行)实时预览。
  • 批次快照(types/naming.ts:104-119):建单时固化 materialTemplate/zipTemplate/renderFallbacks,保证「客户事后改规则不影响在途/历史批次,重试产出同名文件」。
  • 文件名安全:非法字符清洗 sanitizeFilename + UTF-8 字节截断 truncateFilename(namingTemplate.ts:177、:218、:277)。注意:main 分支没有「提交前重名门禁」——若命名模板不含商品维度,同批次会产出同名文件;ZIP 下载路径里有注释承认「会互相覆盖」(productionBatchController.ts:2096),而「撞名返回 400」的重名门禁只存在于 AI 分支(32f1a09)。整合时需补这条校验。

5.5 客户级配置与数据范围

  • 客户级配置范式:clients.naming_config JSONB,null = 用系统默认(models/Client.ts:61-65)。AI 侧方案明确要求「新增客户级配置照这个模式,别发明新机制」(docs/AI素材生成-与现有系统整合方案.md:19)。
  • 数据范围:users.client_scope_mode + user_clients。语义是 fail-closed:restricted + 无绑定 = 什么都看不到,绝不放大成「全部客户」(utils/clientScopeCore.ts:12-22)。
  • 落地很扎实:涉及客户数据的 10 个 Router 都挂了 attachClientScope;模板清单、建批次、上传商品图、命名预览、批次模板都做 checkClientReadable/Writable;甚至专门修过「生产入口未消费客户范围 → 可用别家模板出图并套出命名规则」的安全 bug(commit b7e2c68、100544e)。

5.6 通知、站内信与 WebSocket

  • 通知模板可配:5 类模板(批次全部成功 / 部分失败 / 全部失败 / ZIP 就绪(自动清理)/ ZIP 就绪(保留)),支持变量占位(批次号、客户名称、数量、失败原因、过期日期),长度上限标题 60/内容 200,uiControl: 'notification-templates' 挂专用编辑器(utils/notificationTemplates.ts:130-180、:411)。
  • 触发点:workers.ts 批次完成与失败、ZIP 打包完成;开关可配(notification.on_batch_completed 等)。
  • 前端形态:顶栏铃铛 hover 下拉(最近 10 条 + 未读数 + 标记/删除/清空),没有独立通知中心页(AdminLayout.tsx:126-133、:400-420)。
  • WS:/ws?token=<jwt>(浏览器 WS 不能带 header),推整行快照,300ms 按批合并,30s 心跳,鉴权失败 4401 让前端停止重连;前端 useRealtimeBatches 在无连接时降级轮询(utils/realtime.ts:20-70)。

5.7 系统配置框架(统一平台应整套继承)

  • 40 个配置项 / 10 模块:basic(2)、production(9)、upload(3)、naming(1)、queue(8)、notification(4)、monitor(3)、security(5)、log(1)、storage(4)(utils/systemConfigRegistry.ts:192-760)。
  • 每个配置项声明:module/label/type/default/level/description/min/max/options/nullable/isPublic/warning/uiControl/uiControlMeta/validate。
  • 默认值只能定义在注册表,DB 只存改过的值;default 支持函数形式从 env 派生(升级不重置现网调优)(systemConfigRegistry.ts:33-100)。
  • 明确禁止把进程级基础设施(JWT_SECRET/DB_/REDIS_/PORT)放进注册表——改完不生效只会制造错觉(systemConfigRegistry.ts:1-20)。
  • 审计:system_config_audits 存 old/new,不脱敏(因此不适合放凭据)。
  • 这套机制直接对应统一平台所需的「平台级参数、AI 模型/并发/上限、上传限制、队列并发、通知开关、安全策略」等集中治理。

6. 代码规模与质量

6.1 LOC / 文件数(口径命令)

cd 参考项目/sucaigongfang

# 后端源代码(ts/js,不含 node_modules/dist/uploads)
find backend/src -type f \( -name '*.ts' -o -name '*.js' \) -print0 | xargs -0 wc -l | tail -1
# → 30835

# 前端源代码(ts/tsx/css)
find frontend/src -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.css' \) -print0 | xargs -0 wc -l | tail -1
# → 32797

# 后端测试
find backend/tests -type f -name '*.ts' -print0 | xargs -0 wc -l | tail -1
# → 2078

# 文件数
find backend/src -type f -name '*.ts' | wc -l          # 137
find frontend/src -type f \( -name '*.ts' -o -name '*.tsx' \) | wc -l   # 74
模块 文件数 LOC 占比 说明
backend/utils 55 14,169 46.0% 渲染/队列/命名/配置/清理/日志,绝对核心
backend/controllers 17 9,746 31.6% productionBatchController 2,404 行、templateController 1,500+ 行
backend/models 20 2,721 8.8% 19 表 + associations
backend/scripts 8 1,348 4.4% 运维脚本
backend/migrations 11 778 2.5% umzug
backend/middlewares 6 766 2.5% auth/clientScope/upload/rateLimit
backend/routes 17 657 2.1% 薄层
backend/app.ts + types 3 650 2.1% 入口 + 类型
后端合计 137 30,835 100%
frontend/pages 16 16,705 50.9% Production 2,625、SystemConfig 1,860、TemplateList 1,735、Tasks 1,610
frontend/components 24 8,303 25.3% BatchDetailDrawer 1,125、AdminLayout 874、TaskLogBoard 779
frontend/utils 20 2,528 7.7% 纯函数多,易复用
frontend/types 1 1,648 5.0% 单文件类型字典
frontend/styles 7 1,561 4.8% token/theme/arco-overrides
frontend/services 1 1,223 3.7% 113 个 API 方法
frontend/hooks + stores + 入口 11 829 2.5% 4 hooks + 2 store + App/main/index.css/App.css/arcoStyles.ts
前端合计 74(+css) 32,797 100%
总计 211+ 63,632 — 约 6.4 万行(与任务书「约 62k 行 TS」量级一致)

补充:AI 验证工作台 tools/vlm-lab 10,469 行、tools/ai-image-validation 2,122 行(非产品代码);分支 backup/ai-asset-m1 整体约 10 万行。

6.2 TypeScript 严格度

  • 后端 tsconfig.json:strict: true、target ES6、skipLibCheck: true(无 noUnusedLocals/noUncheckedIndexedAccess)。
  • 前端 tsconfig.app.json:strict + noUnusedLocals + noUnusedParameters + verbatimModuleSyntax + noFallthroughCasesInSwitch + erasableSyntaxOnly(比后端更严)。
  • 全量 tsc --noEmit 纳入 CI(前后端 + 测试独立 tsconfig),且后端生产镜像是 tsc 全量编译,类型错误会直接卡住镜像构建(ci-local.sh:28-32)。

6.3 测试

  • node --test(Node 内置 test runner),175 个用例 / 14 个文件 / 2,078 行。
  • 覆盖的都是「口径类纯函数」:通知模板(41)、统计趋势(26)、客户范围(23+4+2)、口令有效性与策略(14+11)、规格名称派生(13)、存储清理计划(10)、缩略图路径(10)、批次状态(8)、失败目录(7)、事件目录(3)、命名变量别名(3)。
  • 缺口:无 DB 集成测试、无 API 契约测试、无渲染快照测试、无 E2E(Playwright 只在另一项目里)。PSD 渲染这种最容易静默出错的模块,没有自动化回归。

6.4 Lint / CI

  • 后端 .eslintrc.js(@typescript-eslint 8)+ prettier 3;前端 .eslintrc.cjs + react-hooks/react-refresh。
  • deploy/ci-local.sh 六步:格式 → lint → 单测 → 前端设计 token 静态校验(scripts/verify-design-tokens.mjs,穷举扫描 Arco CSS 变量三元组/完整色值混用)→ 失效筛选判定(verify-invalid-filters.mjs)→ tsc → 构建。
  • 设计 token 校验被硬卡的原因写得很实在:Arco 变量格式用错不报错、只静默失效,2026-09 因此连续出过两次线上视觉事故(ci-local.sh:18-24)。
  • 版本管理:commitizen(git cz),语义化提交(feat/fix/docs/refactor/style/chore/test/ci)。

6.5 技术债与已知问题(须带入整合评估)

# 问题 影响 证据
1 docs/ 整体 gitignore,110 个文件 0 入库 AI 验证结论、命名方案、部署手册都只存在本机;换人/换机即丢失上下文 .gitignore:122、tools/ai-image-validation/README.md:5-8
2 API 与 Worker 同进程 无法独立扩缩容;Worker OOM/崩溃会连带 API;uncaughtException 直接退出 app.ts:64-78、app.ts:402
3 文件存储纯本地磁盘 多副本/多机部署不可行;无 OSS/S3 适配层 utils/uploadPath.ts:20、docs/AI多行业素材生成方案.md:87
4 登录限流用进程内存 水平扩容后限流失效(代码自述) middlewares/rateLimit.ts:11-18
5 无 secret 配置类型、审计不脱敏 API Key 等凭据不能进系统配置 docs/AI素材生成-与现有系统整合方案.md:122-155
6 渲染引擎只支持单张商品图 无法做 Logo/促销/AI 模特多资产叠加 materialComposer.ts:222-236
7 大量 console.log 混在渲染器里 生产日志噪音大、性能损耗 materialComposer.ts:288-357
8 文档漂移:database/README.md 写「15 张表」实际 19;deploy.sh:16-20 仍写「启动 DBSync alter」实际已是 umzug 运维按文档操作会误判 database/README.md:11、deploy/deploy.sh:16-20、utils/dbSync.ts:9-40
9 estimatedDuration 后端从未写入,前端曾据此展示「预估剩余时间」 已修(前端改为不显示),但字段仍是死字段 pages/Home.tsx:306-310
10 标签 logo 上传后端有、前端未接线 资产能力半成品 tagController.ts:21-37、frontend/src 无 logoPath 消费
11 history 路由被注释 素材历史页缺失 App.tsx:118-120
12 sharp 锁 0.32.6 升级需回归 PNG 量化行为 backend/package.json:45、materialComposer.ts:317-329
13 Windows 下抠图不可用(动态 require 降级) 开发环境与生产行为不一致 utils/backgroundRemover.ts:5-30
14 前端菜单/路由/权限映射三处硬编码 加一个模块要改 4 处,易漏 AdminLayout.tsx:85-98、:763-841、App.tsx:100-120
15 权限模型只有「页面级」,没有「动作级」;任务日志因此刻意不提供暂停/取消/重试 统一平台的提审、投放配置、AI 产出复核都需要动作级/数据级权限,现模型不够用 routes/taskLogRoutes.ts:18-24、utils/permissions.ts:4-20
16 素材历史(materials)与生产批次两套记录并存,前者无页面 后续若做「素材资产/提审」会有两套口径 routes/materialRoutes.ts:28-34、App.tsx:118-120

7. 逐模块复用评估(核心交付)

7.1 逐模块评估表

复用级别:A=几乎直接复用;B=改造可控;C=需重写;D=废弃。 人日为「改造成统一平台形态」的粗估,不含产品/测试/联调,需与研发负责人校准。

模块 现有实现 统一平台中的目标形态 复用级别 改造要点 粗估人日 风险
工程地基(Express/Sequelize/PG/umzug/日志/健康检查) 17 Router、19 模型、11 迁移、结构化错误兜底 统一后端基座 A 拆 platform 维度;健康检查增加 OSS/第三方 AI 探活 3–5 低
认证 / 口令安全 / 限流 / 审计 JWT+pwdv、强制改密、三态有效期、一次性口令、IP+用户名限流 同一套 A 限流迁 Redis(为多副本) 2–3 低
RBAC + 客户数据范围 权限 key 目录 + fail-closed 范围 + 全链路校验 平台/客户双层范围 A 权限 key 按新模块扩充;客户范围升级为「平台×客户」 3–4 权限遗漏=静默越权,需补回归测试
系统配置框架 40 项/10 模块/L1-L3/审计/专用控件 加 platform、ai、selection、video 模块 A 加 secret 类型 + 审计脱敏(AI Key 前置条件) 3–5 低
模板/分类/标签/规格管理 完整 CRUD + 批量 + 复制 + 自动匹配 平台级模板资产库 B 加 platform_id/project;标签 logo 接入渲染;规格扩三档 8–10 模板迁移与兼容
PSD 解析与渲染引擎 1773 行合成器 + 字体兜底 + 质量压缩 多资产合成(模板/商品/AI模特/信息/Logo) B 核心改造:按图层注入不同资产;Logo 组合与拼接字符;促销图层;三尺寸派生 12–18 改造面大、无自动化回归、字体版权
抠图 imgly + ONNX medium + 白底判定 + 降级告警 同能力 A 抽成独立推理服务(可选);非白底/透明底策略 2–3 单机 ONNX 内存峰值
批量任务/队列/进度/收尾/重试 BullMQ 2 队列 + DB 计数 + WS + 监控 + 失败口径 多产线统一任务中心 A 队列按产线拆分;Worker 独立进程化(可选) 6–8 同进程 OOM
命名规则引擎 变量模板 + 客户级 + 快照 + 校验 + 商品图识别 提审命名规范引擎 A 变量域扩 SPUID/平台/活动/日期 等;与提审状态联动 3–4 字段域扩展后校验规则要同步
导出 / ZIP / 下载 CSV + 选集 ZIP + 整批 ZIP 异步 按路径导出/打包 A 导出字段调整;路径规则(平台/项目专用路径) 3–4 低
通知 / 站内信 / WS 可配模板 + 3 类触发 + 铃铛下拉 + WS 通知中心(含提审/投放事件) B 补独立通知中心页;补事件类型;WS 跨进程改 Redis pub/sub 3–4 低
任务事件 / 失败目录 / 时间线 / 任务日志 事件目录 + 失败目录 + 90 天保留 + 管理端看板 统一可观测中心 A 新增事件类型;权限粒度可能需细分 3–4 低
文件存储 / 缩略图 / 清理 本地磁盘 + 按需 WebP + 先预览后清理 对象存储 + CDN B 抽 StorageAdapter(local/OSS),URL 规则改造,清理策略按存储对象 4–6 迁移期双写/回填
前端设计体系/布局/守卫/共享组件 token 单点 + 自动校验 + AssetThumb/StatCard/SectionCard 等 统一设计系统 B 菜单/路由/权限映射改为配置驱动;主题换肤 5–7 菜单硬编码三处耦合
素材制作页(2625 行) 选模板/传图/识别/填字段/参数/二次确认 「平台 → 选品 → 品类 → 尺寸 → 模板 → 展示方式 → Logo/促销 → 预览 → 导出」 C 按新信息架构重写,复用其上传识别与字段表格逻辑 10–15 新交互未定稿即返工
首页 Dashboard 5 卡环比 + 今日任务 + 待我处理 新 KPI(单套成本/模板占比/提审通过率) C 指标口径重定义 + 后端聚合 3–5 指标口径待业务确认
AI 生图 无可运行产品代码(仅 M2-0 验证) 9 要素表单→提示词→生成→校验→挑图→入生产 C 从零:模型网关、配额排队、成本预估、文字校验闸门、素材落库、UI 20–30 成本/限流/合规/一致性
AI 素材生成(M1 分支) 53 commits / ~3.1 万行新增 — D 官方已声明作废;仅可借鉴擦除遮罩/文字校验/合规词库经验 0(不计) 误用会引入大量死代码
数据字典 / 枚举 仅文档 + 未合并分支 字典类型→字典项(code/label/description) C 重写(表+API+页面+权限),供 AI 提示词与筛选消费 3–4 低
多平台 / 平台切换 无 得物/唯品会切换,资源路径按平台隔离 C/新建 平台表、平台上下文、菜单/模板/命名/ZIP 全链路带平台 5–8 与客户维度正交,需先定数据模型
选品 / 原始物料获取 无(在 Electron 桌面端) 商品检索(SPUID/粗词)→ 圈选 → 详情页图片抓取归档 新建 迁移 dewu-material-Downloader 的抓取能力到服务端 + 物料库 15–25 平台反爬/登录态/合规
视频素材 AI 生产 无 脚本(AI/人工)→ 画面 → 组合,16:9 / 9:16 新建 完全新产线(模型选型、异步长任务、素材管理) 40+ 成本、时长、质量不可控
提审 无 待审清单 + 状态跟踪 + 与素材/商品关联 新建 新表+状态机+清单页+通知事件 8–12 平台提审口径未定义
投放配置(DP/承接页) 无 输入点(SPUID/官网链接)→ 自动生成链接 → 一键复制/批量替换 新建 新表+生成规则+批量操作+校验 8–12 规则来源与合规未确认

7.2 能否直接作为统一 WEB 平台的技术底座?

结论:能作为「图片素材产线 + 平台工程地基」的底座,但不能直接当作整个统一平台的底座。

可以成立的四个理由

  1. 工程底座是成熟的:认证/权限/客户范围/系统配置/迁移/队列/事件/失败目录/通知/打包/部署/CI,几乎覆盖统一平台 70% 的「非业务」工作量,且质量高于平均水平(大量注释是「为什么这么写 + 踩过什么坑」,对后来者价值极高)。
  2. 图片产线的主干已经跑通:PSD 模板 → 图层契约 → 批量交叉生产 → 命名 → 打包 → 交付,正是 PRD P-02 的骨架。
  3. 命名引擎就是 P-04 的一半,且实现质量明显高于「按规范重写」的预期(客户级可配 + 快照 + 兜底 + 校验)。
  4. 可观测性天然具备:任务事件时间线 + 失败分类目录 + 管理端任务日志,统一平台最容易忽略、又最难后补的东西这里已经有了。

必须补齐的 8 块(按优先级)

# 缺口 现状 建议
1 多平台/项目抽象 完全无「平台」概念 先定数据模型:platform(得物/唯品会)+ 资源路径规则 + 平台上下文贯穿模板/命名/ZIP/导出
2 选品 / 原始物料获取 在另一 Electron 项目 服务端化抓取(登录态/反爬/限速),建物料库与 SPU 关联
3 四层信息中的三块(展示方式/Logo/促销) 只有单品图 + 文本 改造渲染引擎支持「按图层注入不同资产」;Logo 组合与拼接字符;促销模板叠加
4 视频素材产线 空白 独立产线,勿与图片产线耦合;先做脚本/画面/组合三段 MVP
5 提审 空白 新状态机 + 清单 + 通知 + 与素材/商品稳定关联
6 投放配置 空白 DP/承接页生成器 + 批量替换 + 一键复制
7 对象存储 / 队列水平扩展 本地磁盘 + 同进程 Worker + 内存限流 抽存储适配层;Worker 独立进程 + Redis 限流;否则多副本不可行
8 权限体系细化 菜单级 key + 客户范围 提审/投放/AI 需要更细的能力点 + 数据范围(平台×客户)

一个必须提前说明的取舍:若把「AI 生图」和「视频」放进同一期,本系统的「单进程 + 本地磁盘 + 同步重 CPU 渲染」架构会先撞墙——图片渲染(CPU/内存密集)与 AI 调用(长耗时、外部限流)应该分属不同队列与不同 Worker 进程,这在原系统里是有意合并的(app.ts:65-66),整合时必须拆。


8. 可复用资产清单

8.1 后端(可直接搬运/改造)

资产 路径 价值
PSD 渲染合成引擎 backend/src/utils/materialComposer.ts(1773 行) 剪贴蒙版/混合模式/缩放模式/字体兜底/质量压缩,全项目最贵资产
字体管理 backend/src/utils/fontManager.ts + backend/fonts/方正兰亭中黑简体.TTF 字体扫描双目录 + 别名兜底(防豆腐块事故);字体商用授权待确认
PSD 解析 backend/src/utils/psdParser.ts 图层前缀识别 + 预览图生成
图层字段匹配 backend/src/utils/layerFieldMatcher.ts placeholder/key/alias/fuzzy 四级匹配,纯函数可单测
抠图 backend/src/utils/backgroundRemover.ts + imageTypeDetector.ts 白底判定 + ONNX 抠图 + 降级告警
命名引擎 backend/src/utils/namingTemplate.ts、namingConfig.ts、namingRuleResolver.ts、filenameParser.ts、types/naming.ts 变量模板/识别/校验/快照,纯函数多
队列与 Worker backend/src/utils/queue.ts、workers.ts(1074 行)、batchTasks.ts、batchStatus.ts、taskMonitor.ts 入队/重试/收尾/超时/卡死恢复
任务事件体系 taskEvents.ts、taskEventCatalog.ts、failureCatalog.ts、taskEventQuery.ts 事件目录 + 失败目录 + 保留期,可观测底座
系统配置框架 systemConfigRegistry.ts(40 项)、systemConfigService.ts、models/SystemConfig(Audit).ts 声明式配置 + L1/L2/L3 + 审计
权限与范围 utils/permissions.ts、clientScope.ts、clientScopeCore.ts、middlewares/auth.ts、middlewares/clientScope.ts RBAC + fail-closed 数据范围
账号安全 utils/passwordPolicy.ts、passwordExpiry*.ts、middlewares/rateLimit.ts、utils/jwt.ts 口令策略/有效期/令牌失效/限流
文件服务 utils/uploadPath.ts、imageThumbnail.ts、thumbnailPath.ts、storageCleanup.ts、storageCleanupScheduler.ts、`middlewares/upload(Thumbnail Auth).ts`
通知模板 utils/notificationTemplates.ts 变量化模板 + 校验 + 渲染
实时推送 utils/realtime.ts 整行快照 + 节流 + 心跳 + 401 停止重连
迁移机制 utils/migrator.ts、dbSync.ts、schemaFromModels.ts、backend/src/migrations/*(11 个) 模型即 DDL 来源 + 幂等迁移
运维脚本 backend/src/scripts/*(init-admin/migrate/backfill/clean/clear-queue) 部署与数据治理
数据模型 backend/src/models/*(19 表)+ associations.ts 用户/客户/模板/批次/任务/事件/配置全量
API 契约 backend/src/routes/*(113 接口)+ frontend/src/services/api.ts(113 方法) 前后端一一对应的契约样板
测试 backend/tests/*(175 用例) 纯函数测试范式,可直接扩展

8.2 前端(可直接复用)

资产 路径 价值
设计 token / 主题 frontend/src/styles/tokens.ts、theme.ts、arco-overrides.css 字号 7 档/颜色/圆角/控件描边,全站唯一来源
设计规范 + 自动校验 frontend/前端设计规范.md、frontend/scripts/verify-design-tokens.mjs 规范落到可执行脚本(CI 硬卡)
布局与守卫 components/AdminLayout.tsx、AuthGuard.tsx、PermissionGuard.tsx 侧栏/面包屑/通知/用户菜单/双守卫
复用组件 AssetThumb(统一缩略图)、StatCard、SectionCard、HelpTip、BatchEventTimeline、TaskLogTimeline、TemplateHoverPreview、useHoverPreview 直接可用
业务重组件 BatchDetailDrawer(1125 行)、TaskLogBoard、LayerBindingEditor、NamingConfigEditor、NotificationTemplatesEditor、ImageLayerTable、TemplateChecklist 改造后价值高
工具函数 utils/naming.ts、assetUrl.ts、download.ts、clipboard.ts、batchDisplay.ts、taskEvents.ts、specification.ts、realtime.ts 纯函数,易搬
页面参考 pages/Production.tsx、Tasks.tsx、TemplateList.tsx、SystemConfig.tsx、UploadTemplate.tsx/EditTemplate.tsx 作为重构蓝本而非直接复制
发布说明(12 篇) frontend/发布说明-*.md 记录每次改动与踩坑,交接价值高

8.3 文档(注意:全部未入库)

文档 价值
docs/AI素材生成-M0验证记录.md(924 行) VLM 反推/图层分离的实测数据与 Go/No-Go 判定
docs/AI生图-M2-0验证记录.md(335 行) Seedream 五项门槛实测、flash/pro 对比、限流与成本注意点
docs/AI生图相关功能-实现方案.md(757 行) 最新 AI 口径(表单化/不套模板)+ 9 要素表单 + 官方参数硬边界
docs/AI素材生成-与现有系统整合方案.md(459 行) 代码勘察结论、API Key 不能进配置、整合顺序
docs/AI多行业素材生成方案.md(959 行) 契约化方案(已部分作废,但行业分析/现有能力边界表仍有效)
docs/命名规范梳理与客户级配置方案.md(874 行) 命名现状/硬编码落点/改造影响面
docs/数据字典与枚举管理评估.md(478 行) 字典建模结论(code/label 分离、单值/多值取舍)
docs/系统配置页面规划文档-v2.md(799 行) L1/L2/L3 分级的来源与「不要放进页面」清单
docs/通知中心页面需求.md(92 行) 通知中心独立页的交互稿(未实现)
docs/用户使用手册.md(543 行) 三个角色的真实操作路径
deploy/部署上线手册.md 容器化部署/迁移/回滚的标准流程
tools/vlm-lab/、tools/ai-image-validation/ 可复跑的 AI 验证工作台(注意 config.json 含真实 Key,永不入库)

9. 风险与待确认问题

9.1 六个最大风险

# 风险 说明 影响 缓解建议
R1 单机架构撞上「多产线 + AI」 API 与 Worker 同进程、抠图 ONNX 单机内存峰值、本地磁盘存储、内存限流(app.ts:65-66、rateLimit.ts:11-18) 无法水平扩容;AI 长任务会拖垮图片产线的 API 响应;OOM 导致整站不可用 整合前先拆三层:API / 图片渲染 Worker / AI 任务 Worker;存储抽象层 + 对象存储;限流迁 Redis
R2 AI 生图从零开始,成本与合规双未知 无产品代码;flash 单张 19–25s、16,428 token;文字校验接近翻倍;账号级 IPM 限流真实存在;单张单价未获取(docs/AI生图-M2-0验证记录.md:62-65、:134-135) 排期与成本预估都会失真;上线后易被限流/账单打爆 先做 1 人日连通性与配额压测;把单价与日调用上限做成配置;默认 flash;强制人工复核闸门
R3 PSD 渲染引擎改造的正确性风险 1773 行、无自动化回归、只支持单商品图;字体/混合模式/剪贴蒙版细节多(materialComposer.ts) 一次改造就可能让存量模板产出错图,且错误是静默的(图能出、内容错) 建立「存量模板黄金样本 + 像素级回归」再动引擎;灰度客户;保留旧渲染器开关
R4 PRD 的四层信息与现引擎不匹配 Logo 组合/拼接字符、促销模板、AI 模特/脚模都要「按图层注入不同资产」,现引擎共用一个 productImageBuffer(materialComposer.ts:222-236) P-02 的验收标准(四层信息)达不到 把「多资产图层」列为引擎改造第一优先级;先与产品确认四层的技术边界
R5 文档与知识全部未入库 docs/ 110 文件 0 入库;AI 验证结论只在本机(.gitignore:122) 人员变动/机器损坏即丢失决策上下文;「为什么这么设计」无法追溯 整合启动第一件事:文档入库(或迁到统一知识库),先抢救 AI 验证结论与配置分级结论
R6 平台/客户维度正交 + 存量数据迁移 现在只有「客户」,PRD 要「平台(得物/唯品会)」;模板/命名/ZIP/导出都要带平台;现有 854MB 文件与 19 表数据要迁 模型改错代价最大(迁移难回滚);历史产出可能无法归属到平台 先出「平台 × 客户 × 项目」数据模型评审;迁移脚本先 dry-run + 备份;不动 19 表而是加列/加表

其余风险(次级):中文/字体版权(方正兰亭中黑简体.TTF 商用授权待确认);PSD 兼容性(ag-psd 对智能对象/文字特效/图层样式的支持边界未系统测试);许可证(依赖多为 MIT/Apache,但 sharp 0.32.6/onnxruntime 需过安全扫描);AI 输出内容合规(券商场景已证明需要人工复核,电商场景的商标/肖像/功效宣称同样有风险)。

9.2 待确认清单

编号 问题 为什么影响整合 建议向谁确认
Q-01 统一平台的「平台」是数据维度还是独立部署?(得物/唯品会是否共享同一套模板与命名规则) 决定是否需要给 19 张表加 platform_id,以及资源路径规则 产品负责人 + 运营
Q-02 图片产线是否必须保留「PSD 模板」为唯一模板载体?是否允许图片模板(非 PSD)并存? 决定是否复活 M1 分支的 SchemaRenderer,还是只改造 MaterialComposer 产品 + 设计负责人
Q-03 AI 生图的定位:替代 PSD 产线,还是「无模板场景」的补充产线? 决定 AI 是 P0 还是 P2,以及是否与模板体系解耦 产品负责人
Q-04 三规格(800×800 / 1280×720 / 1080×1920)是固定枚举还是可扩展规格? 现有规格是通用 (w,h) 实体;固定则逻辑更简单 产品 + 设计
Q-05 Logo 的「拼接方式与拼接字符」具体是什么交互?字符是否需要上传字体/图形? 决定渲染引擎是否需要「图形组合器」,工作量差异大 设计负责人 + 唯品会对接人
Q-06 促销信息(折扣/活动标识)是模板叠加还是独立图层组? 决定促销图层的模型与编辑器 设计 + 运营
Q-07 选品主键:得物用 SPUID、唯品会用什么?是否统一? 决定物料库与模板变量域 运营 + 平台对接人
Q-08 详情页图片抓取是否有合规/授权依据?是否需要登录态? 决定选品模块可行性与架构(是否要浏览器自动化) 法务 + 运营
Q-09 提审是「平台后台人工提审」还是「系统内审批流」?需要跟踪到哪一级状态? 决定提审模块是轻量清单还是完整工作流 运营 + 产品
Q-10 DP / 承接页的生成规则由谁提供?是否有稳定模板与校验规则? 决定投放配置模块是「规则引擎」还是「固定拼接」 运营 + 平台对接人
Q-11 AI 生图的单张成本上限与日预算?可接受的单张耗时? 决定模型档位(flash/pro)、是否做文字校验、是否批量 财务 + 产品
Q-12 AI 生图是否需要「文字逐字校验 + 人工复核」双闸门? 决定额外 VLM 调用成本(接近翻倍)与流程设计 合规 + 产品
Q-13 视频素材的模型选型、时长上限、单条预算? 视频是最大不确定性,需前置验证(M0 式) 产品 + 财务
Q-14 视频/图片产出是否需要对象存储与 CDN?部署形态是单机还是多副本? 决定是否必须先做存储适配层与 Worker 拆分 运维 + 技术负责人
Q-15 字体商用授权:方正兰亭中黑简体 是否已购买商用授权?新增字体如何管理? 字体是合规红线,且换字体会改变渲染结果 法务 + 设计
Q-16 存量数据(19 表 + 854MB 文件)是否需要迁移?迁移到哪个平台维度? 决定迁移工作量与回滚方案 产品 + 运维
Q-17 「历史选品」「历史脚本」「模板复用次数」等 P1 指标是否需要埋点体系? 现有统计只有批次/素材维度,无选品/脚本 产品 + 数据
Q-18 统一平台是否需要多租户(不同客户数据硬隔离)?还是继续「单部署 + 客户范围」? 决定权限与存储架构(这是最大的架构分叉) 技术负责人 + 业务负责人

10. 证据索引

格式:结论 → 文件:行。均为本次只读勘察直接可见。

# 结论 证据
1 17 个业务 Router 挂载 + 静态文件 + 健康检查 backend/src/app.ts:147-164、:139-144、:175-201
2 API 与 BullMQ Worker 同进程 backend/src/app.ts:65-66、:402
3 WebSocket 复用同一 http.Server backend/src/app.ts:429-432
4 17 个控制器 / 113 个接口 backend/src/routes/*.ts(逐文件 router.<verb> 计数)
5 19 张表与建表顺序 backend/src/utils/schemaFromModels.ts:30-56、models/*.ts 的 tableName
6 umzug 迁移取代 alter:true 及原因 backend/src/utils/migrator.ts:8-30、utils/dbSync.ts:9-40
7 批次/子任务/结束态状态机与失败口径 models/ProductionBatch.ts:12-51、models/BatchTask.ts:19-34、utils/batchStatus.ts:12-80
8 生产参数与命名规则在建批次时快照(L2) models/ProductionBatch.ts:37-48、productionBatchController.ts:680-712、:797-806、:873-877
9 交叉批量 N×M 与命名预渲染 productionBatchController.ts:839-840、:888-908、:948-950
10 素材 Worker 主流程(抠图→合成→落库→计数→WS) utils/workers.ts:70-412、:193-230、:271-312
11 自动重试与「最终失败才计数」的语义 utils/workers.ts:324-401
12 ZIP 打包 Worker utils/workers.ts:764-860
13 PSD 只识别 3 类图层前缀 utils/psdParser.ts:123-147
14 图层契约结构(图片/文本/剪贴蒙版/缩放模式) models/Template.ts:10-34
15 文本图层↔字段四级匹配(placeholder/key/alias/fuzzy) utils/layerFieldMatcher.ts:1-20
16 合成器入口与签名 utils/materialComposer.ts:143-154
17 以 PSD 合成画布为底 + 替换图层四分支 utils/materialComposer.ts:212-236、:516-620
18 15 种混合模式支持 utils/materialComposer.ts:427-477
19 字体简写引号不成对导致 SIGABRT 的坑 utils/materialComposer.ts:100-125
20 中文字体兜底栈(防豆腐块静默交付) utils/materialComposer.ts:27-38、utils/fontManager.ts:1-40
21 JPG 二分质量 / PNG 调色板减半压缩 utils/materialComposer.ts:258-357
22 所有图片替换图层共用同一张商品图 utils/materialComposer.ts:222-236、:585-620、:750-752
23 默认命名模板与字段定义 utils/namingConfig.ts:28-72
24 系统变量清单(11 个) backend/src/types/naming.ts:19-40
25 命名配置校验(重名/别名/未知变量) utils/namingConfig.ts:240-328
26 批次级命名快照结构 backend/src/types/naming.ts:104-119
27 商品图识别三层兜底(客户→legacy→fallback) utils/namingConfig.ts:352-403
28 系统配置注册表与 L1/L2/L3 utils/systemConfigRegistry.ts:1-100、:192-760(40 个 key)
29 权限 key 目录(11 个)与历史角色兜底 utils/permissions.ts:4-45
30 客户范围 fail-closed 语义 utils/clientScopeCore.ts:12-22、:40-60
31 登录限流为进程内存(扩容失效) middlewares/rateLimit.ts:11-30
32 口令策略/强制改密/令牌版本 docs/PRD.md:46-56、middlewares/auth.ts:1-80、models/User.ts:1-60
33 存储目录保护清单与清理原则 utils/storageCleanup.ts:16-65
34 缩略图按需生成 + 失败回退原图 utils/imageThumbnail.ts:22-60、middlewares/uploadThumbnail.ts:9-30
35 上传路径越界漏洞与修复 utils/uploadPath.ts:1-40
36 通知模板可配 + 变量 utils/notificationTemplates.ts:38-180、:411-455
37 WS 整行快照 + 300ms 节流 + 心跳 utils/realtime.ts:20-70
38 任务事件目录与 90 天保留 utils/taskEventCatalog.ts:1-40、utils/taskEvents.ts:15-45
39 失败原因目录(code/audience/rawDetail) utils/failureCatalog.ts:1-50
40 任务监控(超时/卡死/巡检可配) utils/taskMonitor.ts:9-40
41 规格名称由尺寸派生、唯一性迁到尺寸 utils/specificationName.ts:46-57、migrations/20260924000001-specification-name-derivation.ts:1-40
42 CI 六步硬卡与设计 token 校验动机 deploy/ci-local.sh:24-45、frontend/前端设计规范.md:1-12
43 容器化部署与网络模型 deploy/docker-compose.yml:1-40、frontend/Dockerfile:1-66、frontend/nginx.conf.template:20-80
44 健康检查真实探活 DB/Redis backend/src/app.ts:175-201
45 docs/ 全目录被 gitignore(110 文件 0 入库) .gitignore:122、git ls-files docs = 0、find docs -type f = 110
46 AI 生图「main 无任何 AI 代码 + 从零新写」 docs/AI生图相关功能-实现方案.md:4-11、`grep -rniE "seedream
47 M1 分支被整体作废 docs/AI生图相关功能-实现方案.md:6、git log main..backup/ai-asset-m1(53 commits)
48 M2-0 五项验证结论(34 张全成功、flash 快 3 倍、透明底成立) docs/AI生图-M2-0验证记录.md:8-11、:46-66、:120-135
49 AI 账号级 IPM 限流真实存在 docs/AI生图-M2-0验证记录.md:62-65、tools/ai-image-validation/lib/config.mjs:59
50 AI API Key 不能进系统配置(无 secret 类型 + 审计不脱敏) docs/AI素材生成-与现有系统整合方案.md:122-155
51 AI 验证工作台不是产品代码 tools/ai-image-validation/README.md:3-8、tools/ai-image-validation/lib/config.mjs:1-12
52 M0 反推/图层分离结论与未达标项 docs/AI素材生成-M0验证记录.md:10-35
53 M1 验收定义与量化门槛 docs/AI素材生成-M1正式开发方案与计划.md:16-25、:1275-1298
54 现系统无视频/提审/投放/平台/抓取/OSS 以下 grep 均 0 命中:grep -rniE "ffmpeg|\bvideo\b" backend/src frontend/src、grep -rniE "\boss\b|s3|minio|对象存储" backend/src、grep -rniE "crawl|scrape|puppeteer|playwright" backend/src frontend/src、grep -rniE "提审|审核" backend/src frontend/src、grep -rniE "平台切换" backend/src frontend/src(「得物」仅在通知模板示例中)
55 文档漂移:database README 写 15 表、deploy 注释写 alter database/README.md:11、deploy/deploy.sh:16-20
56 estimatedDuration 从未写入 frontend/src/pages/Home.tsx:306-310
57 素材历史页被注释、历史 API 仍在 frontend/src/App.tsx:118-120、backend/src/routes/materialRoutes.ts:28-34
58 标签 logo 后端有、前端未消费 controllers/tagController.ts:21-37、grep -rn "logoPath" frontend/src 仅 types/index.ts
59 端口/部署实测环境 deploy/docker-compose.yml:1-30、生产环境部署/PRODUCTION.md:1-8(旧文档已自标失效)
60 提交活跃度与时间分布 git log --format='%ad' --date=format:'%Y-%m' | sort | uniq -c(3 月 85 / 4 月 33 / 9 月 131)

附:本报告未展开的部分

  • dewu-material-Downloader(另一参考项目,Electron 桌面端)只做了边界确认:它承担「得物素材下载」能力,未做深读,选品/抓取的服务端化评估需以其专项报告为准。
  • docs/API文档/ 下 4 份火山方舟 PDF(约 4.9–7MB/份)为二进制,未解析;模型参数边界以 docs/AI生图相关功能-实现方案.md:15-70 的摘录为准。
  • frontend/发布说明-*.md(12 篇)仅做存在性登记,未逐篇展开。
  • 未运行任何测试/构建,所有质量结论均来自静态代码与脚本内容;「实际能否一次跑通」属待确认。