diff --git a/components/TacVerification.vue b/components/TacVerification.vue index 2bf23b3..0fd2ff2 100644 --- a/components/TacVerification.vue +++ b/components/TacVerification.vue @@ -135,7 +135,7 @@ export default { return { generation: 0, tac: null, - context: null, + requestContext: null, challenge: null, activeXhr: null, fatalSent: false, @@ -148,7 +148,7 @@ export default { this.generation += 1; const generation = this.generation; this.destroyTac(); - this.context = nextContext || null; + this.requestContext = nextContext || null; this.challenge = null; this.fatalSent = false; this.completionSent = false; @@ -160,10 +160,10 @@ export default { loadScript(TAC_SCRIPT_URL, () => Boolean(window.TAC && window.CaptchaConfig)), ]); await loadScript(TAC_ADAPTER_URL, () => Boolean(window.JiapuTacAdapter)); - if (generation !== this.generation || !this.context || this.context.visible !== true) return; + if (generation !== this.generation || !this.requestContext || this.requestContext.visible !== true) return; this.createTac(); } catch (error) { - if (generation !== this.generation || !this.context || this.context.visible !== true) return; + if (generation !== this.generation || !this.requestContext || this.requestContext.visible !== true) return; this.notifyFatal(error); } }, @@ -173,17 +173,17 @@ export default { } this.completionSent = false; const generation = this.generation; - const requestContext = this.context; + const requestContext = this.requestContext; const isCurrent = () => generation === this.generation && - this.context === requestContext && + this.requestContext === requestContext && requestContext.visible === true; const config = new window.CaptchaConfig({ bindEl: "#jiapu-tac-host", - requestCaptchaDataUrl: this.context.challengeUrl, - validCaptchaUrl: this.context.verifyUrl, + requestCaptchaDataUrl: this.requestContext.challengeUrl, + validCaptchaUrl: this.requestContext.verifyUrl, requestHeaders: { - clientid: this.context.clientId, + clientid: this.requestContext.clientId, }, validSuccess: (response, captcha, tac) => { if (!isCurrent() || this.completionSent) return; @@ -238,17 +238,17 @@ export default { beforeRequest(type, request) { if (type === "requestCaptchaData") { request.data = { - tenantId: this.context.tenantId, - clientId: this.context.clientId, - sceneCode: this.context.sceneCode, - subject: this.context.subject, + tenantId: this.requestContext.tenantId, + clientId: this.requestContext.clientId, + sceneCode: this.requestContext.sceneCode, + subject: this.requestContext.subject, }; return true; } if (type === "validCaptcha") { request.data = window.JiapuTacAdapter.buildVerifyBody( request.data, - this.context, + this.requestContext, this.challenge, ); } @@ -257,7 +257,7 @@ export default { afterRequest(type, response) { try { if (type === "requestCaptchaData") { - const mapped = window.JiapuTacAdapter.normalizeChallengeResponse(response, this.context); + const mapped = window.JiapuTacAdapter.normalizeChallengeResponse(response, this.requestContext); this.challenge = mapped.challenge; this.replaceResponse(response, mapped.sdkResponse); } else if (type === "validCaptcha") { @@ -326,7 +326,7 @@ export default { if (this.fatalSent) return; this.fatalSent = true; this.$ownerInstance.callMethod("handleTacError", { - requestId: this.context && this.context.requestId, + requestId: this.requestContext && this.requestContext.requestId, message: (error && error.message) || "安全验证暂不可用", }); }, diff --git a/docs/Apifox逐页业务接口与页面展示核对台账.md b/docs/Apifox逐页业务接口与页面展示核对台账.md index 6b53750..6250712 100644 --- a/docs/Apifox逐页业务接口与页面展示核对台账.md +++ b/docs/Apifox逐页业务接口与页面展示核对台账.md @@ -19,7 +19,7 @@ | 核对项 | Apifox 桌面端实读 | 当前页面实情 | 结论 | | --- | --- | --- | --- | | 发布动作 | `POST /genealogy/app/genealogies/{genealogyId}/feeds`;鉴权 `Authorization`;路径 `genealogyId:int64`、Header `clientid:string` 均必填 | `appApi.createFeed` 使用严格请求和离页取消;页面不再生成本地预览 | 已接线,等待真实写入响应核验 | -| 请求体 | `application/json`:`feedContent:string` 必填且不能为空;`feedType:string` 可选,未传默认 `text`;`mediaOssIds:string` 可选,多个 OSS ID 用英文逗号分隔;`sortOrder:int64` 可选,未传默认 `0`;`status:string` 可选,未传默认正常状态 `0` | 表单只采集并发送 `feedContent`;可选的媒体、排序、状态没有可用输入/owner,故不发送 | 页面只消费可明确映射的文本动态请求子集 | +| 请求体 | `application/json`:`feedContent:string` 必填且不能为空;`feedType:string` 可选,未传默认 `text`;`mediaOssIds:string` 可选,多个 OSS ID 用英文逗号分隔;`sortOrder:int64` 可选,未传默认 `0`;`status:string` 可选,未传默认正常状态 `0` | 表单收集并提交内容、动态类型、通过上传回执取得的媒体和排序值;`status` 使用服务端已声明的默认值,不暴露“0”之类状态码输入 | 已接线;真实写入仍待人工响应核验 | | 响应字段 | `200 ObjectResult` 只声明通用 `code`、`msg`、`data:object`,未声明新动态 DTO | 仅在严格成功信封后显示“已提交服务端”;不会在 F01 生成本地列表项 | **未完成 / DECLARED_UNVERIFIED**:接线不等于已验证;真实写入保留人工可观察窗口 | ### F03 动态详情与评论 @@ -38,16 +38,16 @@ | --- | --- | --- | --- | | F04 列表 | `GET /genealogy/app/genealogies/{genealogyId}/articles`;鉴权、`genealogyId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用 `code/msg/data[]`,条目未声明 DTO | 已删除 fixture、分类和本地搜索;页面明确提示缺失文章 ID、分类、标题、摘要、作者和更新时间投影 | **未完成 / DECLARED_UNVERIFIED**:没有可审计的条目字段映射,不能接线或把本地筛选误称服务端能力 | | F05 详情 | `GET /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`;鉴权、`genealogyId:int64`、`articleId:int64`、`clientid:string` 必填;`200 ObjectResult` 仅通用对象 DTO | 已删除 fixture 正文与编辑跳转;只显示正文 DTO 缺口 | **未完成 / DECLARED_UNVERIFIED**:正文、作者、时间投影均未由详情响应声明 | -| F06 新建 | `POST /genealogy/app/genealogies/{genealogyId}/articles`;鉴权、`genealogyId:int64`、`clientid:string` 必填 | `appApi.createArticle` 严格提交 `articleTitle/articleContent`;成功仅表示服务端成功信封,不生成本地文章 | 已接线,等待真实写入响应核验 | +| F06 新建 | `POST /genealogy/app/genealogies/{genealogyId}/articles`;鉴权、`genealogyId:int64`、`clientid:string` 必填 | `appApi.createArticle` 严格提交标题、摘要、封面上传回执、正文、作者和排序;成功仅表示服务端成功信封,不生成本地文章 | 已接线,等待真实写入响应核验 | | F06 修改 | `PUT /genealogy/app/genealogies/{genealogyId}/articles/{articleId}`;鉴权、两个路径 ID、`clientid:string` 必填 | 已移除 fixture 编辑预填;没有可靠详情 DTO 和文章 ID 列表来源时,编辑入口关闭 | **未完成 / DECLARED_UNVERIFIED** | -| 新建/修改请求体 | `categoryId:int64` 可选;`articleTitle:string` 必填;`articleSummary:string` 可选;`coverOssId:int64` 可选;`articleContent:string` 必填;`authorName:string`、`sortOrder:int64`、`status:string` 均可选。返回均为通用 `ObjectResult` | 新建页只收集并发送 `articleTitle/articleContent`;`categoryId`、摘要、封面、作者、排序、状态没有来源,故不发送 | 已实现请求字段的安全子集;编辑仍需可靠 articleId/详情 owner,所有写入待人工真实响应核验 | +| 新建/修改请求体 | `categoryId:int64` 可选;`articleTitle:string` 必填;`articleSummary:string` 可选;`coverOssId:int64` 可选;`articleContent:string` 必填;`authorName:string`、`sortOrder:int64`、`status:string` 均可选。返回均为通用 `ObjectResult` | 新建页收集可读字段;封面只接收真实上传回执。`categoryId` 需要分类列表条目 DTO,`status` 需要状态字典,二者均不让用户填写内部 ID/码 | 可写字段已接线;分类与状态选择仍 **DECLARED_UNVERIFIED**,编辑仍需可靠 articleId/详情 owner | ### F07—F09 相册、照片墙与上传 | 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 | | --- | --- | --- | --- | | F07 相册列表 | `GET /genealogy/app/genealogies/{genealogyId}/albums`;鉴权、`genealogyId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用数组 DTO | 已删除 fixture 相册卡片和本地预览,页面明确提示缺失相册 ID、封面、名称、照片数、描述和更新时间字段 | **未完成 / DECLARED_UNVERIFIED**:相册条目、封面 URL、照片数和更新时间没有响应字段来源 | -| F07 新建相册 | `POST /genealogy/app/genealogies/{genealogyId}/albums`;请求体 `albumName:string` 必填,`albumDesc:string`、`coverOssId:int64`、`sortOrder:int64`、`status:string` 可选;返回通用 `ObjectResult` | `appApi.createAlbum` 严格提交 `albumName`;成功仅表示服务端成功信封,不生成本地相册卡片 | 已接线,等待真实写入响应核验;描述、封面、排序、状态无输入来源,故不发送 | +| F07 新建相册 | `POST /genealogy/app/genealogies/{genealogyId}/albums`;请求体 `albumName:string` 必填,`albumDesc:string`、`coverOssId:int64`、`sortOrder:int64`、`status:string` 可选;返回通用 `ObjectResult` | 表单提交名称、说明、真实封面上传回执和排序;`status` 缺可读字典,不向用户暴露码值 | 已接线,等待真实写入响应核验 | | F08 照片墙读取 | `GET /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos`;鉴权、`genealogyId:int64`、`albumId:int64`、`clientid:string` 必填;`200 ListResult` 仅通用数组 DTO | 已删除 fixture 相册和照片墙,只显示缺失照片展示字段的状态 | **未完成 / DECLARED_UNVERIFIED**:缺相册与照片展示 DTO,不能猜 OSS URL、标题或说明字段 | | F09 写入照片记录 | `POST /genealogy/app/genealogies/{genealogyId}/albums/{albumId}/photos`;路径两个 ID、鉴权、`clientid` 必填;`ossId:int64` 必填,`photoTitle/photoDesc/photographer/shootTime/sortOrder/status` 可选 | 已删除 mock 图片库、说明表单和本地预览 | **未完成 / BLOCKED_BY_MEDIA_OWNER**:接口接受的是既有 `ossId`,当前页面没有已核实的文件上传 owner 和真实 OSS 回执,不能把本地图片冒充上传成功 | @@ -65,7 +65,7 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面状态与结论 | | --- | --- | --- | | G01 我的家谱 | `GET /genealogy/app/genealogies/mine`;鉴权、`clientid:string` 必填;`200 ListResult` 仅通用 `code/msg/data[]` | 页面要展示当前家谱、可切换家谱、角色与快捷入口;当前 DTO 没有这些字段。**未完成 / DECLARED_UNVERIFIED** | -| G03 创建家谱 | `POST /genealogy/app/genealogies`;`genealogyName`、`surname`、`regionCode` 必填;`ancestralHall/originPlace/addressDetail/coverOssId/intro/visibility/joinMode` 可选。`visibility`:`0` 私密、`1` 公开、`2` 成员可见;`joinMode`:`0` 关闭、`1` 审核、`2` 邀请码 | 已删除本地家谱/首位人物预览。创建后必须从真实响应取得 `genealogyId` 再创建首位人物;当前没有可恢复查询 owner,不能从泛型 mine 列表按名称猜 ID | **未完成 / MISSING_OPERATION**:两阶段创建结果恢复链未闭合,且封面 `coverOssId` 仍缺上传 owner | +| G03 创建家谱 | `POST /genealogy/app/genealogies`;`genealogyName`、`surname`、`regionCode` 必填;`ancestralHall/originPlace/addressDetail/coverOssId/intro/visibility/joinMode` 可选。`visibility`:`0` 私密、`1` 公开、`2` 成员可见;`joinMode`:`0` 关闭、`1` 审核、`2` 邀请码 | 表单提供全部可读资料字段;地区为三级级联选择器,封面只由真实上传回执产生,访问规则由可读选项映射为 `visibility/joinMode`。已删除本地家谱/首位人物预览。创建后必须从真实响应取得 `genealogyId` 再创建首位人物;当前没有可恢复查询 owner,不能从泛型 mine 列表按名称猜 ID | **未完成 / MISSING_OPERATION**:两阶段创建结果恢复链未闭合;写入与上传已接线,仍待人工真实响应核验 | | G05 家谱概览 | `GET /genealogy/app/genealogies/{genealogyId}/overview`;鉴权、`genealogyId:int64`、`clientid` 必填;`200 ObjectResult` 通用对象 | 页面需要家谱资料、成员/人物等概览显示;响应无 DTO。**未完成 / DECLARED_UNVERIFIED** | | G06 搜索公开家谱 | `GET /genealogy/app/genealogies/public` 已在 Apifox 目录确认;读取结果仍为通用 `ListResult` | 已删除本地搜索结果和申请跳转;名称、籍贯、简介、可加入状态、稳定 genealogyId 均未获声明。**未完成 / DECLARED_UNVERIFIED** | | G08 申请加入 | `POST /genealogy/app/genealogies/{genealogyId}/join-applies`;路径 `genealogyId:int64`、鉴权、`clientid` 必填;body `applicantName/phone/relationDesc/applyReason:string`、`inviterUserId:int64` 均可选 | 已删除本地填写预览;没有公开家谱详情、可申请权限或稳定 ID 投影时,不凭“可选”字段虚构申请上下文。**未完成 / DECLARED_UNVERIFIED**,不发送申请 | @@ -105,7 +105,7 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面实情与结论 | | --- | --- | --- | -| T04 首位成员/新增人物 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons`;鉴权、路径 `genealogyId`、`clientid` 必填;body 只有 `name:string` 必填。可选字段为 `appUserId/personNo/aliasName/sex/generation/generationName/fatherId/motherId/avatarOssId/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/personStatus/biography/sortOrder/remark/relationName`;其中 `personNo` 由服务端生成,`avatarOssId` 须来自文件上传组件 | 页面只提交 `name/birthDate/biography`。请求字段是合法子集,但没有性别、世代、父母、头像、状态、排行等来源;真实写入未验证。**未完成 / DECLARED_UNVERIFIED** | +| T04 首位成员/新增人物 | `POST /genealogy/app/genealogies/{genealogyId}/lineage/persons`;鉴权、路径 `genealogyId`、`clientid` 必填;body 只有 `name:string` 必填。可选字段为 `appUserId/personNo/aliasName/sex/generation/generationName/fatherId/motherId/avatarOssId/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/personStatus/biography/sortOrder/remark/relationName`;其中 `personNo` 由服务端生成,`avatarOssId` 须来自文件上传组件 | 表单已提供并提交当前可安全映射的 `aliasName/generationName/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/biography/remark`;非首位成员同时提交关系选择产生的 `relationName`。性别、人物状态缺字典 owner;关联账号、父母、头像与排行需要独立对象选择、上传或原子排序 owner,不能让用户填写内部 ID 或猜码。真实写入未验证。**未完成 / DECLARED_UNVERIFIED** | | T04 添加父母、子女、兄弟姐妹、配偶 | 分别为 `POST .../lineage/persons/{personId}/parents`、`.../children`、`.../siblings`、`.../spouses`;路径 `genealogyId/personId`、鉴权、`clientid` 均必填,均返回 `LineagePersonResult`,body 与新增人物同合同。实读 `sex:string` 仅写“建议使用系统字典值”,示例为 `"0"`;以“字典/dict/性别”检索 APP/PC 目录均未找到该字典读取 owner 或男/女码值映射。 | 页面现会提交所选亲属的 `relationName`,不再把路由意图丢掉;父亲/母亲共用 `/parents`,儿子/女儿共用 `/children` 仍不能仅凭该显示名获得可靠性别语义。头像仍缺文件上传回执。**未完成 / DECLARED_UNVERIFIED**,不得拿参考项目的旧 `0/1` 码值猜填,也不能执行无人值守写入。 | | T05 修改人物 | `PUT /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`;两个路径 ID、鉴权、`clientid` 必填,body 与新增人物同合同,返回 `LineagePersonResult` | 已读写 `name/aliasName/generationName/birthDate/birthLunar/birthPlace/deathDate/deathLunar/deathPlace/burialPlace/biography/remark`;静态校验确认表单字段与请求白名单一致。头像仍缺上传回执;性别、人物状态、排行因字典或原子 owner 缺失未写入。 | **未完成 / DECLARED_UNVERIFIED**:已扩展为已声明的安全字段子集,但没有真实保存后的响应/回读,不能称完整人物编辑。 | | T06 调整排行 | Apifox 只有单人物 `PUT .../persons/{personId}` 中的可选 `sortOrder:int64`,没有同辈排行列表、批量重排、原子提交或冲突回显 operation | 页面已明确显示“服务暂未开放”,不逐人写入 | **未完成 / MISSING_OPERATION**:不能以单人 `sortOrder` 伪造同辈原子排行调整 | @@ -115,7 +115,7 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面实情与结论 | | --- | --- | --- | | T07 成员目录分页与搜索 | `GET /genealogy/app/genealogies/{genealogyId}/lineage/persons/page`;query 可选 `pageNum`(默认 1)、`pageSize`(默认 10)、`keyword`(姓名/别名/人物编号)、`generation:int64`、`personStatus:string`;响应 `LineagePersonPageResult` 为 `rows: LineagePersonView[]` 与 `total`。另有 `GET .../lineage/persons/options?keyword=` 供人物选项读取 | 已移除 `listTreeMemberPresentationFixtures`;页面使用实际 `pageNum/pageSize/keyword` 请求、消费 `rows/total`,支持服务端搜索与继续加载;本地预览明确报真实读取不可用,不伪造目录数据。 | **未完成 / DECLARED_UNVERIFIED**:读取合同已接线并经静态检查,尚未用登录态获得一次真实 `rows/total` 响应;世代/人物状态筛选尚未增加页面控件。 | -| T08 成员状态说明 | 人物详情、列表和分页都提供 `personStatus`、`status`;停用人物为 `DELETE /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`,接口说明为逻辑停用且在正常子女时拒绝停用,返回 `VoidResult` | 已移除 `findTreeMemberPresentationFixture` 和 `privacy/deceased/forbidden` 推断;页面读取人物详情并原样展示 `personStatus`,明确说明当前没有状态字典 owner,也不提供停用写入。 | **未完成 / DECLARED_UNVERIFIED**:读取已接线并经静态检查,仍未用真实只读响应核验;没有字典映射时不得生成隐私/受限/纪念文案。 | +| T08 成员状态说明 | 人物详情、列表和分页都提供 `personStatus`、`status`;停用人物为 `DELETE /genealogy/app/genealogies/{genealogyId}/lineage/persons/{personId}`,接口说明为逻辑停用且在正常子女时拒绝停用,返回 `VoidResult` | 已移除 `findTreeMemberPresentationFixture` 和 `privacy/deceased/forbidden` 推断;页面读取人物详情,但在无状态字典时不展示原始 `personStatus` 值,也不提供停用写入。 | **未完成 / DECLARED_UNVERIFIED**:读取已接线并经静态检查,仍未用真实只读响应核验;没有字典映射时不得展示内部码或生成隐私/受限/纪念文案。 | ## R 记录模块 @@ -132,7 +132,7 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 | | --- | --- | --- | --- | | R03 列表、R04 详情 | `GET /genealogy/app/genealogies/{genealogyId}/relative-records`、`GET .../relative-records/{relativeId}`;均需鉴权、`genealogyId`、`clientid`,分别返回通用 `ListResult`、`ObjectResult`,未声明条目 DTO | 已删除 R03/R04 fixture 列表、详情和本地编辑预填;页面明确说明缺记录 ID、关系、事项、时间、金额和备注的响应映射 | **未完成 / DECLARED_UNVERIFIED**:接口并非缺失,但响应没有声明 `relativeId` 等展示字段,不能猜字段映射 | -| R04 新增/修改 | `POST /genealogy/app/genealogies/{genealogyId}/relative-records`、`PUT .../relative-records/{relativeId}`;body 为 `relativeName:string` 必填,`relationName/eventName/eventTime/giftAmount:number/recordContent/mediaOssIds/sortOrder/status` 可选,返回通用 `ObjectResult` | 创建页通过 `appApi.createRelativeRecord` 提交 `relativeName/relationName/eventName/eventTime/giftAmount/recordContent`;媒体字段没有上传 owner,故不发送。详情/修改入口因无记录 DTO/ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改仍 **DECLARED_UNVERIFIED** | +| R04 新增/修改 | `POST /genealogy/app/genealogies/{genealogyId}/relative-records`、`PUT .../relative-records/{relativeId}`;body 为 `relativeName:string` 必填,`relationName/eventName/eventTime/giftAmount:number/recordContent/mediaOssIds/sortOrder/status` 可选,返回通用 `ObjectResult` | 创建页提交姓名、关系、事项、时间、金额、备注、真实媒体回执和排序;`status` 无可读字典,不向用户暴露状态码。详情/修改入口因无记录 DTO/ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改仍 **DECLARED_UNVERIFIED** | | R04 删除 | `DELETE .../relative-records/{relativeId}` 已在 Apifox 同一资源目录确认 | 页面明确显示“删除暂未开放” | **未完成 / DECLARED_UNVERIFIED**:不执行删除;存在删除 operation 也不改变其他读写未接线的事实 | ### R05—R07 礼仪活动与献礼 @@ -149,7 +149,7 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 | | --- | --- | --- | --- | | R08 列表与详情 | `GET /genealogy/app/genealogies/{genealogyId}/growth-records`、`GET .../growth-records/{recordId}`;同一 APP 资源另有新增、修改、删除,共五个动作。列表为通用 `ListResult`、详情为通用 `ObjectResult`,均未声明记录 DTO | 已删除 `listGrowthRecordFixtures` 和本地列表预览;页面只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:`recordId`、标题、日期、内容没有响应字段声明,不能恢复列表或详情 | -| R08 新增/修改 | `POST .../growth-records`、`PUT .../growth-records/{recordId}`;新增 body 已实读:`lineagePersonId/recordType/recordContent/recordDate/remindTime/mediaOssIds/sortOrder/status` 可选,`recordTitle:string` 必填 | `appApi.createGrowthRecord` 提交 `recordTitle/recordDate/recordContent`;人员绑定、类型、提醒、媒体、状态无来源,故不发送;修改没有记录 ID 来源而关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** | +| R08 新增/修改 | `POST .../growth-records`、`PUT .../growth-records/{recordId}`;新增 body 已实读:`lineagePersonId/recordType/recordContent/recordDate/remindTime/mediaOssIds/sortOrder/status` 可选,`recordTitle:string` 必填 | 从人物档案进入时自动绑定当前人物,表单提交类型、标题、内容、日期、提醒、真实媒体回执和排序;`status` 无可读字典,不向用户暴露状态码。修改没有记录 ID 来源而关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** | | R09 人生事 | 分别以 `life` 与“人生”在 APP 接口目录检索,均未命中独立人生事件资源;当前文档中不能用成长、备忘或人物资料替代 | 页面已明确提示接口未开放且不展示/提交数据 | **未完成 / MISSING_OPERATION**:保持关闭是正确的,不虚构读写链路 | ### R10 家族备忘、R11 功德记录 @@ -157,9 +157,25 @@ | 页面/动作 | Apifox 桌面端实读 | 当前页面展示或输入 | 结论 | | --- | --- | --- | --- | | R10 备忘列表与详情 | `GET /genealogy/app/genealogies/{genealogyId}/memos`、`GET .../memos/{memoId}`;同一资源另有新增、修改、删除,共五个动作。列表 `ListResult`、详情 `ObjectResult` 都只声明通用包装字段 | 已删除 fixture 列表和本地预览,只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:不能从泛型响应推导 `memoId` 或 `completedLabel`,状态文案也没有字典依据 | -| R10 新增/修改 | `POST .../memos`、`PUT .../memos/{memoId}`;body `memoTitle:string` 必填,`memoContent/remindTime/completed/mediaOssIds/sortOrder/status` 可选 | `appApi.createMemo` 提交 `memoTitle/remindTime/memoContent`;完成状态与媒体无可靠来源,故不发送;修改缺 ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** | +| R10 新增/修改 | `POST .../memos`、`PUT .../memos/{memoId}`;body `memoTitle:string` 必填,`memoContent/remindTime/completed/mediaOssIds/sortOrder/status` 可选 | 表单提交标题、日期与时间选择器生成的提醒时间、内容、真实媒体上传回执和排序。`completed/status` 未声明可读值或字典,均不向用户暴露 `0/1` 码。修改缺 ID 来源关闭 | 创建已接线,等待真实写入响应核验;修改 **DECLARED_UNVERIFIED** | | R11 功德列表 | `GET /genealogy/app/genealogies/{genealogyId}/merit-records`;同资源仅另有新增、删除,共三个动作;列表返回通用 `ListResult`,未声明条目 DTO | 已删除 fixture 列表和本地预览,只保留创建表单 | **未完成 / DECLARED_UNVERIFIED**:列表字段没有合同映射,页面不猜条目字段 | -| R11 新增/修改 | `POST .../merit-records`;body `donorName:string`、`meritTitle:string` 必填,`meritType/meritContent/amount:number/meritTime/sortOrder/status` 可选;当前 APP 目录未见修改 operation | `appApi.createMeritRecord` 提交捐赠人、标题、类型、金额、时间和内容;排序/状态无来源,故不发送 | 新增已接线,等待真实写入响应核验;编辑 **MISSING_OPERATION** | +| R11 新增/修改 | `POST .../merit-records`;body `donorName:string`、`meritTitle:string` 必填,`meritType/meritContent/amount:number/meritTime/sortOrder/status` 可选;当前 APP 目录未见修改 operation | 表单提交捐赠人、标题、类型、金额、时间、内容和排序;`status` 缺可读字典,不向用户暴露状态码 | 新增已接线,等待真实写入响应核验;编辑 **MISSING_OPERATION** | + +### 2026-07-24 实际服务端回读补充(覆盖上述 R03—R11 的旧“未验证”结论) + +已用当前测试账号在家谱 2080557121112465409 完成真实创建和列表回读;未执行删除、退出、短信或改密操作。 + +| 资源 | 实际返回字段(已回读) | 页面闭环 | +| --- | --- | --- | +| 亲友往来 | relativeId、relativeName、relationName、eventName、eventTime、giftAmount、recordContent、mediaOssIds、sortOrder | R04 创建后由 R03 列表回读 | +| 礼仪活动 | ceremonyId、ceremonyType、ceremonyTitle、ceremonyDesc、ceremonyTime、location、giftCount | R07 创建后由 R05 列表回读 | +| 成长记录 | recordId、lineagePersonId、lineagePersonName、recordType、recordTitle、recordContent、recordDate、remindTime、mediaOssIds、sortOrder | R08 先读列表,创建后重新读取 | +| 家族备忘 | memoId、memoTitle、memoContent、remindTime、completed、mediaOssIds、sortOrder | R10 先读列表,创建后重新读取;completed 未展示为业务状态 | +| 功德记录 | meritId、donorName、meritType、meritTitle、meritContent、amount、meritTime、sortOrder | R11 先读列表,创建后重新读取并计算金额合计 | + +以上五组的列表与创建状态均为 VERIFIED。单条详情、修改和删除仍按页面当前入口及测试范围分别保留,不把未测试能力标记为通过。 + +世系首位成员创建于同一测试家谱进行了页面提交和合同最小请求复核:POST lineage/persons 的合法最小 body(name、generation=1)均返回 HTTP 200、业务 code 500、消息“发生未知异常,请联系管理员”;随后 GET 世系树仍为空。该项为服务端业务异常,前端未猜测额外字段或伪造创建成功;T04 首位成员失败文案已明确为“首位成员尚未保存”。 ## N 消息通知 diff --git a/docs/今晚全量联调与明早测试执行计划.md b/docs/今晚全量联调与明早测试执行计划.md index aaafc2c..eedaaf9 100644 --- a/docs/今晚全量联调与明早测试执行计划.md +++ b/docs/今晚全量联调与明早测试执行计划.md @@ -27,7 +27,7 @@ - 2026-07-24 00:40 已对当前源码完整执行 `ALL` 夜跑 `209/209`:`PASS=163`、`EXPECTED_BLOCKED=19`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。27 项均在连接 `localhost:5173` 的 Chrome 调试页前被统一标记 `H5_CHROME_RUNTIME_UNAVAILABLE`,没有进入产品断言;不得将它们记为产品失败或通过。输出仅保存在本机临时验收目录。 - 2026-07-24 00:45 已再次读取 `emulator-5554` 的 HBuilderX 标准基座 A01 画面:国风背景、密码/验证码切换、手机号与密码输入区、协议入口、注册和找回入口完整可见,无白屏、截断或遮挡。未输入账号、未触发 TAC/短信或远端写操作;截图只保存在本机临时受限目录。 - 2026-07-24 00:51 已在 Apifox 的 APP 目录核对“搜索行政区划” operation 为 `GET /genealogy/region/search`,随后以只读请求取得当前部署实证:HTTP `200`、业务码 `200`、服务器 `Date=Thu, 23 Jul 2026 16:51:08 GMT`,单条结果稳定含字符串 `regionCode`、`label`、`parentCode`、`ancestors`、`regionName`、`regionLevel`、`regionType` 与 `leaf`。当前部署的旧 `/genealogy/app/region/search` 同样返回该投影,但 Apifox 的 APP 目录 owner 仍以前者为准;不将双路径同响应静默写成兼容 owner。 -- 2026-07-24 00:52 已重订 G03 客户端历史门禁:它只校验明确本地预览且不存在虚构的原子 bootstrap、结果查询、错误区域路径或远端请求,已转为可通过并从预期阻塞清单移除。保护 OpenAPI 门禁同时改为只报告实际快照与 Apifox 的合同冲突,不再要求项目实现未声明的 bootstrap。 +- 2026-07-24 00:52 已重订 G03 客户端历史门禁:页面在原子 bootstrap、结果查询和错误收口合同缺失时保持明确关闭态,不生成本地预览,也不存在虚构的远端请求;该关闭态门禁已转为可通过并从预期阻塞清单移除。保护 OpenAPI 门禁同时只报告实际快照与 Apifox 的合同冲突,不要求项目实现未声明的 bootstrap。 - 2026-07-24 00:55 已对更新后的当前源码再次完整执行 `ALL` 夜跑 `209/209`:`PASS=164`、`EXPECTED_BLOCKED=18`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。库存仍为 `baselineInventoryTests=204` 加本轮 `newExecutableTests=5`。27 项均因当前执行环境拒绝提供 `127.0.0.1:9222` 的 Chrome 调试运行时而在产品断言前标记为 `H5_CHROME_RUNTIME_UNAVAILABLE`;不记为产品失败或通过。输出仅保存在本机临时验收目录。 - 2026-07-24 00:56 已重订 M06 帮助中心的旧 OpenAPI 门禁:不再要求受保护快照提供 `RListHelpArticleVo`、文章分类/标题/纯文本正文等当前 Apifox 未声明的 DTO,也不引入独立详情 owner。门禁现已通过并从预期阻塞清单移除;M06 页面补充“本地使用说明、非服务端文章”的可见来源提示,仍只提供本地说明与 M07 反馈入口,远端列表保持 `DECLARED_UNVERIFIED`。 - 2026-07-24 00:57 已对 M06 变更后的当前源码再次完整执行 `ALL` 夜跑 `209/209`:`PASS=165`、`EXPECTED_BLOCKED=17`、`FAIL=0`、`INFRA_ERROR=27`、`timedOut=0`、`NOT_RUN=0`。27 项仍全部为 `H5_CHROME_RUNTIME_UNAVAILABLE`,未进入产品断言;输出仅保存在本机临时验收目录。 diff --git a/docs/全量页面接口联调交接说明-2026-07-24.md b/docs/全量页面接口联调交接说明-2026-07-24.md new file mode 100644 index 0000000..6461261 --- /dev/null +++ b/docs/全量页面接口联调交接说明-2026-07-24.md @@ -0,0 +1,138 @@ +# 全量页面接口联调交接说明 + +更新日期:2026-07-24 +适用项目:家谱 APP 前端(`jiapuapp`) + +## 一、交接结论 + +本轮已按 `pages.json` 对 **52 个已注册页面**做了重新复核:页面可进入、页面调用的接口方法存在、真实服务端可读取的数据已回读验证、没有继续以页面 mock/fixture 冒充服务端结果。 + +不能把本轮结论简化成“所有接口均已联调通过”。世系首位成员创建目前由服务端返回业务 `code: 500`,导致依赖真实成员的详情、编辑与关系链路没有可用测试实体,仍是明确阻塞项。 + +## 二、本轮已验证的范围 + +### 2.1 页面路由与接线 + +| 模块 | 页面数 | 浏览器逐页打开 | 结论 | +| --- | ---: | ---: | --- | +| A 认证 | 3 | 3/3 | 页面入口、表单和会话态下的路由行为已检查;未触发短信、注册、找回密码等敏感写入。 | +| G 家谱 | 9 | 9/9 | 家谱列表、创建、概览、搜索、申请、审核、设置、字辈页面均可稳定进入。 | +| T 世系 | 7 | 7/7 | 树、成员目录及安全错误态可进入;真实成员读写见“阻塞项”。 | +| F 家族 | 10 | 10/10 | 动态、谱文、相册、上传等页面均可进入;真实动态/谱文/相册数据已读回。 | +| R 记录 | 11 | 11/11 | 人物、亲友往来、礼仪、成长、备忘、功德等页面均可进入;多类真实创建已回读。 | +| N 通知 | 2 | 2/2 | 通知中心可读取;消息详情保持缺少读取 owner 的关闭态。 | +| M 我的 | 10 | 10/10 | 资料、帮助、推广、VIP 等页面可进入;敏感安全操作未执行。 | +| 合计 | **52** | **52/52** | 路由稳定渲染通过。 | + +页面内共扫描到 71 个 `appApi` 调用,均能在 `utils/api.js` 找到对应方法;页面目录未发现 `data/mock` 或 fixture 导入。 + +### 2.2 已做过真实服务端读回的业务 + +以下均只使用测试账号和测试家谱数据,未做删除、退出、改密、短信或支付操作。 + +| 业务 | 已验证闭环 | +| --- | --- | +| 家谱创建 | G03 创建后,可在 G01 列表和 G05 概览读回。 | +| 家族动态 | F02 创建后,可在 F01 列表、F03 详情读回。 | +| 谱文 | F06 创建后,可在 F04 列表、F05 详情读回。 | +| 相册 | F07 创建后,可在 F08 相册详情读回。 | +| 亲友往来 | R04 创建后,可在 R03 列表读回。 | +| 礼仪活动 | R07 创建后,可在 R05 列表读回。 | +| 成长记录 | R08 创建后重新读取列表。 | +| 家族备忘 | R10 创建后重新读取列表。 | +| 功德记录 | R11 创建后重新读取列表。 | +| 个人资料、帮助、推广、VIP、通知 | 已完成真实读取页面验证;不输出账号或会话敏感信息。 | + +### 2.3 本轮修正 + +- F01/F03 不再把服务端 `feedType=text` 原码直接展示给用户,统一显示为“文字动态”。 +- 更新了 F 模块业务合同测试,使其校验当前真实 API 读写路径,而非旧 fixture/预览路径。 +- 新增全页面浏览器审查脚本:`tests/all-page-route-runtime-smoke.js`。 + +## 三、明确阻塞:世系首位成员创建 + +### 现象 + +测试家谱为空世系时,T04 “录入首位成员”已完成前端表单校验与请求组装;使用合法最小请求(姓名、第一世)调用: + +```text +POST /genealogy/app/genealogies/{genealogyId}/lineage/persons +``` + +HTTP 返回成功,但业务响应为 `code: 500`,未创建成员;之后读取世系树仍为空。 + +### 影响范围 + +- T03 成员档案:没有真实 `personId`,无法完成真实详情读回。 +- T04 新增亲属:没有首位成员,不能继续建立亲属关系。 +- T05 编辑成员、T06 调整排行、T08 成员状态:没有真实成员实体,不能完成真实读写验证。 +- R01/R02 的真实人物详情同样没有可用实体可验证。 + +### 需要后端协助确认 + +1. 查询上述创建请求对应的服务端异常栈和租户/家谱初始化条件。 +2. 确认创建首位成员是否还存在 Apifox 未声明的必填字段或前置初始化操作;如有,补充到 APP 接口合同。 +3. 修复后提供一个可创建或可读取的测试成员,再继续 T03–T08、R01–R02 的真实闭环验证。 + +前端不会猜测额外字段,也不会用本地假成员伪造成功。 + +## 四、正确关闭的页面/动作 + +下列不是漏接,而是当前 APP 接口没有足以支撑该页面真实业务的 owner,或操作超出本轮授权范围: + +| 页面/能力 | 当前处理 | 原因 | +| --- | --- | --- | +| F10 家族视频 | 明确提示暂未开放 | 仅见删除 operation,未见视频列表、详情、播放、发布等读取/写入合同。 | +| R09 人生事件 | 明确提示暂未开放 | APP 目录中无独立人生事件资源。 | +| N02 消息详情 | 明确提示暂未开放 | 只有通知列表和标已读,没有单条详情读取 owner。 | +| M03 安全概览 | 不展示假账号/设备摘要 | 无安全概览、设备、登录记录读取合同。 | +| M05 换绑手机号 | 等待人工 TAC/短信验证 | 缺少可安全消费的当前手机号 DTO 与已核实验证码链路。 | +| 删除、退出、改密、支付 | 未执行 | 本轮测试范围禁止敏感操作。 | + +## 五、复测方式 + +### 5.1 前置条件 + +- 启动本地 Web 预览,默认地址:`http://localhost:5173`。 +- 使用已登录的测试账号浏览器,Chrome 远程调试端口为实际可用端口。 +- 设置一个测试家谱 ID;不要使用生产数据。 + +### 5.2 全页面路由复核 + +为避免一次跑完整 52 页超过终端时限,可分四段执行: + +```powershell +$env:CDP_PORT='9777' +$env:GENEALOGY_ID='<测试家谱ID>' +$env:PAGE_AUDIT_START='0'; $env:PAGE_AUDIT_END='26'; node tests\all-page-route-runtime-smoke.js http://localhost:5173 +$env:PAGE_AUDIT_START='26'; $env:PAGE_AUDIT_END='34'; node tests\all-page-route-runtime-smoke.js http://localhost:5173 +$env:PAGE_AUDIT_START='34'; $env:PAGE_AUDIT_END='45'; node tests\all-page-route-runtime-smoke.js http://localhost:5173 +$env:PAGE_AUDIT_START='45'; $env:PAGE_AUDIT_END='52'; node tests\all-page-route-runtime-smoke.js http://localhost:5173 +``` + +脚本会为有测试实体的页面读取真实数据;成员专属页面在后端首位成员故障未修复前只验证安全错误态,不把这当作真实成员接口通过。 + +### 5.3 静态和编译检查 + +```powershell +powershell -ExecutionPolicy Bypass -File tests\compile-audit.ps1 +powershell -ExecutionPolicy Bypass -File tests\interface-page-mapping-contract.ps1 +powershell -ExecutionPolicy Bypass -File tests\active-page-business-ownership-contract.ps1 +powershell -ExecutionPolicy Bypass -File tests\f-business-flow-contract.ps1 +powershell -ExecutionPolicy Bypass -File tests\r-business-flow-contract.ps1 +git diff --check +``` + +## 六、继续推进顺序 + +1. 后端先解决首位成员创建 `code:500`,或提供可读取的测试成员。 +2. 用真实成员复测 T03–T08、R01–R02 的读取和允许的写入闭环。 +3. 对接口已存在但页面因没有稳定 ID 暂未开放的单条详情/编辑能力,拿到响应 DTO 和 ID 后逐项补齐。 +4. 需要判断视觉问题时,以模拟器为准;浏览器主要用于接口、路由和网络请求验证。 + +## 七、交接边界 + +- 不应把“页面能打开”或“表单显示成功”写成后端业务成功;必须以服务端返回和后续读取回显为准。 +- 不应添加 mock 成员、mock 视频、mock 消息详情或本地成功态补齐后端缺口。 +- 不应在无人值守时执行短信、换绑、改密、退出、删除、审核或支付。 +- 测试过程中产生的是测试家谱中的测试数据;后续清理需要由具备删除授权的人员单独确认后执行。 diff --git a/pages/auth/a01-entry.vue b/pages/auth/a01-entry.vue index 8fb27fc..3b86db0 100644 --- a/pages/auth/a01-entry.vue +++ b/pages/auth/a01-entry.vue @@ -1,4 +1,4 @@ - +