Files
jiapuapp/docs/后端接口缺口与首位成员阻塞清单-2026-07-24.md
T
2026-07-27 06:50:23 +08:00

536 lines
36 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端接口缺口与首位成员阻塞清单
更新日期:2026-07-24
适用范围:家谱 APP 前端(`jiapuapp`)与 APP API 合同维护
## 目的与边界
本文供后端确认接口 owner、DTO 和测试数据,不要求前端猜测字段或用本地数据绕过接口。下文的“需要”分为两种:
- **已有接口但不可闭环**:路径和当前参数已存在,需修复服务端行为或补全可消费的 DTO。
- **缺少业务 owner**:现有 APP OpenAPI 没有该页面所需的读取/写入 operation;需要后端和产品先确定资源归属,再发布合同。
除非下文明确写为“当前已声明字段”,字段名、枚举、分页形式和响应结构都由后端在 APP OpenAPI 中一次性定义;前端不会从其他模块、PC 接口或示例数据推断。
## 通用请求约束
当前已声明的受保护 APP 接口均需要当前测试账号的认证会话和 `clientid` 请求头。若请求体含 `clientId`,其值必须与该 Header 一致。本文不记录真实 token、手机号或生产数据。
后端交付一个新 operation 或 DTO 时,请同时在 APP OpenAPI 的 YAML/JSON 中补齐:路径、HTTP 方法、鉴权、所有 path/query/body 参数、成功响应、可预期的 4xx/5xx 业务码及字段必填性。仅有 HTTP 200 而业务 `code` 为失败,不能视为接口成功。
## 一、缺少业务 operation 的页面
### F10 家族视频:缺视频读取 owner
现状:`pages/family/f10-video-list.vue` 已明确关闭。当前 OpenAPI 只声明:
```text
DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}
```
没有视频列表、详情、播放地址或发布 operation。删除接口不能反推出读取和播放合同。
当前页面入口可提供的业务上下文只有:
| 参数语义 | 来源 | 状态 |
| --- | --- | --- |
| `genealogyId` | 页面路由 | 已有,必需 |
| 当前登录账号 | 认证会话 | 已有,必需 |
| `clientid` | APP 请求头 | 已有,必需 |
请后端/产品先确认视频资源是否归属某个家谱。若是,最小可用的首个 operation 应是“读取该家谱可见视频列表”,并明确:
1. 是否分页;若分页,统一选择并声明 `pageNum/pageSize``cursor/pageSize` 之一,不能让前端猜测。
2. 每条记录的稳定视频标识,以及当前页面用于渲染列表所需的明确字段和字段类型。
3. 当前账号无权、资源不存在、空列表的响应语义。
视频详情、播放、发布、编辑、评论、点赞和分享目前没有对应页面表单或页面数据模型;若产品要开放这些能力,请为每项单独给出 operation 与 DTO,不要用相册或动态接口兼容代替。
### R09 人生大事:缺独立资源与归属定义
现状:`pages/records/r09-life-events.vue` 已明确关闭;APP/PC OpenAPI 中都未发现独立“人生事件/life event”资源。
从 R02 人物详情跳转 R09 时会传入 `genealogyId``personId`,但 R09 当前没有读取或写入表单,因此不能从 UI 推断事件到底是“人物专属”还是“家谱公共”。请后端/产品先在以下两种归属中选择一种:
| 资源归属 | 最少识别参数 |
| --- | --- |
| 人物专属事件 | `genealogyId``personId` |
| 家谱公共事件 | `genealogyId` |
归属确定后,请提供对应的列表/详情/创建或编辑 operation(以产品实际要开放的页面为准),并定义事件的必填业务字段、时间字段、排序/分页、权限和错误语义。归属未确定前,前端不会把成长记录、备忘或人物简介映射成人生大事。
### N02 消息详情:缺单条详情读取 operation
现状:当前已声明:
```text
GET /genealogy/app/notifications
POST /genealogy/app/notifications/{notificationId}/read
POST /genealogy/app/notifications/read-all
```
没有单条详情读取 owner,因此 `pages/notification/n02-message-detail.vue` 不展示 fixture 正文,也不从通知字段推断业务跳转。
建议后端补一个单条详情读取 operation;具体路径可由后端确定,但其最小输入和输出语义应为:
| 位置 | 需要项 |
| --- | --- |
| path 参数 | `notificationId`;应与现有“标记已读”接口使用同一通知标识语义 |
| 请求上下文 | 当前登录账号、`clientid` |
| 响应必需内容 | 通知标题、完整纯文本正文、发布时间、已读状态,以及供服务端内部定位的稳定通知标识 |
| 错误语义 | 当前账号无权/通知不存在时应明确失败,不能返回其他账号的通知 |
业务跳转不是本次最低需求。若后端未来要返回业务目标,需另行提供受权限约束的 `bizType → 前端路由键 + 必填参数 + 失效语义` 闭合字典;前端不会由 `bizId`、标题或正文猜路由。
## 二、已有路径但缺少可安全消费合同的页面
### M03 账号与安全:已解除(真实 profile 只读概览)
2026-07-26 已用测试账号真实读取 `GET /genealogy/app/auth/profile`。响应含 `phone``userNo``status`;M03 已接入并只显示本地掩码手机号、账号编号和账号状态。页面不把明文手机号写入路由、日志或缓存。
“设备列表”“登录记录”“安全等级”仍没有独立读取 owner,也不属于当前 M03 的数据模型;页面不会展示或推断这些内容。建议后端仍在 Apifox 为 profile 发布明确 DTO;如产品要展示上述资源,应分别定义 operation、字段、权限和保留期。
### M05 换绑手机号:已有最终 PUT,但缺可验证的安全链路与读取 DTO
当前 OpenAPI 已声明最终写入接口:
```text
PUT /genealogy/app/auth/phone
```
当前已声明的请求参数如下;它们是现状记录,不是前端新增猜测:
| 位置 | 字段 | 约束 |
| --- | --- | --- |
| Header | `clientid` | 必填 |
| Body | `clientId` | 必填,必须等于 Header `clientid` |
| Body | `phone` | 必填,新手机号 |
| Body | `smsCode` | 必填;当前导出合同为 4 位数字 |
| 请求上下文 | 当前登录账号 | 必填 |
当前 OpenAPI 还声明通用发码接口:
```text
POST /genealogy/app/auth/sms/code
```
其当前 body 必填字段为 `clientId``tenantId``grantType``sceneCode``phone``validToken`;换绑场景为 `APP_PHONE_CHANGE`。当前 profile 已能只读获取并掩码显示手机号,但没有经过人工确认的换绑专用 TAC/发码/校验闭环;M05 因而继续保持关闭,且不在无人值守时发送短信或换绑。
请后端确认并在同一版本交付:
1. `APP_PHONE_CHANGE``validToken` 获取、绑定手机号主体校验、过期和一次性消费语义;如通用发码接口不适合作为换绑 owner,请提供专用 operation,而不是要求前端复用未知场景。
2. 最终 PUT 成功、验证码错误/过期/重复、手机号已占用、无权限和结果未知时的明确 HTTP 与业务码语义。
本问题单只要求合同和人工可控的测试条件,不授权前端执行短信、换绑或其他账号安全写入。
## 三、已有接口但被服务端 `code:500` 阻断的成员页面
这不是“缺接口”,而是首位成员无法创建导致没有真实 `personId`。阻断请求为:
```text
POST /genealogy/app/genealogies/{genealogyId}/lineage/persons
```
当前已验证的最小请求:
| 位置 | 参数 | 值/约束 |
| --- | --- | --- |
| Path | `genealogyId` | 可访问的测试家谱 ID |
| Header | `clientid` | 必填 |
| 请求上下文 | 当前测试账号 | 必填 |
| Body | `name` | 当前 `LineagePersonBody` 唯一 required 字段;非空成员姓名 |
| Body | `generation` | 首位成员固定为整数 `1` |
2026-07-26 又从 T04 页面填写了可安全收集的全量资料并真实提交:姓名、人物编号、示例字典值、排序、别名、字辈、生卒日期、生卒地、安葬地、简介、备注;HTTP `200`,业务仍返回 `code:500 / 发生未知异常,请联系管理员`。首位成员不应伪填 `fatherId``motherId``relationName``appUserId` 缺同类型候选映射,头像 `avatarOssId` 仍受 19 位 `ossId` 类型冲突阻断。`sex``birthLunar``deathLunar``personStatus` 虽为可选,但 Apifox 仅称项目字典值、无枚举,页面不能把猜测的代码或农历文本作为正式交互。
已复现结果:最小请求与上述全字段页面请求均为 HTTP 层成功、业务响应 `code:500`;随后读取世系树仍为空。
请后端处理:
1. 查询该请求的异常栈,以及空世系创建首位成员所需的家谱/租户初始化条件。
2. 修复后使该最小合法请求返回业务成功,并返回可读取的成员结果(至少可取得稳定 `personId`)。
3. 以同一测试家谱验证后续读取:世系树、成员目录分页、成员详情均能读到该成员。
4. 若暂不能修复,请提供当前测试账号有访问权限的测试 `genealogyId` 与真实 `personId`,供只读和允许写入的回读验证;不要提供生产数据。
解锁范围为 T03–T08、R01–R02:成员详情、首位成员/亲属创建、编辑、排行、成员目录与成员状态等。已有读取/写入路径应在取得真实 `personId` 后按页面顺序验证,不应改成 mock 或本地假成功。
## 四、后端回传模板
请每个问题按下列项目回复,便于前端不重做已接线部分:
```text
页面/问题:
资源 owner
APP operationHTTP 方法 + 路径):
鉴权和 clientid 要求:
path/query/body 参数(字段、类型、必填、枚举/范围):
成功响应 DTO(字段、类型、必填):
错误响应(HTTP 状态 + 业务 code + 可展示文案):
分页/排序/权限语义(如适用):
可使用的测试 genealogyId / personId(仅测试数据):
OpenAPI YAML/JSON 更新版本:
```
前端收到更新后的合同和测试数据后,会先做最小浏览器真实请求,并以服务端成功响应后的列表/详情回读作为验收依据;样式问题另在模拟器复核。
## 五、A01 密码登录:已解除
2026-07-25 已在桌面版 Apifox 核对并用测试账号直连验证。最新已发布合同如下:
| 位置 | 字段 |
| --- | --- |
| Header | `clientid` |
| Body | `grantType=password``tenantId``phone`、32 位 MD5 `password``validToken` 仅在验证中心策略开启时必传 |
`clientId``sceneCode` 不再属于密码登录 body:后端根据 `POST /genealogy/app/auth/login` 绑定 `APP_PASSWORD_LOGIN` 场景。前端先查询 `GET /genealogy/app/auth/verification/password-login/require`;服务端返回 `required:false` 时不伪造滑块或票据,直接提交上述 body;返回 `required:true` 时才完成验证中心 challenge/verify 并提交真实 `validToken`
实际结果:`password-login/require` 返回 `HTTP 200 / code:200 / required:false`;随后密码登录返回 `HTTP 200 / code:200`,响应含 `access_token`。本项不再是后端阻塞。
## 六、2026-07-25 Apifox 认证动作合同更新(已接入)
Apifox 当前“家谱”项目新增并发布了下列 APP 认证动作接口;本地旧 `APP.openapi.json/yaml` 尚未同步这次导出,不能再作为认证链的 source of truth
```text
GET /genealogy/app/auth/verification/{operationCode}/require
POST /genealogy/app/auth/verification/{operationCode}/challenge
POST /genealogy/app/auth/verification/{operationCode}/verify
POST /genealogy/app/auth/sms/{operationCode}/code
```
`operationCode` 的已发布枚举为:
```text
password-login | sms-login | register | forgot-password | phone-change | account-deactivate
```
合同要点:
| 操作 | Header | path/query/body |
| --- | --- | --- |
| 查询策略 | `clientid` | path `operationCode`query `tenantId``subject` |
| 获取挑战 | `clientid` | path `operationCode`body `tenantId``subject` |
| 校验挑战 | `clientid` | path 必须与挑战使用同一 `operationCode`body `tenantId``subject``challengeId` 和验证码证据 |
| 发送短信 | `clientid` | path `operationCode`body `tenantId``phone``grantType=sms`;仅服务端策略开启时提交 `validToken` |
所有新接口都明确禁止前端再提交 `clientId``sceneCode`;服务端按 APP 路由的当前激活绑定解析验证场景。
已做的最小真实验证(仅测试手机号、未发送短信):
| 请求 | 结果 |
| --- | --- |
| `GET …/verification/APP_SMS_LOGIN/require` | `HTTP 200`,业务 `code:500`:不支持的认证业务动作 |
| `GET …/verification/sms-login/require` | `HTTP 200`,业务 `code:200``required:true``TIANAI/SLIDER` |
| `GET …/verification/password-login/require` | `HTTP 200`,业务 `code:200``required:false`,服务端绑定 `sceneCode: APP_LOGIN` |
前端已将 A01/A04/A05 的验证、挑战、校验和发码链接到新路径;A01 密码登录使用 `password-login`,策略为 `required:false` 时直接调用最新密码登录 body;返回 `required:true` 时携带真实 `validToken`。短信、注册、找回仍只在服务端返回 `required:true` 后完成 TAC 并携带真实 `validToken`
已用测试账号验证 A01 密码登录的真实成功响应;本轮未发送短信、注册、改密、换绑、退出或执行其他敏感操作。
## 七、2026-07-25 桌面 Apifox 复核:仍缺 owner 与分页响应异常
以下结论直接来自桌面版 Apifox 当前 APP 目录,前端不以其他资源替代:
| 页面 | Apifox 当前 operation | 缺口 |
| --- | --- | --- |
| F10 家族视频 | 仅 `DELETE /genealogy/app/genealogies/{genealogyId}/videos/{videoId}` | 缺视频列表、详情、播放地址、发布/上传和编辑 owner |
| R09 人生大事 | “族务记录”目录仅有成长记录、备忘、亲友记录、功德记录四类 operation | 缺人生事件的列表、详情、创建、编辑、删除 owner |
| N02 消息详情 | 通知目录只有列表、单条标已读、未读数、全部标已读 | 缺单条消息详情读取 owner |
另发现一个后端响应异常,不影响当前 F01(F01 使用非分页 `GET …/feeds`,已真实返回数组),但会使已发布分页 operation 无法使用:
```text
GET /genealogy/app/genealogies/{genealogyId}/feeds/page?pageNum=1&pageSize=20
```
桌面 Apifox 将成功响应声明为 `PageResult`;同一测试账号实际得到 `HTTP 200 / code:200`,却完全省略 `data`。客户端的分页合同需要 `data.rows`(数组)和 `data.total`(整数),因此当前会精确拒绝为分页响应无效,不能把空 envelope 当成空列表。
请后端:
1. 为 F10、R09、N02 分别提供独立 APP operation 与完整 DTO;不要让前端复用相册、成长记录或通知列表字段。
2. 修复 `feeds/page` 成功响应,使 `data.rows``data.total` 与 Apifox `PageResult` 一致;若该 operation 已废弃,请在 Apifox 明确下线,避免保留可调用但无结果的合同。
## 八、2026-07-26 真实 H5 图片上传:`ossId` 跨接口类型冲突
本项使用测试家谱的 F09「添加照片」页面、浏览器文件选择器和本地真实图片
`static/assets/foundation/transparent/auth-login-outline.png` 验证;没有使用 mock、fixture 或手工伪造上传回执。
实际请求链路均返回 `HTTP 200 / code:200`
```text
POST /genealogy/app/files/resumable/init
POST /genealogy/app/files/resumable/chunk
POST /genealogy/app/files/resumable/complete
```
`complete` 的真实响应为(URL 已省略):
```json
{
"code": 200,
"data": {
"fileName": "auth-login-outline.png",
"ossId": "2081232520259612673"
}
}
```
`ossId` 是 19 位雪花标识,必须以字符串原样传递。它大于 JavaScript `Number.MAX_SAFE_INTEGER`;转换为 number 会丢失精度。当前照片创建 DTO 却把 `ossId` 声明为 `int64` 数值,F09 无法在不篡改标识的前提下提交:页面已经明确提示并停止在关联业务数据之前。
受影响的是所有“上传回执 → 业务表单”页面,而不只是 F09:动态配图、谱文封面、相册封面/照片、家谱封面、礼仪图片、备忘附件等。前端不会把字符串转为不安全 number,也不会提交截断后的 ID。
请后端在同一 APP OpenAPI 版本统一文件标识合同:
| 位置 | 需要确定的合同 |
| --- | --- |
| 上传完成响应 | `ossId` 保持十进制字符串(现网已如此返回),并明确为稳定文件标识 |
| 所有消费该标识的 APP 请求 DTO | 对应字段统一接受同一十进制字符串;不要在 JSON 中要求前端传 `int64` 数值 |
| 响应 DTO 与字段示例 | 同步明确字符串类型、正整数词法约束和真实大于 `2^53-1` 的示例 |
| Apifox 发布内容 | 更新照片创建、封面、附件等所有相关 operation,避免上传接口和业务接口各自定义一套类型 |
后端发布统一合同后,请提供仅测试数据可写入的家谱上下文。前端会重新从 F09 页面选择真实文件,完成“上传 → 创建照片 → 相册列表/详情回读”验收;在此之前不会猜测创建照片接口是否私下兼容字符串。
## 九、2026-07-26 Apifox 全量复核:贺礼邀约缺少受邀人候选来源
桌面 Apifox 当前已发布以下 4 个“贺礼邀约” operation
```text
PUT /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitees
GET /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitations
PUT /genealogy/app/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitations/me
GET /genealogy/app/genealogies/ceremony-invitations/mine
```
其中请求合同已明确,前端不会补猜字段:
| operation | 必填参数 | 可选参数 | 备注 |
| --- | --- | --- | --- |
| 替换活动受邀人 | path `genealogyId``ceremonyId`body `inviteeUserIds` | 无 | `inviteeUserIds` 是唯一业务用户 ID 的完整数组;空数组表示取消全部尚未响应的邀请 |
| 查询活动邀请名单 | path `genealogyId``ceremonyId` | 无 | 返回邀请记录列表 |
| 响应当前用户邀请 | path `genealogyId``ceremonyId`body `inviteStatus` | 无 | 枚举仅允许 `ACCEPTED``DECLINED` |
| 查询我的活动邀请 | 无业务 path/body | 无 | 当前登录业务用户的有效邀请列表 |
当前 `CeremonyInvitationVo` 可读取字段为:`invitationId``genealogyId``ceremonyId``inviteeUserId``inviteStatus``PENDING` / `ACCEPTED` / `DECLINED` / `CANCELED`)、`inviteVersion``deliveredTime``readTime``responseTime``ceremonyTitle``ceremonyTime``location``locationAddress``longitude``latitude`。这些 ID 均为 `int64`,真实雪花 ID 必须统一允许十进制字符串传递,不能要求 H5 转为不安全的 JavaScript number。
### 阻塞点
R07 需要的是 `inviteeUserIds`(业务用户 ID),但当前 APP 家谱成员列表没有声明可供选择的业务用户 ID,也没有“可受邀用户候选列表” operation。`memberId``lineagePersonId``inviteeUserId` 是不同资源标识,前端不会用任一个替代另一个,也不会提供让用户手输未知业务 ID 的伪流程。
请后端在同一版 APP OpenAPI 中二选一,并提供仅测试数据:
1. 在现有“家谱成员列表/选项”成功 DTO 中明确返回稳定的 `appUserId`(或等价字段),并声明该字段就是 `inviteeUserIds` 的合法值;或
2. 新增“查询活动可邀请用户候选列表” operation,至少返回业务用户 ID、展示名、是否可邀请、不可邀请原因。
同时请确认 `int64` 业务用户 ID 在所有 APP JSON 请求/响应中使用十进制字符串合同,避免与第八节 `ossId` 相同的精度丢失问题。候选来源和字符串 ID 合同发布前,前端只接入邀请读取/响应的精确 API 方法,不会把“替换受邀人”伪装成可用页面功能。
## 十、2026-07-26 Apifox 路径修正:行政区划
桌面 Apifox 当前正式路径为:
```text
GET /genealogy/region/children?parentCode={parentCode}
GET /genealogy/region/path/{regionCode}
GET /genealogy/region/search?keyword={keyword}&level={level?}&limit={limit?}
GET /genealogy/region/{regionCode}
```
其中 `search.keyword` 必填;`search.level``search.limit` 可选;其余 `regionCode` path 参数必填,`children.parentCode` 可选。G03 原先错误使用了 `/genealogy/app/region/children`,已改为正式路径并在 H5 浏览器验证省、市、区三级均返回业务 `code:200`。其余 3 个 operation 尚无当前页面交互入口,待桌面 Apifox 补齐可消费的响应 DTO 后按实际页面需求接入;不会以 `additionalProperties` 的导出占位结构猜字段。
## 十一、2026-07-26 F03 真实点赞后缺少当前用户状态
测试账号通过 F03 动态详情页面执行了一次真实“点赞”(没有执行取消点赞或其他删除操作):
```text
POST /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}/likes
```
该请求返回 `HTTP 200`。随后页面重新读取详情,`likeCount``0` 变为 `1`,说明服务端已写入点赞;但详情响应没有给出可用的当前用户点赞状态,前端读取到的 `likedByMe` 仍为 `false`/缺失,按钮继续显示“点赞”而不是“取消点赞”。
这不是前端可以用本地布尔值补齐的缺口:页面刷新后必须以服务端状态决定下一次应该调用 `POST /likes` 还是 `DELETE /likes`。当前合同会导致重复点击语义不明确,也无法安全展示已点赞状态。
请后端在以下 APP 读取 DTO 中统一提供当前登录用户维度的必填布尔字段 `likedByMe`(或同义且明确的字段),并与点赞写入立即一致:
```text
GET /genealogy/app/genealogies/{genealogyId}/feeds
GET /genealogy/app/genealogies/{genealogyId}/feeds/page
GET /genealogy/app/genealogies/{genealogyId}/feeds/{feedId}
```
字段必须是 `boolean`,不能以点赞总数、空值或仅他人点赞记录代替。后端发布后,前端会再从 F03 页面验证“点赞 → 详情回读为已点赞 → 仅在用户主动操作时取消点赞”的完整闭环。
前端已将缺失/非布尔值保留为“状态未知”,并在 F03 禁用点赞按钮、显示明确原因;不会再把它转换为 `false` 后重复发送点赞请求。
## 十二、2026-07-26 谱文分类列表缺少可消费的条目 DTO
桌面 Apifox 的正式 operation 为:
```text
GET /genealogy/app/genealogies/{genealogyId}/article-categories
```
请求仅要求 path `genealogyId`(以及认证 `clientid`),成功响应在当前桌面文档中标注为通用 `ListResult`,没有声明列表项字段模型、字段示例或 `categoryId` 的类型。F06 的创建谱文请求可选 `categoryId`,但前端不能在不知道“分类标识”和“分类展示名”字段的情况下把任意对象渲染成选择器。
请后端把该 operation 的 `data[]` 明确为具名 DTO,至少包含:
| 字段 | 合同要求 |
| --- | --- |
| `categoryId` | 稳定分类标识;若为 int64,APP JSON 统一使用十进制字符串 |
| `categoryName` | 非空展示名称 |
| `status` / `enabled` | 明确是否允许在新建谱文中选择;若不需要则明确只返回可选项 |
| `sortOrder` | 可选的稳定排序字段;若服务端已排序则在文档明确 |
在条目 DTO 发布前,F06 继续允许按现有创建合同不带 `categoryId` 发布,不会把导出文件里的通用对象或本地硬编码分类当作真实分类数据。
## 十三、当前全部已确认阻塞总表
本表是当前 APP 136 operation 审计的唯一汇总入口;详情、请求字段和回传模板见本文件对应章节,以及 `APP-136请求参数字段核对表-2026-07-26.md`。这里的“阻塞”不等于前端缺少调用代码:可能是 operation 根本不存在、响应 DTO 无法消费、服务端真实失败,或 H5 不存在安全参数来源。
| 编号 | 类别 | operation / 合同 | 影响页面 | 已验证事实 | 后端解除条件 |
| --- | --- | --- | --- | --- | --- |
| B01 | 缺 operation | 视频仅有 `DELETE /videos/{videoId}` | F10 | 无列表、详情、播放地址、创建、上传、编辑等 owner | 发布视频读取与发布完整 operation/DTO |
| B02 | 缺 operation | 人生大事无资源 owner | R09 | 族务目录只有成长、备忘、亲友、功德 | 明确人物专属或家谱公共归属后发布列表/详情/写入 DTO |
| B03 | 缺 operation | 通知仅有列表和标已读 | N02 | 无 `notificationId` 单条详情读取 | 发布单条详情读取及授权/错误语义 |
| B05 | 安全链路缺失 | `PUT /auth/phone` | M05 | 只有最终 PUT,缺经确认的当前账号读取、TAC/发码闭环 | 发布专用换绑验证合同与读 DTO;敏感写入仍需人工测试许可 |
| B06 | 服务端异常 | `POST /genealogies/{genealogyId}/lineage/persons` | T03T08、R01R02 | 2026-07-26 从 T04 页面分别以最小首位成员数据、以及包含编号/示例字典值/排序/生卒信息/简介备注的全字段资料真实提交,均为 HTTP `200` 但业务 `code:500 / 发生未知异常`,未生成本地或伪造 `personId`;同谱只读 `GET .../lineage/persons/options` 实测 `200 / data: []`,因此也没有可读取的真实人物候选 | 修复最小合法 body,返回并可读取真实 `personId` |
| B08 | ID 类型冲突 | 上传 complete 与所有消费 `ossId` 的 DTO | F02/F06/F07/F09/G03/G11/R04/R07/R08/R10/T04/M02 | 真实 complete 返回 19 位字符串,消费者声明 `int64` number | APP JSON 统一十进制字符串 `ossId`;同版更新示例与所有消费者 |
| B09 | 候选 ID 缺失 | `PUT .../ceremonies/{ceremonyId}/invitees` | R06/R07、我的邀请入口 | body 需要 `inviteeUserIds`,现有 member/person DTO 无同类型候选 | 公开 `appUserId` 对应关系或新增可邀请用户候选 operation |
| B10 | 当前用户状态缺失 | 动态列表/分页/详情 `likedByMe` | F03 | 实际点赞后数量变更,详情未给当前用户布尔状态 | 三个读取 DTO 均返回同步的 required boolean `likedByMe` |
| B11 | 条目 DTO 缺失 | `GET .../article-categories` | F06 | 只有通用 `ListResult`,无分类 ID/名称/状态/排序字段 | 发布 `categoryId``categoryName`、可选状态与排序 DTO |
| B12 | 页面交互待确认 | 行政区划 path/search/detail | G03/G11 后续回填、搜索 | 2026-07-26 复测已返回 `value``label``regionCode`、层级等真实条目;但当前产品页面没有搜索/路径回填入口 | 产品确认地区搜索与路径回填交互后接入页面;接口 DTO 不再阻塞 |
| B13 | 资源语义不能混用 | `members``lineage/persons` | 成员管理、R06/R07 | `memberId``personId``appUserId` 是不同资源,当前无独立成员管理页 | 提供成员管理页需求与稳定候选/映射 DTO,不得前端猜代 |
| B14 | 业务绑定 owner 缺失 | `POST /files/reference` | 所有附件业务 | 需要 `bizTable``bizId``bizField`,页面没有可信业务表/字段来源 | 后端为各业务资源声明文件绑定 owner,或明确由创建 DTO 原子绑定 |
| B15 | 枚举/候选缺失 | 多个 body 中的 `sex``birthLunar``deathLunar``personStatus``roleType``status``payType` 等 | T04/T05 及 T/M/G/R/F 写入扩展 | 2026-07-26 复核 `LineagePersonBody``birthLunar``deathLunar` 的含义是“日期是否农历”的项目字典值,不是农历日期文本;性别和人物状态也都是字典值。导出与桌面 Apifox 只给出示例 `0`,没有 value-label 枚举或字典 options operation,因此不能把输入框、农历日期文本或猜测的 `0/1` 映射留给用户 | 在 operation 详情给出完整 value-label enum,或发布字典 options operation;前端收到确定合同后统一改为选择器,并同步详情页的字典值展示 |
| B16 | 测试边界,不是接口缺失 | 短信、改密、换绑、注销、退出、删除、审核、支付 | A/M/G/F/R/N 全域 | 当前任务禁止执行这些敏感动作 | 仅在用户另行授权、测试账号与可回收数据齐备后执行真实写入 |
| B17 | 导出与实际校验冲突 | `POST /genealogy/app/files/resumable/init`(并影响 complete | F02/F06/F07/F09/G03/G11/R04/R07/R08/R10/T04/M02 | 2026-07-26 真实 H5 上传:省略 `uploadId` 返回“上传ID不能为空”;以导出字段 `fileSize` 替代 `totalSize` 返回“文件大小不能为空”。实际可用请求为 `uploadId + totalSize`;秒传 `instant:true` 会合法返回 `uploadId:null` 与真实 `ossId` | 在桌面 Apifox 与可导出 OpenAPI 中统一请求/响应 DTO、required、示例及秒传分支;明确普通分片与秒传的 `uploadId` 可空规则 |
## 十四、真实浏览器请求与返回记录(供后端排查)
说明:以下均在测试账号、测试家谱中从 APP 页面发起;未记录账号密码、令牌或完整 `clientid`。所有请求均已携带运行时 `clientid`、测试账号登录态和 `genealogyId=2081191846772518914`
### 1. B06:首位成员创建
接口:
```text
POST /genealogy/app/genealogies/2081191846772518914/lineage/persons
```
最小请求(2026-07-26,页面 T04):
```json
{
"name": "首位成员最小请求验证",
"generation": 1
}
```
实际返回:
```text
HTTP 200
{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
```
页面结果:`保存失败 / 首位成员尚未保存 / 发生未知异常,请联系管理员`
后端称已修复后的复测(2026-07-26,重新登录测试账号后从 T04 提交):
```json
{
"name": "后端修复验证首位成员",
"generation": 1
}
```
返回仍为:
```text
HTTP 200
{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
```
因此 B06 仍未解除;本次不是会话过期导致的结论。首次请求得到 `code:401` 后已通过 A01 真实密码登录,重试才得到上述业务 `code:500`
全字段诊断请求(同一页面、同一测试家谱;用于验证可选字段是否会改变异常,不是字段字典的最终验收):
```json
{
"name": "LineageFullBody0726",
"generation": 1,
"personNo": "P20260726001",
"sex": "0",
"generationName": "FullGen",
"aliasName": "FullBodyAlias",
"birthLunar": "1900-01-01",
"birthPlace": "TestBirthPlace",
"deathLunar": "2000-01-01",
"deathPlace": "TestDeathPlace",
"burialPlace": "TestBurialPlace",
"biography": "Full body browser submission verification",
"remark": "test only",
"personStatus": "0",
"birthDate": "2026-07-26",
"deathDate": "2026-07-26",
"sortOrder": 1
}
```
实际返回同样为:
```text
HTTP 200
{"code":500,"msg":"发生未知异常,请联系管理员","data":null}
```
特别说明:该诊断请求暴露出旧页面把 `birthLunar``deathLunar` 当作农历日期文本;Apifox 的真实语义是“是否农历”的字典值。不能把这一请求视为正确字典值示例,也不能要求前端据此猜选项。首位成员不应伪填 `fatherId``motherId``relationName``appUserId` 没有同类型候选,`avatarOssId` 被 B08 阻断。
随后读取:
```text
GET /genealogy/app/genealogies/2081191846772518914/lineage/persons/options
HTTP 200 / code:200 / data: []
```
因此 T01 没有成员数据并非前端空白占位:服务端尚未成功写入任何真实成员。
### 2. 初次验证记录(历史结果;以 2.1 的复测结论为准)
| 编号 | 接口与页面 | 实际请求值/返回值 | 结论 |
| --- | --- | --- | --- |
| B07 | `GET /genealogy/app/genealogies/{genealogyId}/feeds/page`,F01/F03 | 已按页面分页参数真实读取;HTTP `200`、业务 `code:200`,但响应没有 Apifox `PageResult` 所需的 `data.rows``data.total` | 无法安全分页或把空对象伪装为无动态 |
| B08 | `POST /genealogy/app/files/resumable/init`F09 等上传页面 | 省略 `uploadId`:返回“上传ID不能为空”;将 `totalSize` 改为导出字段 `fileSize`:返回“文件大小不能为空”;实际可用字段为 `uploadId``fileName``fileMd5``totalSize``totalChunks``chunkSize`。秒传返回 `{"uploadId":null,"instant":true,"ossId":"2081232520259612673"}` | 文件服务返回 19 位字符串 ID,而业务 DTO 写 `int64` 数字,前端不能无损作为 JSON 数字提交 |
| B10 | 动态点赞,F03 | 已真实点赞,点赞数量变化;详情/列表未返回 `likedByMe` | 不能据数量推断当前用户是否已点赞,页面已禁用不确定状态下的再次写入 |
| B11 | `GET /genealogy/app/genealogies/{genealogyId}/article-categories`F06 | HTTP `200`、业务 `code:200``data: []` | 无分类候选可供选择;同时合同没有分类条目字段定义 |
| B12 | 行政区划 childrenG03/G11 | `GET /genealogy/region/children` 已可真实读取;path/search/detail 没有可消费的条目 DTO 和页面交互归属 | 不猜地区回填字段或新增搜索行为 |
| B17 | 分片上传初始化,F09 等 | 见 B08 的实际请求和返回;导出与服务端校验字段冲突 | Apifox 与导出必须先统一为唯一合同 |
### 2.1 后端称修复后的复测结果(2026-07-26)
| 编号 | 复测结果 | 当前结论 |
| --- | --- | --- |
| B06 | 重新登录后,T04 最小 body 仍返回 HTTP `200`、业务 `code:500``data:null` | 未修复 |
| B07 | `GET .../feeds/page?pageNum=1&pageSize=20` 现在返回根级 `total:1``rows:[...]`,不再是空 envelope | 分页数据已出现;但 `likedByMe` 返回字符串 `"1"`B10 仍未修复 |
| B08 | F09 从真实图片文件上传到“已上传”成功;保存照片时前端收到真实 19 位文件 ID 后仍报“超出 APP 安全整数范围”,未发出照片创建请求 | 未修复,需统一字符串 `ossId` 合同 |
| B09 | 礼仪列表可读取,`GET .../ceremonies/{ceremonyId}/invitations``GET .../ceremony-invitations/mine` 均返回 `data:[]`;没有可提交的 `inviteeUserIds` 候选 | 未修复,仍缺 `appUserId` 候选/映射 |
| B11 | 谱文分类仍返回 `HTTP 200 / code:200 / data:[]` | 测试谱没有分类;仍需分类 DTO 与可用测试候选才能验证选择/写入 |
| B12 | `GET /genealogy/region/path/110101``GET /genealogy/region/110101``GET /genealogy/region/search?keyword=北京&limit=10` 均返回包含 `value``label``regionCode`、层级等字段的真实数据 | 后端已补齐可消费条目;待产品确认搜索/回填交互后接入页面 |
### 3. 未发起写入请求的原因(不是漏测)
| 编号 | 接口/功能 | 未发起的原因 | 后端需要提供 |
| --- | --- | --- | --- |
| B01 | 视频 F10 | 仅发布删除接口;没有列表、详情、播放、创建、编辑或上传 owner | 完整资源 operation 与 DTO |
| B02 | 人生大事 R09 | 没有资源 operation | 明确人物或家谱归属后的列表、详情、写入 DTO |
| B03 | 通知详情 N02 | 只有列表、标已读;没有按 `notificationId` 读取详情 | 单条详情接口及授权语义 |
| B05/B16 | 短信、改密、换绑、退出、注销、删除、审核、支付 | 属于本轮明确禁止的敏感动作 | 另行授权、测试账号和可回收数据后再测 |
| B09/B13 | 礼仪受邀人、成员绑定 | 请求需要 `appUserId`,现有 `memberId``personId``appUserId` 不能互相替代;没有候选映射 | 同类型候选接口或稳定映射 DTO |
| B14 | 文件业务引用 | 请求需要 `bizTable``bizId``bizField`,没有页面可信 owner | 各资源的文件绑定归属合同 |
| B15 | 性别、人物状态、出生/逝世是否农历等 | 需要选择器,但 Apifox 仅给示例 `0`,没有枚举、中文标签或字典 options 接口 | value-label 枚举或字典 options operation |
### 不应误标为阻塞的已完成项
- A01 密码登录、G03 创建家谱、家族动态/评论、谱文、相册、亲友往来、礼仪、成长记录、备忘、功德均已做过真实创建后的列表或详情回读。
- M03 账号与安全已真实读取当前 profile,并仅展示掩码手机号、账号编号和账号状态;设备与登录记录不在当前页面范围内。
- 4 条行政区划 operation 都已有 API owner`children` 已在 G03/G11 页面真实读取,其余三条的阻塞是没有可安全消费 DTO/产品交互,不是路径不存在。
- 136 条 `method + path` 均可在桌面 Apifox 当前目录找到;数量差异不是“导出漏了 path”,而是页面数、功能入口、DTO 和安全参数来源不同。