01-guest.md 12 KB

用户使用场景 · 游客(Guest / 未登录)

来源:AGENTS.md(统一认证、公开路径)、API_REFERENCE.md(/api/auth/*、/api/articles/* 部分公开、/api/media/upload 公开)、黑盒方案 T-01~T-05。 关联用例:test-cases/guest.md(TC-G-01~TC-G-12)。


场景 G-1:首次打开小程序,看到引流首页

用户故事:作为还没注册的访客,我想一打开就能看到产品价值并找到登录入口,以便我决定是否注册。

  • 角色:游客(无 token)
  • 前置条件:清除本地登录态;小程序启动,wechat.test-mode 可开。
  • 主流程
    1. 冷启动进入 splash / home 引流页。
    2. 页面不自动进入任何业务页(家庭/任务/能量等)。
    3. 明显展示「微信一键登录 / 手机号登录 / 邀请加入」入口。
  • 异常/边界:弱网或微信授权失败时不白屏,提供「稍后」「手机号登录」兜底。
  • 关联需求/设计:JwtInterceptor 拦截 /api/**(仅 8 个公开路径除外);游客不应看到业务数据。
  • 关联用例:TC-G-01

场景 G-2:微信一键登录(默认成为家长)

用户故事:作为新用户,我想用微信一键登录免去注册麻烦,以便快速进入家庭管理。

  • 角色:游客
  • 前置条件:微信授权可用(测试模式走模拟 openid)。
  • 主流程
    1. 点击「微信一键登录」→ 授权昵称/头像。
    2. 调用 POST /api/auth/wechat-login → 返回 Result 含 token + 用户信息。
    3. 角色默认 parent,跳转家长首页。
    4. 若该微信首次登录,自动创建 User + family_members(memberType=login)。
  • 异常/边界:同一微信重复登录应返回已有账号(不重复建号);授权拒绝则停留在登录页。
  • 关联需求/设计:AuthController /api/auth/* 公开;openid 关联 User,决定 memberType。
  • 关联用例:TC-G-02

场景 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(多端兼容)

场景 G-4:凭邀请注册并加入指定家庭

用户故事:作为被家人邀请的用户,我想通过邀请码/二维码直接加入家庭,以便立即成为成员。

  • 角色:游客(持有家庭邀请令牌)
  • 前置条件:家长已在 POST /api/family/invite/generate 生成邀请码/二维码(含令牌与落地页)。
  • 主流程
    1. 扫码或点开落地页 → 进入注册/登录。
    2. 走 POST /api/auth/register-with-invite(携带邀请令牌)。
    3. 登录成功后自动归属到对应家庭,家庭成员列表出现该用户。
  • 异常/边界:令牌失效/过期 → 提示「邀请已失效」;已登录用户用他人邀请 → 按业务规则处理(加入或被拒)。
  • 关联需求/设计:FamilyInviteController /api/family/invite/*;二维码含令牌+落地页(cfclub 特性)。
  • 关联用例:TC-G-04

场景 G-5:未登录访问业务页被拦截;浏览商城/文章可被放行

用户故事:作为游客,我想随便看看商品和内容,但访问我的家庭/任务时必须先登录,以便数据安全。

  • 角色:游客(无 token)
  • 前置条件:已知某业务页路由(如 /pages/family/index、/pages/tasks/index)。
  • 主流程
    1. 直接请求带业务路由的页面(无 Authorization)。
    2. JwtInterceptor 返回 401 → 前端跳转登录页;登录后回跳原页。
    3. 打开商城主页 POST /api/product/list、文章列表 POST /api/articles/list → 可见内容(公开路径)。
    4. 点击商品详情/文章详情需登录项 → 被拦截提示登录。
  • 异常/边界:仅 8 个公开路径免鉴权;其余 /api/** 一律拦截;登录态过期后接口统一 401。
  • 关联需求/设计:JWT 认证;Authorization Header;8 个公开路径白名单。
  • 关联用例:TC-G-05

场景 G-6:越权接口拦截(未登录不可触达受保护资源)

用户故事:作为未登录的访客,我想直接调用业务接口时被统一拦截,以便保护数据安全、不泄露内部错误细节。

  • 角色:游客(无 token)
  • 前置条件:已知任一受保护接口(如 POST /api/family/list、POST /api/task/list)。
  • 主流程
    1. 直接携带业务接口请求(无 Authorization Header)。
    2. JwtInterceptor 校验 token → 返回 401/403。
    3. 前端捕获后跳转登录页;登录成功后回跳原页。
  • 异常/边界:仅 8 个公开路径(登录/注册/邀请/公开文章/公开商品/媒体上传等)免鉴权,其余 /api/** 一律拦截;缺 token / token 过期 / 非法 token 统一 401/403;错误信息不泄露内部堆栈或系统细节。
  • 关联需求/设计:JwtInterceptor;Authorization Header;8 个公开路径白名单;统一 Result<T>(code/message/data)。
  • 关联用例:TC-G-06

场景 G-7:微信测试模式跳过授权

用户故事:作为联调期的测试人员,我想开启测试模式免真微信授权,以便快速验证登录流程而不依赖真实微信环境。

  • 角色:游客(测试环境)
  • 前置条件:后端 wechat.test-mode: true;小程序端对应配置开启。
  • 主流程
    1. 测试模式开 → 登录走模拟 openid / 模拟数据。
    2. 免微信授权回调,直接返回测试 token + 用户信息。
  • 异常/边界:测试模式仅测试环境生效;生产环境强制真实微信授权,禁止测试模式泄露到生产;测试模式登录的用户仅限测试库。
  • 关联需求/设计:AGENTS.md 测试模式(wechat.test-mode);AuthController。
  • 关联用例:TC-G-07

场景 G-8:环境自适应切换

用户故事:作为开发者/发布者,我希望小程序自动按环境选择 API 地址,以便 develop/trial/release 三环境无缝切换。

  • 角色:游客(启动时)
  • 前置条件:config.js 内置三套环境 API 地址。
  • 主流程
    1. 启动时调用 uni.getAccountInfoSync() 判定当前环境(develop/trial/release)。
    2. 按环境切换对应 API base URL。
    3. 后续所有请求走对应环境地址。
  • 异常/边界:环境识别失败(如 getAccountInfoSync 异常)回退默认(release)地址并告警;环境切换后缓存 token 按环境隔离。
  • 关联需求/设计:config.js 环境自适应;uni.getAccountInfoSync()。
  • 关联用例:TC-G-08

场景 G-9:退出登录

用户故事:作为已登录用户,我想安全退出并清除本地登录态,以便换号登录或保护设备隐私。

  • 角色:游客(已登录)
  • 前置条件:当前有有效 token;处于个人中心。
  • 主流程
    1. 点击「退出登录」→ 调用退出接口(可选)→ 清除本地 token 与缓存。
    2. 跳转登录页;再次进入需重新登录。
  • 异常/边界:退出后本地缓存的敏感数据(用户信息/家庭成员/报告缓存)清除;退出后访问受保护接口被 401;退出失败(网络)时本地仍强制清除并提示。
  • 关联需求/设计:AuthController;本地缓存管理。
  • 关联用例:TC-G-09

场景 G-10:账号不存在引导注册

用户故事:作为尚未注册的用户,我想在登录失败时被引导去注册,以便顺畅完成新用户建档。

  • 角色:游客(微信授权成功但无账号)
  • 前置条件:微信授权通过,但后端无对应 User。
  • 主流程
    1. 登录接口返回「未注册/账号不存在」提示。
    2. 页面引导进入注册流程(填写必要信息 / 直接建档)。
    3. 注册成功后进入默认家长首页。
  • 异常/边界:已注册账号不重复建档(openid 已存在则直接登录不新建);注册信息校验失败给出明确提示。
  • 关联需求/设计:AuthController;User + family_members 建档逻辑。
  • 关联用例:TC-G-10

场景 G-11:隐私政策 / 用户协议查看

用户故事:作为首次使用用户,我想查看隐私政策与用户协议并确认同意,以便合规进入核心流程。

  • 角色:游客(首次进入)
  • 前置条件:进入注册/登录页或首次打开核心功能。
  • 主流程
    1. 点击「隐私政策 / 用户协议」→ 查看全文。
    2. 阅读后点「同意」→ 记录同意时间戳 → 允许进入核心流程。
    3. 「不同意 / 返回」→ 停留在引导页,不进入核心流程。
  • 异常/边界:未同意不可进入注册/核心流程;同意记录需留痕(版本 + 时间);协议版本更新后需重新同意。
  • 关联需求/设计:协议页 / AgreementController;合规告知。
  • 关联用例:TC-G-11

场景 G-12:非微信环境 H5 兜底

用户故事:作为通过非微信浏览器(如手机 Safari/Chrome)打开小程序链接的用户,我想获得明确引导,以便知道如何在微信内使用。

  • 角色:游客(非微信浏览器)
  • 前置条件:通过链接/二维码打开小程序落地页。
  • 主流程
    1. H5 打开 → 环境探测判定非微信。
    2. 展示「请在微信内打开」引导页或降级静态内容页。
  • 异常/边界:环境探测失败给出明确引导(不白屏);降级页可正常浏览公开内容;不引导下载/安装(避免诱导)。
  • 关联需求/设计:config.js 环境探测;H5 兜底页。
  • 关联用例:TC-G-12