88 lines
4.1 KiB
Markdown
88 lines
4.1 KiB
Markdown
# 2026-10-19 K19 客户端账号中心
|
||
|
||
## 基线
|
||
|
||
- ReelShort `develop`: `7d68699`
|
||
- FruitServer `develop`: `5c93ba9`
|
||
- 只改 ReelShort;不改 FruitServer 业务代码、ReelShortWeb、specs、main。
|
||
|
||
## 范围
|
||
|
||
对接 `docs/api-phase1.md` §1.2 的六个个人中心接口:
|
||
|
||
| 方法 | 路径 | 客户端用途 |
|
||
| --- | --- | --- |
|
||
| GET | `/app/me` | 资料展示 |
|
||
| PUT | `/app/me` | 修改昵称、性别、生日 |
|
||
| GET | `/app/me/devices` | 只读登录设备列表 |
|
||
| GET | `/app/me/export` | 账号数据摘要与完整 JSON 复制 |
|
||
| POST | `/app/me/deactivate` | 申请注销并进入 15 天冷静期 |
|
||
| POST | `/app/me/deactivate/cancel` | 撤销待处理注销申请 |
|
||
|
||
## 接口口径
|
||
|
||
1. 资料响应仅使用:
|
||
`uid/nickname/avatarUrl/gender/countryCode/regionCode/language/timezone/currency/status/maskedTarget/createdAt/lastLoginAt/vipLevel/vipExpireAt`。
|
||
`vipLevel` 是整数;时间字段按 `LocalDateTime` 字符串解析。
|
||
2. 资料更新只发送本次变更字段:
|
||
`nickname/avatarUrl/gender/birthday/language/timezone/regionCode`。
|
||
本页只修改 `nickname/gender/birthday`;昵称 trim 后非空且不超过 30 字符,
|
||
性别取 `male/female/unknown`,生日格式 `yyyy-MM-dd`。
|
||
3. 设备数组只解析并展示
|
||
`deviceId/platform/deviceModel/firstSeenAt/lastSeenAt/status`;
|
||
`id/userId/deleted` 不展示、不打印。页面只读。
|
||
4. 导出按实际结构解析
|
||
`{profile, credentials, consents, devices}`,展示资料摘要、凭据、授权记录数和设备数;
|
||
“复制完整 JSON”只写系统剪贴板,不写本地文件。
|
||
5. 注销请求只发送 `reason`,不采集或上送密码;成功返回 `scheduledAt`。
|
||
成功后清本地会话,不调用 logout。撤销接口成功 `data=null`,失败原样透传后端文案。
|
||
6. 所有数值和 ID 使用 `jsonToId/jsonToInt`;错误由 `ApiException` 透传到逻辑层。
|
||
|
||
## 客户端改造
|
||
|
||
- `lib/core/data/remote/account_api.dart`
|
||
- `lib/core/data/models/account_profile.dart`
|
||
- `lib/core/data/models/account_device.dart`
|
||
- `lib/core/data/models/account_export.dart`
|
||
- `lib/core/data/repositories/account_repository.dart`
|
||
- `lib/pages/account/` 下四个页面及各自的 binding/logic
|
||
- `lib/pages/mine/mine_view.dart` 登录态新增“账号”卡
|
||
- `lib/core/data/services/auth_controller.dart` 新增 `applyProfile`
|
||
- `lib/app.dart` 注册 `AccountRepository` Provider
|
||
- `lib/l10n/app_{en,zh,id}.arb` 与生成文件
|
||
- 测试新增 `test/account/`、`test/support/fake_account_repository.dart`
|
||
|
||
## TDD 顺序
|
||
|
||
1. 先写 API/模型测试:六条路径、方法、请求体、字符串/数字 ID、缺字段;
|
||
运行定向测试确认红灯。
|
||
2. 实现 AccountApi、三个模型和 AccountRepository,定向测试转绿。
|
||
3. 先写 AuthController.applyProfile 测试:保留令牌、更新昵称/头像并持久化;
|
||
再实现。
|
||
4. 先写 profile/device/export/deactivate logic 测试:
|
||
资料保存回调登录态、注销成功清会话、撤销失败透传文案、导出复制内容;
|
||
再实现逻辑层。
|
||
5. 先写 widget 测试:我的页入口登录可见、资料回填与保存、设备空态、
|
||
注销二次确认、导出加载/失败/重试;再实现页面和入口。
|
||
6. 生成 l10n,跑全量门禁;最后一次全量测试与 APK 构建。
|
||
|
||
## 门禁
|
||
|
||
```text
|
||
dart analyze lib test
|
||
flutter test
|
||
flutter build apk --debug
|
||
```
|
||
|
||
Flutter 分支:`feature/flutter-k19-account`。
|
||
|
||
## 风险与待确认
|
||
|
||
- `GET /app/me` 不返回注销申请状态,UI 不猜测状态;撤销失败展示后端文案。
|
||
- 无设备下线接口,设备页只读;`TC-ACCOUNT-10` 的“单点下线”保留为缺口。
|
||
- 无头像上传接口,头像只展示;空值使用现有占位。
|
||
- 资料响应不含 `birthday`,也没有清空入口。本批生日只能设置,无法回填或清除;
|
||
不补后端字段,页面文案明确为本次设置。
|
||
- 注销成功后服务端立即吊销全部会话,本地同步清理;撤销入口在重新登录后仍可使用。
|
||
- 真机验证由用户执行,本批不提供开发机 curl 或设备侧结果作为证据。
|