定位
pf-app 是图模工坊的终端用户入口,专为手机浏览器(H5)设计,覆盖”选模板 → 传图 → 编辑 → 提交合成”全流程。
目标用户:非专业设计人员(普通消费者、企业员工自助下单),核心场景在手机端。
- 框架:Quasar 2.16 + Vue 3.5 + TypeScript 5.9
- 渲染:Leafer 2.x(与 pf-editor 共用)
- 状态:Pinia 3.x + pinia-plugin-persistedstate
- 图片裁剪:Cropper.js 1.6
- 端口:开发环境
8000
主流程
1 | 首页/活动入口 |
页面与组件
1 | apps/pf-app/src/ |
工坊页(Workshop)
工坊页是用户端的主战场,承载所有定制操作。它在内存里维护一份当前 sceneJson 实例——以模板的 sceneJson 为基底,把用户的填值(图片 URL、文字)覆盖到对应节点上,由 Leafer 实时重绘。
1 | ┌─────────── sceneJson (来自模板) ───────────┐ |
提交时只把 userUploads / userTexts 加上模板 id 提交给后端——sceneJson 的”原貌”在后端通过 templateId 反查,避免大 JSON 传输;同时后端会按当前模板版本快照存一份到 order_template_submission_items.sceneJson。
图片处理能力
1. 自适应裁剪(默认)
模板节点的 width / height / fit 已确定,用户传图后系统按比例自动裁剪:
- 普通节点:等比缩放 + 居中裁切(
fit: cover) - 标记
faceSafe: true的节点:先调用 face-service 取人脸框 → 再计算裁剪窗口让人脸尽量居中且不被裁掉
2. 手动裁剪
用户长按图片节点 → 唤起 ImageCropper.vue(Cropper.js)→ 触控拖动调框、旋转、翻转 → 实时预览。
3. 批量上传(相册场景)
ImageUploadSheet.vue 支持一次选数十张:
- 取消单次上传图片数量限制(按设计文档)
- 分片上传适配大文件(单图 ≤ 200MB)
- 上传过程中显示进度、断点续传
- 上传完毕后系统按相册模板顺序自动绑定,用户可拖拽重排
4. 原图模式
支持”不动原图”上传——适用对清晰度极敏感的写真/高清海报,保留 TIFF / 原始 PNG,绕过自动压缩。
文字编辑
文字节点遵循 sceneJson 中的 fontFamily / fontSize / fill / align,用户可在工坊页面的属性子面板修改。可改维度:
- 文字内容
- 字号(受限于节点允许范围)
- 字体(从
font_variants拉取) - 颜色、对齐、行间距
字体加载走 composables/fontPreload.ts——首次进入工坊时按模板用到的 fontFamily 集合预加载 woff2,避免渲染闪烁。
状态与持久化
Pinia store + pinia-plugin-persistedstate 把当前编辑中的草稿持久化到 localStorage:
- 用户中途切到微信、回来还能继续
- 网络断开时本地继续编辑,恢复后再提交
- 草稿与订单/模板绑定,避免串草稿
提交与状态查询
1 | pf-app |
完整路由位于 apps/pf-service/src/routes/projects/pf-app/orderTemplateRoutes.ts。
与 pf-editor 的复用
- 同一个渲染层(Leafer + sceneJson)
- 同一份字体预加载逻辑
- 同一套
ImageCropper / ImagePreview组件 - 共享
packages/*中的 hooks / 工具
差别在交互形态:pf-editor 暴露全部节点属性;pf-app 只允许触达模板里标记为 editable: true 的字段。
移动端优化要点
- 视口适配:所有触控目标 ≥ 44×44 px
- 触摸手势:双指缩放画布、长按出菜单
- 图片预压缩:超 5 MB 的图在前端做一次有损压缩再上传(原图模式除外)
- 网络容错:上传失败自动重试,断点续传
- 字体兜底:远端字体未加载完成时回落到 Quasar 默认字体,不阻塞 UI