Compare commits
3
Commits
d3b347aa09
...
28d2679b83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28d2679b83 | ||
|
|
6b5e70e554 | ||
|
|
5c93ba9131 |
No files matched your search
@@ -0,0 +1,87 @@
|
||||
# 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 或设备侧结果作为证据。
|
||||
@@ -20,6 +20,166 @@
|
||||
|
||||
---
|
||||
|
||||
## [已处理·待用户验收] 2026-10-19 | K19 客户端账号中心:资料 / 设备 / 数据导出 / 注销
|
||||
|
||||
**用户指令(2026-10-19)**:「先写 K19 任务书并派单」。
|
||||
> 只改客户端 `ReelShort`。后端、`ReelShortWeb`、`specs`、`main` 一律不动。
|
||||
|
||||
### 一、背景与缺口
|
||||
|
||||
后端 `/app` 共 45 个接口,客户端已接 26 个。本轮对接账号中心 6 个(`api-phase1.md` §1.2,第 157–162 行;实现见
|
||||
`fruitshorts-app-api/.../AppMeController.java`):
|
||||
|
||||
| 方法 | 路径 | 客户端现状 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/app/me` | 未对接 |
|
||||
| PUT | `/app/me` | 未对接 |
|
||||
| GET | `/app/me/devices` | 未对接 |
|
||||
| GET | `/app/me/export` | 未对接 |
|
||||
| POST | `/app/me/deactivate` | 未对接 |
|
||||
| POST | `/app/me/deactivate/cancel` | 未对接 |
|
||||
|
||||
### 二、接口与字段口径(以后端代码为准确认,勿臆造)
|
||||
|
||||
1. **GET `/app/me`** → `AppUserRespVO`:`uid, nickname, avatarUrl, gender, countryCode, regionCode,
|
||||
language, timezone, currency, status, maskedTarget, createdAt, lastLoginAt, vipLevel(Integer),
|
||||
vipExpireAt`。`vipLevel` 是数字,其余时间字段是 `LocalDateTime` 字符串。
|
||||
2. **PUT `/app/me`** → 请求 `ProfileUpdateReqVO`,全部字段可选,**只传本次改动的字段**:
|
||||
`nickname, avatarUrl, gender, birthday(yyyy-MM-dd), language, timezone, regionCode`。
|
||||
`nickname` 为空串时后端忽略;`gender` 取值按 `schema-phase1.sql` 注释用小写
|
||||
`male / female / unknown`;`birthday` 后端只能设置、不能清空。响应同 `AppUserRespVO`。
|
||||
3. **GET `/app/me/devices`** → **直接返回 `AppUserDevice` 实体数组**(不是专用 VO):
|
||||
`id, userId, deviceId, platform, deviceModel, firstSeenAt, lastSeenAt, status, createdAt, updatedAt, deleted`。
|
||||
按契约 §0,`Long` 字段以字符串下发。客户端**只展示** `deviceId/platform/deviceModel/firstSeenAt/lastSeenAt/status`,
|
||||
`userId`、`deleted` 一律忽略、不落日志、不上屏。
|
||||
4. **GET `/app/me/export`** → `{profile: AppUserRespVO, credentials: [{type, masked, verified}], consents: [...], devices: [...]}`
|
||||
(以 `AppUserService.exportAccount` 实际结构为准)。
|
||||
5. **POST `/app/me/deactivate`** → 请求 `{reason}`(`password` 后端当前不校验,**客户端不采集、不上送**);
|
||||
成功返回 `scheduledAt`(15 天冷静期截止时间,`LocalDateTime`)。后端同时吊销全部会话。
|
||||
已有申请时返回业务错误,文案「注销申请已在处理中」。
|
||||
6. **POST `/app/me/deactivate/cancel`** → 成功 `data = null`;无待处理申请时错误文案「没有待处理的注销申请」。
|
||||
|
||||
**契约缺口(本批如实标注,不得自行补后端)**:
|
||||
|
||||
- `GET /app/me` 不返回「注销申请中」状态 → UI 不能做状态判断,只能把后端错误文案原样透传;
|
||||
「撤销注销」入口常驻,无申请时展示后端返回的文案。
|
||||
- 无「设备下线 / 踢出」接口 → 设备页**只读**;`TC-ACCOUNT-10` 中「单点下线」记为缺口,留待后续批次。
|
||||
- 无头像上传接口 → 头像**只展示**(`avatarUrl` 为空用现有占位图标),本批不做上传、不做 URL 输入框。
|
||||
|
||||
### 三、客户端改造范围
|
||||
|
||||
1. **remote**:新增 `lib/core/data/remote/account_api.dart`,六个方法,路径与请求体严格按上表;
|
||||
错误一律抛现有 `ApiException`(禁止吞异常、禁止空 catch)。
|
||||
2. **models**:新增 `account_profile.dart`、`account_device.dart`、`account_export.dart`。
|
||||
数值/ID 解析用 `json_numbers.dart` 的 `jsonToId` / `jsonToInt`,兼容字符串与数字两种下发形式。
|
||||
3. **repository**:新增 `account_repository.dart`(接口 + `HttpAccountRepository`);
|
||||
在 `app.dart` 的 Provider 树注册,供页面与测试注入(`FakeAccountRepository` 放 `test/support/`)。
|
||||
4. **页面**(建议 `lib/pages/account/`,沿用 provider binding/logic/view 三层):
|
||||
- **个人资料**:进入时 `GET /app/me`;可改 `nickname`(去空格后非空、≤30 字符,客户端校验)、
|
||||
`gender`(male/female/unknown,本地化文案)、`birthday`(日期选择,`yyyy-MM-dd`);
|
||||
`uid / maskedTarget / countryCode / currency / status` 只读展示;`language / timezone / regionCode` 只读。
|
||||
保存调 `PUT /app/me`,成功后用响应刷新页面,并**同步本地登录态**(见第 6 条)。
|
||||
- **登录设备**:`GET /app/me/devices`,列表展示平台、机型、设备号(脱敏显示,保留首尾各 4 位)、
|
||||
首次/最近活跃时间、状态;空态用现有 `EmptyState`;本页只读。
|
||||
- **数据导出**:`GET /app/me/export`,展示资料摘要、凭据(`type/masked/verified`)、授权记录数、设备数;
|
||||
提供「复制完整 JSON」到剪贴板(`Clipboard.setData`)+ SnackBar 提示;不写本地文件。
|
||||
- **注销账号**:15 天冷静期与「申请后立即登出全部设备」的显著提示;可选注销原因(≤200 字);
|
||||
「申请注销」必须二次确认弹窗 → 成功后展示 `scheduledAt` 并清空本地会话(服务端已吊销全部会话,
|
||||
用 `AuthController.clear()`,不要再调 logout),回到未登录态;
|
||||
「撤销注销申请」常驻,成功/失败均以后端文案提示。
|
||||
5. **入口**:`lib/pages/mine/mine_view.dart` 在已登录态新增「账号」卡(置于钱包卡之后、菜单卡之前):
|
||||
个人资料 / 登录设备 / 数据导出 / 注销账号,四项带图标与分隔线;未登录不显示。样式沿用现有 `_menuCard`。
|
||||
6. **登录态同步**:`AuthController` 增加公开方法(如 `applyProfile(AuthUser)`),资料保存成功后更新
|
||||
内存 session 的 `uid/nickname/avatarUrl` 并持久化,使「我的」页昵称即时生效;不改令牌与刷新逻辑。
|
||||
7. **l10n**:新增文案必须同时写入 `app_en.arb / app_zh.arb / app_id.arb` 并重新生成;
|
||||
印尼语为印尼市场主语言,禁止留英文占位。
|
||||
8. **测试(TDD,先红后绿)**:
|
||||
- API/模型:六接口路径与请求体、`Long` 字符串/数字两种解析、缺字段容错、错误文案透传;
|
||||
- logic:资料保存成功后回调登录态、注销成功后清会话、撤销失败展示后端文案、导出复制内容;
|
||||
- widget:我的页四个入口仅登录态可见、资料页字段回填与保存、设备空态、注销二次确认、
|
||||
数据导出页加载/失败/重试。
|
||||
- 既有测试不得改断言;如需适配只改注入的 Fake。
|
||||
|
||||
### 四、约束与门禁
|
||||
|
||||
- 代码规模红线:函数 ≤50 行、参数 ≤5、类 ≤300 行、文件 ≤500 行、嵌套 ≤4、圈复杂度 ≤10;禁止魔法值。
|
||||
- public 类/方法必须有文档注释,文件首行统一 `// Author: fruit.com.cn`;禁止裸 `then()`、空 catch。
|
||||
- 门禁(不达标不提交):`dart analyze lib test` 零告警;`flutter test` 全过;
|
||||
`flutter build apk --debug` 构建通过。
|
||||
- 真机验证由用户执行,Codex **不得**自行做设备侧验证,也不得用本机 curl 充当设备证据。
|
||||
|
||||
### 五、Git 与交接
|
||||
|
||||
- 从干净 `develop`(基线 `7d68699`)拉 `feature/flutter-k19-account`;小步提交,
|
||||
`type(scope): 描述`(≤50 字符),只 `git add` 本次文件。
|
||||
- 完成后 `git checkout develop && git merge --no-ff feature/flutter-k19-account && git push origin develop`;
|
||||
**不动 `main`**;提交作者与提交者统一 `Zhou Weidong <502333560@qq.com>`。
|
||||
- 任务书与留痕属于 FruitServer 仓库:`docs/plans/PROGRESS.md` 追加命令 + 原始输出 + 解读,
|
||||
单独提交到 FruitServer `develop`(`docs(plans): ...`),不夹带客户端代码。
|
||||
|
||||
### 六、回执要求
|
||||
|
||||
完成后停住并回执:分支与提交号、六个接口的调用位置、测试条数与结果、`dart analyze` / `flutter test` /
|
||||
`flutter build apk --debug` 原始结论、已知缺口(设备下线 / 头像上传 / 注销状态查询),
|
||||
以及「用户可照做的真机验证步骤 + 每步预期结果」。
|
||||
|
||||
### 七、K19 完成回执
|
||||
|
||||
- 客户端分支:`feature/flutter-k19-account`
|
||||
- 功能末提交:`7151bc9`
|
||||
- 合并回 develop:`9b3ab9d`
|
||||
- 已推送:`7d68699..9b3ab9d develop`
|
||||
- author/committer:`Zhou Weidong <502333560@qq.com>`
|
||||
|
||||
六个接口调用集中在 `ReelShort/lib/core/data/remote/account_api.dart`,分别由:
|
||||
|
||||
- `AccountProfilePage` 调 GET/PUT `/app/me`
|
||||
- `AccountDevicesPage` 调 GET `/app/me/devices`
|
||||
- `AccountExportPage` 调 GET `/app/me/export`
|
||||
- `AccountDeactivatePage` 调 POST `/app/me/deactivate` 与 `/deactivate/cancel`
|
||||
|
||||
门禁原始结论:
|
||||
|
||||
```text
|
||||
$ dart analyze lib test
|
||||
No issues found!
|
||||
|
||||
$ flutter test
|
||||
00:26 +335: All tests passed!
|
||||
|
||||
$ flutter build apk --debug
|
||||
Running Gradle task 'assembleDebug'... 10.0s
|
||||
✓ Built build/app/outputs/flutter-apk/app-debug.apk
|
||||
```
|
||||
|
||||
已知缺口:
|
||||
|
||||
- `GET /app/me` 不返回注销申请状态,UI 不判断状态;撤销失败展示后端文案。
|
||||
- 没有设备下线接口,登录设备页只读;`TC-ACCOUNT-10` 的“单点下线”未实现。
|
||||
- 没有头像上传接口,头像只展示;空值使用占位图标。
|
||||
- 资料响应不含生日,当前只支持设置生日,不能回填或清空。
|
||||
|
||||
用户真机验证步骤(设备侧取证由用户执行):
|
||||
|
||||
1. 登录后进入「我的」。
|
||||
预期:钱包卡之后、菜单卡之前显示「账号」卡,包含个人资料 / 登录设备 /
|
||||
数据导出 / 注销账号四项。
|
||||
2. 打开「个人资料」。
|
||||
预期:昵称、性别、UID、脱敏账号、国家、币种、状态、语言、时区、地区回填;
|
||||
修改昵称与性别后保存,返回「我的」后昵称立即更新。
|
||||
3. 打开「登录设备」。
|
||||
预期:设备号脱敏,展示平台、机型、首次/最近活跃时间和状态;无设备时显示空态。
|
||||
4. 打开「数据导出」。
|
||||
预期:展示资料摘要、凭据、授权记录数和设备数;点「复制完整 JSON」出现成功提示。
|
||||
5. 打开「注销账号」。
|
||||
预期:显示 15 天冷静期与立即登出提示;输入原因后必须二次确认。
|
||||
6. 确认注销并重新打开 App。
|
||||
预期:成功页展示预计注销时间,本地会话已清空,App 回到未登录态。
|
||||
7. 重新登录后再次进入「注销账号」,点击「撤销注销申请」。
|
||||
预期:有申请时显示撤销成功;无申请时原样展示后端“没有待处理的注销申请”。
|
||||
|
||||
---
|
||||
|
||||
## [已处理·待用户验收] 2026-10-17 | K16 注册限流改为可配置(支持不限制)
|
||||
|
||||
**用户指令(2026-10-17)**:「注册 429 限流做成可配置的,不限制或限制数量」。
|
||||
|
||||
@@ -2202,6 +2202,175 @@ $ flutter test
|
||||
|
||||
---
|
||||
|
||||
## 34. K19 客户端账号中心
|
||||
|
||||
### 34.1 基线与实施范围
|
||||
|
||||
基线确认:
|
||||
|
||||
```text
|
||||
ReelShort: 7d68699 fix(config): 合并开发默认服务器地址
|
||||
FruitServer: 5c93ba9 docs(plans): 下发 K19 账号中心接口对接任务
|
||||
```
|
||||
|
||||
计划文档先提交为 `6b5e70e docs(plans): 增加 K19 账号中心实施计划`。
|
||||
客户端从干净 develop 创建 `feature/flutter-k19-account`,只对接:
|
||||
|
||||
```text
|
||||
GET /app/me
|
||||
PUT /app/me
|
||||
GET /app/me/devices
|
||||
GET /app/me/export
|
||||
POST /app/me/deactivate
|
||||
POST /app/me/deactivate/cancel
|
||||
```
|
||||
|
||||
接口口径以后端实际代码为准:设备直接返回实体数组;导出返回
|
||||
`profile / credentials / consents / devices`;注销请求只发送 `reason`。
|
||||
|
||||
### 34.2 TDD 与实现
|
||||
|
||||
先用不存在的 `AccountApi/AccountProfile` 跑红灯,确认测试在实现前失败:
|
||||
|
||||
```text
|
||||
Error: Error when reading 'lib/core/data/remote/account_api.dart':
|
||||
No such file or directory
|
||||
Some tests failed.
|
||||
```
|
||||
|
||||
第一批实现后:
|
||||
|
||||
```text
|
||||
$ flutter test test/account/account_api_test.dart
|
||||
00:00 +7: All tests passed!
|
||||
```
|
||||
|
||||
登录态同步先红灯:
|
||||
|
||||
```text
|
||||
Error: The method 'applyProfile' isn't defined for the type 'AuthController'.
|
||||
```
|
||||
|
||||
实现 `applyProfile(AuthUser)` 后:
|
||||
|
||||
```text
|
||||
00:00 +1: All tests passed!
|
||||
```
|
||||
|
||||
逻辑层覆盖资料保存回调、设备读取、导出复制、注销清会话和撤销失败文案:
|
||||
|
||||
```text
|
||||
$ flutter test test/account/account_logic_test.dart
|
||||
00:00 +5: All tests passed!
|
||||
```
|
||||
|
||||
页面与入口先红灯,随后用稳定 Key 实现:
|
||||
|
||||
```text
|
||||
$ flutter test test/account/account_pages_test.dart \
|
||||
test/account/mine_account_entry_test.dart
|
||||
00:01 +6: All tests passed!
|
||||
```
|
||||
|
||||
实现文件:
|
||||
|
||||
```text
|
||||
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/*
|
||||
lib/pages/mine/mine_view.dart
|
||||
lib/core/data/services/auth_controller.dart
|
||||
lib/app.dart
|
||||
lib/l10n/app_{en,zh,id}.arb
|
||||
```
|
||||
|
||||
### 34.3 首屏布局回归
|
||||
|
||||
首次全量测试时,新增账号卡把既有偏好设置和观看历史入口挤出可视区:
|
||||
|
||||
```text
|
||||
Found 0 widgets with text "App Language"
|
||||
Found 0 widgets with text "Watch History"
|
||||
Some tests failed.
|
||||
```
|
||||
|
||||
处理:不改既有测试断言,把账号卡收敛为 48px 紧凑横向入口,
|
||||
保留四项图标、分隔线和账号标题;原有菜单项改用紧凑密度。
|
||||
三个受影响测试回归:
|
||||
|
||||
```text
|
||||
$ flutter test test/home/home_nav_ui_test.dart \
|
||||
test/watch/watch_history_provider_test.dart test/widget_test.dart
|
||||
00:06 +21: All tests passed!
|
||||
```
|
||||
|
||||
### 34.4 最终门禁
|
||||
|
||||
```text
|
||||
$ dart analyze lib test
|
||||
Analyzing lib, test...
|
||||
No issues found!
|
||||
```
|
||||
|
||||
```text
|
||||
$ flutter test
|
||||
00:26 +335: All tests passed!
|
||||
```
|
||||
|
||||
```text
|
||||
$ flutter build apk --debug
|
||||
Running Gradle task 'assembleDebug'... 10.0s
|
||||
✓ Built build/app/outputs/flutter-apk/app-debug.apk
|
||||
```
|
||||
|
||||
### 34.5 Git
|
||||
|
||||
```text
|
||||
44f6feb feat(account): 接入个人中心接口模型
|
||||
ef7f4ce feat(account): 同步资料保存后的登录态
|
||||
c68f024 feat(account): 增加账号中心页面逻辑
|
||||
da09511 feat(account): 增加账号中心页面与入口
|
||||
6fce24d refactor(account): 收敛账号页组件结构
|
||||
7151bc9 style(account): 保持账号入口首屏可用
|
||||
9b3ab9d feat(account): 合并 K19 账号中心
|
||||
7d68699..9b3ab9d develop -> develop
|
||||
```
|
||||
|
||||
所有提交 author/committer 均为 `Zhou Weidong <502333560@qq.com>`。
|
||||
|
||||
### 34.6 已知缺口
|
||||
|
||||
- 无注销状态查询:不能预先判断是否在冷静期,撤销失败直接展示后端文案。
|
||||
- 无设备下线接口:设备页只读。
|
||||
- 无头像上传接口:头像只展示。
|
||||
- 资料响应不含生日:本批生日只能本次设置,不能回填或清空。
|
||||
|
||||
### 34.7 用户真机验证
|
||||
|
||||
以下步骤必须在设备侧执行并取证,开发机不代跑:
|
||||
|
||||
1. 登录后打开「我的」。
|
||||
预期:钱包卡后、菜单卡前出现「账号」卡,四项入口完整可点击。
|
||||
2. 打开「个人资料」。
|
||||
预期:服务端字段回填;修改昵称/性别并保存后,我的页昵称同步更新。
|
||||
3. 打开「登录设备」。
|
||||
预期:设备号首尾可见、中间脱敏;平台、机型、时间、状态正确;空列表显示空态。
|
||||
4. 打开「数据导出」。
|
||||
预期:显示资料、凭据、授权记录数、设备数;复制 JSON 成功。
|
||||
5. 打开「注销账号」。
|
||||
预期:显示 15 天冷静期和立即登出提示;提交必须经过二次确认。
|
||||
6. 确认注销。
|
||||
预期:显示 `scheduledAt`,本地 token 清空并回到未登录状态。
|
||||
7. 重新登录后撤销注销。
|
||||
预期:有申请时成功;无申请时显示后端“没有待处理的注销申请”。
|
||||
|
||||
设备侧截图、日志和最终验收结论由用户执行。
|
||||
|
||||
---
|
||||
|
||||
## 2026-10-17 K10 统一空列表占位
|
||||
|
||||
### 26.1 范围、分支与计划
|
||||
|
||||
Reference in new issue
Block a user