# 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 或设备侧结果作为证据。