# 衣服搭配子模块设计文档 ## 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。 验收标准: - 快速记账不影响衣服编辑状态。 - 记账保存逻辑与现有记账模块一致。