--- name: 通知与分享入口互换 overview: 将底部 tabBar 的「通知」替换为「分享」,通知入口移入「我的」页面菜单;「分享」tab 页内实现「我的分享 / 分享给我的」两个分段,未读红点迁移到「我的」tab 图标上。 design: styleKeywords: - iOS HIG - 清爽克制 - 胶囊分段 - 系统蓝 - 线性图标 fontSystem: fontFamily: PingFang SC heading: size: 34rpx weight: 600 subheading: size: 28rpx weight: 500 body: size: 26rpx weight: 400 colorSystem: primary: - "#007AFF" - "#5856D6" - "#FF2D55" background: - "#F2F2F7" - "#FFFFFF" text: - "#000000" - "#3C3C43" - "#8E8E93" - "#C7C7CC" functional: - "#FF3B30" - "#34C759" - "#FF9500" todos: - id: update-tabbar content: 调整 tabBar 入口与红点(app.json + custom-tab-bar) status: completed - id: upgrade-share-page content: 升级分享页为 tab 页并实现「我的分享/分享给我的」双分段 status: completed dependencies: - update-tabbar - id: update-profile content: 修改我的页通知入口并同步未读红点 status: completed - id: adjust-notification content: 调整通知页为普通页面(返回按钮、移除 tab 同步) status: completed --- ## 产品概述 对微信小程序「纸条AI衣橱」的底部导航与入口布局进行调整:将底部导航栏第 4 个入口由「通知」改为「分享」,原「我的」页面内的「我的分享」入口改为「通知」;分享页新增「我的分享 / 分享给我的」两个分段展示;未读通知红点由通知 tab 移至底部「我的」tab 图标右上角。 ## 核心功能 - 底部导航栏第 4 个入口显示「分享」(分享图标),点击进入分享页。 - 「我的」页面功能列表中新增「通知」入口(铃铛图标),点击进入通知列表页。 - 分享页顶部提供「我的分享 / 分享给我的」分段切换: - 「我的分享」展示当前用户发起的衣柜分享,保留「新建分享」入口。 - 「分享给我的」展示他人分享给当前用户的衣柜分享,卡片展示分享者头像与昵称。 - 底部「我的」tab 图标右上角显示未读通知数红点,超过 99 显示「99+」。 - 通知页由 tab 页改为普通二级页,支持返回上一页。 ## 技术栈 - 平台:微信小程序原生 + TypeScript(沿用现有 `skyline` + `glass-easel` 架构) - 网络层:复用现有 `miniprogram/utils/request.ts` 的 `request` 封装 - UI:纯 WXSS 手写,复用现有 `navigation-bar`、`empty-state`、`custom-tab-bar` 组件与 `styles/icons.wxss` 图标库 ## 实现方案 ### 整体策略 在现有「5 个 tabBar 页 + 二级页」架构上做入口互换与页面能力升级,不引入新页面、新组件、新依赖。分享页从二级页升级为 tabBar 页并新增分段切换;通知页从 tabBar 页降级为二级页。红点数据源由原通知页单向写缓存,扩展为 tabBar 组件主动拉取 `/notification/unread`。 ### 关键决策 - **分享页分段采用「单一当前列表 + 切换重置」模式**:用 `activeTab`(0=我的分享,1=分享给我的)控制当前展示,切换分段时清空 `list` 并重置分页状态,再调用对应接口。避免维护两套分页状态,符合 KISS/YAGNI,切换后重新拉取的开销可接受。 - **两个列表接口复用同一响应结构**:`GET /closet-share` 与 `GET /closet-share/received` 均返回 `PagedResult`;后者额外返回 `owner_name/owner_avatar`,前端 `ClosetShareItem` 补字段即可,`decorate()` 对两接口通用。 - **红点刷新采用「缓存先行 + 异步刷新」**:tabBar 组件 `attached` 时先读 `zt_closet_unread` 立即渲染,再请求 `/notification/unread` 更新缓存与视图;通知页 `fetchUnread` 保持写缓存并调 `tabBar.refreshUnread()`,形成闭环。 - **入口切换避免 tab 页跳转错误**:`profile` 中删除原 `onTapShare` 的 `navigateTo('/pages/closet-share/closet-share')`(tab 页不能用 navigateTo),改为 `navigateTo('/pages/notification/notification')`。 ### 实现注意事项 - `closet-share` 成为 tab 页后,`onShow` 需 `syncTabBar()` 设置 `selected: 3`(对应第 4 项),与现有 wardrobe/outfit/horoscope/profile 页的 selected 同步模式一致。 - `closet-share.wxml` 中 `navigation-bar` 增加 `back="{{false}}"`(tab 页不显示返回键),标题由「衣柜分享」调整为「分享」;`closet-share-create`、`closet-share-detail` 仍为二级页,用 `navigateTo` 跳转不受影响。 - `notification.wxml` 去掉 `back="{{false}}"` 以恢复默认返回按钮;`notification.ts` 删除 `syncTabBar()`(避免误将 tabBar 高亮切到已不存在的第 4 项),但保留 `fetchUnread()` 以刷新「我的」tab 红点。 - 分享给我的卡片头像使用 `image` 渲染 `owner_avatar`,为空时回退 `icon-user` 占位,与 profile 页头像处理方式一致。 ## 架构设计 数据流保持「页面/组件 → request → 后端 API」的单向依赖: - tabBar 组件 `attached` → 读本地缓存 `zt_closet_unread` 立即显示 → 请求 `GET /notification/unread` → 写缓存并更新红点。 - 分享页 `onShow` → 同步 tabBar 高亮 → 按 `activeTab` 请求 `GET /closet-share` 或 `GET /closet-share/received` → 渲染列表。 - 我的页 `onShow` → 同步 tabBar 高亮 → 拉取用户/额度信息,并调用 `tabBar.refreshUnread()` 刷新红点。 ## 目录结构 本次仅修改现有文件,不新增文件: ``` miniprogram/ ├── app.json # [MODIFY] tabBar.list 第4项由 notification 改为 closet-share,text 由「通知」改为「分享」 ├── custom-tab-bar/ │ ├── index.ts # [MODIFY] 列表第4项改为分享/icon-share;refreshUnread 增加主动请求 /notification/unread │ └── index.wxml # [MODIFY] 红点条件由 icon-bell 改为 icon-user(我的 tab) ├── pages/ │ ├── closet-share/ │ │ ├── closet-share.ts # [MODIFY] 增加 activeTab 双分段、双接口取数、分页重置、syncTabBar(selected=3) │ │ ├── closet-share.wxml # [MODIFY] 增加分段控件;分享给我的卡片展示 owner 信息;新建入口仅我的分享展示;back=false │ │ └── closet-share.wxss # [MODIFY] 增加分段样式、分享者头像昵称样式 │ ├── profile/ │ │ ├── profile.ts # [MODIFY] onTapShare 改为 onTapNotification(navigateTo notification);onShow 刷新 tabBar 红点 │ │ └── profile.wxml # [MODIFY] 「我的分享」菜单行改为「通知」(icon-bell,bindtap=onTapNotification) │ └── notification/ │ ├── notification.ts # [MODIFY] 删除 syncTabBar;保留 fetchUnread 刷新 tabBar 红点 │ └── notification.wxml # [MODIFY] navigation-bar 去掉 back="{{false}}",恢复返回按钮 └── types/ └── models.ts # [MODIFY] ClosetShareItem 补充 owner_name、owner_avatar ``` ## 关键代码结构 补充分享列表项类型,兼容「分享给我的」返回的分享者信息: ```ts export interface ClosetShareItem { share_uuid: string share_type: number clothes_count: number expire_time: number status: number owner_name?: string // 分享者昵称(分享给我的列表返回) owner_avatar?: string // 分享者头像(分享给我的列表返回) } ``` 分享页核心状态: ```ts data: { activeTab: 0 | 1, // 0=我的分享 1=分享给我的 list: ClosetShareItem[], loading: boolean, page: number, pageSize: number, hasMore: boolean, } ``` ## 设计风格 延续现有 iOS HIG 视觉语言:清爽克制、系统分组灰底 #F2F2F7 + 纯白卡片 + 发丝分隔线,强调色系统蓝 #007AFF,线性 SF Symbols 风格图标。 ## 分享页分段设计 - 顶部在导航栏下方放置胶囊式分段控件(Segmented Control):两个等宽胶囊「我的分享」「分享给我的」,选中项为系统蓝底白字,未选中项为灰底深字,切换有轻量过渡;样式与通知页筛选胶囊保持一致,保证全站视觉统一。 - 「我的分享」列表顶部保留「+ 新建分享」描边按钮,卡片沿用现有四宫格衣物缩略图 + 件数 + 类型 + 有效期布局。 - 「分享给我的」列表卡片在左侧缩略图基础上,右侧信息区顶部新增分享者行(小圆头像 + 昵称),帮助用户快速识别来源;无头像时回退系统灰色人形占位。 - 两个分段的空态复用 empty-state 组件,文案分别区分「还没有分享」与「还没有收到分享」。 ## 底部导航设计 - 第 4 个 tab 由铃铛图标替换为分享图标(三圆点连线),文字由「通知」改为「分享」。 - 未读通知红点从分享 tab 移至「我的」tab 图标右上角,沿用现有红色胶囊数字样式,超过 99 显示「99+」,无未读时隐藏。