feat: 支持游客免登录浏览核心页面

未登录用户可先浏览衣橱、穿搭、运势、分享等内容,登录改为用户主动选择,并在登录页增加协议勾选确认与暂不登录入口。
This commit is contained in:
2026-09-16 21:44:04 +08:00
parent c07a969642
commit 45222317af
47 changed files with 996 additions and 12150 deletions
@@ -0,0 +1,210 @@
---
name: wx-review-compliance-fix
overview: 整改微信小程序两项审核驳回:① 登录页改为默认不勾选的《用户协议》《隐私政策》勾选框,未勾选不得登录(点击登录弹窗确认);② 将衣橱页设为启动首页,未登录用户以「游客态 + 本地示例内容」浏览各 tab 页,仅在主动使用受限功能时才引导登录。
design:
styleKeywords:
- 墨色极简
- 细描边
- 玻璃弹层
- 示例角标
- 无侵入引导
fontSystem:
fontFamily: PingFang-SC
heading:
size: 60rpx
weight: 500
subheading:
size: 30rpx
weight: 500
body:
size: 26rpx
weight: 400
colorSystem:
primary:
- "#0A0A0A"
- "#1C1C1E"
background:
- "#FFFFFF"
- "#F7F7F5"
text:
- "#0A0A0A"
- "#6E6E73"
- "#AEAEB2"
functional:
- "#0A0A0A"
- "#C9C9CE"
- "#6E6E73"
todos:
- id: entry-guest-utils
content: 调整 app.json 启动页为衣橱页,新增 utils/guest.ts 提供示例数据与 goLogin 登录引导
status: completed
- id: wardrobe-guest
content: 衣橱页实现游客态示例浏览、分类本地筛选与登录引导,受限操作改走 goLogin
status: completed
dependencies:
- entry-guest-utils
- id: login-consent
content: 登录页新增默认不勾选协议勾选框、未勾选弹窗确认与「先逛逛」返回浏览入口
status: completed
dependencies:
- entry-guest-utils
- id: other-tabs-guest
content: 穿搭/运势/分享/我的页增加游客态示例或引导,移除未登录强制跳登录
status: completed
dependencies:
- entry-guest-utils
- id: verify-compliance
content: 用 [skill:lsp-code-analysis] 核查登录守卫调用点,自测游客浏览、主动登录与 401 兜底全链路
status: completed
dependencies:
- wardrobe-guest
- login-consent
- other-tabs-guest
---
## 背景与目标
小程序提审被驳回两条:一是隐私政策不合规,默认自动同意《用户协议》《隐私政策》,须由用户自主阅读后自行选择是否同意;二是打开小程序一进入首页即要求授权登录,须先浏览体验功能服务,再由用户自行选择是否授权登录。本次整改解决这两项合规问题,使小程序可通过重新提审。
## 核心功能
1. 「衣橱」改为启动首页:打开小程序不再直达登录页,未登录用户以游客身份直接进入并可浏览页面。
2. 游客态浏览体验:衣橱展示本地示例衣物网格(可切换分类即时筛选),穿搭展示示例搭配,运势展示示例运势内容,均带「示例」标注,并附低调的登录引导;不发起任何需要授权的请求,不打断浏览。
3. 登录仅在用户主动选择时发生:未登录用户点击上传衣物、AI 推荐、创建分享、编辑资料、通知、订单等需登录的功能时,才进入登录页;登录页提供「暂不登录,先逛逛」入口,可随时返回继续浏览。
4. 协议同意整改:登录按钮下方提供默认未勾选的勾选框,文案为「我已阅读并同意《用户协议》和《隐私政策》」,两份协议均可点击查看;未勾选直接点击登录时弹出确认弹窗,选择「同意并继续」才继续登录,选择「不同意」则关闭弹窗并停留在当前页。
5. 分享、我的两个页面在未登录时呈现引导状态:分享页提示登录后可创建与查看分享,我的页显示未登录资料卡与「点击登录」,其中协议、关于等只读入口在未登录时仍可访问。
6. 登录成功后的原有流程保持:新用户礼包、生日完善引导、回到衣橱或回跳来源页,均与现状一致。
## 视觉与交互效果
- 延续现有黑白墨色极简风格:直角卡片、细描边、线稿图标、玻璃弹层,不引入新的色彩与控件体系。
- 游客态顶部为一条细描边浏览提示条,示例内容统一带「示例」胶囊角标,受限操作点击后进入登录页,不做强制打断。
- 勾选框为墨色方框:未选为空心细描边,选中为黑色实底加白色对勾;未勾选点击登录时的确认弹窗沿用现有毛玻璃居中卡片与双按钮样式。
## 技术栈
- 微信小程序原生开发(WXML/WXSS/TypeScript,`miniprogram` 目录,无 npm 构建步骤),类型依赖 `miniprogram-api-typings`。
- 复用现有资产,零新增依赖、零后端改动:自定义组件 `v2-overlay`(玻璃弹层,`login.json` 已注册)、`empty-state`、`navigation-bar`、`clothes-card`;设计令牌 CSS 变量(`--ink`/`--ink-2`/`--ink-3`/`--paper`/`--hairline`/`--fill`)与线稿图标库 `styles/icons.wxss`(含 `icon-check`);工具层沿用 `utils/logger` 统一日志与 `utils/auth.isLoggedIn()` 判据。
## 实现思路与关键决策
1. 入口调整:`app.json` 的 `pages` 首位改为 `pages/wardrobe/wardrobe`(游客可浏览的首页),`pages/login/login` 保留在页面列表中作为按需页;tabBar 结构与顺序不变。
2. 新增 `utils/guest.ts` 收敛游客态:本地示例数据(示例衣物/搭配/运势文案)+ `goLogin({ redirect? })` 统一登录引导入口(防抖、已在登录页则跳过、`wx.navigateTo` 到登录页,支持登录后回跳)。此方式避免使用 `reLaunch` 直达登录页带来的「清栈式强推登录」观感。
3. 页面游客分支:5 个 tab 页 `onShow` 中把 `!isLoggedIn()` 分支从「强制 `redirectToLogin()`」改为「渲染本地示例/引导并 return」,游客态零网络请求;已登录用户走原有 `refresh()` 逻辑不变。受限动作(上传、AI 入口、创建分享、编辑资料、额度/订单、通知等)在游客态统一走 `goLogin()`,深链页(upload/notification/mall/order/ai-*)内部逻辑保持不变,因入口已被拦截。
4. 协议合规交互:`login.wxml` 删除「登录即代表同意」默认强制文案,替换为自绘墨色勾选行 + 可点击的协议链接(链接用 `catchtap` 阻止冒泡,避免误触勾选);未勾选点击登录时用 `v2-overlay` modal 二次确认(「不同意」/「同意并继续」),确认后置 `agreed=true` 并继续原登录流程。登录链路仍仅使用 `wx.login`,不新增任何手机号/头像/昵称授权接口。
5. 状态同步与回跳:`goLogin` 的 `redirect` 参数复用 `login.ts` 既有 `goAfterLogin()` 回跳能力;登录成功回到衣橱时 `onShow` 自然切到已登录分支拉取真实数据,并保留 `firstShown` 首帧延迟刷新以规避 webview 首帧 setData 冲突。
## 架构与流程
```mermaid
flowchart TD
A[启动小程序] --> B[衣橱首页]
B -->|未登录| C[游客态: 本地示例与浏览提示]
C -->|点击受限功能| D[登录页]
D -->|未勾选协议点登录| E[确认弹窗: 不同意 / 同意并继续]
E -->|不同意| C
E -->|同意并继续| F[wx.login 换取登录态]
D -->|勾选后点登录| F
D -->|先逛逛| C
F --> B
B -->|已登录| G[真实数据: 衣物列表与上传额度]
G -->|401 登录失效| H[redirectToLogin 幂等跳转]
H --> D
```
## 性能与可靠性
- 游客态零请求、零存储写入;示例数据为模块级常量,仅本地 filter(O(n),n≤8),无渲染放大与内存残留。
- 不改动 `utils/request.ts` 的 401 → 刷新 token → `redirectToLogin` 幂等链路,也不改 `app.ts` 的清态 handler;游客态不发送鉴权请求,因此不会触发 `reLaunch` 打断路由。
- 回退方案:若审核对自绘勾选控件存疑,可仅替换为原生 `checkbox`(`color="#0A0A0A"`),数据字段 `agreed` 与交互分支无需改动。
## 目录结构(仅列新增/修改文件)
```
miniprogram/
├── app.json # [MODIFY] pages 首位改为 pages/wardrobe/wardrobe,login 保留为按需页
├── app.wxss # [MODIFY] 新增游客态通用样式:浏览提示条、示例角标、登录引导按钮(复用 --ink/--hairline/--fill 令牌)
├── utils/
│ └── guest.ts # [NEW] 游客态唯一数据源与登录引导:示例衣物/搭配/运势数据 + goLogin({redirect})(防抖、已在登录页跳过、navigateTo 登录页)
├── pages/
│ ├── wardrobe/
│ │ ├── wardrobe.ts # [MODIFY] onShow 增加游客分支:不发请求、渲染示例数据;分类本地筛选;onUpload/onClothesTap/onRefresh 游客态走 goLogin;resolvePending 仅登录态执行
│ │ ├── wardrobe.wxml # [MODIFY] 游客态渲染示例网格(示例角标)、浏览提示条与登录引导;加载/空态/正常三分支保持不变
│ │ └── wardrobe.wxss # [MODIFY] 示例卡片等游客态局部样式
│ ├── login/
│ │ ├── login.ts # [MODIFY] 新增 agreed/consentVisible 状态、onToggleAgree、未勾选点击登录的弹窗分支、onBrowse(先逛逛 → switchTab 衣橱);wx.login/礼包/生日引导/回跳逻辑保持不变
│ │ ├── login.wxml # [MODIFY] 删除「登录即代表同意」文案;新增自绘勾选行与协议链接(catchtap 防冒泡)、「暂不登录,先逛逛」、协议确认 v2-overlay
│ │ ├── login.wxss # [MODIFY] 勾选行与「先逛逛」样式,沿用 --ink 系列令牌
│ │ └── login.json # [不变] 已注册 v2-overlay,无需改动
│ ├── outfit/
│ │ ├── outfit.ts # [MODIFY] onShow 游客分支(本地示例、零请求);tab 切换与收藏入口在游客态走 goLogin
│ │ ├── outfit.wxml # [MODIFY] 游客态示例搭配列表 + 登录引导
│ │ └── outfit.wxss # [MODIFY] 游客态局部样式(如有必要)
│ ├── horoscope/
│ │ ├── horoscope.ts # [MODIFY] 游客分支返回本地静态示例运势,不请求;「去设置生日」/重试在游客态走 goLogin
│ │ └── horoscope.wxml # [MODIFY] 游客态示例运势卡 + 登录引导(复用 hs-* 样式)
│ ├── closet-share/
│ │ ├── closet-share.ts # [MODIFY] 游客分支:不发请求,渲染引导态;创建分享入口走 goLogin
│ │ └── closet-share.wxml # [MODIFY] 游客态 empty-state 引导(登录后可创建与查看分享)
│ └── profile/
│ ├── profile.ts # [MODIFY] onShow 游客分支:不请求 fetchUser;编辑资料/额度/订单/通知等入口走 goLogin
│ ├── profile.wxml # [MODIFY] 游客资料卡(icon-user 占位 + 点击登录),保留协议/关于等可浏览入口
│ └── profile.wxss # [MODIFY] 游客资料卡样式
```
## 保持不变(回归重点)
- `utils/request.ts`、`utils/auth.ts`、`app.ts`:401 → 刷新 → `redirectToLogin` 幂等链路与清态 handler 不动。
- `pages/notification`、`pages/upload`、`pages/mall`、`pages/order`、`pages/ai-*` 等深链页:入口已在游客态被 `goLogin` 拦截,页面内部逻辑与未登录兜底提示维持现状。
- `custom-tab-bar/index.ts` 未登录时红点静默置 0,无需改动;`pages/agreement` 与 `utils/legal.ts` 已满足「未登录可访问」,不再改动。
## 关键接口(guest.ts)
```ts
export interface GuestClothes {
key: string // 本地唯一 key(wx:key 用)
name: string
category: string // 与衣橱分类条 value 对齐:上装/下装/连衣裙/外套/鞋/配饰
icon: string // icons.wxss 线稿图标类名,如 'icon-shirt'
}
export interface GuestOutfit { key: string; name: string; icons: string[]; tags: string[] }
export const GUEST_WARDROBE: GuestClothes[]
export const GUEST_OUTFITS: GuestOutfit[]
export const GUEST_HOROSCOPE: { zodiac: string; score: number; lines: string[] }
export function goLogin(options?: { redirect?: string }): void
```
## 设计风格
延续 v2 墨色极简体系:零彩色灰阶、发丝线分隔、衬线大标题、线稿图标、毛玻璃弹层,仅在既有版式内追加「游客态」视觉层,整改前后观感一致,不引入新组件库与彩色。
## 首页(衣橱)游客态
- 页头保留杂志式大标题「我的衣橱」,统计行改为「浏览模式 · 登录后上传你的衣物」。
- 分类条保持可点,对本地示例数据即时筛选,提供可操作、可体验的浏览感。
- 主体为两列直角示例卡:细描边 + 线稿图标占位,右上角「示例」胶囊角标(浅填充底 + 灰色字)。
- 顶部一条细描边提示条说明当前为浏览模式;右下角保留上传悬浮按钮,点击进入登录页。
## 其他页面游客态
- 穿搭、运势直接呈现本地示例内容(示例搭配、示例运势卡),统一带「示例」角标,底部一行低调的「登录后查看你的专属内容」引导。
- 分享、我的使用现成空态与资料卡:用户线稿占位头像 + 「点击登录」,协议与关于等只读入口保持可点。
## 登录页
- 勾选行位于登录按钮下方:小号灰字 + 自绘方框(未选为细描边空心,选中为墨色实底加白色对勾,120ms 缓动),协议链接保留下划线。
- 「暂不登录,先逛逛」为居中细描边文字按钮,与主按钮形成清晰主次。
- 未勾选点击登录的确认弹窗复用 v2-overlay 毛玻璃居中卡,按钮为「不同意」(描边)与「同意并继续」(墨色实底主按钮)。
## 交互与响应式
- 新增控件热区不小于 88rpx,反馈使用 hover-class 或 120ms 透明度过渡,不使用弹跳动画;过渡遵循既有 --ease 缓动。
- 底部间距沿用安全区适配;示例网格按屏幕宽度两列自适应,游客态切换为登录态时列表淡入,避免闪跳。
## Agent Extensions
### Skill
- **lsp-code-analysis**
- Purpose: 在整改中做调用点核查与影响分析,检索并确认全部 `auth.isLoggedIn` 强制跳转分支、`redirectToLogin` 既有调用点与新增 `goLogin` 调用点,避免遗漏或误改登录守卫链路。
- Expected outcome: 输出完整的引用清单与改动覆盖确认,确保游客态零请求、登录态原逻辑无回归。