Просмотр исходного кода

docs(test): SC-G-03 登录方式口径修正

- 小程序端不提供手机号+验证码登录(login-sheet 仅微信手机号快捷登录,
  phone-login 页面零调用),登录=微信授权 SC-G-02 / wechat-phone-login
- Web 管理后台微信扫码登录为待实现需求(当前仅密码/验证码登录)
- guest.md TC-G-03 降 P2 并标注 API 兼容保留;TC-G-N02 归属改 SC-G-02
- user-auth-flow.md phone-login 端口标注为 API 预留
- admin-overview-flow.md 加微信扫码登录(待实现)节点+端点行+完整性说明

口径澄清:2026-11-01(用户拍板)
Agnes Agent 1 неделя назад
Родитель
Сommit
a671a958d6

+ 5 - 1
docs/flows/admin-overview-flow.md

@@ -34,6 +34,9 @@ flowchart TD
         A2a -->|"手机号, 密码"| S2a["⚙️ 密码校验 + JWT生成"]:::service
         S2a -->|"用户信息"| D_USER
 
+        P1 -->|"微信扫码登录(待实现)"| A2b["🔗 POST /api/admin-auth/wechat-scan-login (待实现)"]:::api
+        A2b -.->|"扫码确认后签发后台角色JWT"| S_JWT
+
         D_USER -->|"用户ID, 角色"| S_JWT["⚙️ JwtConfig.generateToken()"]:::service
         S_JWT -->|"JWT token"| D_JWT["📦 JWT Token(返回前端)"]:::data
 
@@ -225,6 +228,7 @@ flowchart TD
 | `POST /api/admin-auth/send-code` | 发送管理员登录验证码 | 🖥管理后台 | `{phone}` | `{success}` |
 | `POST /api/admin-auth/login` | 验证码登录 | 🖥管理后台 | `{phone, code}` | `{token, adminId, username, role, roles}` |
 | `POST /api/admin-auth/login-by-password` | 密码登录 | 🖥管理后台 | `{phone, password}` | `{token, adminId, username, role, roles}` |
+| `POST /api/admin-auth/wechat-scan-login` | 微信扫码登录(**待实现**,2026-11-01 需求;当前无此接口,需签发后台角色 JWT) | 🖥管理后台 | `{state, code}` | `{token, adminId, username, role, roles}` |
 | `POST /api/admin-auth/info` | 获取当前管理员信息 | 🖥管理后台 | Header: `Authorization` | `{id, nickname, phone, role, roles, user}` |
 | `POST /api/admin-auth/change-password` | 修改密码 | 🖥管理后台 | `{oldPassword, newPassword}` | `{success}` |
 | `POST /api/admin-auth/update-info` | 更新个人信息 | 🖥管理后台 | `{nickname, phone}` | `{nickname, phone}` |
@@ -363,4 +367,4 @@ flowchart TD
 | 3 | **端点覆盖** | ✅ 完整 | 52+个端点全部映射到流程图中,涵盖AdminAuthController、AdminController、AdminGuideController、AdminProductController、AdminProductOrderController、AdminFoodController、AdminEnergyConfigController |
 | 4 | **角色覆盖** | ✅ 完整 | 管理员(admin)全量管理功能覆盖;规划师(teacher)审核等跨角色操作已标注 |
 | 5 | **数据实体** | ✅ 完整 | users、family_members、families、tasks、rewards、points_logs、task_templates、guide_packages、products、product_orders、foods、admins等表均在图中映射 |
-| 6 | **一致性** | ✅ 与代码一致 | 所有端点路径与实际Controller中的`@PostMapping`匹配,无重复路由 |
+| 6 | **一致性** | ✅ 与代码一致 | 所有**已实现**端点路径与实际Controller中的`@PostMapping`匹配,无重复路由;`wechat-scan-login`(微信扫码登录)为**待实现需求**,已在图中以虚线标注 |

+ 2 - 2
docs/flows/user-auth-flow.md

@@ -34,7 +34,7 @@ flowchart TD
         A1 -->|"微信code"| S1["⚙️ WechatService.silentLogin()"]:::service
         S1 -->|"openid, 新用户标记"| D1["📦 users 表(查询/创建)"]:::data
 
-        P1_reg -->|"手机号"| P1b["🏠 输入手机号"]:::page
+        P1_reg -->|"手机号(API预留)"| P1b["🏠 输入手机号(小程序端无入口)"]:::page
         P1b -->|"手机号"| A2["🔗 POST /api/auth/send-code"]:::api
         A2 -->|"手机号"| S2["⚙️ SmsService.sendCode()"]:::service
         S2 -->|"验证码, 过期时间"| D2["📦 sms_codes 表(写入)"]:::data
@@ -158,7 +158,7 @@ flowchart TD
 | 端点 | 说明 | 端口 | 请求数据 | 响应数据 |
 |------|------|------|---------|---------|
 | `POST /api/auth/send-code` | 发送短信验证码 | ⚙️系统自动 | `{phone}` | `{success, expireIn}` |
-| `POST /api/auth/phone-login` | 手机号+验证码登录 | 📱小程序 | `{phone, code}` | `{token, userInfo}` |
+| `POST /api/auth/phone-login` | 手机号+验证码登录(**API 兼容保留**:小程序端无入口,2026-11-01 口径) | ⚠️ 预留 | `{phone, code}` | `{token, userInfo}` |
 | `POST /api/auth/wechat-phone-login` | 微信手机号登录 | 📱小程序 | `{encryptedData, iv, code}` | `{token, userInfo}` |
 | `POST /api/auth/silent-login` | 微信静默登录(自动注册) | 📱小程序 | `{code}` | `{token, userInfo, isNew}` |
 | `POST /api/auth/auto-login` | openid自动登录 | 📱小程序 | `{openid}` | `{token, userInfo}` |

+ 3 - 3
tests/test-cases/guest.md

@@ -6,14 +6,14 @@
 |---|---|---|---|---|---|---|---|---|---|---|
 | TC-G-01 | G-1 | 启动/首页 | 游客 | P1 | 功能 | 清除登录态 | 1. 冷启动进入 splash/home 2. 观察首页与入口 | 显示引流首页,不进入任何业务页;明显展示微信/手机号/邀请登录入口 | JwtInterceptor 拦截 `/api/**` | `e2e/roles/child/login.spec.js`(反向) |
 | TC-G-02 | G-2 | 认证 | 游客 | P0 | 接口 | 微信授权可用(test-mode) | 1. 点微信一键登录 2. `POST /api/auth/wechat-login` | 返回 `Result` 含 token+用户信息;角色默认 parent;跳转家长首页;首次登录建 User+family_members(memberType=login) | `AuthController`/`API_REFERENCE` 1.1 | `e2e/roles/parent/../login` |
-| TC-G-03 | G-3 | 认证 | 游客 | P0 | 接口 | 有效手机号 13800000001 | 1. `POST /api/auth/send-code` 2. `POST /api/auth/phone-login`(验证码) 3. 重复错误验证码 | 验证码正确→登录下发 token;错误→提示失败且**不产生会话**;限流生效 | 统一 POST/JWT | — |
+| TC-G-03 | G-3 | 认证 | 游客 | P2 | 接口 | 有效手机号 13800000001 | 1. `POST /api/auth/send-code` 2. `POST /api/auth/phone-login`(验证码) 3. 重复错误验证码 | 验证码正确→登录下发 token;错误→提示失败且**不产生会话**;限流生效 ⚠ **API 兼容保留**:小程序端无入口(登录走 SC-G-02),2026-11-01 口径 | 统一 POST/JWT | — |
 | TC-G-04 | G-4 | 家庭/邀请 | 游客 | P1 | 功能 | 家长已 `POST /api/family/invite/generate` 生成邀请 | 1. 扫码/落地页进入 2. `POST /api/auth/register-with-invite`(带令牌) | 登录后自动归属对应家庭,成员列表出现该用户;令牌失效→「邀请已失效」 | `FamilyInviteController` | `e2e/roles/teacher/family-binding.spec.js`(参考) |
 | TC-G-05 | G-5 | 权限 | 游客 | P0 | 权限 | 无 token;已知业务路由 | 1. 直接请求 `/pages/family/index` 等(无 Authorization) 2. `POST /api/product/list`、`/api/articles/list` 3. 点商品/文章详情需登录项 | 业务页→401 跳登录,登录后回跳;商城/文章列表可见(公开);需登录详情被拦截 | JWT;8 公开路径白名单(1.1) | `e2e/debug-control.spec.js`(参考) |
 
 ### 异常/边界补充
 
 - **TC-G-02a(异常)**:同一微信二次登录应返回已有账号,不重复建号(验重)。
-- **TC-G-03a(异常)**:验证码过期/频繁发送触发限流,提示明确。
+- **TC-G-03a(异常)**:验证码过期/频繁发送触发限流,提示明确(同为 API 兼容保留级)。
 - **TC-G-05a(权限)**:token 过期后任意 `/api/**` 接口统一 401,前端统一跳登录。
 
 ## 补齐用例(缺口场景 SC-G-06~10)
@@ -86,7 +86,7 @@
 | TC 编号 | 所属场景 | 模块 | 角色 | 优先级 | 类型 | 前置条件 | 测试步骤 | 预期结果 | 关联需求/设计 | 对应 e2e |
 |---|---|---|---|---|---|---|---|---|---|---|
 | TC-G-N01 | SC-G-01 | 落地页 | 游客 | P2 | 性能 | 弱网/首次访问 | 1. 打开落地页/邀请页 2. 测首屏时间 | 首屏 ≤ 3s;骨架屏生效;CDN 资源命中;无白屏 | 落地页/邀请 | — |
-| TC-G-N02 | SC-G-03 | 浏览转化 | 游客 | P2 | 兼容 | 微信内 H5 / Safari / Chrome / 小程序 webview | 1. 各端浏览内容 2. 触发登录 | 布局一致;微信授权正常;兜底登录可用;无错位 | 登录注册 | e2e/api/nonfunc-perf-compat.spec.js |
+| TC-G-N02 | SC-G-02 | 浏览转化 | 游客 | P2 | 兼容 | 微信内 H5 / Safari / Chrome / 小程序 webview | 1. 各端浏览内容 2. 触发登录 | 布局一致;微信授权正常;兜底登录可用;无错位 | 登录注册(微信授权) | e2e/api/nonfunc-perf-compat.spec.js |
 | TC-G-N03 | SC-G-12 | 非微信H5 | 游客 | P2 | 兼容 | 非微信浏览器(Chrome PC) | 1. 打开 H5 2. 走手机号兜底登录 | 功能可用;无微信 SDK 依赖报错;流程闭环 | H5 兜底 | e2e/api/nonfunc-perf-compat.spec.js |
 | TC-G-N04 | SC-G-01 | 落地页 | 游客 | P0 | 安全 | 未登录态(无 token) | 1. 直接调 `/api/family/*`、`/api/health/report/list` 等受保护接口 | 返回 401;不泄露数据与结构 | 接口鉴权 | e2e/api/nonfunc-security.spec.js |
 | TC-G-N05 | SC-G-02 | 登录注册 | 游客 | P0 | 安全 | 爆破/重放工具 | 1. 高频错误密码登录 2. 验证码重放 | 触发限流/锁定;验证码一次性;防爆破;无撞库成功 | 登录限流 | — |

+ 21 - 12
tests/user-scenarios/01-guest.md

@@ -38,18 +38,27 @@
 
 ---
 
-## 场景 G-3:手机号 + 验证码登录
-
-**用户故事**:作为不想用微信的用户,我想用手机号登录,以便也能使用全部功能。
-
-- **角色**:游客
-- **前置条件**:有效手机号(如 `13800000001`)。
-- **主流程**
-  1. 点击「手机号登录」→ `POST /api/auth/send-code` 获取验证码。
-  2. 输入验证码 → `POST /api/auth/phone-login`。
-  3. 验证码正确 → 登录成功并下发 token;错误 → 提示失败且**不产生会话**。
-- **异常/边界**:验证码错误/过期、频繁发送限流;错误验证码绝不签发 token。
-- **关联用例**:TC-G-03
+## 场景 G-3:登录方式口径(小程序端 / Web 管理后台)
+
+**用户故事**:作为用户,我希望在小程序端用微信直接登录、在 Web 管理后台用微信扫码登录,以便不必记账号密码。
+
+> **口径澄清(2026-11-01)**:小程序端**不提供**「手机号+验证码登录」。该能力在服务端以 `send-code` / `phone-login` 保留,但小程序前端无任何入口(`login-sheet` 仅 `open-type="getPhoneNumber"` 微信手机号快捷登录 + 微信授权),不作为产品路径测试。Web 管理后台登录方式为**密码 / 验证码(现状)+ 微信扫码登录(待实现)**。
+
+- **角色**:游客(小程序端) / 管理员·规划师(Web 管理后台)
+- **前置条件**:小程序已授权微信;Web 后台账号具备后台角色(`admin` / `operator` / `finance` / `org_admin` 等)。
+- **小程序端主流程(现状)**
+  1. `login-sheet` → `open-type="getPhoneNumber"` → `POST /api/auth/wechat-phone-login`(微信手机号快捷授权登录)。
+  2. 微信授权昵称/头像 → `POST /api/auth/wechat-login`(见 SC-G-02)。
+- **Web 管理后台主流程(现状)**
+  1. 密码登录 → `POST /api/admin-auth/login-by-password`(滑块验证 + 身份下拉)。
+  2. 验证码登录 → `POST /api/admin-auth/send-code` → `POST /api/admin-auth/login`。
+- **Web 管理后台主流程(待实现 · 微信扫码登录)**
+  1. 登录页展示扫码入口 → 服务端生成二维码与 `state`。
+  2. 微信扫码 → 已登录用户确认 → 服务端签发**后台角色 JWT**(须校验后台角色,parent/child 不得进后台)。
+  3. 边界:二维码过期/已使用、扫码者无后台角色、轮询超时。
+- **API 兼容保留**:`POST /api/auth/send-code` / `POST /api/auth/phone-login` 端点仍存在(服务端能力保留),小程序端**无入口**,不计入产品端登录路径。
+- **关联需求/设计**:`AuthController` `/api/auth/*`;`AdminAuthController` `/api/admin-auth/*`;扫码登录参考 `/api/auth/wechat-web`(用户端小程序码扫码 SSO)。
+- **关联用例**:TC-G-03(API 兼容保留)、TC-G-N02(多端兼容)
 
 ---
 

+ 1 - 1
tests/user-scenarios/应用场景总览.md

@@ -29,7 +29,7 @@
 
 - **SC-G-01 · 首次进入小程序/落地页** — 目标:未登录也能看到产品形态。流程:打开 → 落地页/引导 → 触发登录引导。边界:网络异常展示重试;微信环境探测失败降级提示。模块:`config.js` 环境自适应。
 - **SC-G-02 · 微信授权登录** — 目标:微信身份一键登录。流程:点登录 → 微信 OAuth → 回跳建/取 User + openid。边界:拒绝授权回退手机号;openid 已存在直接登录不重复建号。模块:`AuthController`。
-- **SC-G-03 · 手机号+验证码登录** — 目标:无微信也能登录。流程:输手机号 → 取验证码 → 校验 → 登录。边界:验证码错误/过期提示重发;号码格式非法拦截。模块:`AuthController`。
+- **SC-G-03 · 登录方式口径(小程序端 / Web 管理后台)** — **小程序端不提供「手机号+验证码登录」**:登录=微信授权(SC-G-02)/ 微信手机号快捷登录(`wechat-phone-login`),无输入验证码流程(`phone-login` 仅 API 预留、前端页面零入口)。**Web 管理后台支持微信扫码登录**:当前实现为密码/验证码登录(`AdminAuthController`),微信扫码登录为**待实现**(可参考 `/api/auth/wechat-web` 小程序码扫码 SSO,须签发后台角色 JWT)。口径澄清:2026-11-01。
 - **SC-G-04 · 邀请码注册加入家庭** — 目标:通过分享链接成为成员。流程:打开邀请落地页 → 注册/登录 → `register-with-invite` 绑定家庭。边界:邀请码失效/篡改拒绝;重复加入幂等。模块:`FamilyInviteController`。
 - **SC-G-05 · 浏览商城/文章(未登录受限)** — 目标:先逛后转。流程:进入商城/文章列表 → 查看公开内容。边界:受限操作(下单/评论)重定向登录。模块:`ArticleController` / `MallController`。
 - **SC-G-06 · 越权接口拦截** — 目标:未登录不可触达受保护资源。流程:直接调 `/api/**` 受保护接口。边界:`JwtInterceptor` 拦截(8 个公开路径除外);缺 token → 401/403,不泄露内部错误。模块:`JwtInterceptor`。