Files
workspace/code/app/CLOTHING_OUTFIT_DESIGN.md
T
2026-06-29 15:48:39 +08:00

610 lines
19 KiB
Markdown

# 衣服搭配子模块设计文档
## 1. 背景
在现有家庭 App 中新增「衣服搭配」子模块,用于管理家庭共享的衣物资产,并基于衣物设计、保存、复用搭配方案。
本模块先按 App 内工具设计,不做营销页。界面重点应是图片可浏览、筛选顺手、保存动作明确。
## 2. 目标
- 录入衣服,形成可管理的衣橱。
- 给衣服维护标签/分类,分类支持自定义。
- 设计搭配,选择多件衣服组合成一个搭配方案。
- 保存搭配,搭配也支持标签/分类。
- 后续可基于分类、标签等维度检索衣服和搭配。
## 3. 非目标
第一期暂不做:
- AI 自动搭配。
- 社区分享、公开穿搭广场。
- 电商购买链接。
- 复杂身材数据、尺码推荐。
- 日历穿搭计划。
- 洗护/库存/折旧管理。
- 多成员私有衣橱隔离。
这些能力可以作为后续扩展,不进入第一版主流程。
## 4. 核心用户故事
### 衣服管理
- 作为用户,我可以新增一件衣服,上传图片,填写名称、分类、标签等信息。
- 作为用户,我可以按分类、标签筛选衣服。
- 作为用户,我可以编辑或删除已录入的衣服。
- 作为用户,我可以停用/隐藏不常穿的衣服,而不是必须删除。
- 作为用户,删除被搭配引用的衣服时,我可以选择是否同时删除相关搭配。
### 搭配管理
- 作为用户,我可以从衣橱中选择多件衣服组成一套搭配。
- 作为用户,我可以保存搭配,填写搭配名称、分类、标签等信息。
- 作为用户,我可以查看搭配详情,看到包含的所有衣服。
- 作为用户,我可以编辑搭配中的衣服列表和基础信息。
- 作为用户,我可以删除搭配,删除搭配不会删除搭配中引用的衣服。
### 分类/标签管理
- 作为用户,我可以维护衣服分类,例如上衣、裤子、外套、鞋、包、配饰。
- 作为用户,我可以维护搭配分类,例如通勤、约会、运动、旅行、居家。
- 作为用户,我可以维护标签组,例如尺寸、季节、风格、材质、颜色。
- 作为用户,我可以给衣服和搭配添加多个标签,例如春秋、黑色、正式、宽松、显瘦。
- 衣服标签和搭配标签需要区分,避免两个场景下的标签互相干扰。
## 5. 信息架构
建议一级入口叫「穿搭」或「衣橱」。
模块内建议 3 个主视图:
- 衣橱:衣服列表、筛选、录入入口。
- 搭配:搭配列表、筛选、创建入口。
- 分类:衣服分类、搭配分类、标签维护。
第一期保留独立「分类」页,放在衣服搭配模块的底部 Tab 中;新增/编辑流程里也可以保留快速新建入口,减少录入中断。
## 5.1 已确认规则
- 子模块永远是家庭共享,不做个人私有衣橱。
- 衣服图片必须上传,不允许无图衣服。
- 分类和标签不做默认初始化,由用户自行创建。
- 分类保持单层,不做父子结构。
- 尺寸、季节、风格、颜色等父子结构使用“标签组 -> 标签”表达。
- 衣服标签和搭配标签区分管理。
- 不做颜色结构化字段,颜色这类信息由用户通过标签处理。
- 标签使用表情做视觉识别,不单独配置标签颜色。
- 不做季节、场景固定枚举,季节/场景由用户通过标签或分类自行处理。
- 数据保存优先使用现有公共接口,例如 `data/loadData`、`data/saveData`。
- 尽量都走通用接口;只有通用接口明显无法保证体验或一致性时,再补特殊接口。
- 能在前端完成的能力优先放前端,减少后端特殊接口。
- 删除搭配时,只删除搭配和搭配明细,不删除衣服。
- 删除衣服时,如果衣服没有被搭配引用,直接删除或软删除该衣服。
- 删除衣服时,如果衣服已被搭配引用,需要提示用户是否同时删除相关搭配:
- 用户确认:删除该衣服,同时删除所有引用该衣服的搭配及其明细。
- 用户取消:衣服和搭配都不删除。
## 5.2 搭配编辑模式
第一版采用「自由拖拽画布」模式。
推荐模式:
- 搭配编辑页顶部或主体是固定比例画布,建议 1:1。
- 下方或底部抽屉是衣服选择区,可按分类、标签筛选衣服。
- 用户点击衣服加入画布。
- 画布内衣服支持拖拽移动、缩放、删除。
- 第一版可以先不做旋转,降低手势复杂度。
- 画布内衣服支持置顶/置底,或通过点击选中后调整层级。
- 保存搭配时保存画布布局数据,并生成搭配缩略图。
原因:
- 穿搭本质上是视觉组合,固定槽位会限制用户表达。
- 用户需要自己控制衣服摆放位置,否则操作体验会显得僵硬。
- 自由画布更接近“搭配板”,更符合用户对穿搭设计的预期。
第一版边界:
- 画布比例固定为 1:1,不支持任意画布尺寸。
- 每件衣服记录位置、尺寸、层级;第一版暂不支持旋转。
- 不做撤销/重做。
- 不做自动吸附、对齐辅助线。
- 不做多选。
- 不做复杂贴纸、文字、背景。
- 画布背景固定为浅色或透明。
后续扩展:
- 支持旋转。
- 支持撤销/重做。
- 支持吸附、对齐线、居中线。
- 支持背景模板。
- 支持文字说明或贴纸。
## 6. 数据对象草案
### 衣服 b_clothing_clothes
字段草案:
- id
- family_id
- name
- image_file_key
- category_id
- brand
- remark
- status
- sort_number
- create_time
- update_time
- create_by
- update_by
说明:
- `family_id`:衣服属于家庭空间。
- `image_file_key`:走现有 S3 规则,上传到 `family_id/年/月/日/...`。
- `image_file_key` 必填。
- `status`:建议 1 启用,0 停用。
- 颜色、季节这类检索信息不做结构化字段,由标签承载。
### 搭配 b_clothing_outfit
字段草案:
- id
- family_id
- name
- cover_file_key
- layout_json
- category_id
- remark
- status
- sort_number
- create_time
- update_time
- create_by
- update_by
说明:
- `cover_file_key` 建议保存一张搭配缩略图,用于搭配列表快速展示。
- 缩略图只保存生成后的结果,列表不实时拼图。
- 缩略图由前端生成后通过 S3 上传,保存时写入 `cover_file_key`。
- 如果缩略图生成失败,可以降级使用搭配内第一件衣服图片作为封面。
- `layout_json` 保存画布级配置,例如画布宽高比例、背景、版本号等。
### 搭配明细 b_clothing_outfit_clothes
字段草案:
- id
- outfit_id
- clothes_id
- x
- y
- width
- height
- z_index
- sort_number
- create_time
说明:
- 一套搭配包含多件衣服。
- `x/y/width/height` 建议使用归一化比例值,范围 0 到 1,便于不同屏幕尺寸还原。
- `z_index` 用于控制叠放层级。
- `sort_number` 可作为列表排序或备用顺序。
- 第一版不保存旋转角度,后续如果支持旋转再增加 `rotate` 字段。
### 分类 b_clothing_category
字段草案:
- id
- family_id
- name
- type
- sort_number
- status
说明:
- `type = 0` 衣服分类。
- `type = 1` 搭配分类。
- 衣服分类和搭配分类可以共用一张表,减少表数量。
- 分类保持单层,不设置 `parent_id`。
### 标签组 b_clothing_tag_group
字段草案:
- id
- family_id
- name
- type
- sort_number
- status
说明:
- `type = 0` 衣服标签组。
- `type = 1` 搭配标签组。
- 示例:尺寸、季节、风格、材质、颜色。
- 标签组由用户自定义,不做默认初始化。
### 标签 b_clothing_tag
字段草案:
- id
- family_id
- tag_group_id
- name
- type
- emoji
- sort_number
- status
说明:
- `type = 0` 衣服标签。
- `type = 1` 搭配标签。
- `tag_group_id` 指向所属标签组,例如“XL”属于“尺寸”。
- `emoji` 用于标签视觉识别。颜色不做结构化配置。
### 标签关联 b_clothing_tag_relation
字段草案:
- id
- family_id
- target_type
- target_id
- tag_id
说明:
- `target_type = 0` 衣服。
- `target_type = 1` 搭配。
- 一个衣服/搭配可以有多个标签。
## 7. 第一版流程
### 新增衣服
1. 进入「衣橱」。
2. 点击新增。
3. 上传或拍摄衣服图片。
4. 填写名称、分类、标签。
5. 保存。
6. 返回衣橱列表并刷新。
校验规则:
- 图片必填。
- 分类可以为空,但如果用户输入新分类,应自动创建分类后再保存衣服。
- 标签可以为空,支持选择已有标签或新建标签。
### 新增搭配
1. 进入「搭配」。
2. 点击新增。
3. 进入自由画布编辑页。
4. 从底部衣服选择区添加衣服到画布。
5. 在画布中拖拽、缩放衣服,调整层级。
6. 填写搭配名称、分类、标签。
7. 生成搭配缩略图并上传。
8. 保存搭配、搭配明细、画布布局和缩略图 key。
9. 返回搭配列表并刷新。
校验规则:
- 至少选择 1 件衣服。
- 分类可以为空。
- 标签可以为空。
- 画布内每件衣服必须有有效的位置和尺寸。
### 自定义分类/标签组/标签
第一版采用组合方案:
- 在底部 Tab 中提供独立「分类」页,统一维护衣服/搭配分类、标签组、标签。
- 在新增/编辑表单里保留快速新建分类、标签组、标签能力,减少录入中断。
### 删除衣服
1. 用户点击删除衣服。
2. 后端检查是否存在搭配引用。
3. 如果没有引用,删除衣服。
4. 如果有引用,前端提示“该衣服已被 X 个搭配使用,是否同时删除这些搭配?”
5. 用户确认后,后端在同一事务中删除衣服、相关搭配、相关搭配明细、相关标签关联。
6. 用户取消后,不执行任何删除。
### 删除搭配
1. 用户点击删除搭配。
2. 后端删除搭配、搭配明细、搭配标签关联。
3. 不删除任何衣服。
### 衣服快速记账
这是后置功能,可以最后再做。
1. 用户在编辑衣服页点击记账按钮。
2. 页面弹出新增记账 BottomSheet。
3. BottomSheet 复用现有记账新增能力。
4. 可选地把衣服名称带入备注,例如“衣服:白色衬衫”。
5. 保存成功后关闭 BottomSheet,不影响衣服编辑状态。
## 8. MVP 范围建议
第一期建议做:
- 衣服 CRUD。
- 搭配 CRUD。
- 衣服分类自定义。
- 搭配分类自定义。
- 衣服/搭配标签组自定义。
- 衣服/搭配标签多选和新建。
- 图片上传。
- 自由拖拽画布。
- 画布内衣服拖拽、缩放、层级调整、删除。
- 搭配缩略图生成。
- 基础筛选:分类、标签。
第一期暂缓:
- AI 搭配推荐。
- 穿搭日历。
- 多成员衣橱隔离。
- 画布旋转、撤销/重做、吸附对齐、多选。
- 衣服编辑页快速记账。
- 统计分析。
## 9. 剩余待确认问题
暂无。
## 10. 初步技术建议
- 数据库建议新增独立表,不混入现有记账分类。
- 图片上传复用现有 S3 上传接口,路径遵循 `family_id/年/月/日`。
- 衣服、搭配、分类、标签组、标签保存优先复用当前公共接口 `data/saveData`。
- 删除衣服前先用公共查询接口检查搭配引用;用户确认后,用 `data/saveData` 批量删除衣服、相关搭配、明细和标签关联。
- 分类/标签组/标签创建也优先走公共接口。
- 自由画布数据优先直接存入搭配明细字段;如果后续字段膨胀,再考虑使用 `layout_json` 承载更复杂的画布数据。
- 搭配缩略图由前端生成,尺寸可先定为 512x512,S3 路径同样遵循 `family_id/年/月/日`。
- 当前 `react-native-view-shot` 支持 `jpg/png`,首版使用 512x512 JPG;后续如果补图片转换链路,再升级为 WebP。
- 前端缩略图生成可考虑使用 `react-native-view-shot` 截取画布视图,再走现有 S3 上传。
- 衣服快速记账复用现有新增记账 BottomSheet,作为后置功能实现。
- 前端状态可以新增 `clothing` store,负责衣服、搭配、分类、标签组、标签缓存。
## 11. 下一步
已确认核心业务规则。下一步可以进入:
1. 数据库表结构设计。
2. 页面与交互流程设计。
3. 公共接口调用方案设计。
4. 第一版任务拆分。
缩略图样式可以在页面流程设计阶段继续细化。
## 12. 实施计划
说明:
- 每一步完成后,把 `[ ]` 改成 `[x]`。
- 严格按阶段推进,前一阶段没有确认前,不进入下一阶段。
- 默认优先使用通用接口;遇到通用接口明显无法覆盖的场景,再单独讨论是否增加特殊接口。
### 阶段 1:数据库表结构
- [x] 设计 `b_clothing_clothes` 表结构。
- [x] 设计 `b_clothing_outfit` 表结构。
- [x] 设计 `b_clothing_outfit_clothes` 表结构,包含画布坐标、尺寸、层级字段。
- [x] 设计 `b_clothing_category` 表结构,分类保持单层。
- [x] 设计 `b_clothing_tag_group` 表结构。
- [x] 设计 `b_clothing_tag` 表结构,关联 `tag_group_id`。
- [x] 设计 `b_clothing_tag_relation` 表结构。
- [x] 补充索引设计,例如 `family_id/status/type/sort_number`。
- [x] 生成 SQL 文件并确认命名、字段类型、默认值。
- [x] 执行 SQL 到 dev 数据库并验证 7 张表已创建。
产出文件:
- `app-go/db/clothing.sql`
验收标准:
- 表名全部使用 `b_clothing_` 前缀。
- 不出现 `ref` 表名。
- 分类无父子结构。
- 标签组和标签可以表达尺寸、季节、风格等自定义属性。
### 阶段 2:前端基础模型与公共接口封装
- [x] 新增衣服、搭配、分类、标签组、标签相关 TypeScript 类型。
- [x] 新增 `clothing` store,管理衣服、搭配、分类、标签组、标签缓存。
- [x] 在 `clothing` store 中封装基于公共接口的查询方法。
- [x] 在 `clothing` store 中封装基于公共接口的保存方法。
- [x] 在 `clothing` store 中封装图片上传复用逻辑,路径继续走 `family_id/年/月/日`。
- [x] 不新增 services 层,避免重复封装。
产出文件:
- `app-rn/src/types/clothing.ts`
- `app-rn/src/store/clothing.ts`
- `app-rn/src/store/index.ts`
验收标准:
- 前端类型和数据库字段一致。
- 查询和保存优先使用现有 `loadData`、`saveData`。
- 不引入不必要的后端特殊接口。
### 阶段 3:衣服管理
- [x] 新增衣橱列表页。
- [x] 支持按分类、标签筛选衣服。
- [x] 新增衣服编辑页或 BottomSheet。
- [x] 衣服图片必填,支持上传图片。
- [x] 支持创建或选择分类。
- [x] 支持创建或选择标签组/标签。
- [x] 支持编辑衣服。
- [x] 支持删除衣服前检查搭配引用。
- [x] 如果存在搭配引用,提示是否同时删除相关搭配。
- [x] 用户确认后批量删除衣服、相关搭配、搭配明细、标签关联。
- [x] 用户取消后不删除任何数据。
产出文件:
- `app-rn/src/app/clothes/(tabs)/_layout.tsx`
- `app-rn/src/app/clothes/(tabs)/home/index.tsx`
- `app-rn/src/app/clothes/(tabs)/outfit/index.tsx`
- `app-rn/src/app/clothes/edit/index.tsx`
- `app-rn/src/components/clothing/ClothingImage.tsx`
验收标准:
- 无图衣服不能保存。
- 删除衣服的引用提示逻辑正确。
- 删除搭配时不会误删衣服。
### 阶段 4:分类、标签组、标签管理
- [x] 在衣服编辑流程中支持快速新建分类。
- [x] 在衣服编辑流程中支持快速新建标签组。
- [x] 在衣服编辑流程中支持在标签组下新建标签。
- [x] 标签支持 `emoji`。
- [x] 衣服标签和搭配标签按 `type` 区分。
- [x] 独立分类/标签管理页放到底部 Tab。
- [x] 独立管理页支持维护衣服分类、搭配分类。
- [x] 独立管理页支持维护衣服标签组/标签、搭配标签组/标签。
产出文件:
- `app-rn/src/app/clothes/(tabs)/_layout.tsx`
- `app-rn/src/app/clothes/(tabs)/manage/index.tsx`
验收标准:
- 分类单层。
- 标签必须归属标签组。
- 衣服标签和搭配标签互不混用。
### 阶段 5:自由拖拽搭配画布
- [x] 新增搭配列表页。
- [x] 新增搭配编辑页。
- [x] 搭配编辑页提供 1:1 固定比例画布。
- [x] 从衣服选择区添加衣服到画布。
- [x] 支持画布内拖拽移动。
- [x] 支持画布内缩放。
- [x] 支持删除画布中的衣服。
- [x] 支持调整层级,例如置顶、置底。
- [x] 保存每件衣服的 `x/y/width/height/z_index`。
- [x] 坐标和尺寸使用 0 到 1 的归一化比例。
- [x] 重新打开搭配时准确还原画布。
产出文件:
- `app-rn/src/app/clothes/(tabs)/outfit/index.tsx`
- `app-rn/src/app/clothes/outfit/edit/index.tsx`
第一版不做:
- 旋转。
- 撤销/重做。
- 多选。
- 吸附线和对齐线。
- 文字、贴纸、背景模板。
验收标准:
- 不同屏幕尺寸下画布能稳定还原。
- 画布操作不卡顿。
- 保存后再次进入,布局不丢失。
### 阶段 6:搭配保存与缩略图
- [x] 引入或确认 `react-native-view-shot`。
- [x] 保存搭配前截取画布生成缩略图。
- [x] 缩略图上传到 S3。
- [x] 保存搭配主表 `cover_file_key`。
- [x] 保存搭配明细和画布布局。
- [x] 搭配列表使用 `cover_file_key` 展示。
- [x] 缩略图生成失败时,降级使用第一件衣服图片作为封面。
产出文件:
- `app-rn/src/app/clothes/outfit/edit/index.tsx`
- `app-rn/src/store/clothing.ts`
验收标准:
- 搭配列表不实时拼图,只加载缩略图。
- 缩略图路径遵循 `family_id/年/月/日`。
- 保存失败时不产生错误的半成品数据。
### 阶段 7:搭配管理
- [x] 支持搭配详情查看。
- [x] 支持编辑搭配基础信息。
- [x] 支持编辑搭配画布。
- [x] 支持删除搭配。
- [x] 删除搭配时删除搭配明细和搭配标签关联。
- [x] 删除搭配时不删除衣服。
产出文件:
- `app-rn/src/app/clothes/(tabs)/outfit/index.tsx`
- `app-rn/src/app/clothes/outfit/detail/[id]/index.tsx`
- `app-rn/src/app/clothes/outfit/edit/index.tsx`
验收标准:
- 搭配 CRUD 完整。
- 删除搭配不影响衣橱。
### 阶段 8:收尾与体验优化
- [x] 补充空状态。
- [x] 补充加载状态。
- [x] 补充保存中和上传中状态。
- [x] 补充错误提示。
- [x] 检查移动端小屏布局。
- [x] 检查图片加载失败兜底。
- [x] 跑 lint/format/type check。
- [x] 根据实际结果更新本文档完成状态。
验证结果:
- `oxfmt --check` 通过。
- `oxlint` 通过。
- `tsc --noEmit` 已执行,仅剩 `src/components/iconfont/*` SVG 类型问题,本阶段不处理。
验收标准:
- 核心流程从新增衣服到保存搭配可完整走通。
- 异常状态有明确反馈。
- 文档计划状态和代码实现保持一致。
### 阶段 9:后置功能:衣服快速记账
- [ ] 在衣服编辑页增加记账入口。
- [ ] 点击后弹出新增记账 BottomSheet。
- [ ] 复用现有记账新增能力。
- [ ] 可选地把衣服名称带入备注。
- [ ] 保存成功后关闭 BottomSheet。
验收标准:
- 快速记账不影响衣服编辑状态。
- 记账保存逻辑与现有记账模块一致。