1
This commit is contained in:
963
docs/prd/ACCOUNT_SYSTEM_AND_LOGIN_ENTRY_PRD_2026-04-09.md
Normal file
963
docs/prd/ACCOUNT_SYSTEM_AND_LOGIN_ENTRY_PRD_2026-04-09.md
Normal file
@@ -0,0 +1,963 @@
|
||||
# 账号系统与登录入口重构 PRD
|
||||
|
||||
更新时间:`2026-04-09`
|
||||
|
||||
## 0. 目标
|
||||
|
||||
这份 PRD 面向当前仓库,要解决的是一个已经非常明确的产品问题:
|
||||
|
||||
**游戏开始界面目前还是“开始游戏”导向,但项目已经进入后端账号模式,真正缺的是一套正式可运营的账号登录入口和账号体系。**
|
||||
|
||||
这次要完成的不是单纯把按钮文案改掉,而是把当前入口、鉴权、存档归属和跨设备使用体验一起重构成完整闭环:
|
||||
|
||||
1. 游戏开始界面从“开始游戏”切换为“账号登录”
|
||||
2. 支持 `手机号验证码登录`
|
||||
3. 支持 `微信登录`
|
||||
4. 微信登录后必须先绑定手机号,绑定完成后才能进入游戏
|
||||
5. 账号与存档、自定义世界、运行时设置统一绑定到后端用户体系
|
||||
6. 整体体验保持移动端优先、界面清爽、规则不堆满前台
|
||||
|
||||
一句话目标:
|
||||
|
||||
**让“登录账号”成为进入游戏的第一步,让手机号和微信成为正式身份入口,并把账号与游戏数据归属真正接到 Express 后端。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 当前现状
|
||||
|
||||
## 1.1 当前仓库已经有基础鉴权,但不是正式账号系统
|
||||
|
||||
从当前代码看:
|
||||
|
||||
- `src/components/auth/AuthGate.tsx`
|
||||
- 当前会在无 token 时自动创建或恢复匿名账号
|
||||
- `src/services/authService.ts`
|
||||
- 当前支持“用户名 + 密码”直进,且带自动生成游客凭据逻辑
|
||||
- `server-node/src/routes/authRoutes.ts`
|
||||
- 当前只有 `/api/auth/entry`、`/api/auth/me`、`/api/auth/logout`
|
||||
- `server-node/src/auth/authService.ts`
|
||||
- 当前后端仍是“用户名不存在就自动创建,存在就校验密码”的轻量方案
|
||||
- `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
- 开始页前台主语仍然是“开始游戏 / 新游戏 / 继续游戏”
|
||||
|
||||
这说明当前系统已经有“用户 ID + JWT + 用户隔离存档”,但还没有正式运营可用的:
|
||||
|
||||
- 手机号体系
|
||||
- 微信身份体系
|
||||
- 绑定关系体系
|
||||
- 验证码体系
|
||||
- 会话过期与刷新体系
|
||||
- 账号归并与换绑规则
|
||||
|
||||
## 1.2 当前方案存在的直接问题
|
||||
|
||||
### 1.2.1 入口主语错位
|
||||
|
||||
当前开始页告诉玩家的是:
|
||||
|
||||
- 开始游戏
|
||||
|
||||
但真实系统需要的是:
|
||||
|
||||
- 先确认你是谁
|
||||
- 再把你的存档和世界数据挂到你的账号下
|
||||
|
||||
也就是说,前台入口和后端真实数据归属已经不一致。
|
||||
|
||||
### 1.2.2 匿名自动账号不适合正式用户体系
|
||||
|
||||
当前自动生成随机账号的方案适合开发期快速联调,但不适合正式版本,因为它会带来:
|
||||
|
||||
- 用户无法理解自己的账号是什么
|
||||
- 跨设备登录和找回几乎不可用
|
||||
- 微信登录无法落地
|
||||
- 手机号绑定没有锚点
|
||||
- 用户会误以为“换设备 = 进度丢失”
|
||||
|
||||
### 1.2.3 微信登录缺少落点
|
||||
|
||||
如果只做“微信授权成功即进入游戏”,会出现两个问题:
|
||||
|
||||
1. 账号恢复能力弱
|
||||
- 一旦微信环境变化,恢复和找回仍然不稳。
|
||||
2. 数据归属不稳定
|
||||
- 仅靠微信身份,不利于后续账号运营、客服排查、风控与跨端同步。
|
||||
|
||||
因此:
|
||||
|
||||
**微信登录不是最终归属,手机号绑定才是正式账号落点。**
|
||||
|
||||
### 1.2.4 当前永久 JWT 不适合正式登录系统
|
||||
|
||||
现状文档已经说明当前 JWT 是永久签发。
|
||||
|
||||
这对开发期方便,但对正式账号系统有明显风险:
|
||||
|
||||
- token 泄露后难以及时失效
|
||||
- 多设备会话管理能力不足
|
||||
- 换绑手机号和安全操作缺少会话边界
|
||||
|
||||
---
|
||||
|
||||
## 2. 设计原则
|
||||
|
||||
## 2.1 账号先于游戏
|
||||
|
||||
正式版本中,玩家进入游戏主流程前,应该先完成账号确认。
|
||||
|
||||
前台语义改为:
|
||||
|
||||
- 未登录:账号登录
|
||||
- 已登录:继续冒险 / 选择世界 / 开始新档
|
||||
|
||||
而不是一上来先点“开始游戏”。
|
||||
|
||||
## 2.2 移动端优先,前台保持清爽
|
||||
|
||||
开始界面和登录面板要继续遵循当前项目已经沉淀出的 UI 经验:
|
||||
|
||||
- 手机竖屏优先
|
||||
- 入口动作少而清晰
|
||||
- 不堆大段规则说明
|
||||
- 主按钮只保留关键动作
|
||||
|
||||
所以登录前台默认只呈现:
|
||||
|
||||
- 手机号登录
|
||||
- 微信登录
|
||||
- 开发团队(次级)
|
||||
|
||||
## 2.3 前端只负责表现,账号逻辑全部进 Express 后端
|
||||
|
||||
必须严格遵守当前项目约束:
|
||||
|
||||
- 前端只渲染登录状态、错误态、输入态、成功态
|
||||
- 验证码发送、验证码校验、微信 OAuth、绑定决策、账号归并、token 签发全部由 Express 后端处理
|
||||
|
||||
前端不能自行决定:
|
||||
|
||||
- 账号是否新建
|
||||
- 是否允许绑定
|
||||
- 是否归并到已有账号
|
||||
- 是否允许进入游戏
|
||||
|
||||
## 2.4 微信登录不是免绑定通行证
|
||||
|
||||
微信登录后,如果账号没有绑定手机号,则:
|
||||
|
||||
- 允许展示绑定手机号页
|
||||
- 不允许进入游戏主流程
|
||||
- 不允许创建正式存档
|
||||
- 不允许进入世界选择和冒险流程
|
||||
|
||||
一句话约束:
|
||||
|
||||
**微信授权成功 != 可以开始游戏,绑定手机号成功后才算正式激活账号。**
|
||||
|
||||
## 2.5 一个手机号对应一个正式主账号
|
||||
|
||||
MVP 阶段建议采用最稳妥规则:
|
||||
|
||||
- 一个手机号只能绑定一个正式账号
|
||||
- 一个微信身份只能绑定一个正式账号
|
||||
- 一个正式账号必须有已验证手机号
|
||||
- 微信是可选登录方式,手机号是正式归属方式
|
||||
|
||||
---
|
||||
|
||||
## 3. 产品范围
|
||||
|
||||
## 3.1 本期要做
|
||||
|
||||
1. 开始界面改成账号登录入口
|
||||
2. 手机号验证码登录
|
||||
3. 微信登录
|
||||
4. 微信后强制绑定手机号
|
||||
5. 账号会话管理
|
||||
6. 账号与存档/自定义世界/运行时设置统一绑定
|
||||
7. 基础账号中心与退出登录
|
||||
|
||||
## 3.2 本期不做
|
||||
|
||||
1. 用户名密码注册
|
||||
2. 游客正式入口
|
||||
3. 账号密码找回
|
||||
4. 实名认证
|
||||
5. 社交好友体系
|
||||
6. 多微信绑定同一账号
|
||||
|
||||
说明:
|
||||
|
||||
当前用户名密码模式可仅保留为开发环境兜底能力,不作为正式前台入口。
|
||||
|
||||
---
|
||||
|
||||
## 4. 用户状态设计
|
||||
|
||||
建议把账号状态统一为下面 5 类:
|
||||
|
||||
## 4.1 未登录
|
||||
|
||||
特征:
|
||||
|
||||
- 本地无有效会话
|
||||
- 前台只显示登录入口
|
||||
|
||||
允许动作:
|
||||
|
||||
- 手机号登录
|
||||
- 微信登录
|
||||
- 查看开发团队
|
||||
|
||||
不允许动作:
|
||||
|
||||
- 开始游戏
|
||||
- 选择世界
|
||||
- 进入已有存档
|
||||
|
||||
## 4.2 手机号已登录
|
||||
|
||||
特征:
|
||||
|
||||
- 已完成手机号验证码校验
|
||||
- 已有正式账号
|
||||
|
||||
允许动作:
|
||||
|
||||
- 继续冒险
|
||||
- 开始新档
|
||||
- 选择世界
|
||||
- 查看账号信息
|
||||
- 退出登录
|
||||
|
||||
## 4.3 微信已授权但未绑定手机号
|
||||
|
||||
特征:
|
||||
|
||||
- 已拿到微信身份
|
||||
- 后端已创建待激活账号壳
|
||||
- 账号状态为 `pending_bind_phone`
|
||||
|
||||
允许动作:
|
||||
|
||||
- 绑定手机号
|
||||
- 切换其他登录方式
|
||||
- 退出当前授权态
|
||||
|
||||
不允许动作:
|
||||
|
||||
- 进入游戏
|
||||
- 创建正式存档
|
||||
- 使用正式运行时能力
|
||||
|
||||
## 4.4 微信已授权且已绑定手机号
|
||||
|
||||
特征:
|
||||
|
||||
- 微信身份已归属到正式账号
|
||||
- 手机号已验证
|
||||
|
||||
允许动作:
|
||||
|
||||
- 与手机号登录用户相同
|
||||
|
||||
## 4.5 会话过期或失效
|
||||
|
||||
特征:
|
||||
|
||||
- access token 过期
|
||||
- refresh session 无效
|
||||
- 或账号状态被强制失效
|
||||
|
||||
表现:
|
||||
|
||||
- 前台回到登录入口
|
||||
- 如果是绑定中状态失效,则回到重新登录
|
||||
|
||||
---
|
||||
|
||||
## 5. 开始界面重构方案
|
||||
|
||||
## 5.1 未登录状态下的开始界面
|
||||
|
||||
当前开始界面的主按钮“开始游戏”应被替换为“账号登录”语义。
|
||||
|
||||
建议界面结构:
|
||||
|
||||
### 顶部
|
||||
|
||||
- 游戏名
|
||||
- 一句极短副标题
|
||||
|
||||
副标题只保留类似:
|
||||
|
||||
- 登录后同步你的冒险进度
|
||||
|
||||
不要再出现规则说明式长文案。
|
||||
|
||||
### 中部主按钮
|
||||
|
||||
只保留两个一级主按钮:
|
||||
|
||||
1. `手机号登录`
|
||||
2. `微信登录`
|
||||
|
||||
按钮样式要求:
|
||||
|
||||
- 手机端纵向堆叠
|
||||
- 桌面端仍以单列为主,不做复杂双栏表单
|
||||
- 点击目标区域足够大
|
||||
- 视觉主语明确是“登录方式”,不是“功能菜单”
|
||||
|
||||
### 底部次级入口
|
||||
|
||||
- `开发团队`
|
||||
|
||||
联系方式面板不建议再作为开始页主信息块长期占据核心位置,避免稀释登录主动作。
|
||||
|
||||
## 5.2 微信未绑定状态下的开始界面
|
||||
|
||||
微信授权成功但未绑定手机号时,开始界面应切成“待激活账号”形态。
|
||||
|
||||
只展示:
|
||||
|
||||
- 微信头像/昵称(可选)
|
||||
- 当前提示:请绑定手机号后进入游戏
|
||||
- 绑定手机号按钮
|
||||
- 返回其他登录方式按钮
|
||||
|
||||
这个状态下不要显示:
|
||||
|
||||
- 继续游戏
|
||||
- 新游戏
|
||||
- 世界选择
|
||||
|
||||
## 5.3 已登录状态下的开始界面
|
||||
|
||||
当账号已正式激活后,开始界面才恢复游戏入口动作,但按钮文案要重新组织。
|
||||
|
||||
建议一级动作:
|
||||
|
||||
- `继续冒险`(存在存档时)
|
||||
- `开始新档`
|
||||
- `选择世界`
|
||||
|
||||
建议次级动作:
|
||||
|
||||
- `账号设置`
|
||||
- `退出登录`
|
||||
- `开发团队`
|
||||
|
||||
也就是说:
|
||||
|
||||
**“开始游戏”不再是未登录态按钮,而是登录后的游戏内动作集合。**
|
||||
|
||||
---
|
||||
|
||||
## 6. 核心功能设计
|
||||
|
||||
## 6.1 手机号验证码登录
|
||||
|
||||
### 交互
|
||||
|
||||
用户输入手机号后:
|
||||
|
||||
1. 点击发送验证码
|
||||
2. 收到 6 位短信验证码
|
||||
3. 输入验证码完成登录
|
||||
|
||||
### 规则
|
||||
|
||||
- 验证码有效期:`5` 分钟
|
||||
- 重新发送冷却:`60` 秒
|
||||
- 单手机号日发送上限:需配置
|
||||
- 单 IP / 单设备分钟级频控:需配置
|
||||
- 验证成功后自动登录
|
||||
|
||||
### 账号策略
|
||||
|
||||
- 手机号已存在:登录已有账号
|
||||
- 手机号不存在:创建正式账号并登录
|
||||
|
||||
MVP 阶段不需要单独设置密码。
|
||||
|
||||
## 6.2 微信登录
|
||||
|
||||
微信登录按终端拆分:
|
||||
|
||||
### 微信内 H5
|
||||
|
||||
- 走微信 OAuth 授权
|
||||
- 后端换取 `code`
|
||||
- 优先获取 `unionid`
|
||||
|
||||
### 桌面网页
|
||||
|
||||
- 走微信扫码登录
|
||||
- 用户扫码确认后由后端完成登录回调
|
||||
|
||||
### 普通手机浏览器
|
||||
|
||||
如果不在微信环境内,不强行做复杂跳转,建议:
|
||||
|
||||
- 优先提示使用手机号登录
|
||||
- 或提示“请在微信内打开以使用微信登录”
|
||||
|
||||
这样比做一套体验不稳定的浏览器跳转更稳。
|
||||
|
||||
### 微信账号策略
|
||||
|
||||
- 若微信身份已绑定正式账号:直接登录
|
||||
- 若微信身份首次出现:创建 `pending_bind_phone` 账号壳,并进入绑定手机号流程
|
||||
|
||||
## 6.3 微信后绑定手机号
|
||||
|
||||
这是本期最关键规则。
|
||||
|
||||
### 绑定目标
|
||||
|
||||
把微信身份最终归属到一个已验证手机号的正式账号上。
|
||||
|
||||
### 绑定流程
|
||||
|
||||
1. 用户完成微信授权
|
||||
2. 前台进入“绑定手机号”页
|
||||
3. 输入手机号
|
||||
4. 获取短信验证码
|
||||
5. 后端校验验证码并处理账号归属
|
||||
|
||||
### 绑定结果分两类
|
||||
|
||||
#### 情况 A:手机号未被使用
|
||||
|
||||
结果:
|
||||
|
||||
- 将该手机号绑定到当前微信待激活账号
|
||||
- 账号转为正式激活
|
||||
- 登录成功,进入游戏开始界面已登录态
|
||||
|
||||
#### 情况 B:手机号已绑定已有正式账号
|
||||
|
||||
建议采用最稳的归并策略:
|
||||
|
||||
1. 短信验证码校验通过
|
||||
2. 后端确认该手机号已有正式账号
|
||||
3. 将当前微信身份直接绑定到该正式账号
|
||||
4. 废弃当前待激活账号壳
|
||||
5. 用户登录到已有手机号账号
|
||||
|
||||
这样做的好处是:
|
||||
|
||||
- 规则简单
|
||||
- 不需要做复杂数据合并
|
||||
- 因为未绑定手机号前禁止进入游戏,所以待激活账号壳上不会挂正式存档数据
|
||||
|
||||
## 6.4 账号中心
|
||||
|
||||
MVP 阶段建议至少提供一个轻量账号中心,包含:
|
||||
|
||||
- 当前登录方式
|
||||
- 已绑定手机号(脱敏展示)
|
||||
- 微信绑定状态
|
||||
- 最近登录时间
|
||||
- 退出登录
|
||||
|
||||
二期可以再补:
|
||||
|
||||
- 更换手机号
|
||||
- 退出全部设备
|
||||
- 查看登录设备
|
||||
|
||||
## 6.5 存档与数据归属
|
||||
|
||||
当前项目已有:
|
||||
|
||||
- 存档快照
|
||||
- 自定义世界库
|
||||
- 运行时设置
|
||||
|
||||
这些数据已经在后端按用户隔离。
|
||||
|
||||
本期要求是把它们统一稳定归属到正式账号,而不是匿名随机用户。
|
||||
|
||||
也就是说:
|
||||
|
||||
- 手机号登录后,数据归属到该账号
|
||||
- 微信登录并绑定手机号后,数据归属到绑定后的正式账号
|
||||
- 同一账号跨设备登录,应读取同一份用户数据
|
||||
|
||||
---
|
||||
|
||||
## 7. 后端账号模型设计
|
||||
|
||||
## 7.1 设计思路
|
||||
|
||||
建议保留当前 `users` 主表,但把“登录方式”和“账号归属”拆到独立身份表中。
|
||||
|
||||
正式模型应区分:
|
||||
|
||||
- 用户主实体
|
||||
- 登录身份
|
||||
- 验证码记录
|
||||
- 会话记录
|
||||
|
||||
## 7.2 建议数据表
|
||||
|
||||
### `users`
|
||||
|
||||
建议保留并扩展:
|
||||
|
||||
- `id`
|
||||
- `display_name`
|
||||
- `account_status`
|
||||
- `primary_phone`
|
||||
- `phone_verified_at`
|
||||
- `token_version`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
- `last_login_at`
|
||||
|
||||
其中:
|
||||
|
||||
- `account_status` 需至少支持:
|
||||
- `active`
|
||||
- `pending_bind_phone`
|
||||
- `disabled`
|
||||
|
||||
### `auth_identities`
|
||||
|
||||
用于记录登录身份。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `provider`
|
||||
- `provider_uid`
|
||||
- `provider_unionid`
|
||||
- `phone_e164`
|
||||
- `is_verified`
|
||||
- `is_primary`
|
||||
- `bound_at`
|
||||
- `last_login_at`
|
||||
- `meta_json`
|
||||
|
||||
其中 `provider` 至少支持:
|
||||
|
||||
- `phone`
|
||||
- `wechat`
|
||||
|
||||
说明:
|
||||
|
||||
- 手机号登录身份存 `phone_e164`
|
||||
- 微信登录身份优先存 `unionid`
|
||||
- 若极端场景拿不到 `unionid`,需明确风险并做降级策略,但正式上线应优先确保 `unionid`
|
||||
|
||||
### `phone_verification_codes`
|
||||
|
||||
用于短信验证码管理。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `phone_e164`
|
||||
- `scene`
|
||||
- `code_hash`
|
||||
- `expires_at`
|
||||
- `consumed_at`
|
||||
- `send_ip`
|
||||
- `device_id`
|
||||
- `created_at`
|
||||
|
||||
`scene` 建议至少区分:
|
||||
|
||||
- `login`
|
||||
- `bind_phone`
|
||||
- `change_phone`
|
||||
|
||||
### `user_sessions`
|
||||
|
||||
用于会话刷新和设备管理。
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `refresh_token_hash`
|
||||
- `client_type`
|
||||
- `user_agent`
|
||||
- `ip`
|
||||
- `expires_at`
|
||||
- `revoked_at`
|
||||
- `created_at`
|
||||
- `last_seen_at`
|
||||
|
||||
## 7.3 与当前仓库的关系
|
||||
|
||||
当前仓库已有:
|
||||
|
||||
- `users`
|
||||
- JWT 鉴权
|
||||
- `token_version`
|
||||
|
||||
因此本期不是推翻重做,而是:
|
||||
|
||||
1. 保留 `users` 作为账号主表
|
||||
2. 废弃“用户名密码自动注册”作为正式入口
|
||||
3. 增加手机号与微信身份层
|
||||
4. 增加验证码表与会话表
|
||||
|
||||
---
|
||||
|
||||
## 8. 接口设计
|
||||
|
||||
所有接口均由 Express 后端承接。
|
||||
|
||||
## 8.1 手机号登录相关
|
||||
|
||||
### `POST /api/auth/phone/send-code`
|
||||
|
||||
用途:
|
||||
|
||||
- 发送登录验证码
|
||||
|
||||
入参:
|
||||
|
||||
- `phone`
|
||||
- `scene`
|
||||
|
||||
出参:
|
||||
|
||||
- `ok`
|
||||
- `cooldownSeconds`
|
||||
|
||||
### `POST /api/auth/phone/login`
|
||||
|
||||
用途:
|
||||
|
||||
- 使用手机号 + 验证码登录或注册
|
||||
|
||||
入参:
|
||||
|
||||
- `phone`
|
||||
- `code`
|
||||
|
||||
出参:
|
||||
|
||||
- `accessToken`
|
||||
- `accessTokenExpiresAt`
|
||||
- `user`
|
||||
- `bindingStatus`
|
||||
|
||||
## 8.2 微信登录相关
|
||||
|
||||
### `GET /api/auth/wechat/start`
|
||||
|
||||
用途:
|
||||
|
||||
- 获取微信授权跳转地址或扫码会话
|
||||
|
||||
### `GET /api/auth/wechat/callback`
|
||||
|
||||
用途:
|
||||
|
||||
- 微信授权完成后的后端回调
|
||||
|
||||
回调结果分两类:
|
||||
|
||||
1. 已绑定正式账号
|
||||
- 直接签发会话
|
||||
2. 未绑定手机号
|
||||
- 签发临时登录态,并标记 `pending_bind_phone`
|
||||
|
||||
### `POST /api/auth/wechat/bind-phone`
|
||||
|
||||
用途:
|
||||
|
||||
- 微信授权后绑定手机号
|
||||
|
||||
入参:
|
||||
|
||||
- `phone`
|
||||
- `code`
|
||||
|
||||
出参:
|
||||
|
||||
- `accessToken`
|
||||
- `accessTokenExpiresAt`
|
||||
- `user`
|
||||
- `bindingStatus: active`
|
||||
|
||||
## 8.3 会话与账号信息
|
||||
|
||||
### `GET /api/auth/me`
|
||||
|
||||
返回建议扩展为:
|
||||
|
||||
- `user`
|
||||
- `bindingStatus`
|
||||
- `boundPhoneMasked`
|
||||
- `wechatBound`
|
||||
- `availableLoginMethods`
|
||||
|
||||
### `POST /api/auth/logout`
|
||||
|
||||
用途:
|
||||
|
||||
- 当前设备退出登录
|
||||
|
||||
### `POST /api/auth/refresh`
|
||||
|
||||
用途:
|
||||
|
||||
- 刷新 access token
|
||||
|
||||
说明:
|
||||
|
||||
当前仓库已有 Bearer token 调用链,MVP 阶段可继续保留 Bearer access token 的前端接法,但不应再使用永久 token。
|
||||
|
||||
---
|
||||
|
||||
## 9. 会话与安全设计
|
||||
|
||||
## 9.1 token 策略
|
||||
|
||||
建议从“永久 JWT”切为:
|
||||
|
||||
- `access token`:短期有效
|
||||
- `refresh session`:中期有效
|
||||
|
||||
建议时长:
|
||||
|
||||
- access token:`2` 小时
|
||||
- refresh session:`30` 天
|
||||
|
||||
## 9.2 失效策略
|
||||
|
||||
- 退出登录:失效当前 refresh session,并提升 `token_version`
|
||||
- 账号异常:可强制失效全部 session
|
||||
- 换绑手机号:旧高风险会话应重新校验
|
||||
|
||||
## 9.3 验证码风控
|
||||
|
||||
至少要有:
|
||||
|
||||
- 发送频控
|
||||
- 校验次数限制
|
||||
- 图形验证码扩展点
|
||||
- 日志审计
|
||||
|
||||
## 9.4 微信安全要求
|
||||
|
||||
- 校验 `state`
|
||||
- 回调只能由后端处理
|
||||
- 不在前端直接换 token
|
||||
- 优先使用 `unionid` 作为跨应用稳定身份标识
|
||||
|
||||
---
|
||||
|
||||
## 10. 详细用户流程
|
||||
|
||||
## 10.1 手机号登录流程
|
||||
|
||||
1. 用户打开游戏开始界面
|
||||
2. 点击 `手机号登录`
|
||||
3. 输入手机号
|
||||
4. 点击 `获取验证码`
|
||||
5. 输入验证码
|
||||
6. 后端校验验证码
|
||||
7. 若账号存在则登录,若不存在则创建正式账号
|
||||
8. 返回已登录开始界面
|
||||
9. 用户再选择 `继续冒险 / 开始新档 / 选择世界`
|
||||
|
||||
## 10.2 微信登录流程
|
||||
|
||||
1. 用户打开游戏开始界面
|
||||
2. 点击 `微信登录`
|
||||
3. 进入微信授权或扫码授权
|
||||
4. 后端拿到微信身份
|
||||
5. 若该微信已绑定正式账号,则直接登录
|
||||
6. 若该微信未绑定正式账号,则进入 `绑定手机号` 页
|
||||
7. 用户完成手机号验证码校验
|
||||
8. 后端完成绑定或归并
|
||||
9. 返回已登录开始界面
|
||||
|
||||
## 10.3 微信绑定已有手机号账号流程
|
||||
|
||||
1. 用户微信首次登录
|
||||
2. 系统要求绑定手机号
|
||||
3. 用户输入一个已注册手机号
|
||||
4. 用户完成短信验证码校验
|
||||
5. 后端识别该手机号已有正式账号
|
||||
6. 系统将当前微信身份绑定到该正式账号
|
||||
7. 当前待激活账号壳废弃
|
||||
8. 用户直接登录到已有正式账号
|
||||
|
||||
---
|
||||
|
||||
## 11. 前端实现要求
|
||||
|
||||
## 11.1 前端只维护这些状态
|
||||
|
||||
前端主要只需要表现这些状态:
|
||||
|
||||
- `idle`
|
||||
- `sending_code`
|
||||
- `code_sent`
|
||||
- `wechat_authorizing`
|
||||
- `pending_bind_phone`
|
||||
- `authenticated`
|
||||
- `session_expired`
|
||||
- `error`
|
||||
|
||||
## 11.2 前端不做业务裁决
|
||||
|
||||
前端不能自行决定:
|
||||
|
||||
- 当前手机号是新账号还是老账号
|
||||
- 微信是否允许直进
|
||||
- 当前绑定是“绑定”还是“归并”
|
||||
- 当前账号是否已经正式激活
|
||||
|
||||
前端只根据后端返回的:
|
||||
|
||||
- `bindingStatus`
|
||||
- `availableLoginMethods`
|
||||
- `user`
|
||||
- `errorCode`
|
||||
|
||||
来切换页面表现。
|
||||
|
||||
## 11.3 与当前代码结构的建议映射
|
||||
|
||||
建议优先改造这些区域:
|
||||
|
||||
- `src/components/auth/AuthGate.tsx`
|
||||
- 去掉正式环境的匿名自动登录逻辑
|
||||
- `src/components/auth/LoginScreen.tsx`
|
||||
- 重做为手机号 / 微信双入口
|
||||
- `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
- 将未登录态入口从“开始游戏”调整为“账号登录后进入”
|
||||
- `src/services/authService.ts`
|
||||
- 改为手机号、微信、绑定手机号、刷新会话等服务层
|
||||
- `src/services/apiClient.ts`
|
||||
- 增加 refresh / 过期处理
|
||||
- `packages/shared/src/contracts/auth.ts`
|
||||
- 扩展新的鉴权 contract
|
||||
|
||||
后端建议优先改造:
|
||||
|
||||
- `server-node/src/routes/authRoutes.ts`
|
||||
- `server-node/src/auth/authService.ts`
|
||||
- `server-node/src/repositories/userRepository.ts`
|
||||
- `server-node/src/middleware/auth.ts`
|
||||
|
||||
---
|
||||
|
||||
## 12. 分阶段落地建议
|
||||
|
||||
## 阶段 A:登录入口重构 + 手机号登录 MVP
|
||||
|
||||
目标:
|
||||
|
||||
- 开始界面从“开始游戏”切为“账号登录”
|
||||
- 手机号验证码登录可用
|
||||
- 正式环境关闭匿名自动账号
|
||||
|
||||
建议同时保留一个仅开发环境可开的兜底开关:
|
||||
|
||||
- `AUTH_ALLOW_DEV_GUEST=true`
|
||||
|
||||
但默认不开,不进入正式前台。
|
||||
|
||||
## 阶段 B:微信登录 + 强制绑定手机号
|
||||
|
||||
目标:
|
||||
|
||||
- 微信授权可用
|
||||
- 微信首次登录后强制绑定手机号
|
||||
- 已有手机号账号与微信身份可自动归并
|
||||
|
||||
## 阶段 C:会话完善 + 账号中心
|
||||
|
||||
目标:
|
||||
|
||||
- access/refresh 机制稳定
|
||||
- 账号中心可查看绑定状态
|
||||
- 支持更稳的退出登录与过期恢复
|
||||
|
||||
## 阶段 D:安全与运营补强
|
||||
|
||||
目标:
|
||||
|
||||
- 更细的风控策略
|
||||
- 登录审计
|
||||
- 换绑手机号
|
||||
- 退出全部设备
|
||||
|
||||
---
|
||||
|
||||
## 13. 验收标准
|
||||
|
||||
做到以下几点,才说明这套账号系统真正成立。
|
||||
|
||||
## 13.1 入口验收
|
||||
|
||||
1. 未登录时,开始界面不再出现“开始游戏”作为主按钮。
|
||||
2. 未登录时,前台主动作只剩手机号登录和微信登录。
|
||||
3. 已登录后,才出现继续冒险、开始新档、选择世界等游戏动作。
|
||||
|
||||
## 13.2 功能验收
|
||||
|
||||
1. 手机号验证码登录可稳定完成注册/登录。
|
||||
2. 微信首次登录后不能直接进入游戏,必须绑定手机号。
|
||||
3. 微信绑定一个已存在手机号时,能够归并到已有正式账号。
|
||||
4. 同一正式账号在不同设备登录后能看到同一份用户数据。
|
||||
|
||||
## 13.3 安全验收
|
||||
|
||||
1. 不再使用永久有效 access token。
|
||||
2. 验证码具备有效期、冷却和频控。
|
||||
3. 退出登录后旧会话不能继续访问受保护接口。
|
||||
|
||||
## 13.4 体验验收
|
||||
|
||||
1. 手机竖屏下登录入口一屏内就能看懂并操作。
|
||||
2. 登录页文案简洁,不堆规则说明。
|
||||
3. 微信未绑定状态下,用户能清楚知道下一步就是绑定手机号。
|
||||
|
||||
---
|
||||
|
||||
## 14. 为什么这套方案适合当前仓库
|
||||
|
||||
这套 PRD 不是凭空换一套系统,而是顺着当前仓库现状做升级:
|
||||
|
||||
1. 当前后端已经具备 `users + JWT + 用户隔离存档`
|
||||
- 所以正式账号体系不是从零开始。
|
||||
2. 当前前端已经有 `AuthGate + authService`
|
||||
- 所以登录入口和登录态切换已有承载点。
|
||||
3. 当前项目是移动端优先
|
||||
- 所以“两个主按钮 + 一个绑定流程”的轻量方案比厚重注册页更适合。
|
||||
4. 当前项目明确要求前端只做表现、逻辑下沉 Express
|
||||
- 所以这套方案把所有裁决都压到后端,和现有工程原则一致。
|
||||
|
||||
---
|
||||
|
||||
## 15. 最后结论
|
||||
|
||||
当前项目真正需要的,不是把“开始游戏”按钮换成另一个文案,而是把进入游戏的第一步从“点开始”升级成“确认正式账号身份”。
|
||||
|
||||
最合理的产品路径是:
|
||||
|
||||
1. 用手机号验证码建立正式账号主入口
|
||||
2. 用微信登录补充更低摩擦的登录方式
|
||||
3. 用“微信后必须绑定手机号”保证账号归属稳定
|
||||
4. 用后端统一承接身份、绑定、会话、存档归属
|
||||
|
||||
这样改完之后,玩家进入游戏时感知到的将不再是:
|
||||
|
||||
- “先点开始再说”
|
||||
|
||||
而会更接近:
|
||||
|
||||
- “先登录我的正式账号,再继续我的冒险进度。”
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user