docs(plans): J1 回执(全局 ID 字符串化 + 契约统一),标为已处理·待用户验收
This commit is contained in:
1 parent
f35db2cd3b
commit
0cab094194
2 files changed
+205
-1
No files matched your search
+89
-1
@@ -19,7 +19,7 @@
|
||||
|
||||
---
|
||||
|
||||
## [待处理] 2026-10-16 18:30 | J1 全局 ID 字符串化(Long → String)+ 契约统一
|
||||
## [已处理·待用户验收] 2026-10-16 18:30 | J1 全局 ID 字符串化(Long → String)+ 契约统一
|
||||
|
||||
**用户裁定(2026-10-16 18:10)**:雪花 id 精度问题 **「按方案 (a) 全局修改,统一契约」**。
|
||||
|
||||
@@ -201,3 +201,91 @@ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/v3/api-docs
|
||||
任务只有 S0/S1/S0-16、A1–A6、B1/B2、C1–C3 —— **没有 I1(后台管理端 商品配置 + 系统公告)这一条**,
|
||||
所以本轮没有可同步的任务号,我没有动任何既有任务的状态(避免误改 B1/C1/A* 这些别的批次)。
|
||||
下一步请给 I1 建任务并告知任务号,我补一次状态同步(`codex01` 的 token 已可用)。
|
||||
|
||||
---
|
||||
|
||||
### 回执(Codex,2026-10-16):J1 完成,停在干净交接点
|
||||
|
||||
**提交**(三个仓库各自 `develop`,`main` 未动)
|
||||
- FruitServer `f35db2c`(develop,已推):全局 Long→String + 契约 §0 + 测试
|
||||
- ReelShortWeb `3ec9ea6`(develop,已推):4 处 id 数字语义适配
|
||||
- ReelShort `94ff9f1`(**新建 develop**,已推):客户端 Long 计数兼容解析
|
||||
**留痕**:`docs/plans/PROGRESS.md`(本轮追加 J1 段,含原始输出);计划 `docs/plans/2026-10-16-J1.md`。
|
||||
|
||||
**门禁数字**
|
||||
| 门禁 | 结果 |
|
||||
| --- | --- |
|
||||
| `mvn test` | **BUILD SUCCESS** — commerce 33 / admin-api 21 / app-api 49 / worker 12 = **115 条全过**(存量 110 未跑红,新增 5) |
|
||||
| `mvn … package -DskipTests` | BUILD SUCCESS |
|
||||
| `pnpm ts:check` / eslint / `pnpm build:pro` | 0 错误 / 0 error / Build successful |
|
||||
| `dart analyze lib test` / `flutter test` | No issues found! / All tests passed!(+167) |
|
||||
|
||||
**每个仓库改了什么**
|
||||
|
||||
FruitServer(后端)
|
||||
- 新增 `fruitshorts-framework/.../web/JacksonLongToStringConfig.java`(`Long`/`long` → 字符串;
|
||||
`PageResult.total` 用 mixin 保持数字;`PlainLongSerializer` 供 mixin 使用)
|
||||
- `docs/api-phase1.md`:§0 新增「ID 字段一律以字符串下发」总口径(含示例、边界、`total` 例外),
|
||||
§2.11/§2.12 改为引用 §0
|
||||
- I1 的特例回退:`ProductRespVO` / `NoticeRespVO` 去掉 `@JsonSerialize`,
|
||||
`ProductAdminController` / `NoticeAdminController` 的 `create` 回到 `Result<Long>`
|
||||
- 测试:新增 `admin-api/.../web/LongToStringSerializationTest.java`(5 条);
|
||||
`ControllerContractSupport`(admin + app 两处)挂上模块,避免契约测试假绿;
|
||||
C 端 4 条 id 断言改成 `value("…") + isString()`
|
||||
|
||||
ReelShortWeb(4 个文件)
|
||||
- `src/utils/creatorImpersonation.ts` — 代看创作者 id 全程字符串(原来 `Number(raw)`,19 位会被四舍五入)
|
||||
- `src/views/contentManagement/EpisodeManagementView.vue` — `Number(route.query.drama)` → 字符串比较
|
||||
- `src/views/creator-center/composables/useDramaEdit.js` — `Number(route.params.id)` → 字符串比较
|
||||
- `src/views/permission/composables/useMenuManagement.js` — 顶级菜单哨兵 `0` → `'0'`(与接口的 `"0"` 对齐)
|
||||
|
||||
ReelShort(Flutter)逐文件清单(**只有这些,没夹带别的**)
|
||||
- `lib/core/data/models/json_numbers.dart`(新增)— `jsonToInt`:接受数字或数字字符串
|
||||
- `lib/core/data/models/auth_session.dart` — `expiresIn`(后端 `long`)改用 `jsonToInt`
|
||||
- `lib/core/data/models/drama.dart` — `viewCount`(后端 `Long`)两处改用 `jsonToInt`
|
||||
- `test/core/json_id_parsing_test.dart`(新增)— 8 条回归用例
|
||||
|
||||
**三个需要你确认的口径**
|
||||
|
||||
1. **`PageResult.total` 保持数字(唯一例外)** —— 它是条数不是 id,前端分页组件(el-pagination / Flutter 分页)
|
||||
都要数字。实测 `total = 2 int`。若你要求"Long 一律字符串",删掉 `JacksonLongToStringConfig` 里那一行 mixin 即可。
|
||||
2. **反向(请求方向)未做限制**:请求体 `"id":"…"`、路径变量、查询参数都接受字符串并转 `Long`(有测试)。
|
||||
`Integer`/`int`(`pageIndex`/`pageSize`/`Result.code`/`totalEpisodes`/`durationSec`…)保持数字 —— 实测已确认。
|
||||
3. **客户端适配范围比"只改 id 解析"宽了一点点,原因是物理上必须**:客户端 id 本来就是
|
||||
`(json['id'] ?? '').toString()`,不会崩;真正会崩的是被全局规则扫到的 **Long 计数**,
|
||||
所以改了 `expiresIn` 与 `viewCount` 共 3 处(`json_numbers.dart` 是新增工具)。
|
||||
其余 8 处 `as num?` 对应的 Java 字段都是 `Integer`/`int`,**按最小改动原则没动**。
|
||||
⚠️ **ReelShort 仓库原来只有 `main`**(无 develop),我按条目要求新建了 `develop` 并在上面提交。
|
||||
客户端由另一位同事推进,若他继续在 `main` 上走,需要把这笔 `94ff9f1` 带过去。
|
||||
|
||||
**用户可照做的验证步骤(每步都有预期结果)**
|
||||
|
||||
准备:`cd FruitServer && mvn -pl fruitshorts-app-api,fruitshorts-admin-api -am package -DskipTests`,起两个 jar;
|
||||
`curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/v3/api-docs` → 200。
|
||||
|
||||
1. **复现 PM 那条(最直观)**:注册一个 C 端账号
|
||||
```
|
||||
curl -s -X POST http://127.0.0.1:8081/app/auth/register -H 'Content-Type: application/json' \
|
||||
-d '{"targetType":"EMAIL","target":"你的邮箱@example.com","password":"Passw0rd!23","nickname":"手测","deviceId":"manual-1"}'
|
||||
```
|
||||
预期:`"expiresIn": "7200"`(字符串)。
|
||||
2. **用响应里的 user id 调后台**:`curl -s "http://127.0.0.1:8080/admin/app-users/page?pageSize=50" -H "Authorization: Bearer <admin token>"`,
|
||||
拿新用户的 `id`(预期是 `"2111…"` 这种**带引号的字符串**、`total` 是**不带引号的数字**),再
|
||||
`curl -s "http://127.0.0.1:8080/admin/app-users/<id>" -H "Authorization: Bearer <token>"` → 预期 `code=0`、`data.id` 与列表一致
|
||||
(**修复前这里返回 `200002 数据不存在`**)。
|
||||
3. **JS 逐位一致**:把第 2 步的响应存成 `r.json`,然后
|
||||
```
|
||||
node -e 'const d=JSON.parse(require("fs").readFileSync("r.json","utf8"));console.log(String(d.data.id))'
|
||||
```
|
||||
预期与 `psql -c "select id::text from app_user where uid='<uid>'"` **逐位相同**。
|
||||
对照:`node -e 'console.log(String(JSON.parse("2111015748376858626")))'` → `2111015748376858620` 附近(会被改写),说明精度问题真实存在。
|
||||
4. **后台界面(:3005)**:`admin/admin123` 登录 → 商品配置新建一个商品 → **点它那一行的状态/编辑**,
|
||||
预期正常(toast 成功,不再"商品不存在");菜单管理编辑一个顶级菜单,预期父级下拉显示「顶级菜单」而不是 `0`。
|
||||
5. **短剧管理 → 剧集管理带参跳转**:从短剧管理点某剧的「剧集」,URL 带 `?drama=<id>`,
|
||||
预期剧集页自动选中该剧(改成字符串比较前这里会选不中)。
|
||||
6. **客户端**:`cd ReelShort && flutter test`(预期 All tests passed);有设备时 `flutter run` 打开首页看播放量/详情
|
||||
不报解析异常(后端 `viewCount` 现在下发字符串)。
|
||||
7. **异常路径**:请求体里 id 传**数字**(老客户端行为)也应被接受:`PUT /admin/products/<id>/status?status=1` 用数字 id 路径同样 200。
|
||||
|
||||
**禅道**:J1 在禅道里同样没有对应任务(项目 2 下仍是 S0/S1/S0-16、A1–A6、B1/B2、C1–C3),未动任何既有任务状态。
|
||||
**服务现状**:8080/8081 是我刚重建起回的新 jar(自测时在跑);:3005 的 dev server 也在。若被环境回收,按上面「准备」起回来即可。
|
||||
Reference in new issue
Block a user