Files
jiapu/docs/PC接口对接规划.md
T
2026-08-03 16:49:38 +08:00

122 KiB
Raw Blame History

PC 接口字段与页面落地规划(供 AI 执行)

文档状态:规划,不代表当前代码已经完成 基线日期:2026-07-27 当前本地快照:根目录 PC.openapi.jsonOpenAPI 3.1.0 使用对象:另一台电脑上的执行 AI 本轮边界:只写规划;执行 AI 才能修改页面、脚本和测试

0. 强制要求:必须打开 Apifox 查看

执行 AI 在修改任何代码前,必须实际登录并打开 Apifox 的“家谱”项目,进入每一个本轮接口的详情页逐项查看。不得只读取 PC.openapi.json、Apifox 本地缓存、旧截图或历史文档。

每个接口都必须在 Apifox 详情页记录:

  1. method、完整 path、接口状态和所属 PC 目录;
  2. Path、Query、Header、Cookie 和 Body 的全部字段;
  3. 每个字段的类型、必填/可选/条件必填、默认值、枚举、格式、长度和取值范围;
  4. 字段说明、示例值、关联字典和条件显示规则;
  5. 请求体中折叠对象、数组元素和嵌套字段的完整结构;
  6. 成功响应、失败响应、列表元素、详情对象和分页结构的完整字段;
  7. 登录要求、角色权限、业务前置条件和错误码;
  8. Apifox 页面有但 OpenAPI 导出遗漏的字段或说明。

核对结果必须写入本规划对应模块的字段表,并为每个字段标明 U/S/F/A/R/I/V 分类、使用页面、数据来源和提交时机。Apifox 详情没有确认的字段不得进入代码;Apifox 与导出文件不一致时,以现场核对结果形成问题清单,先让接口 owner 修正并重新导出,再实施。

1. 最终目标

执行 AI 要把 Apifox 中的 PC 接口准确落到现有 PC 页面,最终同时满足:

  1. 请求体中的必填字段、可选字段全部有明确页面归属。
  2. 字段被明确分成:
    • 用户输入;
    • 用户选择;
    • 文件选择后自动生成;
    • 页面上下文自动带入;
    • 接口响应后只读展示;
    • 仅内部保存、不得展示或手工填写;
    • 纯前端校验字段、不得发给后端。
  3. ID、Token、clientidtenantId、OSS ID、分页参数等系统字段不得让用户手工输入。
  4. 下拉框和选择器必须有真实数据源;没有选项接口时不得改成“请输入 ID”。
  5. Apifox 未展开的响应 DTO、未声明的枚举和互相冲突的路径不得靠前端猜测。
  6. APP 接口不得用于填补 PC 接口缺口。
  7. 所有家谱内业务必须使用真实 genealogyId,不得写死示例值。
  8. 每一阶段必须有契约测试、页面行为测试和真实联调结果。

2. 执行 AI 的工作协议

执行 AI 开始前必须按顺序完成:

  1. 阅读项目根目录 AGENTS.md
  2. 检查工作树,只修改本计划点名的文件;保留用户已有改动。
  3. 登录 Apifox,打开“家谱”项目,逐条核对实时 PC 接口详情。
  4. 从 Apifox 重新导出最新 OpenAPI,和仓库 PC.openapi.json 做结构化差异比较。
  5. 完成第 5 节“契约阻断项”;阻断项未解决的模块只保留页面设计,不接真实写操作。
  6. 按第 8 节阶段顺序施工,每完成一阶段立即验证,不能把所有模块一次性混改。

遇到以下情况时,停止当前模块并整理成一份待后端确认清单,同时继续其他不受影响的模块:

  • Apifox 页面和导出文件的 method、path、必填性、枚举或类型不一致;
  • 响应仍是无属性的 ObjectResult / ListResult
  • 选择字段没有合法选项来源;
  • 更新接口没有说明“字段不传”和“传 null/空串”的区别;
  • 页面需要的业务能力在 PC 目录中不存在。

不得通过兼容多个旧字段、读取 APP DTO、保留旧路径 fallback 或展示原始 JSON 绕过阻断。

3. 契约依据与优先级

发生冲突时按以下顺序处理:

  1. Apifox “家谱”项目中当前 PC 接口详情;
  2. 从该详情当场重新导出的 OpenAPI 文件;
  3. 本规划中的字段和流程分类;
  4. 当前仓库代码;
  5. 旧规划和历史交接记录。

通常以 Apifox 的 PC 目录作为 PC 前端接口的正式契约源。2026-07-28 用户明确指定本轮直接以 D:/WorkSpace/Java/Genealogy/doc/apifox/genealogy-pc-openapi.yaml 对接,因此该 YAML 是本轮冻结契约;在线 Apifox 的旧重复记录不再覆盖它。utils/ApiClient.js 是前端路径和请求方法的唯一 owner。页面脚本只能调用 ApiClient 业务方法,不能直接拼 URL 或调用 Axios。

旧 OpenAPI 文件不再作为新增功能依据,只用于结构化差异比较和追踪导出遗漏。

如果 Apifox 在线内容发生变化,先更新本地 OpenAPI、本规划的受影响章节和契约测试,再修改运行时代码。不得让文档、测试和运行时同时保留两套契约。

4. 当前基线与复核结论

4.1 当前导出范围

当前 PC.openapi.json 共 96 个操作、15 个标签、68 个 Schema

模块 操作数 当前主要页面
验证中心 3 登录、注册、找回密码、安全设置
认证登录 11 login.htmlregister.htmlforgot-password.html、个人资料和安全页
文件上传 3 所有头像、图片、附件和视频选择控件
家谱 1 profile-families.html
家族圈 14 profile-feed.htmlprofile-feed-edit.html、待新增动态详情页
行政区划 8 个人资料及以后需要地区的表单
字辈谱 6 profile-generation.html
世系人物 12 profile-tree.html
内容文章 1 profile-article.htmlprofile-article-edit.html
相册 2 profile-album.html
视频 5 profile-video.html、待新增视频编辑页
贺礼邀约 4 profile-gift.html、邀约管理面板
祭祀 2 profile-gift.html
族务记录 20 成长、亲友、备忘录、功德录页面
消息通知 4 profile-messages.html
合计 96

4.2 已对照到的 Apifox 现状

本机 Apifox 缓存中的“家谱”项目包含 APP、PC、共享区划等 246 条接口记录。当前导出的 96 条路径均能在该项目缓存的接口树中找到,但存在以下差异:

  1. Apifox 缓存同时保留了两条逻辑相同的短信接口:

    • 错误旧路径:genealogy/pc/auth/sms/{operationCode}/code
    • 正确路径:/genealogy/pc/auth/sms/{operationCode}/code

    当前导出只保留正确路径。执行前必须在 Apifox 删除或正式废弃缺少 / 的旧定义,前端只实现正确路径。

  2. 导出文件同时含 /genealogy/region/*/genealogy/pc/region/* 两套共 8 个区划操作;两套的参数、响应和描述完全相同。执行前必须由后端选定一套唯一正式路径并删除另一套。选定后实际唯一操作数应从 96 收口为 92。

  3. 旧版“85 接口规划”已经失效。新增范围主要包括 PC 区划 4 条、视频列表/新增/详情/修改 4 条、功德列表/新增/详情/修改 4 条。

  4. 当前 96 个操作全部被声明为需要 Authorization,连注册、登录、短信发送和验证中心也不例外。这与未登录流程冲突,必须在 Apifox 逐项修正 security。

  5. 当前有 21 个成功响应使用无业务属性的 ObjectResult,12 个使用无元素 Schema 的 ListResult;另有 LineagePersonTreeView 名义上是专用 DTO,但没有任何属性。

4.3 2026-07-28 补齐版 YAML 与在线 Apifox 复核

补齐文件 genealogy-pc-openapi.yaml 含 98 个 path、137 个 HTTP operation、17 个 tag、319 个 schema;旧 PC.openapi.json 含 71 个 path、96 个 operation、68 个 schema。补齐文件新增了家谱、成员、相册、文章、祭祀、通知、反馈、VIP 和官网内容等路径及 DTO,但它还不能替代在线 Apifox:

  1. 已实际登录并打开 Apifox“家谱”项目的 PC 模块。在线概览显示 142 个接口、87 个数据模型,与补齐 YAML 的 137 个 HTTP operation 不一致。

  2. 在线“认证登录”目录仍显示 12 个接口,同时存在:

    • 错误旧路径:genealogy/pc/auth/sms/{operationCode}/code
    • 正确路径:/genealogy/pc/auth/sms/{operationCode}/code

    补齐 YAML 只包含正确路径,因此 C02 在线尚未完成。

  3. 补齐 YAML 给注册、密码登录、短信登录和短信发送标了 security: [];在线密码登录详情仍展示必需的 Authorization API Key,并显示 Auth 1。因此 C03 的导出定义和在线详情冲突。

  4. 在线 GET /genealogy/pc/auth/profile 成功响应仍为泛型 ObjectResult;展开后的 data 只有任意附加属性,没有 ProfileView 字段。补齐 YAML 同样引用泛型 ObjectResultC04/C06 未完成。

  5. ProfileUpdateBody.avatar 仍为 integer<int64>,而 FileUploadVo.ossIdLineagePersonView.avatarOssId 等 OSS ID 为 string;部分头像字段也仍为 integer<int64>。C10 未完成。

  6. 已用真实登录响应和后端 AppLoginVo 复核:token 的唯一 JSON 字段是 access_token;原 YAML 的 tokenaccessTokentokenValueuserIdtenantIdclientId 均不是该响应的直接字段,现已删除。

  7. ProfileUpdateBody 仍只有 nickNamerealNameavatarsexbirthdayemail,没有地区字段,也没有说明缺省、null、空串的清空语义。C07/C18 未完成。

用户已明确要求本轮直接按补齐 YAML 施工,所以在线旧短信路径和公开接口 security 残留不再阻断本轮实现。YAML 自身仍存在的 profile 泛型响应、头像 ID 类型冲突和更新清空语义缺失继续保留为阻断项,前端不得自行补造。

5. 实施前必须解决的契约阻断项

以下事项不是前端自由选择,必须先在 Apifox 明确:

编号 问题 影响 完成条件
C01 两套区划路径完全重复 页面和客户端会形成双路径 Apifox 只保留一套;导出和客户端只出现一次
C02 短信接口有缺少开头 / 的旧记录 可能生成错误 URL 删除/废弃旧记录,只保留正确路径
C03 所有操作均要求 Authorization 未登录流程无法成立 注册、登录、找回、验证、短信等逐项标明公开;登录后接口明确鉴权
C04 33 个操作使用泛型对象/列表响应 列表、详情、编辑回填和 ID 来源不确定 为每个业务资源增加明确 View/DTO Schema
C05 LineagePersonTreeView 没有属性 世系树只能猜字段 补齐节点 ID、人物资料、配偶、子女和递归结构
C06 用户资料响应未展开 个人资料无法可靠回填 增加 ProfileView,明确所有可读字段
C07 ProfileUpdateBody 没有地区字段 现居地区无法保存 明确增加地区编码字段或删除“保存地区”功能
C08 区划响应没有元素 DTO 下拉选项的 code/name/level 不受契约约束 增加 RegionView 及列表/路径响应
C09 上传初始化响应未展开,却描述了 instant=true 秒传、续传和 uploadId 状态不明确 增加初始化响应 DTO,明确 instant、已传分片和 OSS 信息
C10 OSS ID 类型冲突 可能发生 JS 精度丢失或校验失败 所有 ossIdavataravatarOssId、视频和附件 ID 统一为 string
C11 completed 只有 string 类型,无枚举 不能决定复选框提交 0/1、true/false 或其他值 Apifox 增加枚举和中文含义
C12 feedTyperecordTyperegisterSource 等无枚举 无法判断文本输入还是选择项 明确为自由文本,或补全枚举
C13 多个日期字段没有 format/时区规则 页面值和后端解析可能不一致 明确 date 或 date-time,并统一时区
C14 已由后端 PC 实链接决 GET /genealogy/pc/genealogies/mine/options 返回完整 AppGenealogyVogenealogyId 从响应取得 前端只从真实列表选择,不允许手填 ID
C15 bindingMode=SPECIFIED 需要 appUserId,但无业务用户选项接口 不能提供合法选择器 增加家谱成员/业务用户选项接口
C16 邀约的 inviteeUserIds 没有选项接口 不能让管理员选择受邀人 增加同一家谱成员选项接口
C17 视频、成长、亲友、备忘、功德、通知响应未展开 无法安全展示、编辑或单条操作 分别增加资源 View 和列表/详情响应
C18 更新接口未说明缺省、null、空串语义 可选字段可能无法清空 Apifox 对每个可清空字段写明更新规则
C19 多数 View 没有 canEdit / canDelete 等权限字段 页面无法可靠决定按钮可见性 增加能力字段,或提供明确且可实现的角色规则
C20 文章、相册、祭祀只有删除操作 没有真实 ID 来源和完整资源流程 补全 PC 列表/详情/新增/修改后才开放页面
C21 家族圈动态只返回 mediaOssIds,PC 没有 OSS ID 批量解析/访问 URL 接口 已上传图片只能统计数量,不能在列表和详情安全回显缩略图 PC 增加按 OSS ID 返回授权 URL、文件名和媒体类型的接口,或让动态 View 直接返回媒体对象数组
C22 停用动态不会出现在普通列表,普通详情接口也拒绝读取 管理员可以停用,但停用后无法从 PC 页面重新读取、恢复或验证最终状态 增加包含停用记录的管理列表/详情,或增加独立的状态恢复接口
C23 VideoVo 只返回 coverOssId / videoOssId,没有 PC 文件访问 URL 或解析接口 可以维护视频记录,但不能安全播放视频或回显封面 视频 View 直接返回授权 URL,或增加按 OSS ID 获取文件访问地址的 PC 接口
C24 视频列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法从页面重新读取和恢复 增加视频 management 列表/详情,或增加独立状态恢复接口
C25 GrowthRecordVo 只返回附件 mediaOssIds,没有 PC 文件访问 URL 或解析接口 可以维护附件引用,但不能安全预览、下载或回显文件名 成长记录 View 返回附件对象,或增加按 OSS ID 获取授权地址、文件名和类型的 PC 接口
C26 成长记录列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法写后重读、恢复或再次编辑 增加成长记录 management 列表/详情,或增加独立状态恢复接口
C27 giftAmount 只有 number / BigDecimal 类型,没有精度、范围和正负规则 前端不能自行限定两位小数、最大金额或禁止负数 Apifox 明确 scale、precision、minimum/maximum 和负数业务含义
C28 RelativeRecordVo 只返回附件 mediaOssIds,没有 PC 文件访问 URL 或解析接口 可以维护附件引用,但不能安全预览、下载或回显文件名 亲友记录 View 返回附件对象,或增加按 OSS ID 获取授权地址、文件名和类型的 PC 接口
C29 亲友记录列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法写后重读、恢复或再次编辑 增加亲友记录 management 列表/详情,或增加独立状态恢复接口
C30 MemoVo 只返回附件 mediaOssIds,没有 PC 文件访问 URL 或解析接口 可以维护附件引用,但不能安全预览、下载或回显文件名 备忘录 View 返回附件对象,或增加按 OSS ID 获取授权地址、文件名和类型的 PC 接口
C31 备忘录列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法写后重读、恢复或再次编辑 增加备忘录 management 列表/详情,或增加独立状态恢复接口
C32 功德金额只有 number / BigDecimal 类型,没有精度、范围和正负规则 前端不能自行限定两位小数、最大金额或禁止负数 Apifox 明确 scale、precision、minimum/maximum 和负数业务含义
C33 功德记录列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法写后重读、恢复或再次编辑 增加功德记录 management 列表/详情,或增加独立状态恢复接口
C34 YAML NotificationView 声明了家谱编号/名称、发送人昵称/手机号和业务摘要,但 PC toVo 未填充这些字段 页面可能长期显示空白,导出契约与真实 PC 响应不一致 后端补齐字段,或从 PC Schema 删除不会返回的字段并明确隐私策略
C35 PC 谱文后端列表支持可选 categoryId,YAML 未声明该 query,且没有文章分类选项接口 前端无法可靠提供分类筛选或编辑分类 YAML 补齐 query,并提供当前家谱文章分类选项接口
C36 ArticleVo 只返回 coverOssId,没有 PC 文件访问 URL 谱文可维护封面引用,但不能安全回显封面图片 Article View 返回封面 URL,或增加 OSS ID 授权解析接口
C37 谱文列表只返回正常记录,详情拒绝读取停用记录 status=1 后无法写后重读或恢复 增加谱文 management 列表/详情,或独立状态恢复接口
C38 AlbumVo / AlbumPhotoVo 只返回 coverOssId / ossId,没有 PC 文件访问 URL 相册和照片记录可维护,但不能安全回显封面或照片内容 View 返回授权 URL,或增加 OSS ID 授权解析接口
C39 相册和照片列表只返回正常记录,且没有停用记录的 management 入口 status=1 后无法从页面重读、恢复或再次编辑 增加相册/照片 management 列表,或独立状态恢复接口
C40 CeremonyVo 只返回 coverOssId,没有 PC 文件访问 URL 活动记录可维护,但不能安全回显封面 View 返回封面授权 URL,或增加 OSS ID 授权解析接口
C41 活动列表和详情只允许读取正常记录 status=1 后无法从页面重读、恢复或再次编辑 增加活动 management 列表/详情,或独立状态恢复接口
C42 CeremonyGiftBody.giftAmount 的 YAML 没有精度和最大值,后端实际拒绝负数 页面可按后端约束拒绝负数,但不能自行限定小数位或最大金额 YAML 补充 minimum、scale、precision 和 maximum
C43 YAML 成员更新角色枚举含 owner/visitorPC 后端 DTO 只接受 admin/editor/member 按 YAML 展示会产生必然失败的写入 YAML 收紧枚举;本轮前端按 PC 后端校验冻结为三种可分配角色
C44 GenealogyMemberVo 声明昵称、手机号、家谱和世系人物名称等字段,PC toVo 实际只填充 ID、成员名、角色、关系、来源和时间 列表部分说明可能长期为空,手机号还有隐私风险 后端补齐非敏感展示字段并删除手机号,或从 PC Schema 删除不会返回的字段
C45 PC 没有世系关系解除接口 页面无法合法解除父母、配偶、子女或兄弟姐妹关系 后端增加带权限和关系完整性校验的解除接口
C46 成员更新只在 lineagePersonId != null 时写入,没有解除成员与世系人物绑定的语义 下拉留空只能表示“不修改”,不能完成解绑 增加明确解绑接口或约定可验证的 null/空值语义

当前复核状态:

阻断项 状态 在线/补齐文件证据
C02 本轮按 YAML 解决 只实现带 / 的正确路径,不保留旧路径 fallback
C03 本轮按 YAML 解决 验证、注册、登录、短信、找回使用 security: [];其他认证接口携带 Bearer
C04/C06 阻断 profile GET 在线及 YAML 都只有泛型 ObjectResult
C07 阻断 ProfileUpdateBody 没有地区字段
C01/C08 前端按后端 PC 实链解决 只调用 /genealogy/pc/region/*;列表按 RegionSelectVoregionCode/regionName/regionLevel 读取,不保留公共路径 fallback
C09 前端按后端 PC 实链解决 SysOssResumableInitVo 明确提供 uploadId/instant/ossId/url/fileName/uploadedChunks,完成响应使用 SysOssUploadVo
C10 前端边界解决 后端初始化 ossId 为 Long、完成响应为 string;浏览器统一转十进制字符串,隐藏回填且不转 Number
C11(备忘录) 本轮按后端 PC 实链解决 YAML 仍只有 stringPC AppMemoServiceImpl 明确校验 completed 只能为 0/1,含义为否/是,前端冻结为未完成/已完成
C13 后续日期模块仍阻断 本阶段上传与区划响应不消费日期;其他模块仍需逐字段核验 Java 日期类型
C17(成长记录) 本轮按后端 PC 实链解决 YAML 响应仍为泛型;PC PcGrowthRecordController 明确返回 GrowthRecordVo,前端只冻结该 PC 响应,不读取 APP 路径
C17(亲友记录) 本轮按后端 PC 实链解决 YAML 响应仍为泛型;PC PcRelativeRecordController 明确返回 RelativeRecordVo,前端只冻结该 PC 响应,不读取 APP 路径
C17(备忘录) 本轮按后端 PC 实链解决 YAML 响应仍为泛型;PC PcMemoController 复用的 PC 支持层明确返回 MemoVo,前端只冻结该 PC 响应,不读取 APP 路径
C17(功德记录) 本轮按后端 PC 实链解决 YAML 响应仍为泛型;PC PcMeritRecordController 复用的 PC 支持层明确返回 MeritRecordVo,前端只冻结该 PC 响应,不读取 APP 路径
C17(消息通知) 本轮按 YAML 详情 DTO 和后端 PC 实链解决 详情为完整 NotificationView;列表导出仍是泛型数组,但 PC 控制器实际返回同一 NotificationVo。前端只接受直接数组,不读取 APP 路径
C20(谱文) 本轮按后端 PC 实链解决 PC 控制器实际具备列表、详情、新增、修改、删除并返回 ArticleVo;页面不再只开放删除
C18 阻断 未说明可选更新字段的省略、null、空串语义
C34 阻断非核心展示 PC 实际未填充 genealogyNo/genealogyName/senderNickName/senderPhone/bizSummary;页面兼容空值并始终隐藏手机号,核心通知读取和已读闭环不依赖这些字段
C35 阻断分类能力 本轮不发送 YAML 未声明的 categoryId query,也不提供手填分类 ID
C36/C37 阻断非核心展示/停用管理 本轮不猜封面 URL,并固定提交 status=0,避免产生不可重读谱文
C20(相册/照片) 本轮按后端 PC 实链接决 PC 控制器具备相册列表、新增、修改、删除和照片列表、新增、删除;页面只从响应取得稳定 ID
C38/C39 阻断非核心展示/停用管理 本轮不猜文件 URL,并固定提交 status=0,避免产生不可重读的相册或照片
C20(祭祀活动/祭品) 本轮按后端 PC 实链接决 PC 控制器具备活动完整 CRUD 和祭品列表、新增、删除;页面只使用响应中的稳定 ID
C16 本轮按后端 PC 实链接决 members/options 返回同一家谱成员及真实 appUserId;管理员邀约名单只允许选择正常且已绑定账号的成员
C15 本轮按后端 PC 实链接决 members/options 是当前家谱真实业务账号的唯一选择源;SPECIFIED 只提交正常且已绑定账号成员的 appUserId
C40/C41 阻断非核心展示/停用管理 本轮不猜封面 URL,并固定提交 status=0,避免产生不可重读活动
C42 阻断金额精度/上限 前端只执行后端已确认的非负校验,不自行限制小数位和最大金额
C43 前端按后端 PC 实链收紧 成员角色选择器只允许 admin/editor/member;不发送 YAML 中后端拒绝的 owner/visitor
C44 阻断非核心 enrichment 页面兼容未填充名称,始终隐藏成员、邀请人手机号和内部用户 ID;核心成员管理不依赖这些字段
C45/C46 阻断 页面不提供世系关系解除,也不把空 lineagePersonId 解释为解绑

阶段 0 验收标准:

  • Apifox 中不存在旧短信路径和双区划路径;
  • 重新导出的 OpenAPI 只包含一套正式契约;
  • 公开与鉴权接口标记正确;
  • 本阶段要实现的每个列表/详情都有明确响应 DTO;
  • 所有枚举、日期和 ID 类型已确定;
  • 将旧输入发送给后端时会明确失败,前端不保留兼容读取。

6. 页面字段分类标准

执行 AI 对每个请求字段都要采用下面一种处理类型:

类型 含义 页面处理
U:用户输入 姓名、标题、正文、手机号等 可见输入框/文本域,展示必填或选填
S:用户选择 枚举、人员、字辈、地区、状态等 单选、下拉、多选、日期或开关;选项必须有真实来源
F:文件派生 OSS ID、文件名、MD5、大小等 用户只选文件;值由上传组件生成并隐藏
A:自动填写 header、租户、上下文 ID、分页、默认值等 页面不可编辑,由统一 owner 注入
R:响应只读 创建时间、计数、发布人、状态文本等 列表、详情、徽标或只读信息
I:内部状态 token、challengeId、validToken、资源 ID 等 仅内存/安全存储/URL 中保存,不显示原值
V:前端校验 确认密码、注销确认文字等 可见但不得发给后端

通用规则:

  1. 必填字段使用明确的必填标识,并在提交前校验。
  2. 可选字段也必须有页面归属;不填写时直接省略,除非 Apifox 明确要求传 null。
  3. 枚举必须使用选择控件,禁止自由文本。
  4. 外键 ID 必须使用搜索/选择控件,禁止“请输入人物 ID”“请输入 OSS ID”。
  5. sortOrderstatus 这类管理字段:
    • 有管理权限时放在“高级设置”;
    • 普通用户使用隐藏默认值;
    • 后端未返回权限时不得自行开放高级设置。
  6. 所有 int64 ID 在浏览器中按字符串保存和比较。
  7. 响应中的 codemsg 由请求层统一处理;业务页只消费 datarows/total

7. 字段、页面和流程规划

7.1 全局自动字段

字段 类型 唯一来源 规则
clientid A ApiClient 配置 每个需要它的请求自动加 Header,不进入表单或 body
Authorization I/A 登录响应 token 仅鉴权接口携带;注册登录等公开接口不携带
tenantId A 环境配置 登录、注册、验证等自动带入,不让用户输入
genealogyId I/A PC 家谱上下文 profile-common.js 读取和传播;缺失时阻止家谱内请求
feedIdcommentIdpersonIdpoemIdarticleIdalbumIdphotoIdvideoIdceremonyIdgiftIdrecordIdrelativeIdmemoIdmeritIdnotificationId I/A 列表/详情响应或 URL 由被点击记录带入,禁止文本框输入
pageNumpageSize A/S 分页组件 页码由组件维护;用户只操作翻页/每页条数
ossId / mediaOssIds F/I 文件上传响应 页面展示预览和文件名,隐藏保存 ID
sortOrder S/A 高级设置或默认值 不得把空字符串转成 0;未填写时省略
status S/A 权限化状态选择或默认值 枚举 0=正常、1=停用;不得把 1 标成“草稿”

7.2 验证中心与认证登录

页面字段矩阵

字段 必填性 类型 页面/流程 处理
operationCode 必填 path A 所有认证动作 页面动作固定为 password-loginsms-loginregisterforgot-passwordphone-changeaccount-deactivate
clientid 必填 header A 所有认证请求 ApiClient 自动注入
tenantId 必填 A 所有登录/验证表单 环境配置自动注入
subject require 可选,challenge/verify 必填 A 验证流程 从当前手机号/账号派生,用户不重复填写
grantType 必填 A 注册、登录、短信、找回 密码动作固定 password,短信动作固定 sms
phone 必填 U 登录、注册、找回、换绑 手机号输入和格式校验
password 必填 U/A 密码登录、注册 用户输入明文,提交前生成 32 位 MD5;日志不得记录
oldPassword 必填 U/A 修改密码 同上
newPassword 必填 U/A 修改/重置密码 同上
confirmPassword 前端字段 V 注册、修改、找回 只比较一致性,不发送
smsCode 必填 U 短信登录、注册、找回、换绑、注销 4 位验证码输入
nickName 可选 U 注册 昵称输入
registerSource 可选 A 注册 当前端固定 PCApifox 需确认枚举
validToken 条件必填 I/A 密码登录、发送短信 验证成功后仅存内存,使用一次即清除
challengeId 必填 I/A 验证校验 挑战响应自动回填
providerCodecaptchaType 可选 A 验证校验 挑战响应决定,用户不可修改
payload.track 条件必填 A 天爱验证码 控件原样生成轨迹、尺寸和时间
payload.uuid 条件必填 I/A 系统图形验证码 挑战响应回填
payload.code 条件必填 U 系统图形验证码 用户输入图片答案

天爱控件产生的嵌套字段全部属于 A,不得另做表单让用户填写:

  • bgImageWidthbgImageHeight:控件实际显示尺寸,必填;
  • templateImageWidthtemplateImageHeight:模板实际显示尺寸,可选;
  • startTimestopTime:操作开始和结束毫秒时间戳,必填;
  • lefttop:控件最终偏移,可选;
  • trackList:必填轨迹数组;
  • 每个轨迹点的 xyttype 均由控件生成;
  • data:不同验证码类型的扩展数据,原样提交。

验证和登录响应字段:

响应字段 类型 页面处理
required R/A 决定是否进入挑战流程
providerCodecaptchaType I/A 选择正确验证码控件
sceneCode I/R 服务端解析结果,可用于只读诊断;不得回传
ttlSecondsexpireSeconds R/A 倒计时和过期重试
challengeIduuid I 只在当前挑战内保存
img R 系统图形验证码图片
payload I/A 天爱控件初始化数据
passed R/A 决定校验成功或失败
validToken I 一次性票据,不显示、不落长期存储
message R 安全地显示验证结果
access_token string / I 登录接口 data;密码或短信登录成功时立即保存,后续仅用于 Bearer 鉴权
expire_in integer / I/R 登录接口 data;登录成功时取得,可用于会话到期提示,不由用户填写
client_idclientKeydeviceTypeuserType string / I/R 登录接口 data;登录成功时取得,仅作会话上下文或诊断,不回传为用户输入
profile object / R 登录接口 data.profile;登录成功后取得,可用于页面只读展示或资料页初始回填
profile.userIdprofile.tenantIdprofile.userNo integer/string、string、string / I/R 后端自动产生;不得让用户手工填写,业务 ID 超出 JS 安全整数时保持字符串
profile.phoneprofile.nickNameprofile.realNameprofile.email string/null / R 后端用户资料;登录成功后只读展示或作为资料页回填,编辑时仍只提交 ProfileUpdateBody 允许字段
profile.avatar integer/string/null / R 后端头像 OSS ID;只读回填,用户换头像必须经文件选择和上传组件产生,禁止手填 OSS ID
profile.sex enum 0/1/2 / R 后端用户资料;页面映射男/女/未知
profile.birthday date/null / R 后端用户资料;页面按日期展示
profile.registerSourceprofile.loginIpprofile.loginDate string/null / R/I 后端自动产生;只读或内部诊断,不作为表单输入
profile.status string / R/I 后端账号状态;只读或内部诊断,不作为表单输入
profile.clientKeyprofile.deviceType string / I/R 后端登录上下文;只读或内部诊断

认证业务流程

密码登录:

  1. 用户输入手机号和密码。
  2. password-login + tenantId + phone 调用 require
  3. required=false,直接提交密码登录。
  4. 若需要验证,调用 challenge,展示服务端指定控件,再调用 verify。
  5. 得到 validToken 后与 MD5 密码一起登录。
  6. 成功后只读取并保存 data.access_tokentokenaccessTokentokenValue 均视为非法旧响应,不做兼容读取。

短信类动作:

  1. 用户输入手机号。
  2. 按当前动作完成 require → challenge → verify。
  3. 把一次性 validToken 提交给发送短信接口。
  4. 用户输入短信码后执行短信登录、注册、找回、换绑或注销。
  5. validToken 不进入最终注册、短信登录、换绑或注销 body,除非 Apifox 明确修改契约。

个人资料字段

ProfileUpdateBody 的所有字段必须进入 profile-data.html

字段 必填性 类型 控件
nickName 可选 U 文本,最长 30
realName 可选 U 文本,最长 30
avatar 可选 F/I 图片上传、预览、删除;隐藏保存 OSS ID
sex 可选 S 男 0、女 1、未知 2,三项都要有
birthday 可选 S 日期选择器,yyyy-MM-dd
email 可选 U email 输入,最长 100

现有页面整改点:

  • 当前 avatarOssId 字段名与请求契约 avatar 不一致;
  • 补齐 YAML 中 avatar 仍是 integer<int64>,但示例值已超过 JavaScript 安全整数范围;浏览器边界必须按十进制字符串保留精度,且只能由上传响应自动回填,不能转 Number 或让用户手填;
  • 缺少 realNameemail 和性别“未知”;
  • 页面现居地区、父亲、微信/QQ、学历/职业不在 ProfileUpdateBody,不得混入保存请求;
  • 在后端增加地区字段前,“保存地区”按钮必须关闭或改成纯查询演示;
  • GET /auth/profile 必须补齐 ProfileView 后才能严格回填。

7.3 文件上传

用户在任何业务页只操作“选择文件、取消、重试”;下面字段全部自动产生:

阶段 字段 必填性 类型 来源
初始化 uploadId 必填 I/A 客户端生成一次并贯穿全过程
初始化 fileName 必填 F File.name
初始化 fileMd5 必填 F 文件内容计算
初始化 totalSize 必填 F File.size
初始化 totalChunks 必填 F 根据大小和分片大小计算
初始化 chunkSize 必填 A 上传组件统一配置,默认示例 4 MiB,最后一片除外
初始化 contentType 可选 F File.type
分片 chunkIndex 必填 A 上传循环生成
分片 chunkMd5 必填 F 当前分片计算
分片 file 必填 F 当前 Blob
完成 uploadId/fileName/fileMd5/totalSize/totalChunks 必填 I/A/F 必须与初始化一致

响应处理:

  • FileUploadVo.ossIdI,隐藏写入业务表单;
  • urlthumbnailUrlR,用于预览;
  • fileNameoriginalNameR,用于文件列表;
  • 初始化 instant=true 时直接读取 ossId/url/fileName 完成秒传;instant=false 时使用服务端 uploadIduploadedChunks 跳过已上传分片;
  • 初始化 Long ossId 和完成响应 string ossId 均在浏览器边界转为十进制字符串;
  • 上传成功但业务保存失败时,当前契约没有释放引用接口,必须让后端补充生命周期规则。

统一由 public/js/upload-pages.js 管理分片、进度、重试、取消、MD5 和隐藏 ID。各业务页面不得复制上传算法,也不得出现“请输入 OSS ID”的可见输入框。

7.4 家谱上下文与配额

GET /genealogy/pc/genealogies/quota 只负责在 profile-families.html 展示:

响应字段 类型 页面呈现
createUsedcreateLimitcreateRemaining R 创建额度已用/上限/剩余
canCreate R 控制“创建家谱”是否可用
joinUsedjoinLimitjoinRemaining R 加入额度已用/上限/剩余
canJoin R 控制“加入家谱”是否可用

-1 显示为“不限”,不能参与普通减法或显示负数。

配额响应不包含 genealogyId,不能替代“我的家谱”。当前由 GET /genealogy/pc/genealogies/mine 返回完整 AppGenealogyVo

  • profile-families.html 从真实列表生成家谱入口;
  • genealogyId 在浏览器边界保持字符串,并由 profile-common.js 统一读取和传播;
  • 所有家谱内页面缺少真实 genealogyId 时必须阻止请求并回到家谱选择入口;
  • 不显示静态家谱卡片,不从 APP 接口获取家谱,不允许用户手工输入家谱 ID;
  • 切换家谱通过进入新的带 genealogyId URL 完成整页导航,旧页面模块状态不会复用。

7.5 行政区划

本 PC 前端只实现 /genealogy/pc/region/*,不调用重复的 /genealogy/region/*,也不保留 fallback。

字段 必填性 类型 页面处理
parentCode 可选 query A/S 省级不传;选择上一级后自动查询下级
regionCode 必填 path I/A 从被选择的区划记录带入
keyword 必填 query U 搜索框
level 可选 query S 1 省、2 市、3 区县、4 乡镇街道、5 村社区
limit 可选 query A 搜索组件固定合理上限,不让用户自由输入
clientid 可选 header A 统一请求层注入

真实 Java RegionSelectVo 已明确 regionCoderegionNameregionLevel 等字段。个人资料当前仍没有可保存的地区字段,因此区划组件只提供级联、搜索和路径回显,不提交到资料更新接口。

7.6 家族圈

页面归属:

  • profile-feed.html:分页列表、点赞、轻量评论;
  • profile-feed-edit.html:新增和编辑;
  • 新增 profile-feed-detail.html:详情、完整评论树、回复、通知跳转和分享深链。

写入字段

字段 必填性 类型 页面处理
genealogyId 必填 path I/A 家谱上下文
feedId 详情/修改/删除必填 I/A 列表记录或 URL
feedType 可选 A 或 S 当前默认隐藏 textApifox 补枚举后才能改成选择
feedContent 必填 U 正文编辑器
mediaOssIds 可选 F/I 多文件上传结果拼成英文逗号串,用户只看缩略图
sortOrder 可选 S/A 管理员高级设置;普通发布默认省略/0
status 可选 S/A 0 正常、1 停用;不得显示为“发布/草稿”
parentCommentId 可选 I/A 点击“回复”后自动带入;一级评论省略或 null
commentContent 必填 U 评论输入,最多 1000 字
pageNum/pageSize 可选 A/S 分页组件

动态响应字段

字段 页面处理
feedIdgenealogyId I,用于路由和后续操作
genealogyNogenealogyName R,详情来源信息
publisherUserId I,用于权限判断,但不能单独代替后端鉴权
publisherNickNamepublisherStatus R,发布人和状态
feedTypefeedContent R,类型和正文
mediaOssIds I/F,解析后通过文件 URL 规则展示,不直接显示 ID
likedByMe R,决定点赞按钮状态
likeCountcommentCount R,计数
pinnedpinnedTime R,置顶徽标和时间
sortOrderstatus R/管理信息
remark R,仅在产品确认需要时展示,不能当正文
createTimeupdateTime R,发布时间和编辑时间

评论响应字段:

  • commentIdgenealogyIdfeedIdparentCommentIdappUserIdparentAppUserIdI
  • appUserNickNameappUserAvatarparentAppUserNickNameR
  • commentContentR;为 null 且 userDeleted=1 时显示“该评论已删除”占位;
  • replyCountR,控制“展开回复”;
  • commentLevelRrootreply
  • statuscreateTimeR。

流程:

  1. 列表首屏调用分页接口,不同时调用非分页接口重复取数。
  2. 点击记录进入详情,以 genealogyId + feedId 取详情。
  3. 一级评论调用 comments 分页;回复只调用对应 comment 的 replies 分页。
  4. 点赞、取消、评论、删除成功后以接口返回和重新读取结果校正计数。
  5. 删除有回复的评论后保留占位,不从 DOM 直接移除整棵回复。

2026-07-28 家族圈实施状态:

  • ApiClient 的 14 个家族圈 PC 操作已由契约测试锁定;页面首屏只调用 /feeds/page,评论和回复分别调用各自的 /page
  • 已新增 profile-feed-detail.html,以 genealogyId + feedId 形成稳定详情深链;列表、详情和编辑链接都保留字符串 ID。
  • 列表和详情消费 AppFamilyFeedVo 的发布人、点赞状态与计数、评论计数、置顶、状态和时间字段;评论消费 FamilyFeedCommentVo 的归属、父评论、层级、删除占位、回复计数和时间字段。
  • GET /genealogy/pc/genealogies/{genealogyId}canEditContent/canManage 控制编辑和高级设置,GET /genealogy/pc/auth/profileuserId 结合响应中的发布人/评论人 ID 控制本人删除按钮;后端仍执行最终权限校验。
  • 发布图片只允许文件选择;mediaOssIds 为隐藏的上传派生字段,多文件结果使用英文逗号连接,不允许手填 OSS ID。
  • 新增、修改、点赞、取消点赞、评论和删除均有同资源动作锁;成功后重新读取详情、分页列表或评论分页以校正页面状态。
  • status=1 使用后端定义的“停用”语义,不再显示为“草稿”。C21、C22 未解决前,图片缩略图回显和停用记录恢复仍属于后端阻断,不宣称这两项闭环完成。
  • 已在真实 Chrome 登录态验证:当前账号的 /genealogies/mine 返回空列表;无家谱上下文时家族圈不发业务请求,所有发布入口统一改写到 profile-families.html?next=profile-feed-edit.html。发布表单实测为多文件选择、隐藏 OSS ID、普通用户隐藏且禁用管理字段。由于账号没有家谱,本轮不能进行真实动态列表/详情读取或写操作联调。

7.7 字辈谱

profile-generation.html 同时提供“单条维护”和“批量维护”。

单条字段:

字段 必填性 类型 控件
generationNo 必填 U/S 正整数世代序号
generationText 必填 U 最长 50
description 可选 U 文本域,最长 500
sortOrder 可选 U/S 管理员高级数字字段
status 可选 S 0 正常、1 停用
poemId 修改必填 path I/A 列表记录

批量字段:

字段 必填性 类型 控件
poemText 必填 U 文本域,最长 26000;支持合同中列出的分隔符
disableMissing 可选 S 复选框,必须有“将停用后续世代、不删除历史”的确认说明

批量流程必须是 preview → 用户检查 → save

  • 预览展示 createCountupdateCountkeepCountdisableCount
  • 逐项结果来自 items;每项展示 generationNooldGenerationTextnewGenerationTextoldStatusnewStatusactionwarning
  • poemIdgenealogyId 是内部字段;
  • 保存前再次确认,因为服务端会基于最新数据重新计算差异。

普通展示列表使用正常字辈接口;管理页面使用 management 接口以包含停用项。

当前实现状态:

  • 页面先读取家谱详情,以 canEditContent 决定调用正常列表还是 management 列表;无维护权限时不渲染新增、编辑、停用和批量维护控件,后端继续执行最终权限校验。
  • genealogyId 只来自家谱上下文,poemId 只来自列表响应;所有业务 ID 在浏览器边界保持字符串,不提供手工 ID 输入。
  • 单条新增、修改和状态切换成功后重新读取列表;批量维护严格执行 preview → 当前请求体签名确认 → save → 重新读取列表。
  • 批量预览逐项校验 action、状态、必需的新旧文本和内部 ID,并核对四类汇总计数;勾选 disableMissing 时保存确认明确说明只停用后续世代、不删除历史。
  • 已在真实 Chrome 登录态验证无家谱上下文分支:不发送字辈业务请求,新增按钮和批量面板隐藏,家谱上下文入口统一返回家谱选择页。当前账号家谱列表为空,因此正常/management 列表、单条写入和批量写入仍缺少真实家谱数据联调证据。

7.8 世系人物

全部操作集中在 profile-tree.html,详情和编辑可使用抽屉/弹窗,但所有字段都要有明确控件。

字段 必填性 类型 页面处理
bindingMode 必填 S NONE 不绑定、SELF 当前账号、SPECIFIED 指定账号
appUserId SPECIFIED 时必填 S/I 从当前家谱 members/options 的正常且已绑定账号成员中选择;禁止文本 ID
personNo 可选 U/A 高级设置可填;留空由服务端生成
name 必填 U 姓名
aliasName 可选 U 别名/曾用名
sex 可选 S 0 男、1 女、2 未知
generation 可选 S/I 从正常字辈列表选择世代
generationName 可选 A/R 随字辈选项自动回填并只读显示
fatherId 可选 S/I 世系人物搜索选择器
motherId 可选 S/I 世系人物搜索选择器
avatarOssId 可选 F/I 上传头像自动回填
birthDate 可选 S date-time 选择器
birthLunar 可选 S 0 公历、1 农历开关
birthPlace 可选 U 出生地文本
deathDate 可选 S date-time 选择器
deathLunar 可选 S 0 公历、1 农历开关
deathPlace 可选 U 逝世地
burialPlace 可选 U 安葬地
personStatus 可选 S 0 健在、1 已故、2 未知
biography 可选 U 人物简介
sortOrder 可选 U/S 管理高级设置
remark 可选 U 备注
relationName 可选 U 仅“添加配偶”快捷流程显示

人物响应字段按以下方式使用:

  • personIdgenealogyIdappUserIdfatherIdmotherIdavatarOssIdI
  • genealogyNamegenealogyNoR
  • appUserNickNameR,显示绑定账号;
  • personNonamealiasNamesexgenerationgenerationNameR/编辑回填;
  • fatherNamemotherNamespouseNamesR
  • 出生、逝世、安葬、状态、简介、备注、排序字段:R/编辑回填。

关系流程:

  1. 先选中一个现有 personId 作为关系锚点。
  2. 点击父母、子女、兄弟姐妹或配偶。
  3. 打开完整 LineagePersonBody 表单,创建的是一个新人物并建立关系,不是绑定两个现有人物 ID。
  4. 配偶流程才显示 relationName
  5. 当前没有解除关系接口,页面不得伪造“解除关系”。
  6. DELETE 是逻辑停用;存在正常子女时可能失败,确认文案不能写成物理删除。

列表筛选:

  • keywordU,搜索姓名、别名或人物编号;
  • generationS,从字辈接口选择;
  • personStatusS0/1/2
  • pageNum/pageSize:分页组件自动维护。

LineagePersonTreeView 补全前,不得继续依靠多个字段 fallback 猜树结构。

当前实现状态:

  • 已接入 PC 世系树、普通列表、分页列表、人物选项、详情、新增、修改、逻辑停用,以及父母、子女、兄弟姐妹、配偶四类关系新增;成功写入后统一重新读取树、列表、分页和选项,返回稳定 personId 时再读取详情。
  • 页面先读取家谱详情,canEditContent 只控制新增、编辑、停用和关系维护;树、列表、详情、筛选和分页保持只读可用,后端继续执行最终查看和编辑权限校验。
  • LineagePersonBody 的全部字段均有明确来源:世代从正常字辈列表选择并自动回填字辈,父母从世系人物选项选择,头像通过统一上传组件产生隐藏 avatarOssId,所有业务 ID 在浏览器边界保持字符串且不可手填。
  • 新增和编辑人物开放 NONESELFSPECIFIEDSPECIFIED 选择器只消费当前家谱 members/options,过滤未绑定账号、停用成员和当前账号,不显示手机号,不允许手填 appUserId
  • 编辑已绑定其他账号的人物时,用详情响应的 appUserId 精确匹配同一成员选项;真实选项不存在时不伪造回填,保存会被前端校验阻止。
  • 分页查询已接入 keywordgenerationpersonStatuspageNum/pageSize;详情展示家谱、绑定账号、父母、配偶、出生、逝世、安葬、人物状态、简介和备注等响应字段。
  • DELETE 确认明确使用“停用”语义,并提示存在正常子女时后端会拒绝;页面没有伪造解除关系或物理删除。
  • 已在真实 Chrome 登录态验证无家谱上下文分支:不发送世系业务请求,读区域显示选择家谱提示,新增、关系维护和完整表单隐藏,分页与配偶专用字段不误显示,所有家谱链接返回家谱选择页。当前账号家谱列表为空,因此真实树、列表、详情和写操作仍缺少有数据账号联调证据。
  • C18 仍适用于本模块:可选字段清空语义未明确,本轮仅提交非空值,不宣称可选字段清空闭环。
  • SPECIFIED 账号绑定相关聚焦测试 42/42 通过;真实账号页面验证统一留到阶段 6 收尾执行。

7.9 视频

计划新增 profile-video-edit.htmlprofile-video.html 负责列表。

字段 必填性 类型 页面处理
videoTitle 必填 U 标题
videoDesc 可选 U 说明文本域
coverOssId 可选 F/I 封面上传、预览、隐藏 ID
videoOssId 必填 F/I 视频文件上传;不得输入 ID
durationSeconds 可选 F/A/R 从视频元数据读取,只读显示
sortOrder 可选 U/S 管理高级设置
status 可选 S 0 正常、1 停用
genealogyIdvideoId path I/A 上下文和记录

流程:选视频 → 分片上传 → 得到 videoOssId → 可选封面上传 → 填标题说明 → 保存 → 重新读取详情。

YAML 的视频响应仍使用泛型 ObjectResult / ListResult,但后端已存在独立 PcVideoController,其 PC method/path 与 YAML 一致,并明确返回 VideoVo。根据本轮“后端源码可作为可靠补充契约”的约定,页面响应字段由该 PC 控制器及 VideoVo 冻结:

  • IvideoIdgenealogyIdcoverOssIdvideoOssIdpublisherUserId
  • RgenealogyNogenealogyNamesurnamepublisherNickNamepublisherPhonepublishTimeviewCountremark
  • U/RvideoTitlevideoDesc
  • F/A/RdurationSeconds
  • U/S/RsortOrder
  • A/Rstatus,当前固定提交 0

当前接入状态:

  • profile-video.html 已接入正常视频列表、详情读取、权限化编辑/删除入口、空错状态和无家谱上下文分支;
  • 新增 profile-video-edit.html,新增和修改只提交 VideoBody 七个字段;视频与封面都通过统一分片上传产生隐藏 OSS ID,不允许手填;
  • 选择视频文件后由浏览器媒体元数据自动读取时长,durationSeconds 只读;
  • 保存成功后使用稳定 videoId 重新读取详情,再返回列表;删除确认明确会释放视频和封面文件引用,删除后重读列表;
  • 后端 BigNumberSerializer 对超出 JavaScript 安全整数范围的 Long 输出字符串,对安全整数输出 number;前端接受两种输入并统一保留为字符串;
  • C23 未解决前只显示文件“已上传”,不猜测 OSS URL,不宣称播放或封面预览完成;
  • C24 未解决前不开放 status=1,避免产生无法重新读取和恢复的停用视频;
  • 2026-07-29 已在真实登录 Chrome 验证无家谱上下文:视频列表不发业务请求,发布入口及编辑表单保持隐藏,所有上下文链接返回家谱选择页,控制台无错误。当前账号没有家谱,真实列表、详情、上传和 CRUD 写入仍待有数据账号验证。

7.10 贺礼邀约与祭祀

邀约字段:

字段 必填性 类型 页面处理
inviteeUserIds 必填 S/I 家谱成员多选;提交完整名单,空数组表示取消全部未响应邀请
inviteStatus 必填 S 当前用户只能选择 ACCEPTED 接受或 DECLINED 拒绝
genealogyIdceremonyId path I/A 活动上下文

邀约响应在 profile-gift.html 展示:

  • invitationIdgenealogyIdceremonyIdinviteeUserIdI
  • inviteStatusRPENDING/ACCEPTED/DECLINED/CANCELED 徽标;
  • inviteVersionI/R,只在管理审计需要时显示;
  • deliveredTimereadTimeresponseTimeR
  • ceremonyTitleceremonyTimelocationlocationAddressR
  • longitudelatitude:地图定位内部值,页面显示地图/地址而非原始数字。

“我的邀请”接口有完整响应,可独立实现接受/拒绝流程。管理端替换受邀人依赖 C16,且必须先有真实活动 ID。

当前接入状态:profile-gift.html 已使用 GET /genealogy/pc/genealogies/ceremony-invitations/mine 展示当前账号的邀请列表和响应内详情;仅 PENDING 邀请显示接受/拒绝,并向 PUT /genealogy/pc/genealogies/{genealogyId}/ceremonies/{ceremonyId}/invitations/me 提交唯一字段 inviteStatus,成功后重读列表。内部 ID 和坐标不直接展示,坐标仅用于生成地图链接。2026-07-29 使用真实账号联调,PC “我的邀请”接口成功返回空数组,页面空状态和鉴权正常;由于当前账号没有待响应邀请,真实接受/拒绝写入仍待有邀请数据时复核。后端仓库中的同组 AppCeremonyController 仍以 /genealogy/app/genealogies 为基础路径,与冻结 YAML 的 /genealogy/pc 不一致,但线上 PC mine 路径已实际可用,前端继续以 YAML 为唯一契约,不回退 APP 路径。

当前没有祭祀活动列表、详情、新增、修改和献礼列表/新增接口。现有 profile-gift-edit.html 中的 ceremonyTypeceremonyTitleceremonyTimelocationceremonyDesccoverOssId 不属于任何现有 PC 写入 DTO,必须继续保持禁用,不得向猜测路径提交。

两条删除接口只能在后端补齐列表和详情、产生稳定 ID 后开放:

  • 删除活动是逻辑删除活动及祭品并释放封面引用;
  • 删除祭品只操作被选中的真实 giftId
  • 删除确认必须说明影响范围。

7.11 成长记录

页面:profile-growth.htmlprofile-growth-edit.html

字段 必填性 类型 页面处理
lineagePersonId 可选 S/I 世系人物搜索选择器,禁止 ID 输入框
recordType 可选 U 或 S C12 未解决前按 Apifox 明确结果决定,不能猜枚举
recordTitle 必填 U 标题
recordContent 可选 U 正文编辑器
recordDate 可选 S 日期控件,等待 C13 明确格式
remindTime 可选 S 日期时间控件
mediaOssIds 可选 F/I 多附件上传
sortOrder 可选 U/S 管理高级设置
status 可选 A 当前固定提交 0 正常;C26 解决前不开放 1 停用

YAML 的列表、详情、新增和修改响应仍是泛型对象,但后端已存在独立 PcGrowthRecordController,其 PC method/path 与 YAML 一致,并明确返回 GrowthRecordVo。根据本轮“后端源码可作为可靠补充契约”的约定,页面响应字段由该 PC 控制器及 GrowthRecordVo 冻结:

  • IrecordIdgenealogyIdappUserIdlineagePersonIdmediaOssIds
  • RgenealogyNogenealogyNamesurnameappUserNickNameappUserPhonelineagePersonNolineagePersonNameremark
  • U/RrecordTyperecordTitlerecordContent
  • S/RrecordDateremindTime
  • U/S/RsortOrder
  • A/Rstatus,当前固定提交 0

当前接入状态:

  • profile-growth.html 已接入当前账号成长记录列表、详情、编辑和删除入口;列表接口不传后端额外的 all 参数,只消费当前 YAML 声明的请求;
  • profile-growth-edit.html 已接入新增和修改;lineagePersonId 只从真实世系人物选项接口选择,recordId 只来自列表响应或 URL,均按字符串处理且不能手填;
  • recordType 后端 DTO 和服务均为不带枚举的自由字符串,因此保留可选文本输入;recordDate 提交 yyyy-MM-ddremindTimedatetime-local 转为后端 Date 接受的 yyyy-MM-dd HH:mm:ss
  • 多附件通过统一分片上传产生隐藏 mediaOssIds,支持保留、追加和清除附件选择,不显示 OSS ID;
  • 新增和修改成功后必须使用稳定 recordId 重读同一条详情并校验身份,再返回列表;删除成功后重读列表,确认文案明确逻辑删除且会释放附件引用;
  • C18 未解决前,标题以外可选文本、人物和日期字段清空不宣称闭环;前端对空可选字段保持省略,附件清除使用后端已明确的空引用处理;
  • C25 未解决前只显示附件数量,不猜测 OSS URL、文件名或下载地址;C26 未解决前固定 status=0,不产生无法重新读取和恢复的停用记录;
  • 2026-07-29 已在真实登录 Chrome 验证无家谱上下文:列表和详情不发成长记录业务请求,编辑表单及页头保存按钮隐藏,入口统一返回家谱选择页。当前账号没有家谱,真实列表、详情、世系选项、上传和 CRUD 写入仍待有数据账号验证。

7.12 亲友记录

页面:profile-relative.htmlprofile-relative-edit.html

字段 必填性 类型 页面处理
relativeName 必填 U 亲友姓名
relationName 可选 U 关系名称
eventName 可选 U 事件名称
eventTime 可选 S 日期时间选择器
giftAmount 可选 U 金额输入;只提交 JSON 序列化后数值不变的有限数字,C27 解决前不猜精度、范围或非负规则
recordContent 可选 U 内容
mediaOssIds 可选 F/I 多附件上传
sortOrder 可选 U/S 管理高级设置
status 可选 A 当前固定提交 0 正常;C29 解决前不开放 1 停用

YAML 的列表、详情、新增和修改响应仍是泛型对象,但后端已存在独立 PcRelativeRecordController,其 PC method/path 与 YAML 一致,并明确返回 RelativeRecordVo。根据本轮“后端源码可作为可靠补充契约”的约定,页面响应字段由该 PC 控制器及 RelativeRecordVo 冻结:

  • IrelativeIdgenealogyIdappUserIdmediaOssIds
  • RgenealogyNogenealogyNamesurnameappUserNickNameappUserPhoneremark
  • U/RrelativeNamerelationNameeventNamerecordContent
  • S/ReventTime
  • U/RgiftAmount,后端 BigDecimal 响应按字符串保留;
  • U/S/RsortOrder
  • A/Rstatus,当前固定提交 0

当前接入状态:

  • profile-relative.html 已接入当前账号亲友记录列表、详情、编辑和删除入口;列表接口不传后端额外的 all 参数,只消费当前 YAML 声明的请求;
  • profile-relative-edit.html 已接入新增和修改;relativeId 只来自列表响应或 URL,按字符串处理且不能手填;
  • eventTime 使用 datetime-local,提交前转为后端 Date 接受的 yyyy-MM-dd HH:mm:ss,并校验真实月日和时分秒;
  • giftAmount 请求按 YAML 的 number 提交;提交前比较用户十进制输入与 JSON.stringify(Number(value)) 的精确数值,序列化会改值的超大或高精度金额直接拒绝。后端 BigDecimal 响应按原字符串展示,不转回 Number
  • 多附件通过统一分片上传产生隐藏 mediaOssIds,支持保留、追加和清除附件选择,不显示 OSS ID;
  • 新增和修改成功后必须使用稳定 relativeId 重读同一条详情并校验身份,再返回列表;删除成功后重读列表,确认文案明确逻辑删除且会释放附件引用;
  • C18 未解决前,可选文本、时间和金额字段的清空不宣称闭环;附件清除使用后端已明确的空引用处理;
  • C27 未解决前不增加两位小数、最大金额或非负限制;C28 未解决前只显示附件数量;C29 未解决前固定 status=0,并拒绝编辑停用响应,避免意外恢复;
  • 2026-07-29 已在真实登录 Chrome 验证无家谱上下文:列表和详情不发亲友记录业务请求,编辑表单及页头保存按钮隐藏,入口统一返回家谱选择页。当前账号没有家谱,真实列表、详情、上传和 CRUD 写入仍待有数据账号验证。

7.13 备忘录

页面:profile-memo.htmlprofile-memo-edit.html

字段 必填性 类型 页面处理
memoTitle 必填 U 标题
memoContent 可选 U 内容
remindTime 可选 S datetime-local 选择,提交为 yyyy-MM-dd HH:mm:ss 并校验真实日期
completed 可选 S PC 后端已核验:0 未完成、1 已完成;创建默认 0
mediaOssIds 可选 F/I 多附件上传自动产生;隐藏保存,允许追加和清除,不允许手填
sortOrder 可选 U/S 安全整数;创建默认 0
status 可选 I/A 页面固定隐藏提交 0;不开放不可重读的停用状态

PC MemoVo 响应字段及页面用途:

字段 类型 标记 页面处理
memoIdgenealogyIdappUserId Long I 仅从 PC 响应取得并按十进制字符串保存;用于详情、编辑、删除和写后重读,不显示、不手填
genealogyNogenealogyNamesurname string R 家谱上下文只读信息;当前备忘录页不重复展示
appUserNickName string R 详情显示记录人
appUserPhone string I 隐私字段,不渲染
memoTitlememoContentremindTimecompleted string R 列表摘要、详情展示和编辑回填
mediaOssIds string I 只统计附件数量并回填隐藏上传字段,不暴露原始 OSS ID
sortOrder Long I 编辑回填;列表顺序由后端负责
status string I 仅接受正常记录 0;停用响应拒绝进入编辑器
remark string R 详情只读展示,MemoBody 不含此字段,因此不提交

completed 表示业务完成状态,status 表示记录正常/停用,两者不能合并。列表、详情、新增、修改和删除只调用 /genealogy/pc/genealogies/{genealogyId}/memos 及其 /{memoId} 子路径;列表不发送后端管理专用的 all 查询。新增/修改成功后使用稳定 memoId 重读同一详情,删除后重读列表。

  • C18 未解决前,可选内容和提醒时间的清空不宣称闭环;附件清除使用后端已明确的空引用处理;
  • C30 未解决前只显示附件数量;C31 未解决前固定 status=0,拒绝编辑停用响应,避免意外恢复;
  • 2026-07-29 已在真实登录 Chrome 验证无家谱上下文:列表和详情显示明确提示,编辑表单及页头保存按钮隐藏,控制台无错误。当前账号没有可用家谱,真实列表、详情、上传和 CRUD 写入仍待有数据账号验证。

7.14 功德记录

页面:profile-merit.htmlprofile-merit-edit.html

字段 必填性 类型 页面处理
donorName 必填 U 功德人姓名
meritType 可选 S donation 捐赠、repair 修祠、public 公益、other 其他
meritTitle 必填 U 标题
meritContent 可选 U 内容
amount 可选 U YAML number;提交前拒绝 JSON 序列化会改变精确数值的输入,不自行限制小数位、范围或正负
meritTime 可选 S datetime-local 选择,提交为后端示例和 Date 接受的 yyyy-MM-dd HH:mm:ss
sortOrder 可选 U/S 安全整数;创建默认 0
status 可选 I/A 页面固定隐藏提交 0;不开放不可重读的停用状态

PC MeritRecordVo 响应字段及页面用途:

字段 类型 标记 页面处理
meritIdgenealogyIdappUserId Long I 仅从 PC 响应取得并按十进制字符串保存;用于详情、编辑、删除和写后重读,不显示、不手填
genealogyNogenealogyNamesurname string R 家谱上下文只读信息;当前功德页不重复展示
appUserNickName string R 详情显示记录人
appUserPhone string I 隐私字段,不渲染
donorNamemeritTypemeritTitlemeritContent string R 列表摘要、详情展示和编辑回填;HTML 内容转义后展示
amount BigDecimal R 按响应原始字符串展示,不转回 Number
meritTime Date R 列表、详情展示和 datetime-local 编辑回填
sortOrder Long I 编辑回填;列表顺序由后端负责
status string I 仅接受正常记录 0;停用响应拒绝进入编辑器
remark string R 详情只读展示,MeritRecordBody 不含此字段,因此不提交

现有页面中的契约外 service 已删除,补齐 repairpublic;由于 MeritRecordBody 没有附件字段,功德页不借用其他模块的 mediaOssIds 或上传控件。ApiClient 的新增和修改方法再次按 8 个 YAML 字段白名单过滤,调用者额外传入 appUserIdmediaOssIds 等字段也不会发送。

  • 列表、详情、新增、修改和删除只调用 /genealogy/pc/genealogies/{genealogyId}/merit-records 及其 /{meritId} 子路径;
  • 新增/修改成功后使用稳定 meritId 重读同一详情,删除成功后重读列表;
  • C18 未解决前,可选内容、金额和时间的清空不宣称闭环;C32 未解决前不增加两位小数、最大金额或非负限制;C33 未解决前固定 status=0 并拒绝编辑停用响应;
  • PC 写操作最终由 assertCanEditContent 鉴权;当前 View 没有 canEdit/canDelete,页面保留操作入口并明确处理 403,不猜角色字段;
  • 2026-07-29 已在真实登录 Chrome 验证无家谱上下文:列表和详情显示明确提示,编辑表单及页头保存按钮隐藏,契约外类型和附件控件不存在,控制台无错误。当前账号没有可用家谱,真实列表、详情和 CRUD 写入仍待有数据账号验证。

列表、详情、新增和修改仍是泛型响应。补齐 MeritRecordView 后再开放完整 CRUD。

7.15 消息通知

页面:profile-messages.html

接口冻结:

  • GET /genealogy/pc/notifications:可选 query readStatus=0|1,返回非分页直接数组;全部通知时省略 query。
  • GET /genealogy/pc/notifications/unread-count:返回非负 int64 未读数量。
  • GET /genealogy/pc/notifications/{notificationId}:读取当前账号可见的正常通知详情。
  • POST /genealogy/pc/notifications/{notificationId}/read:将当前账号的一条正常未读通知标记已读。
  • POST /genealogy/pc/notifications/read-all:将当前账号全部未读通知标记已读。
  • 五个接口均由 ApiClient 自动携带 Bearer 和 clientid;页面不采集 Header。YAML 未声明业务错误码;前端统一处理未登录/401、403、404、业务失败和网络失败。
字段 必填性 / 类型 标记 页面用途、来源与提交时机
query readStatus 可选 string;枚举 0/1 S 消息页筛选选择;全部=省略、未读=0、已读=1;切换筛选时提交
path notificationId 详情/单条已读必填 int64 I/A 从列表响应的稳定十进制字符串取得;点击详情或“标记已读”时自动进入 path,不允许手填或转 Number
notificationId 响应 int64 I 列表行内部关联详情和已读动作;不在可见页面展示
genealogyId 响应 int64,可空 I 仅保留为响应内部上下文;不展示、不提交、不允许手填
genealogyNo 响应 string R 详情只读候选字段;当前 PC 未填充,不作为功能依赖
genealogyName 响应 string R 详情只读展示;当前 PC 可能为空
senderUserId 响应 int64,可空 I 内部关联字段;不展示、不提交
senderNickName 响应 string R 详情只读展示;当前 PC 可能为空
senderPhone 响应 string I 隐私字段,页面始终隐藏
noticeType 响应 string,无枚举/默认值 R 列表和详情只读展示;不据此猜测跳转
noticeTitle 响应 string R 列表和详情标题,转义后展示
noticeContent 响应 string R 列表摘要和详情正文,转义后展示
bizType 响应 string,无枚举/默认值 R 详情只读展示;不据此拼业务 URL
bizId 响应 int64,可空 I 内部业务关联字段;PC 未提供目标路由契约前不展示、不跳转
bizSummary 响应 string R 详情只读展示;当前 PC 可能为空
publishTime 响应 string date-time R 列表和详情只读展示,不由页面提交
readStatus 响应 string;枚举 0/1 R 0=未读、1=已读;仅正常未读记录显示单条已读按钮
readTime 响应 string date-time,可空 R 详情只读展示,未读时为空
status 响应 string;枚举 0/1 I 仅用于确认正常状态 0 才能执行单条已读,不提供页面编辑
remark 响应 string R 详情只读展示
未读数量 data 响应 int64 R 顶部计数;只接受非负安全整数

响应和权限边界:

  • YAML 的详情对象没有声明字段级 required、长度、范围或默认值;页面不补造限制,并兼容可选展示字段为空。
  • PC 后端按当前 APP_USER 登录账号隔离通知,只返回 status=0 的正常通知;列表按接收记录倒序,非分页。
  • 详情和单条已读必须命中当前账号的接收记录;重复单条已读保持已读状态,页面仍做写操作防重复。
  • C34 未解决前,genealogyNo/genealogyName/senderNickName/senderPhone/bizSummary 不能被视为稳定可用;手机号即使后端补齐也不展示。
  • 页面不展示原始 JSON,不使用 APP 接口,不开放删除,不根据 bizType/bizId 猜业务深链。
  • 2026-07-29 已在真实登录 Chrome 验证当前账号:未读数为 0,全部和仅未读筛选均成功同步,空列表/空详情状态正确。账号暂无通知,因此有数据详情和单条/全部已读真实写入仍待有数据时复核。

7.16 谱文

页面:profile-article.htmlprofile-article-edit.html

请求字段 必填性 / 类型 标记 页面来源与提交时机
categoryId 可选 int64 I/S C35 未解决前省略;没有真实分类选项时不提供输入框
articleTitle 必填 string U 编辑页标题;保存时提交
articleSummary 可选 string U 编辑页摘要;非空时提交
coverOssId 可选 string/int64 F/I 选择封面并完成统一上传后自动产生;隐藏保存,禁止手填
articleContent 必填 string U wangEditor 正文;同步到 textarea 后提交
authorName 可选 string U 编辑页落款;非空时提交
sortOrder 可选 int64 U/S 编辑页安全整数;非空时提交
status 可选 string 0/1 A/I C37 未解决前固定隐藏提交 0
genealogyIdarticleId path int64 I/A 家谱上下文和列表/详情响应;按十进制字符串处理,不显示、不手填

PC ArticleVo 响应字段及页面用途:

字段 类型 标记 页面处理
articleIdgenealogyId Long I 列表、详情、编辑、删除和写后重读的稳定 ID
genealogyNogenealogyNamesurname string R 家谱只读上下文
categoryId Long,可空 I 仅内部保留;无分类选项源时不回填为可编辑 ID
categoryNamecategoryCode string R 详情分类只读展示
articleTitlearticleSummaryarticleContentauthorName string R/U 列表、详情展示和编辑回填;可见内容均转义
coverOssId Long,可空 I 编辑隐藏回填;C36 未解决前不拼封面 URL
publishTimeviewCount Date/Long R 详情发布时间和浏览量
sortOrder Long I/U 编辑回填;列表顺序由后端负责
status string 0/1 I 只允许正常记录进入编辑器
remark string R 详情只读展示,不进入 ArticleBody

接入边界:

  • 列表、详情、新增、修改和删除只调用 /genealogy/pc/genealogies/{genealogyId}/articles 及其 /{articleId} 子路径;
  • YAML 响应仍为泛型包装,但 PC 控制器明确返回 ArticleVo,前端严格校验该 VO,不读取 APP 路径;
  • 新增/修改成功后使用稳定 articleId 重读同一详情;删除后重读列表;所有写操作防重复;
  • 页面先读取家谱详情,只有 canEditContent/canManage 显示新增、编辑和删除;后端继续执行最终权限校验;
  • C35 未解决前不开放分类筛选/编辑;C36 未解决前不猜封面地址;C37 未解决前不开放停用;
  • 相关聚焦测试 49/49 通过;真实账号页面验证统一留到阶段 6 收尾执行。

7.17 相册与照片

页面:profile-album.htmlprofile-album-edit.htmlprofile-album-detail.html

相册请求字段:

请求字段 必填性 / 类型 标记 页面来源与提交时机
albumName 必填 string U 编辑页相册名称;保存时提交
albumDesc 可选 string U 编辑页描述;非空时提交
coverOssId 可选 string/int64 F/I 选择封面并完成统一上传后自动产生;隐藏保存,禁止手填
sortOrder 可选 int64 U/S 编辑页安全整数;非空时提交
status 可选 string 0/1 A/I C39 未解决前固定隐藏提交 0
genealogyIdalbumId path int64 I/A 家谱上下文及相册响应;按十进制字符串处理,不显示、不手填

照片请求字段:

请求字段 必填性 / 类型 标记 页面来源与提交时机
ossId 必填 string/int64 F/I 选择照片并完成统一上传后自动产生;隐藏保存,禁止手填
photoTitlephotoDescphotographer 可选 string U 照片表单;非空时提交
shootTime 可选 date S 日期选择器;非空时提交 YYYY-MM-DD
sortOrder 可选 int64 U/S 照片表单安全整数;非空时提交
status 可选 string 0/1 A/I C39 未解决前固定隐藏提交 0
albumIdphotoId path int64 I/A 相册和照片响应;按十进制字符串处理,不显示、不手填

PC 响应字段及页面用途:

对象 字段 标记 页面处理
AlbumVo albumIdgenealogyId I 列表、编辑、详情、删除和写后重读的稳定 ID
AlbumVo genealogyNogenealogyNamesurname R 家谱只读上下文
AlbumVo albumNamealbumDesc R/U 列表/详情展示和编辑回填;可见内容均转义
AlbumVo coverOssId F/I 编辑隐藏回填;C38 未解决前不拼封面 URL
AlbumVo photoCount R 列表和详情照片数量
AlbumVo sortOrderstatus I/U 编辑回填;只允许正常记录进入编辑器
AlbumVo remark R 详情只读展示,不进入请求 Body
AlbumPhotoVo photoIdgenealogyIdalbumId I 照片删除和写后重读的稳定 ID
AlbumPhotoVo genealogyNogenealogyNamesurnamealbumName R 家谱与相册只读上下文
AlbumPhotoVo ossId F/I 文件引用;C38 未解决前不拼照片 URL
AlbumPhotoVo photoTitlephotoDescphotographershootTime R/U 照片列表展示;可见内容均转义
AlbumPhotoVo sortOrderstatus I 列表顺序和正常状态校验
AlbumPhotoVo remark R 只读展示,不进入请求 Body

接入边界:

  • 相册只调用 /genealogy/pc/genealogies/{genealogyId}/albums 及其 /{albumId} 子路径;照片只调用该相册下的 /photos/{photoId}
  • 后端没有单独的相册详情接口,详情和编辑页必须重读相册列表并用响应中的稳定 albumId 精确匹配;
  • YAML 响应仍为泛型包装,前端只接受后端 PC 控制器实际返回的 AlbumVo / AlbumPhotoVo 直接数组,不读取 APP 路径;
  • 新增/修改相册后重读相册列表;新增/删除照片后重读照片列表;所有写操作防重复;
  • 页面先读取家谱详情,只有 canEditContent/canManage 显示新增、编辑、删除和照片维护;
  • C38 未解决前不猜文件地址;C39 未解决前不开放停用;
  • 相关聚焦测试 49/49 通过;真实账号页面验证统一留到阶段 6 收尾执行。

7.18 祭祀活动、祭品与管理员受邀名单

页面:profile-ceremony.htmlprofile-gift-edit.htmlprofile-ceremony-detail.html;当前账号收到的邀请继续由 profile-gift.html 负责。

活动请求字段:

请求字段 必填性 / 类型 标记 页面来源与提交时机
ceremonyType 必填 string,无枚举 U 编辑页活动类型;保存时提交,不借用其他端枚举
ceremonyTitle 必填 string U 编辑页标题;保存时提交
ceremonyDesc 可选 string U 编辑页说明;非空时提交
ceremonyTime 可选 date-time S 日期时间选择器;转换为后端 Date 可解析格式后提交
location 可选 string U 编辑页地点名称;非空时提交
locationAddress 可选 string,最长 300 U 编辑页详细地址;非空时提交
longitude 可选 number[-180, 180] U/S 与纬度同时填写并保存
latitude 可选 number[-90, 90] U/S 与经度同时填写并保存
coverOssId 可选 string/int64 F/I 选择封面并完成统一上传后自动产生;隐藏保存,禁止手填
sortOrder 可选 int64 U/S 编辑页安全整数;非空时提交
status 可选 string 0/1 A/I C41 未解决前固定隐藏提交 0
genealogyIdceremonyId path int64 I/A 家谱上下文和活动响应;按十进制字符串处理,不显示、不手填

祭品与受邀名单请求字段:

请求字段 必填性 / 类型 标记 页面来源与提交时机
giverName 可选 string U 祭品表单赠送人姓名;非空时提交
giftAmount 必填 number,后端要求非负 U 祭品表单金额;添加祭品时提交;C42 未解决前不限制精度和最大值
giftMessage 可选 string U 祭品留言;非空时提交
inviteeUserIds 必填、唯一 int64 数组,可为空 S/I members/options 的正常且已绑定账号成员多选产生;更新名单时提交完整数组,禁止手填
giftIdinvitationIdinviteeUserId path/response int64 I/A 只从 PC 响应取得;用于删除、名单匹配和写后重读,不显示原值

PC 响应字段及页面用途:

对象 字段 标记 页面处理
CeremonyVo ceremonyIdgenealogyIdsponsorUserId I 活动 CRUD、详情和写后重读的稳定 ID
CeremonyVo genealogyNogenealogyNamesurname R 家谱只读上下文
CeremonyVo sponsorNickName R 发起人只读展示
CeremonyVo sponsorPhone I 隐私字段,始终不展示
CeremonyVo ceremonyTypeceremonyTitleceremonyDescceremonyTimelocationlocationAddress R/U 列表/详情展示和编辑回填;可见内容均转义
CeremonyVo longitudelatitude I/S 仅用于生成安全地图链接,不直接展示数值
CeremonyVo coverOssId F/I 编辑隐藏回填;C40 未解决前不拼封面 URL
CeremonyVo giftCountgiftAmount R 详情祭品数量与礼金合计
CeremonyVo sortOrderstatus I/U 编辑回填;只允许正常记录进入编辑器
CeremonyVo remark R 详情只读展示,不进入请求 Body
CeremonyGiftVo giftIdgenealogyIdceremonyIdgiverUserId I 祭品删除、关联和写后重读的稳定 ID
CeremonyGiftVo genealogyNogenealogyNamesurnameceremonyTitle R 家谱与活动只读上下文
CeremonyGiftVo giverNickNamegiverNamegiftAmountgiftMessagegiftTime R 祭品列表展示;可见内容均转义
CeremonyGiftVo giverPhone I 隐私字段,始终不展示
CeremonyGiftVo statusremark R/I 正常状态校验和只读备注
CeremonyInvitationVo 全部 ID、版本 I 邀请状态匹配和更新后的重读校验,不显示原值
CeremonyInvitationVo inviteStatus、投递/阅读/响应时间 R 管理员邀请列表只读展示
GenealogyMemberVo 选项 appUserId I/S 受邀人的唯一真实业务用户 ID 来源
GenealogyMemberVo 选项 memberNameappUserNickName R/S 受邀人选择器标签;手机号不展示

接入边界:

  • 活动只调用 /genealogy/pc/genealogies/{genealogyId}/ceremonies/{ceremonyId};祭品只调用其 /gifts 子路径;
  • 管理员邀请列表和替换只调用同一活动下的 /invitations/invitees,受邀人来源只调用当前家谱 /members/options
  • 新增/修改活动后重读同一详情,新增/删除祭品后重读祭品列表,更新受邀人后重读邀请列表;所有写操作防重复;
  • 页面先读取家谱详情,只有 canEditContent/canManage 显示活动、祭品和受邀名单维护;
  • 空数组允许取消全部尚未响应邀请;响应过的历史邀请由后端保留状态,前端不伪造删除;
  • C40 未解决前不猜封面地址;C41 未解决前不开放停用;C42 未解决前不猜金额精度和上限;
  • 相关聚焦测试 56/56 通过;真实账号页面验证统一留到阶段 6 收尾执行。

7.19 家谱成员管理、退出与谱主转移

页面:profile-family-admin.html

成员修改请求字段:

请求字段 必填性 / 类型 标记 页面来源与提交时机
memberName 可选 string,最长 50 U 管理员编辑表单;非空时提交
relationName 可选 string,最长 100 U 管理员编辑表单;后端明确接收空串时可清空
roleType 可选 stringadmin/editor/member S 按当前管理者和目标角色过滤;保存时提交,不发送 owner/visitor
lineagePersonId 可选 int64 S/I 从当前家谱世系人物选项选择;非空时提交,留空表示不修改而不是解绑
genealogyIdmemberId path int64 I/A 家谱上下文和成员列表响应;按字符串处理,不显示、不手填

退出与谱主转移:

字段/操作 必填性 / 类型 标记 页面来源与提交时机
DELETE /members/me 无 Body S/A 当前正常成员二次确认后提交;谱主不显示退出按钮
targetMemberId 必填 int64 S/I 谱主从当前正常成员列表选择新谱主;禁止选择自己和手填 ID
DELETE /members/{memberId} path int64 S/I 管理员从真实成员行执行“移出家谱”;谱主不可被移出

PC GenealogyMemberVo 响应字段及页面用途:

字段 标记 页面处理
memberIdgenealogyIdappUserIdlineagePersonIdinviterUserId I 当前成员匹配、修改、移出、转让和世系绑定的稳定 ID;不显示原值
genealogyNogenealogyNamesurname R C44 未解决前允许为空的家谱只读上下文
appUserNickNamelineagePersonNolineagePersonNamememberName R/U 成员列表标签和编辑回填;可见内容均转义
appUserPhoneinviterPhone I 隐私字段,始终不展示
roleType R/S 响应可含 owner/admin/editor/member/visitor;修改只提交三种后端可分配角色
relationName R/U 列表展示和编辑回填
joinSourceinviterNickNamejoinTime R 加入来源只读说明;C44 未填充时允许为空
status I 列表只接受后端返回的正常状态 0

权限与状态边界:

  • 所有账号可按家谱查看权限读取正常成员;只有家谱详情 canManage=true 时显示修改和移出;
  • 谱主不能直接修改或移出;只有谱主可管理管理员、分配 admin 或转让谱主;管理员只能管理非管理员成员并分配 editor/member
  • 普通成员、编辑和管理员可退出家谱;谱主必须先转让谱主。退出和移出只停用成员关系,不删除世系人物;
  • 更新后重读成员列表并核对同一 memberId;移出后核对该成员不再出现在正常列表;谱主转移后重读家谱详情和成员列表;
  • 页面没有直接新增成员接口;新增成员必须通过后端已有的加入/邀请业务闭环;
  • C44 未解决前不依赖 enrichment 字段并隐藏手机号;C45/C46 未解决前不伪造关系解除或成员-世系人物解绑;
  • 相关聚焦测试 49/49 通过;真实账号页面验证统一留到阶段 6 收尾执行。

7.20 家谱创建与加入申请契约

页面:profile-create-family.htmljoin-genealogy.htmlprofile-join-family.htmlprofile-join-review.html

AppGenealogyCreateBody

字段 类型 必填 来源 页面与提交时机
genealogyName string U 创建页谱名;提交时发送
surname string U 创建页姓氏;提交时发送
regionCode string S 省市区选择器自动取最后一级;提交时发送
ancestralHalloriginPlaceaddressDetailintro string U 创建页可选输入;非空时发送
coverOssId int64/string F 封面上传成功后自动产生;不允许手填
visibility string enum 0/1/2 S 私密/公开/成员可见
joinMode string enum 0/1/2 S 关闭/审核/邀请模式

实现边界:

  • 创建只调用 POST /genealogy/pc/genealogies,提交前读取 GET /genealogy/pc/genealogies/quota
  • 地区选项复用 /genealogy/pc/region/children?parentCode=...,不手写地区编码;
  • 创建成功后使用响应中的稳定 genealogyId 重读同一家谱,匹配后进入家谱主页;
  • 申请页先从 GET /genealogy/pc/genealogies/options 选择响应中的家谱,再调用 POST /genealogy/pc/genealogies/{genealogyId}/join-applies
  • 我的申请页调用 GET /genealogy/pc/genealogies/join-applies/mine;只有 status=0 的响应项可以调用 DELETE /genealogy/pc/genealogies/join-applies/{applyId}
  • 审核页只从当前家谱上下文取得 genealogyId,先读取家谱详情并要求 canManage=true,再读取 GET /genealogy/pc/genealogies/{genealogyId}/join-applies/pending
  • 审核只调用 PUT /genealogy/pc/genealogies/{genealogyId}/join-applies/{applyId}/auditstatus=1 通过、status=2 拒绝;
  • inviterUserId 没有安全 PC 邀请来源,本轮加入申请契约不发送该字段;
  • 创建/申请/审核页面均无家谱 ID、申请 ID、用户 ID 或 OSS ID 文本输入,所有写操作防重复并在成功后重读对应资源。

AppGenealogyJoinApplyBody

字段 类型/约束 必填 来源 页面与提交时机
applicantName string,最长 50 U 申请页姓名;非空时提交
phone string,最长 30 U 申请页联系电话;非空时提交
relationDesc string,最长 100 U 申请页关系说明;非空时提交
applyReason string,最长 500 U 申请页申请理由;非空时提交
inviterUserId int64/string 邀请模式条件必填 I PC 无安全来源,不展示、不发送;邀请模式继续阻断

GenealogyJoinApplyVo 与审核:

字段 类型/枚举 来源 页面用途
applyIdgenealogyId int64/string R/I 响应按钮属性和写入 path;不显示、不手填
genealogyNamesurname string R 我的申请列表只读展示
applicantNamephonerelationDescapplyReason string R 管理员待审核列表;只展示申请人主动提交的 phone
auditTimeauditRemark datetime/string R 我的申请审核结果展示
status string 0/1/2/3 R 待审核/通过/拒绝/撤销;仅 0 可撤销
appUserIdinviterUserIdauditUserId int64/string I 普通列表和审核列表均不展示
appUserPhoneinviterPhoneauditPhone string I 账号/邀请/审核人员隐私字段均不展示
审核 status string 1/2 S 管理员点击通过或拒绝时提交
审核 auditRemark string,最长 500 U 拒绝时可选填写,非空时提交

7.21 意见反馈与工单契约

页面:profile-feedback.htmlsubmit-ticket.htmlmy-tickets.htmlticket-detail.html

后端只提供统一反馈集合:

  • POST /genealogy/pc/feedback:当前业务用户提交反馈;
  • GET /genealogy/pc/feedback:读取当前业务用户自己的反馈列表;
  • 没有独立 ticket path;“工单”只是帮助中心对同一反馈记录的页面名称;
  • 没有用户侧回复、追问、关闭或删除接口,页面不制造这些操作。

AppFeedbackBody

字段 类型/约束 必填 来源 页面与提交时机
feedbackType string enum advice/bug/complaint/other S 两个提交页选择;空值省略并由后端默认 advice
feedbackContent string,非空 U 问题或建议正文;提交时发送
contactInfo string U 用户主动提供的联系方式;非空时发送
feedbackTitle V 旧页面字段不属于 DTO,已从表单移除且不发送

FeedbackVo

字段 类型/枚举 来源 页面用途
feedbackId int64/string R/I 提交后重读匹配、列表详情链接和 URL;不展示、不手填
feedbackTypefeedbackContentcontactInfo string R 列表或详情只读展示
handleStatus string 0/1/2/3 R 待处理/处理中/已处理/已关闭
handleResulthandleTimeremark string/datetime R 后端存在时在详情展示
status string 0/1 I 响应有效性校验,不提供用户修改入口
appUserIdhandlerId int64/string I 内部用户/处理人编号,不展示
appUserNickNameappUserPhone string I 后台 enrichment,不在用户页面展示

实现边界:

  • ApiClient 是 GET/POST path 和三字段 body 白名单唯一 owner;
  • 提交使用防重复锁;成功响应必须包含稳定字符串 feedbackId
  • 提交后重读我的反馈列表并精确找到同一 feedbackId,否则不宣称成功;
  • 工单详情从 URL 读取列表响应产生的 feedbackId,只在我的列表中精确匹配,不回退第一条;
  • 401 清理登录态;403 保留登录态并显示后端权限错误;页面不展示原始 JSON。

7.22 VIP 套餐与会员订单契约

页面:profile-services.html

PC 端只开放三条业务用户接口:

  • GET /genealogy/pc/vip/packages:读取可购买套餐,成功响应 List<VipPackageVo>,无分页结构;
  • POST /genealogy/pc/vip/orders:创建当前业务用户的会员订单,body 为 AppVipOrderBody,成功响应 VipOrderVo
  • GET /genealogy/pc/vip/orders:读取当前业务用户的订单,成功响应 List<VipOrderVo>,无分页结构;
  • 三条接口均要求 APP_USER 登录态;创建接口有后端防重复提交;
  • PC Controller 没有支付发起、支付回调、取消、关闭或退款接口,页面不得制造这些动作。

AppVipOrderBody

字段 类型/约束 必填 来源 页面与提交时机
packageId int64,稳定字符串 ID S/I 用户点击套餐响应生成的卡片时选择;创建订单时发送,禁止手填
genealogyId int64,稳定字符串 ID S/I 用户从“我的家谱”响应生成的下拉项中选择;非空时创建订单发送,禁止手填
payType string;后端空值默认 wechat A PC 页面不提供支付方式选择且默认省略;等待后端开放真实支付能力后再确认枚举

VipPackageVo

字段 类型/枚举 来源 页面用途
packageId int64/string R/I 套餐卡片选择和订单 body;不展示、不手填
packageNamepackageDesc string R 套餐名称和说明
packageType string vip/storage R 显示为会员套餐/存储扩容;未知值整条过滤
priceoriginalPrice decimal,非负 R 价格展示;不参与前端金额计算
durationValue integer,非负,可空 R 与期限单位组合展示
durationUnit string permanent/day/month/year R 永久/天/月/年
genealogyLimitmemberLimitstorageLimitMb integer,非负,可空 R 套餐额度只读展示
featureJson string/JSON I 契约未说明用户侧展示结构,当前不解析、不展示
sortOrder integer I 后端列表顺序 owner,前端不重新排序
status string 0/1 I 只接受正常 0 套餐;不提供修改入口
remark string R 非空时作为套餐补充说明展示

VipOrderVo

字段 类型/枚举 来源 页面用途
orderId int64/string R/I 创建后重读精确匹配;不展示、不手填
orderNo string R 订单列表展示
packageId int64/string R/I 响应有效性校验,不展示
packageName string R 订单套餐名称
genealogyId int64/string,可空 R/I 响应有效性校验,不展示
genealogyNogenealogyName string,可空 R 关联家谱信息展示
orderAmountpayAmount decimal,非负 R 订单金额和应付金额展示;以后端值为准
payType string,可空 R 后端返回时只读展示,不作为支付入口
payStatus string 0/1/2/3 R 待支付/已支付/已关闭/已退款
payTimeexpireTime datetime,可空 R 支付和有效期信息展示
status string 0/1 I 响应有效性校验,不提供修改入口
remark string R 非空时展示
appUserIdappUserNickNameappUserPhone int64/string I 当前账号及 enrichment 字段,不在页面展示

实现边界:

  • ApiClient 是三条 path 与三字段请求白名单唯一 owner;
  • 页面启动时并行读取套餐、我的家谱和订单;所有业务 ID 仅来自响应;
  • 创建使用前端防重复锁;创建响应必须是完整有效 VipOrderVo,随后重读订单列表并精确找到同一 orderId 才宣称成功;
  • 页面省略 payType,由后端使用已确认的默认值;不展示后端尚未提供的支付、取消或退款按钮;
  • 401 清理登录态;403 保留登录态并展示后端错误;非法套餐、订单、金额、枚举或不安全数字 ID 整条过滤。

7.23 家谱主页只读概览契约

页面:profile-family-home.html

只使用两条现有 PC 读取接口:

  • GET /genealogy/pc/genealogies/{genealogyId}/overview:返回当前家谱 AppGenealogyVo
  • GET /genealogy/pc/genealogies/{genealogyId}/lineage/tree:返回 List<LineagePersonTreeView>
  • genealogyId 只从 profile-common.js 的当前家谱上下文取得,两条请求使用同一个稳定字符串 ID;
  • 后端 overview 当前实际复用家谱详情服务,不包含文章、相册、视频、祭祀或动态聚合统计。

AppGenealogyVo 主页字段:

字段 类型/约束 来源 页面用途
genealogyId int64/string I/A/R 当前上下文、两条请求 path、响应一致性校验;不展示、不手填
genealogyNo string R 家谱编号只读展示
genealogyName string,非空 R 页面标题和概览名称
surname string R 姓氏只读展示
ancestralHall string,可空 R 堂号非空时展示
originPlace string,可空 R 祖籍非空时展示
regionFullName string,可空 R 完整地区非空时展示
memberCountpersonCount integer,非负 R 家谱成员数和世系人物数;不在前端计算
status string 0/1 I 只接受正常 0 响应
canManage boolean I 严格为 true 时显示家谱管理入口
canEditContent boolean I 保留为内容权限上下文,主页不据此制造写操作
ownerUserIdcoverOssId int64/string I 当前主页不展示、不手填
其余地址、角色、成员状态字段 对应 DTO 类型 I 当前主页不消费,不输出原始 JSON

LineagePersonTreeView

字段 类型/结构 来源 页面用途
personIdgenealogyId int64/string R/I 树节点稳定标识和响应校验;不直接展示
namegenerationName、人物摘要字段 string R 复用世系页的安全节点渲染
relationType string father/mother/spouse/child/adoptive R 关系数据;主页不提供关系写操作
relationName string R 非空时作为关系说明
spouseschildren LineagePersonTreeView[] R 递归世系预览

实现边界:

  • lineage-pages.js 是世系节点规范化和树 HTML 的唯一 owner;主页不得复制一套树字段解释;
  • 页面并行读取概览和世系树,只展示基础信息、后端已有计数和真实树;
  • /genealogy/dashboard/overview 是后台权限接口,不属于 PC 家谱主页契约,前端不调用;
  • PC 没有成员邀请创建或分享接口,“邀请家人”只显示阻断说明,不提供可点击操作;
  • 主页没有写请求;401 清理登录态,403 保留登录态并显示读取错误。

7.24 帮助中心文章契约

页面:help.html。契约 ownerutils/ApiClient.jshelpArticles / helpArticleDetailpublic/js/help-pages.js

接口:

method 完整 path 目录 鉴权 页面时机
GET /genealogy/pc/help-articles 内容文章 / PC 帮助文章列表 APP_USER 登录态 帮助中心初始化或用户点击刷新
GET /genealogy/pc/help-articles/{helpId} 内容文章 / PC 帮助文章详情 APP_USER 登录态 用户从列表点击“查看完整解答”

请求字段:

位置 字段 必填 类型/约束 分类 页面来源与提交时机
Query helpCategory string;后端按完全相等过滤 S 当前页面不提供猜测分类选项,因此初始化时省略;后端提供正式分类字典后才能开放选择
Path helpId int64;前端始终按非零十进制字符串处理 I 只能来自列表响应;用户点击该文章详情时进入 path
Header clientid 基础请求自动 string A AxiosRequestUtil 统一填写;页面不输入
Header Authorization Bearer <access_token> A AxiosRequestUtil 从登录态自动填写;页面不读取、不展示 token
Body 两个接口均无 Body

HelpArticleVo 响应字段:

字段 类型 分类 页面使用
helpId int64/string I 校验稳定 ID、绑定列表项并精确重读详情;不向用户显示
helpCategory string R 列表和详情分类文字,可空
helpTitle string R 列表标题,空值使整条响应失败
helpContent string R 详情正文;转义并保留换行,不执行响应 HTML
coverOssId int64/string I 当前响应没有文件 URL,页面不显示、不拼接、不允许手填
sortOrder int64 I 仅后端排序,不展示
viewCount int64/string R 非负十进制计数;详情 GET 会由后端累计浏览量
status string I 只接受正常值 0;停用文章整条拒绝
remark string I 后台备注,不展示

响应与错误边界:

  • 列表响应必须是直接数组,不接受分页 rows 猜测;任一元素缺少稳定 ID、标题、正文或正常状态时整批失败;
  • 详情必须返回与 path 中相同的 helpId,不回退到列表第一条;
  • YAML 把两条接口标为 security: [],但 PcHelpArticleController 没有 @SaIgnore,部署环境无 token 实测返回“认证失败”;按用户指定的后端项目为准,当前客户端必须携带登录 token,此项作为 Apifox/后端冲突保留;
  • 后端只声明统一成功包装,未提供帮助文章专属失败码;详情不存在或停用时按业务错误展示,不制造 404 枚举;
  • 无登录态或 401 清理登录状态并进入登录页;403 保留登录态并展示读取错误;
  • 页面只有读取动作,不提供编辑、发布、分类管理、封面 OSS ID 或成员邀请操作。

7.25 应用推广契约

页面:app.html 的“应用推广”区域。契约 owner:utils/ApiClient.jspromotionspublic/js/app-promotion-pages.js

接口:

method 完整 path 目录 鉴权 页面时机
GET /genealogy/pc/promotions 应用推广 / PC 应用推广列表 APP_USER 登录态 应用下载页初始化;仅在本地已有登录 token 时请求一次

请求字段:

位置 字段 必填 类型/约束 分类 页面来源与提交时机
Query platform stringSQL 字典 gen_promotion_platformall 全部(默认)、app APP、pc PC、wechat 小程序 A 应用下载页初始化时固定发送 pc;服务端返回 platform=pcplatform=all 的正常记录,不让用户选择或手填
Header clientid 基础请求自动 string A AxiosRequestUtil 统一填写;页面不输入
Header Authorization Bearer <access_token> A AxiosRequestUtil 从登录态自动填写;页面不读取、不展示 token
Path 无 Path 参数
Body 无 Body

AppPromotionVo 列表元素字段:

字段 类型 必填/约束 分类 页面使用
promotionId int64/string SQL BIGINT NOT NULL 主键;前端按非零十进制字符串处理 I 稳定绑定卡片,不展示、不允许手填
promotionKey string SQL varchar(80) NOT NULL DEFAULT 'banner' I 后台识别字段,页面不展示、不提交
promotionTitle string SQL varchar(200) NOT NULL;页面要求非空 R 推广卡片标题,HTML 转义后展示
promotionDesc string SQL varchar(500) DEFAULT '',可空 R 推广卡片说明,HTML 转义后展示
coverOssId int64/string 可空;响应没有可访问文件 URL I 不显示、不拼接 URL、不允许用户手填 OSS ID
targetUrl string SQL varchar(500) DEFAULT '',可空;页面只接受绝对 http/https URL R 合法时作为新窗口外链;危险、相对或无效地址降级为不可点击卡片
platform string SQL varchar(30) NOT NULL DEFAULT 'all';字典枚举 all/app/pc/wechat I 仅后端筛选,当前页面不展示
sortOrder int64 SQL BIGINT NOT NULL DEFAULT 0;后端按升序排序,同序按 promotionId 降序 I 仅后端排序,页面不二次解释或展示
status string SQL char(1) NOT NULL DEFAULT '0'0 正常、1 停用,页面只接受 0 I 停用或缺失状态的记录使整批响应失败
remark string SQL varchar(500) DEFAULT NULL,可空 I 后台备注,不展示

响应、权限与错误边界:

  • 成功响应经统一请求层解包后必须是直接 AppPromotionVo[],不是分页结构;任一元素缺少稳定 ID、标题或正常状态时整批失败;
  • 空数组显示“当前暂无应用推广”;未登录时页面本身仍可浏览,但推广区域只显示登录入口且不发请求;
  • YAML 把该接口标为 security: [],并且未导出真实 Query platform;后端 PcPromotionApiController 没有 @SaIgnore,全局拦截器要求 APP_USER 登录态。SQL 字典已确认 all/app/pc/wechat,服务层按“请求平台或 all”过滤,因此当前实现携带登录 token 并固定发送 platform=pc
  • SQL gen_app_promotion 另有 (tenant_id, platform, status, del_flag)(tenant_id, sort_order) 索引;del_flag、租户及审计字段不属于 AppPromotionVo,页面不接收、不展示;
  • 401 清理失效 token 并把推广区域切回登录提示;403、网络失败或畸形响应只在推广区域显示读取失败,不跳转、不清理有效登录态;
  • 后端只声明统一成功包装,未提供推广专属失败响应和错误码;字段长度、默认值及平台枚举已由后端 SQL 冻结,不再作为阻断项;
  • 页面没有推广新增、编辑、上下架、排序、封面上传能力,不调用 APP 或后台管理接口,也不向用户暴露推广 ID、推广键或 OSS ID。

7.26 官网资讯契约

页面:news.htmlarticle-detail.html。契约 ownerutils/ApiClient.jssiteArticlesutils/AxiosRequestUtil.js 的公开请求鉴权语义和 public/js/site-news-pages.js

接口:

method 完整 path 目录 鉴权 页面时机
GET /genealogy/pc/site/articles 站点内容 / PC 站点文章列表 公开,auth: false 资讯列表初始化、分类切换后的页面初始化,以及详情页按列表响应 ID 精确重读

请求字段:

位置 字段 必填 类型/约束 分类 页面来源与提交时机
Query articleType stringSQL 字典 gen_site_article_typenews 新闻(默认)、notice 公告、download 下载 S 用户点击固定分类链接后从 URL Query 取得;“全部”省略该字段,非法值不发请求
Query limit integer,客户端只允许 1–100;服务端正数最大取 100 A 列表和详情重读均由页面固定提交 100
Header clientid 基础请求自动 string A AxiosRequestUtil 统一填写;页面不输入
Header Authorization 不发送 方法设置 auth: false;即使本地已有 token 也不发送,公开请求 401/403 不清理既有登录态
Path 无 Path 参数
Body 无 Body

SiteArticleVo 列表元素字段:

字段 类型 必填/约束 分类 页面使用
articleId int64/string SQL BIGINT NOT NULL 主键;前端按非零十进制字符串处理 I 只用于生成详情链接和精确匹配,不展示、不允许手填
articleType string SQL varchar(50) NOT NULL DEFAULT 'news';枚举 news/notice/download R 转换为新闻、公告、下载标签;枚举外记录使整批失败
articleTitle string SQL varchar(200) NOT NULL;页面要求非空 R 列表和详情标题,HTML 转义
articleSummary string SQL varchar(500) DEFAULT '',可空 R 列表摘要和详情导语,HTML 转义
articleContent string SQL text,可空 R 详情正文;HTML 转义并只保留换行,不执行响应 HTML
coverOssId int64/string SQL BIGINT,可空;没有文件 URL 契约 I 不显示、不拼接 URL、不允许手填
externalUrl string SQL varchar(500) DEFAULT '',可空 R 只接受绝对 HTTP/HTTPS;合法时显示安全新窗口外链
publishTime string/date SQL datetime,可空 R 列表和详情发布时间文本,HTML 转义
sortOrder int64 SQL BIGINT NOT NULL DEFAULT 0 I 仅后端排序,不展示
status string SQL char(1) NOT NULL DEFAULT '0'0 正常、1 停用 I 页面只接受 0,其他值使整批失败
remark string SQL varchar(500) DEFAULT NULL,可空 I 后台备注,不展示

响应、详情与错误边界:

  • 成功响应经统一请求层解包后必须是直接 SiteArticleVo[];不接受分页 rows、旧字段别名或任一非法元素;
  • 服务端只查正常状态,按 sortOrder ASCpublishTime DESCarticleId DESC 排序;页面保持服务端顺序;
  • 后端没有站点文章单条详情接口;详情 ID 只能来自列表链接,详情页重读 { limit: 100 } 后精确匹配同一字符串 ID,不存在时不得回退第一条;
  • 标题、摘要、正文、类型和时间全部转义;正文只保留换行,危险或相对外链不渲染;
  • 空数组显示“当前暂无资讯”;非法分类/详情 ID 不发请求;网络、业务或畸形响应只更新内容区域,不跳转登录;
  • YAML 已导出 method/path、articleTypelimitsecurity: [],但响应只引用通用列表结果,未导出 SiteArticleVo 11 个字段;完整字段、长度、默认值和枚举由后端 VO、SQL 与字典补齐;
  • 2026-07-30 使用本地页面对当前部署环境做匿名实测时,接口返回“认证失败,无法访问系统资源”;页面保持在资讯页且不清理已有 token。该行为与 YAML 的 security: [] 冲突,后端需确认部署环境是否遗漏公开放行;前端不通过附带登录 token 绕过公开契约;
  • coverOssId 的文件 URL 和站点文章单条详情接口继续作为后端契约阻断;页面不猜 URL、不制造详情路径;
  • 本批不修改 about/culture/privacy/terms/surname,也不复用登录后的家谱谱文 CRUD 脚本。

8. 分阶段执行顺序

阶段 0:冻结契约

工作:

  1. 完成第 5 节 C01-C20 的本阶段相关项。
  2. 从 Apifox 重导 OpenAPI。
  3. 写契约快照测试,统计操作、请求字段、required、枚举、response $ref
  4. 确认旧路径和旧字段会失败,不保留兼容代码。

验证:

  • JSON 可被解析;
  • 实际接口数与收口后的 Apifox 一致;
  • 0 个重复逻辑路径;
  • 本轮实现模块不存在泛型业务响应;
  • 登录注册等公开接口不带 Authorization。

阶段 1:请求基础设施、验证和认证

工作:

  1. 收口 config.jsAxiosRequestUtil.jsApiClient.js 的 header、token、tenant 和错误处理。
  2. 完成验证中心、登录、注册、短信、找回、换绑、注销、退出。
  3. 完成个人资料全部 6 个写入字段。
  4. 为每条认证流程测试 body 中不存在 clientIdsceneCode 和旧验证码字段。

验证:

  • 密码、短信两种登录成功;
  • 验证策略开/关两条路径都成功;
  • 一次性 validToken 不能复用;
  • 401 清除登录态,403 保留登录态;
  • 确认密码等 V 类字段未进入请求。

阶段 2:文件上传和区划

前提:C01、C08、C09、C10、C13 完成。

工作:

  1. 实现单分片小文件和多分片大文件同一流程。
  2. 实现秒传、进度、重试、重复提交锁。
  3. 只保留一套区划 API,并实现级联、搜索、路径回显。
  4. 所有业务页移除可见 OSS ID 输入框。

验证:

  • 普通图片、最后一片不足 chunkSize、大视频、秒传分别通过;
  • MD5、大小、分片数量与初始化一致;
  • 页面刷新后的业务对象能重新显示文件;
  • 区划不同时请求两套路径。

阶段 3:家谱上下文

前提:C14 完成,或产品正式给出可验证的外部上下文契约。

工作:

  1. profile-common.js 成为 genealogyId 的唯一 owner。
  2. 我的家谱页提供真实选择入口。
  3. 所有家谱内链接传播同一个 ID,切换家谱时清空旧页面状态。

验证:

  • 无 ID 不发请求;
  • 切换两个家谱不串数据;
  • ID 始终按字符串处理;
  • 不存在示例 ID 和 APP 请求。

阶段 4:已具备明确 DTO 的家谱模块

顺序:

  1. 家族圈;
  2. 字辈谱;
  3. 世系人物;
  4. 我的贺礼邀请。

当前进度:阶段 4 已按顺序完成。家族圈的列表、正常状态详情、新增、修改、删除、点赞、评论、回复、权限显隐、空/错状态、防重复和写后重读已接入,C21 图片 URL 回显和 C22 停用记录管理继续阻断;字辈谱的正常/management 权限分流、单条新增修改和状态切换、批量预览保存、响应校验、防重复、写后重读及无家谱上下文分支已接入;世系人物的树、列表、分页、详情、完整字段表单、权限显隐、四类关系新增、逻辑停用、防重复和写后重读已接入,C15 继续阻断新增 SPECIFIED 账号绑定,C18 继续阻断可选字段清空闭环;我的贺礼邀请已接入当前账号列表、响应内详情、PENDING 接受/拒绝、长 ID 校验、权限/空错状态、防重复和写后重读,C16 继续阻断管理员替换受邀人。真实账号已验证邀请读取和空状态;该账号没有待响应邀请,接受/拒绝真实写入仍待有数据时复核。下一阶段为阶段 5,按顺序先核对视频 DTO 是否已完整。

每个模块采用同一闭环:

  1. ApiClient 方法和契约测试;
  2. 列表/详情读取;
  3. 新增;
  4. 修改;
  5. 删除/停用;
  6. 权限、空状态、错误状态、重复提交;
  7. 写入后重新读取验证。

阶段 5:补齐 DTO 后的资源模块

顺序:

  1. 视频;
  2. 成长记录;
  3. 亲友记录;
  4. 备忘录;
  5. 功德记录;
  6. 消息通知。

任何模块的 View/List DTO 未补齐时,只完成表单布局和契约测试,不宣称真实功能完成。

当前进度:阶段 5 已按顺序完成。视频、成长记录、亲友记录、备忘录、功德记录和消息通知均已按对应 PC 契约开放;各模块的文件 URL、停用记录、可选字段清空和金额业务边界仍按 C18、C23–C34 保持阻断,不通过 APP 接口或猜测字段补齐。

阶段 6:当前 PC 契约可闭环模块

已完成:

  • 谱文列表、详情、新增、修改和删除;
  • 相册列表、新增、修改、删除,以及照片列表、新增和删除;
  • 祭祀活动列表、详情、新增、修改和删除,祭品列表、新增和删除;
  • 管理员受邀名单读取和完整替换,当前账号邀请读取与响应;
  • 从同家谱正常成员选项中选择账号完成 SPECIFIED 世系人物绑定;
  • 家谱成员列表、修改、移出、当前成员退出和谱主转移;
  • 个人中心、家谱首页和家谱内容页的稳定入口。

契约收口:

  • replaceCeremonyInvitees(genealogyId, ceremonyId, inviteeUserIds) 只接收真实成员选项产生的 ID 数组,utils/ApiClient.js 唯一封装 { inviteeUserIds }
  • /members/options 严格按 YAML 不发送 Query;后端存在但 YAML 未定义的 keyword 不进入前端契约;
  • 成员角色构造边界只接受 admin/editor/memberowner/visitor 在请求构造前失败;
  • 所有业务 ID 来自 URL、上下文或响应选项,页面不提供手填 ID/OSS ID。

仍阻断:

  • C35–C46 中记录的分类选项、文件 URL、停用记录、金额业务精度/上限、响应 enrichment 与解绑契约;
  • 世系关系解除没有 PC 接口;成员移出/退出不会伪造成世系关系解除或成员与世系人物解绑;
  • 隔离测试账号已验证登录和无家谱上下文分支:阶段 6 页面均阻止业务请求、隐藏管理操作并返回家谱选择页,浏览器控制台无错误。该账号当前无家谱数据,因此列表有数据态、详情以及真实写操作仍待有数据账号复核,未制造家谱或业务记录。

阶段 7:剩余 PC 页面分批开放

首批已完成家谱生命周期 ApiClient 契约和创建家谱页面:额度、三级地区、封面上传派生、严格 DTO 校验、防重复与创建后重读均已接入。第二批已完成申请加入、我的申请、撤销和管理员审核页面;家谱/申请 ID 均来自响应或当前上下文,写后重读确认。第三批已完成意见反馈和工单展示:四页共用 PC 反馈集合、提交后三字段白名单重读、详情精确匹配和隐私过滤。第四批已完成 VIP 套餐、我的家谱选项和会员订单:页面不手填业务 ID,不伪造支付能力,创建后重读同一订单确认。第五批已完成家谱主页只读概览:复用 PC overview 与世系树,权限控制管理入口,不制造聚合统计或邀请能力。第六批已完成帮助中心:登录后读取 PC 帮助文章列表,列表响应产生详情 ID,详情精确重读并安全展示正文;Apifox 的匿名标记与后端实际鉴权冲突已记录。第七批已完成应用下载页的 PC 推广列表:未登录不发请求,登录后固定发送 SQL 字典确认的 platform=pc,只读取服务端返回的 pc + all 正常记录,外链仅允许绝对 HTTP/HTTPS;推广 ID、后台键和 OSS ID 均不向用户开放。第八批已完成官网资讯列表与详情:公开请求不发送或清理 token,分类使用 SQL 字典 news/notice/download,详情 ID 只来自列表响应并通过重读列表精确匹配;YAML 通用响应缺失完整 SiteArticleVo,且当前部署环境匿名访问仍返回认证失败,两项差异均已记录。成员邀请、分享和资料完善提醒没有 PC Controller,继续阻断。

9. 文件级施工建议

执行 AI 应优先修改现有 owner,避免页面各自复制逻辑:

文件 职责
PC.openapi.json 当次 Apifox 导出快照,不手工补字段
config.js 环境、API 基础地址、非敏感客户端配置
utils/ApiClient.js 所有正式 PC method/path/query/body
utils/AxiosRequestUtil.js header、鉴权、响应解包、401/403
utils/FormUtil.js 表单取值、空可选字段省略、前端校验
public/js/profile-common.js 登录页外的家谱上下文
public/js/upload-pages.js 唯一上传流程
public/js/auth-pages.js / security-pages.js 认证业务流程
public/js/feed-pages.js 家族圈
public/js/generation-pages.js 字辈
public/js/lineage-pages.js 世系与指定账号绑定
public/js/video-pages.js 视频列表、详情、编辑、上传元数据和 CRUD
public/js/growth-pages.jsrelative-pages.jsmemo-pages.js 对应族务记录
public/js/ceremony-pages.js 当前用户贺礼邀请列表、响应内详情和接受/拒绝
public/js/article-pages.jsalbum-pages.js 谱文、相册和照片
public/js/ceremony-admin-pages.js 祭祀活动、祭品与管理员邀约
public/js/member-admin-pages.js 成员修改、移出、退出和谱主转移

不得创建一个包揽所有业务的巨型页面脚本,也不得为了单一页面引入通用框架。

10. 测试与验收

10.1 必须新增或更新的测试

  1. OpenAPI 契约快照:
    • operation 数;
    • method/path
    • body Schema
    • required
    • enum
    • response $ref
    • 公开/鉴权标记。
  2. ApiClient 契约测试:
    • URL、query、body、header
    • int64 ID 不转 Number
    • 可选空字段被省略;
    • 旧路径/旧字段不存在。
  3. 页面字段覆盖测试:
    • 每个请求 Schema 字段都能在本规划的 U/S/F/A/I/V 分类中找到;
    • 用户可编辑字段有对应 name
    • 自动字段没有可见文本输入;
    • 枚举选项和值与 Apifox 一致。
  4. 流程测试:
    • 验证与短信;
    • 上传;
    • 家谱上下文;
    • 列表 → 详情 → 编辑 → 重读;
    • 删除/停用;
    • 401/403/404/409/422/429。
  5. 安全测试:
    • 富文本经过净化;
    • 密码、token、validToken 不写日志;
    • 外链和上传文件类型受限;
    • 错误消息不直接插入 HTML。

10.2 建议验证命令

先跑最小相关测试,再跑全量:

node --test tests/api-client-contract.test.js
node --test tests/auth-pages.test.js tests/captcha-pages-contract.test.js
node --test tests/feed-pages.test.js tests/generation-pages.test.js tests/lineage-pages.test.js
node --test tests/growth-pages.test.js tests/relative-pages.test.js tests/memo-pages.test.js tests/notification-pages.test.js
node --test tests/*.test.js

执行 AI 若新增测试文件,应在本节补上精确命令。

10.3 模块完成定义

一个模块只有同时满足以下条件才可标记完成:

  1. Apifox 契约无未决冲突。
  2. 所有请求字段已分类并落到页面。
  3. 列表和详情响应有明确 DTO。
  4. ApiClient 不存在旧路径或 fallback。
  5. 页面有加载、空、成功、校验失败、无权限和网络失败状态。
  6. 写操作防重复提交。
  7. 成功写入后通过重新读取验证。
  8. 相关测试和全量测试通过。
  9. 没有原始 JSON、手填 ID、示例业务数据或 APP 接口冒充真实能力。

11. 执行完成后的报告格式

执行 AI 每个阶段只报告:

Changed: 修改了哪些 owner、页面和契约。
Verified: 运行了哪些测试,真实联调覆盖了哪些流程。
Blocked: 哪些字段或流程仍缺 Apifox/后端契约,具体缺什么。
Next: 下一阶段可以开始的最小范围。

不得用“应该可以”“大概完成”代替测试证据。