--- name: 前端同步后端AI穿搭待保存改造 overview: 跟进后端本轮改动:穿搭对象新增 status(1正常/2封禁/3待保存)、未保存 AI 穿搭 7 天自动清理、任务快照 15 分钟。前端新增 pages/ai-pending 管理页(待保存/已保存分段,支持保存、删除、重新生成、查看详情),我的穿搭只保留手工创建(source=1)并在顶部加入口,同步统一 status 展示口径与超期/清理兜底文案。 design: styleKeywords: - 零彩色灰阶 - 杂志排版 - 发丝线分层 - 毛玻璃悬浮层 - 极简克制 fontSystem: fontFamily: Songti-SC, PingFang-SC heading: size: 68rpx weight: 400 subheading: size: 34rpx weight: 600 body: size: 30rpx weight: 400 colorSystem: primary: - "#0A0A0A" - "#1C1C1E" - "#6E6E73" background: - "#FFFFFF" - "#F7F7F5" - "#EFEFED" text: - "#0A0A0A" - "#6E6E73" - "#AEAEB2" functional: - "#C9C9CE" - "#B9B9BE" - "#D2D2D7" todos: - id: status-contract content: 补 OutfitItem.status 类型,新增 utils/outfit-status.ts 与 utils/outfit-cover.ts 收敛状态口径与封面组装 status: completed - id: my-outfits-entry content: 我的穿搭改为只取 source=1,改用统一状态胶囊并新增 AI 穿搭入口卡片与待保存角标 status: completed dependencies: - status-contract - id: pending-page content: 新增 pages/ai-pending 页面:待保存/已保存分段、保存/删除/重新生成/详情与 7 天清理提示 status: completed dependencies: - status-contract - id: ai-recommend-entry content: AI 推荐页接入 AI 穿搭入口,90402 文案改为引导并补换一套时的未保存提示 status: completed - id: detail-status content: 穿搭详情页支持待保存直接保存、封禁态只读并隐藏管理操作 status: completed dependencies: - status-contract - id: qa-verify content: 用 [subagent:code-explorer] 与 [skill:lsp-code-analysis] 核对引用点,用 [skill:playwright-cli] 对照参考稿,跑 tsc 与静态审计并输出真机验收清单 status: completed dependencies: - my-outfits-entry - pending-page - ai-recommend-entry - detail-status --- ## 产品概述 后端已完成 AI 推荐异步化与穿搭状态体系改造(穿搭对象带 `status`:正常 / 封禁 / 待保存,且超过 7 天未保存的 AI 推荐由后端自动清理)。前端本轮跟进:把 AI 生成的穿搭从「我的穿搭」中完全独立出来,收进新页面「AI 穿搭」统一管理,让用户可随时找回、保存或清理 AI 生成结果。 ## 核心功能 - **新增「AI 穿搭」页**:分「待保存 / 已保存」两段;待保存项支持 保存到我的穿搭、查看详情、删除、重新生成;已保存项仅查看(删除走详情页既有入口) - **待保存说明与超期兜底**:页面顶部说明「保存后进入「我的穿搭」;超过 7 天未保存将自动清理」;保存时若已被清理,给出「这套搭配已被清理,请重新生成」的明确提示并移出列表 - **我的穿搭只留手工创建**:列表请求按来源过滤,AI 穿搭不再混入;顶部新增「AI 穿搭」入口卡片,存在待保存项时显示数量角标 - **AI 推荐页打通入口**:「场景抽屉」底部可进入「AI 穿搭」;生成结果过期提示里引导用户去「AI 穿搭」查看是否已生成;重新生成前提示上一套未保存的推荐去哪找 - **穿搭详情页状态化**:待保存的 AI 穿搭在详情页可直接保存;已封禁的穿搭只读展示,隐藏全部管理操作 - **删除二次确认**:删除 AI 生成结果前弹玻璃确认层,说明该操作不可恢复 ## 视觉效果 延续现有零彩色灰阶杂志风:衬线大标题 + 小字号大写 eyebrow、下划线式文字分段、发丝线分隔、直角卡片配无缝拼图封面、悬浮玻璃操作条与玻璃弹层。新的操作行以「实心黑主按钮 + 无衬线文字按钮」排布,待保存用实心黑胶囊、已封禁以降透明度呈现,保持全站只有白与灰阶。 ## 技术栈 - 原生微信小程序(TypeScript + WXML + WXSS),无构建脚本,沿用 `miniprogram-api-typings` - 复用现有 v2 设计系统:`app.wxss` 令牌与通用类、`styles/icons.wxss`(CSS mask 单色图标)、`components/{navigation-bar, empty-state, v2-overlay}` - 复用现有请求与工具层:`utils/request`、`utils/logger`、`utils/paged`(`normalizePaged / mergePaged / hasMorePaged`)、`utils/nav`(`navScroll`)、`utils/tabbar` ## 实现方案 ### 契约对齐(与后端已确认的真实行为) - `GET /outfit` 请求参数为 `{ page, page_size, is_public?, source? }` —— **只支持 source 过滤,没有 status 过滤**;DAO 不会过滤 `status=3 / status=2` - `OutfitCreateResponse` 已带 `status`(`1` 正常 / `2` 封禁 / `3` 待保存),列表、详情、创建响应都有 - `GET /outfit/community` 固定 `is_public=2 AND audit_status=2 AND status=1`,社区天然不含待保存与封禁 - `POST /ai-recommend/save`:`status=3` → 置 `1`;已为 `1` → 幂等返回 nil;已被清理 → `40000`;封禁 → `40003` - `DELETE /outfit/:uuid` 可用(事务删明细 + 主表) - 待保存 AI 穿搭 7 天后由后端每小时清理一次(软删除,列表与详情立即不可见) ### 关键决策 1. **我的穿搭用服务端过滤**:请求带 `source=1`(后端现成参数),分页 `total` 正确、无需客户端剔除,彻底避免「客户端过滤导致某页全被剔除、列表越翻越空」的分页塌陷问题。 2. **AI 穿搭页用单分页流 + 客户端拆段**:一次 `source=2` 的累积数组,渲染时派生成「待保存(status=3)/ 已保存(status=1)」两段;`hasMore` 只看原始分页是否满额(`hasMorePaged(all, total, pageSize)`)。保存成功后**本地迁移**(把该项从待保存段移入已保存段并置本地 status=1),不重新请求,避免闪屏与流量。 3. **状态口径收敛为单一事实来源**:新增 `utils/outfit-status.ts`,输出胶囊文案 + 类名、以及 `isPendingSave / isBanned` 判定,供 outfit / ai-pending / outfit-detail 三处共用,杜绝同一条语义在三个文件各写一遍 if-else。 4. **复用优先、最小改面**:新页面结构直接套用已上线验证的 outfit 页模式(`.head / .segbar / 骨架 / empty-state / 卡片 / float-duo`);把两页共用的无缝拼图封面(`.collage` 系列样式 + 封面组装函数)上提为共享资产,避免复制粘贴后视觉分叉。 5. **入口计数不追求全量准确**:我的穿搭页 `onShow` 静默拉一页 `source=2&page_size=20` 统计 `status===3` 数量用于角标引导;请求失败或超页则只显示入口不显示数字,避免为角标做 N 次翻页。 6. **口径提示(需在实现中保持一致)**:按已确认口径,所有 `source=2` 穿搭只在「AI 穿搭」页查看,因此「保存到我的穿搭」按钮语义为「保存为正式穿搭(status 3→1)」,保存后该项进入 AI 穿搭页的「已保存」段而**不进入「我的穿搭」列表**;若后续希望保存后的 AI 穿搭回流,只需把 `source=1` 过滤改为「source=1 或 (source=2 且 status=1)」,改动集中在一处。 ### 状态流转 ```mermaid flowchart LR A[AI 推荐生成] --> B[落库 status=3 待保存] B --> C[AI 穿搭页 · 待保存段] C -->|POST /ai-recommend/save| D[status=1 已保存] D --> E[AI 穿搭页 · 已保存段] C -->|DELETE /outfit/:uuid| F[本地移除] C -.->|超过 7 天被后端清理后 save| G[40000 提示已被清理] ``` ### 性能与可靠性 - 列表渲染只对累积数组做一次 `filter`,复杂度 O(n),n 为已加载条数(每页 20),无额外遍历 - 待保存计数为单次静默请求(失败降级不打扰用户),不阻塞首屏 - 保存/删除均加 loading 防抖,避免重复提交;定时器与请求回调统一由 `reqSeq` 防串页 - 所有错误路径必须有可见出口:`40000`(已被清理)、`40002`(删除失败)、网络异常,均弹层或 toast 明示,禁止静默 ## 目录结构(仅列受影响文件) ``` miniprogram/ ├── app.json # [MODIFY] pages 数组末尾注册 pages/ai-pending/ai-pending ├── app.wxss # [MODIFY] 上移共用「无缝拼图封面」样式(.collage/.cg/.pic/.ph/.cg-more/.cg-badge),供穿搭页与 AI 穿搭页共用 ├── types/models.ts # [MODIFY] OutfitItem 补 status: number(1 正常 2 封禁 3 待保存),与后端 OutfitCreateResponse 对齐 ├── utils/outfit-status.ts # [NEW] 状态口径单一事实来源:胶囊文案+类名、isPendingSave/isBanned ├── utils/outfit-cover.ts # [NEW] 拼图封面组装:由 items 取前 4 件图片、生成 4/3/2/1 分格类名与 +N 角标、空数据补线稿格 ├── pages/ai-pending/ai-pending.json # [NEW] usingComponents 声明 navigation-bar / empty-state / v2-overlay(相对路径 ../../components/...) ├── pages/ai-pending/ai-pending.wxml # [NEW] 页头 + 下划线分段(待保存/已保存)+ 说明行 + 卡片列表(封面/名称/场景胶囊/件数/时间)+ 操作行 + 骨架 + 空态 + 删除确认弹层 ├── pages/ai-pending/ai-pending.wxss # [NEW] 页面级样式:入口说明行、卡片操作行(ink 主按钮 + 文字按钮)、角标;拼图卡与全局类一律复用 app.wxss ├── pages/ai-pending/ai-pending.ts # [NEW] 分页拉取 source=2 + 按 status 拆段 + 保存/删除/重新生成/详情 + 下拉刷新与触底加载 ├── pages/outfit/outfit.ts # [MODIFY] 我的穿搭请求带 source=1;getStatusText 收敛到共享口径;新增待保存计数与跳转 AI 穿搭页 ├── pages/outfit/outfit.wxml # [MODIFY] 我的穿搭分段下新增「AI 穿搭」入口卡片(含待保存角标) ├── pages/outfit/outfit.wxss # [MODIFY] 入口卡片样式;删除已上移到 app.wxss 的拼图封面重复定义 ├── pages/ai-recommend/ai-recommend.ts # [MODIFY] 新增进入 AI 穿搭页;90402 文案引导 + 弹层加「去看看」;换一套确认文案补未保存提示 ├── pages/ai-recommend/ai-recommend.wxml # [MODIFY] 场景抽屉底部新增「查看我的 AI 穿搭」文字入口 ├── pages/outfit-detail/outfit-detail.ts # [MODIFY] 待保存态保存逻辑(含防抖与 40000 兜底) └── pages/outfit-detail/outfit-detail.wxml # [MODIFY] 待保存显示「保存到我的穿搭」并隐藏公开;封禁态只读、隐藏更多入口与状态提示行 ``` ## 关键结构(供三个模块共用的状态口径) ```ts export type OutfitStatusPill = { text: string; cls: string } export type OutfitStatusLike = { status?: number; source?: number; is_public?: number } // 待保存(3) 优先于来源判定;封禁(2) 降透明度;AI 已保存(1 且 source=2) 用实心黑胶囊 export function outfitStatusPill(o: OutfitStatusLike): OutfitStatusPill export function isPendingSave(o: OutfitStatusLike): boolean export function isBanned(o: OutfitStatusLike): boolean ``` ## 实现要点(执行注意) - 单位统一 rpx(v2 的 px×2);只允许使用 `app.wxss` 令牌与既有通用类,禁止新增色值(零彩色审计会拦截) - `empty-state` / `v2-overlay` 等组件为 `styleIsolation: apply-shared`,页面样式不要反向覆盖组件内部类 - 日志统一 `logger` + 模块名常量(新页 `LOG = 'ai-pending'`),失败一律 warn 级并带 `code`,不打日志敏感信息 - 工作区已有未提交改动(outfit / ai-recommend / outfit-detail / clothes-detail 等),本轮改动必须叠加在其之上,不回溯、不重构无关逻辑 - 本环境无法启动微信开发者工具,视觉只做静态核对,最终以真机预览为准 ## 设计说明 新增页面严格沿用既有 v2 零彩色灰阶杂志风设计系统,不引入任何新风格要素:颜色只取灰阶令牌,衬线字体用于大标题与数字,无衬线用于正文与按钮,0.5px 发丝线替代边框,仅胶囊/抽屉/小控件使用圆角,统一 `cubic-bezier(.32,.72,0,1)` 动效与 `scale(.97)` 按压反馈。 ## 页面区块设计(AI 穿搭页,自上而下) 1. **顶部导航**:透明起点为 34px 左对齐衬线大标题,向下滚动收缩为居中玻璃小标题,右侧无操作项。 2. **页头**:10px 大写字距 eyebrow「AI Styling」+ 衬线 display「AI 穿搭」,左右 20px 内边距。 3. **下划线式文字分段**:待保存 / 已保存,选中项黑色加粗 + 2px 实心黑下划线,未选中为中性灰,左右滑动不折行。 4. **待保存段**:首行 13px 中性灰说明「保存后进入「我的穿搭」;超过 7 天未保存将自动清理」;卡片为直角无缝拼图封面(4/3/2/1 分格,超出显示 +N 角标,件数胶囊叠右下),下方名称(17px/600)+ 场景描边胶囊 + 生成时间;卡片底部操作行:实心黑主按钮「保存到我的穿搭」占满剩余宽度,「重新生成」「删除」为 14px 中性灰文字按钮。 5. **已保存段**:同款卡片但仅展示与点击进入详情,无内联操作按钮,保持信息密度一致。 6. **状态视图**:骨架为灰阶占位条 + 图片块;空态用线稿图标 + 标题 + 说明 + 主按钮;触底显示「没有更多了」小字。 7. **玻璃弹层**:删除使用居中玻璃 modal(标题 + 说明「删除后不可恢复」+ 取消 / 确认删除),点击遮罩取消,主按钮为实心黑。 8. **动效与响应**:列表项入场 40ms 递进淡入上移,分段切换 320ms 交叉淡入,按钮按压 `scale(.97)` 并降至 60% 透明度;375px 基准宽度自适应,底部预留安全区与 64px 触底间距。 ## Agent Extensions ### SubAgent - **code-explorer** - Purpose: 跨文件盘点状态口径相关的全部引用点(`OutfitItem` / `getStatusText` / `source` 判定 / `outfit-status` 使用处)与旧口径残留,确保「我的穿搭只显示手工创建」与状态胶囊改造无遗漏、无死代码 - Expected outcome: 给出引用点清单与残留清单,作为状态口径收敛与最终走查的核对依据 ### Skill - **lsp-code-analysis** - Purpose: 用语义分析确认 `OutfitItem`、`OutfitSource`、新增 `utils/outfit-status` 的定义与全部引用关系(含类型错误定位),避免仅靠文本搜索漏掉动态引用与类型不匹配 - Expected outcome: 得到准确的引用/定义清单与类型诊断,确认 `status` 字段补齐后无类型错误、无未使用符号 - **playwright-cli** - Purpose: 打开 `stitch_ai_ui_v2/index.html` 的穿搭相关参考屏(outfit / outfit-detail / spec 规范页),抓取分段条、卡片、胶囊、发丝线、间距与字号的真实样式值,与新页面 WXSS 逐项核对 - Expected outcome: 输出一份「参考稿样式值 vs 新页面实现值」的逐项对照结论,修正偏差项,保证新页面与既有 v2 视觉零漂移