# 模板编辑页与任务完成入口调整设计 ## 1. 背景 当前模板模块存在两个问题: 1. 模板制作任务完成后,`TemplateMakeTaskPage` 提供的是“查看模板详情”入口,但用户当前真实后续动作是补充和确认模板基本信息。 2. 现有 `TemplateDetailPage` 同时承担了详情展示和信息编辑职责,页面边界不清晰,不符合“新加一个编辑页面,并且只能编辑模板基本信息”的目标。 本次设计将模板详情与模板编辑拆分: - 保留现有模板详情页作为展示页。 - 新增独立模板编辑页,只允许编辑模板基本信息。 - 模板制作任务完成后的主按钮改为“编辑模板信息”,引导用户进入新编辑页。 ## 2. 目标 本次改动完成后,应满足以下目标: 1. 模板制作任务成功后,用户可直接进入独立的“编辑模板信息”页面。 2. 模板详情页继续保留为展示用途,不再承担任务完成后的主编辑入口。 3. 编辑页只能修改模板基本信息,不允许修改素材、封面、模板包和任务相关数据。 4. 前后端都要建立独立的“读取模板基本信息 / 更新模板基本信息”链路。 ## 3. 非目标 以下内容不在本次范围内: 1. 不重做模板详情页整体视觉结构。 2. 不允许在编辑页重新上传或替换参考图、AI 模特、服装、背景。 3. 不允许在编辑页修改模板封面图或模板包 URL。 4. 不处理模板重新生成、任务重试、任务取消等能力。 5. 不改造模板列表的整体交互模式,列表仍然以详情页为主要查看入口。 ## 4. 目标交互 ### 4.1 任务页 当模板制作任务状态为 `STEP2_SUCCESS` 时: - 当前按钮文案从“查看模板详情”改为“编辑模板信息”。 - 跳转目标从模板详情页改为模板编辑页。 任务页中的“返回模板列表”按钮保持不变。 ### 4.2 模板详情页 模板详情页继续保留,作为展示页存在: - 模板列表点击卡片仍然进入详情页。 - 详情页展示模板封面、生成状态、统计信息、使用结果等现有内容。 - 本次不要求将详情页完全去编辑化,但任务完成态不再把它作为首要后续入口。 ### 4.3 模板编辑页 新增独立模板编辑页,路径与职责如下: - 路由:`/:locale/templates/:templateId/edit` - 职责:仅编辑模板基本信息 允许编辑的字段: 1. 模板名 `templateName` 2. 状态 `status` 3. 分类 `category` 4. 标签 `tags` 5. 描述 `description` 不允许编辑的字段: 1. 封面图 `coverUrl` 2. 模板包 `templateUrl` 3. 参考图 `refHairUrl` 4. 模特图 `modelUrl` 5. 服装图 `clothesUrl` 6. 背景图 `backgroundUrl` 7. 任意任务状态与任务资源字段 页面布局采用现有工作台编辑页骨架: - 顶部使用统一的 `stylist-workbench-top ipad-top-space-margin mb-2` - 提供返回、取消、保存按钮 - 主体使用标准表单布局 ## 5. 路由与页面结构 ### 5.1 前端路由 新增路由: ```ts templateEdit: '/:locale/templates/:templateId/edit' ``` 路由注册到 `App.tsx`,使用登录保护,与其他工作台页面一致。 ### 5.2 页面职责划分 - `TemplateMakeTaskPage` - 任务状态轮询 - 成功后引导进入编辑页 - `TemplateDetailPage` - 模板展示页 - `TemplateEditPage` - 模板基本信息编辑页 ## 6. 前端数据流 ### 6.1 任务成功后的跳转 1. 用户在 `TemplateMakeTaskPage` 轮询到 `STEP2_SUCCESS` 2. 页面显示“编辑模板信息”按钮 3. 点击后跳转到 `/:locale/templates/:templateId/edit` ### 6.2 编辑页加载 1. 页面根据 `templateId` 请求模板基本信息 2. 请求成功后回填表单 3. 请求失败则显示错误或未找到状态 ### 6.3 编辑页保存 1. 用户修改模板基本信息 2. 点击保存按钮 3. 前端调用更新接口 4. 更新成功后保留在当前页,并提示保存成功 5. 更新失败时显示错误提示,不清空现有表单内容 ## 7. 后端接口设计 ### 7.1 获取模板基本信息 新增接口: ```http GET /api/v1/templates/:templateId ``` 职责: - 按模板 ID 返回模板基本信息 - 校验模板存在 - 校验模板属于当前登录发型师 返回字段最少包含: ```json { "id": "43", "templateName": "柔和层次长发", "status": "DRAFT", "category": "LONG", "tags": ["层次", "首次建议"], "description": "适合轻盈感修饰", "coverUrl": "https://example.com/cover.jpg", "templateUrl": "https://example.com/template.zip" } ``` 说明: - 编辑页虽然不允许修改 `coverUrl` / `templateUrl`,但允许后端返回,以便页面按需展示只读信息。 ### 7.2 更新模板基本信息 新增接口: ```http PATCH /api/v1/templates/:templateId ``` 仅允许更新以下字段: ```json { "templateName": "空气感中长发", "status": "PUBLIC", "category": "MEDIUM", "tags": ["空气感", "层次"], "description": "适合脸部轮廓柔化" } ``` 后端必须保证: 1. 只能更新允许字段 2. 不得覆盖模板封面、模板包 URL、素材 URL、任务状态等字段 3. 模板不存在时返回未找到错误 4. 模板不属于当前发型师时返回未找到或无权限错误 ## 8. 后端服务设计 模板模块新增两类能力: 1. `getById(stylistId, templateId)` 2. `updateBasicInfo(stylistId, templateId, dto)` 实现原则: - 以 `hair_template` 为唯一事实来源 - 查询和更新都按 `hairstylist_id + id + is_deleted = 0` 做范围限制 - `tags` 在数据库中仍按现有约定以逗号串存储,接口层负责数组与字符串之间的转换 ## 9. 数据边界 ### 9.1 可写字段边界 本次编辑页只能修改: - `template_name` - `status` - `category` - `tags` - `description` ### 9.2 不可写字段边界 以下字段必须保持只读: - `cover_url` - `template_url` - `ref_hair_url` - `model_url` - `clothes_url` - `background_url` - `is_system_template` - 任务表 `hair_template_make_task` 的全部字段 ## 10. 错误处理 ### 10.1 前端 - 加载失败:显示加载失败提示 - 未找到:显示模板不存在提示 - 保存失败:显示后端返回错误,不清空表单 - 保存中:按钮禁用,避免重复提交 ### 10.2 后端 - 模板不存在:返回 404 - 越权访问:返回 404 或统一业务未找到错误 - DTO 校验失败:返回 400 ## 11. 测试策略 ### 11.1 前端 至少覆盖以下场景: 1. 任务页成功按钮文案变为“编辑模板信息” 2. 任务页成功按钮跳转到 `/templates/:templateId/edit` 3. 编辑页路由可访问 4. 编辑页可加载模板基本信息并完成回填 5. 编辑页保存时只提交允许字段 ### 11.2 后端 至少覆盖以下场景: 1. `GET /templates/:templateId` 成功返回模板基本信息 2. `GET /templates/:templateId` 对不存在模板返回 404 3. `PATCH /templates/:templateId` 可更新基本信息字段 4. `PATCH /templates/:templateId` 不会改动非允许字段 5. 越权访问返回未找到或拒绝访问 ## 12. 验收标准 满足以下条件即视为本次需求完成: 1. 模板制作任务完成页主按钮改为“编辑模板信息” 2. 点击后进入新建的模板编辑页 3. 编辑页只允许修改模板名、状态、分类、标签、描述 4. 后端存在对应的读取与更新接口 5. 模板详情页仍然保留为展示入口 6. 前后端相关测试通过