通用

Q: 这套方案能跑在哪些规模?

  • 开发 / POC:一台 4C8G 单机 + docker compose 起依赖即可
  • 中小生产:几个节点(API、合成服务、依赖)支撑日均万级订单
  • 大型生产:pf-service 多实例(SKIP LOCKED 天然并行)+ 合成服务多副本/多 Worker,瓶颈通常在合成(Puppeteer)吞吐

Q: 为什么后端选 Bun + Elysia 而不是 Java / Node + Express?

docs/项目总体设计.md 早期版本写的是 Java + SpringBoot,落地时改为 Bun + Elysia 主要因为:

  1. 启动 ≤ 1s、零编译、TS 原生
  2. Elysia 借 TypeBox 在路由层做”类型 + 校验”一体化,开发量比 Express 少
  3. 与前端 TS 团队共享语言/工具,单仓库 monorepo 跑得更顺
  4. 合成已拆为独立微服务,主服务无状态、可水平扩展,分组部署只切配置

性能完全够用——瓶颈在合成服务(Puppeteer)/ PostgreSQL,不在 Web 框架。

Q: 模板编辑器为什么选 Leafer 而不是 Konva / Fabric?

Leafer 在 2024–2025 期间生态活跃,原生支持 Vue 3、SSR 渲染(关键:Puppeteer 能跑同一份代码出图)、矢量节点丰富、性能在大量节点场景下优势明显。

Q: 一定要装 MinIO 吗?能不能直接用 OSS / S3 / COS?

可以。只要把各服务(pf-service、pf-compose-service)config.json 里 s3 段换成兼容的 endpoint + 密钥即可;前端的预签名上传链路天然适配 S3 协议。

Q: 数据库是 MySQL 还是 PostgreSQL?

PostgreSQL 16+(早期版本用过 MySQL,已整体迁移)。Schema 全部 drizzle-orm/pg-core(serial / jsonb / timestamp,用 varchar + $type 代替 enum),连接走 postgres.js。合成 Job 依赖 PostgreSQL 的 FOR UPDATE SKIP LOCKED 做多实例抢占,这是选 PG 的一个直接理由。


模板与编辑器

Q: 同一个模板能否被多个相册引用?

可以。通过 album_templates 中间表,一张模板可被 N 个相册关联,并指定 relationType ∈ {inner, cover, back_cover} 与排序。

Q: 模板上线后改了,已下单未合成的订单受影响吗?

不受影响。order_template_submission_items.sceneJson 在提交时做了快照,合成 Job 优先用该快照,避免管理员改模板影响历史订单。

Q: 字体能不能让用户自己上传?

当前不支持。font_variants 是管理员维度的资源;如果业务必须开放给用户,建议沿用 userId 字段约定(0 全局,非 0 个人),并加上版权审核流程。


合成

Q: 一张图合成大概多久?

简单模板约 0.5–1s;复杂相册页约 1–3s。渲染在独立的 pf-compose-service 里由 Puppeteer Worker 池完成,瓶颈是启动 Page + 字体加载。

Q: 我提交了 20 张图,能不能并行合成?

已经并行。pf-service 侧用 FOR UPDATE SKIP LOCKED 抢占 + asyncPool(3),合成服务侧是 3-Worker Chromium 池,两处并发上限均为 3。要提高吞吐:

  1. 调大合成服务 puppeteer.workers
  2. 扩 pf-compose-service 副本
  3. 注意单机内存——每个 Chromium 实例都不便宜(maxUsesPerWorker 控制重启防泄漏)

Q: 合成失败后怎么办?

  • item 级失败:failReason 写原因,attemptCount++,nextRetryAt = now + 2^n s 自动退避重试,≥3 次永久失败
  • 管理员在 pf-manage 触发重合成(composeStatus 回退 pending)
  • 合成服务不可达也走同一退避路径,无本地 Puppeteer 兜底(主服务已无该能力)

Q: 想把合成产物输出成 PDF / TIFF / 高 DPI 怎么改?

合成产物格式在 pf-compose-service 侧控制:POST /api/compose 的 options.format(png/jpg/webp)与 pixelRatio(提高即高 DPI)。要 TIFF 可在导出后用 sharp 转换。


用户端

Q: 用户端能不能跨端编辑(手机端编了一半 PC 端继续)?

按设计文档当前版本暂不支持。已通过 pinia-persistedstate 把草稿持久化在 localStorage,但没有云端草稿同步。若要加,建议在 order_template_submissions 之外再加一张 submission_drafts 表。

Q: 上传单图能多大?

上传走预签名直传 MinIO(GET /api/.../oss/upload-url → axios.put,前端超时 120s、网络错误重试 1 次),大小主要受限于:

  • 浏览器内存(移动端尤其敏感)
  • 反向代理 client_max_body_size(生产 Nginx 当前 50M)
  • MinIO 对象大小限制

要支持更大文件,把这几处一起调(超大文件可改造为分片 multipart)。

Q: 人脸检测必须开吗?

否。只有模板节点显式声明 faceSafe: true 才会调 face-service;不开启的话整个 face-service 可以不部署,前端走普通自适应裁剪。


集成

Q: 怎么和现有电商主站打通?

参见 电商集成方案 的三种账号方案 + 订单同步 + 合成回调。最小集成只要打通账号 + 订单同步 + 回调三条边界。

Q: pf-manage 的账号和电商主站后台是同一套吗?

不建议合并。电商主站后台是面向运营全局的,pf-manage 仅服务”图模工坊”模块;权限粒度差别很大。若一定要 SSO,对接 POST /api/manage/auth/exchange。

Q: 用户的素材会不会泄露?

只要按部署建议把 MinIO 设为私有桶 + 预签名 URL,外部就拿不到任意素材;CDN 回源也建议走签名 URL。pf-service 内部不会把原图发到任何外部服务。


部署 & 运维

Q: Puppeteer 安装失败 / 启动报缺动态库?

合成已在独立的 pf-compose-service,生产镜像直接用 ghcr.io/puppeteer/puppeteer:24.4.0(自带 Chromium 系统库 + 中日韩字体),基本免踩坑。本地开发:

  • bun compose:install-browser 装 Chromium
  • Linux 缺库可装 chromium 包并设 PUPPETEER_EXECUTABLE_PATH
  • 详见 合成微服务

Q: 我把 config.composition.enabled = false 了,为什么提交还会变成 completed?

检查同一 PostgreSQL 是否被其它 pf-service 实例共享——其它实例 Job 仍在跑(SKIP LOCKED 下多实例都会拉取)。生产建议显式区分 API 组与调度组。

Q: 怎么看一条订单到底卡在哪?

1
2
3
4
5
6
7
8
9
10
-- 订单与提交合成状态
SELECT o.order_no, o.compose_status, o.has_downloaded, s.status, s.created_at, s.updated_at
FROM orders o
JOIN order_template_submissions s ON s.order_id = o.id
WHERE o.order_no = '2025...';

-- 明细 + 失败原因 + 重试台账
SELECT id, template_id, status, fail_reason, attempt_count, next_retry_at
FROM order_template_submission_items
WHERE submission_id = ?;

或直接在 pf-manage 的”合成提交”页打开明细弹窗。

Q: 数据备份怎么做?

  • PostgreSQL:pg_dump 全量 + WAL 归档增量
  • MinIO:mc mirror 到异地桶
  • 模板 sceneJson 都在 PostgreSQL;MinIO 主要是素材/成品

二开

Q: 想加一个新前端(比如小程序)怎么对接?

后端接口都是 HTTP/JSON,鉴权 JWT,小程序端只要按 pf-app 的 API 调用范式接即可。/api/app/* 前缀的接口是面向终端用户的,可以共用。

Q: 想把人脸服务换成识别二维码 / 文字行?

接口协议是稳定的:POST /api/face/detect 接受 imageUrl,返回归一化框 + score。人脸服务现在是 Rust(Axum + ORT),换实现时把同协议 ONNX 放 models/、调整 detector.rs 解码、bump modelVersion(取文件名 stem),调用方零侵入。

Q: 模板能不能批量导入?

当前 pf-manage 单张创建为主。批量可参考 apps/pf-service/scripts/seed_*.ts(如 seed_ai_templates.ts 生成风格套系并上传 MinIO 素材),用 bun scripts/... 一次性把 sceneJson 塞进 templates 表。


关于路线图与维护

  • 路线图见 Roadmap
  • 二开问题欢迎提 issue
  • 涉及商业部署 / 私有化交付请联系仓库主页留的联系方式

站内搜索

没有找到内容!