Files
jiapu/docs/superpowers/plans/2026-07-29-genealogy-create-first-batch.md
T
fizzleaf fb1743aa2a feat(api): 完善家谱系统API客户端契约
- 实现家谱管理相关方法,包括创建、详情、概览、我的家谱和选项查询
- 添加家谱加入申请功能,支持申请、审核、取消和待审核列表操作
- 集成通知详情获取方法和通知ID安全验证机制
- 完善功德记录、谱文、相册、视频、祭祀活动的完整CRUD操作契约
- 实现家谱成员管理功能,包含成员列表、更新、移除和转让所有者操作
- 优化路径ID验证逻辑,拒绝不安全的数值ID并提供明确错误提示
- 更新测试用例以验证所有新增API方法的路径和请求体白名单机制
2026-07-29 16:57:27 +08:00

7.9 KiB
Raw Blame History

家谱创建首批 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 在约一小时的首批施工中冻结剩余家谱生命周期 PC 请求契约,并把 profile-create-family.html 从 pending 预览改成可用的真实创建家谱页面。

Architecture: utils/ApiClient.js 唯一拥有请求路径和 body 白名单;public/js/genealogy-entry-pages.js 扩展家谱创建的纯构造、校验、响应规范化和页面初始化;现有 region-pages.js 负责三级地区选项,upload-pages.js 负责生成 coverOssId。创建成功后只使用响应中的稳定 genealogyId 跳转到家谱主页。

Tech Stack: 静态 HTML、原生 JavaScript UMD、Axios、Node node:test

Global Constraints

  • 后端 D:\WorkSpace\Java\Genealogy 全程只读。
  • 只调用 /genealogy/pc/**,不调用 APP 或后台管理接口。
  • 不允许用户手填家谱 ID、申请 ID、用户 ID 或 OSS ID。
  • 每个生产行为必须先有失败测试并实际运行 RED。
  • 每个阶段完成后运行聚焦测试并更新 docs/PC接口对接规划.md

Task 1: 冻结家谱生命周期 ApiClient 契约

Files:

  • Modify: tests/api-client-contract.test.js
  • Modify: utils/ApiClient.js

Interfaces:

  • Produces:

    • createGenealogy(body)
    • applyToGenealogy(genealogyId, body)
    • myGenealogyJoinApplies()
    • pendingGenealogyJoinApplies(genealogyId)
    • auditGenealogyJoinApply(genealogyId, applyId, body)
    • cancelGenealogyJoinApply(applyId)
  • Step 1: 写失败的路径和 body 白名单测试

测试固定以下请求:

await client.createGenealogy({
  genealogyName: '汤氏家谱',
  surname: '汤',
  regionCode: '511622',
  coverOssId: '2062179707935264769',
  legacyField: 'drop'
});

await client.applyToGenealogy(genealogyId, {
  applicantName: '申请人',
  phone: '19100000000',
  relationDesc: '族亲',
  applyReason: '申请加入',
  inviterUserId: 'drop-without-safe-source'
});

await client.auditGenealogyJoinApply(genealogyId, applyId, {
  status: '1',
  auditRemark: '资料一致',
  legacyField: 'drop'
});

断言:

  • 创建请求为 POST /genealogy/pc/genealogies,只保留 genealogyName/surname/regionCode/ancestralHall/originPlace/addressDetail/coverOssId/intro/visibility/joinMode

  • 加入请求为 POST /genealogy/pc/genealogies/{genealogyId}/join-applies,本轮安全 PC 页面只保留 applicantName/phone/relationDesc/applyReason,不发送没有安全来源的 inviterUserId

  • 我的申请、待审核、审核和撤销使用后端 PC Controller 的完整路径。

  • 审核 body 只保留 status/auditRemark

  • 所有 path ID 拒绝不安全数字。

  • Step 2: 运行 RED

Run:

node --test --test-name-pattern "genealogy lifecycle" tests/api-client-contract.test.js

Expected: FAIL,新方法尚不存在。

  • Step 3: 最小实现方法和白名单

使用现有 request()pickDefined()toRequiredPathId();不增加兼容别名或 APP fallback。

  • Step 4: 运行 GREEN

Run:

node --test tests/api-client-contract.test.js
node --check utils/ApiClient.js

Expected: PASS。


Task 2: 家谱创建纯行为

Files:

  • Modify: tests/genealogy-entry-pages.test.js
  • Modify: public/js/genealogy-entry-pages.js

Interfaces:

  • Consumes: createGenealogy(body)genealogyQuota()

  • Produces:

    • buildGenealogyCreateBody(values)
    • validateGenealogyCreateBody(body)
    • normalizeCreatedGenealogy(item)
    • buildCreatedGenealogyUrl(item)
  • Step 1: 写失败的创建行为测试

assert.deepEqual(GenealogyEntryPages.buildGenealogyCreateBody({
  genealogyName: ' 汤氏家谱 ',
  surname: ' 汤 ',
  regionCode: '511622',
  ancestralHall: '',
  coverOssId: '2062179707935264769',
  visibility: '1',
  joinMode: '1',
  manualId: 'drop'
}), {
  genealogyName: '汤氏家谱',
  surname: '汤',
  regionCode: '511622',
  coverOssId: '2062179707935264769',
  visibility: '1',
  joinMode: '1'
});

同时断言:

  • 缺少谱名、姓氏或地区时返回明确校验错误。

  • visibility 只允许 0/1/2joinMode 只允许 0/1/2

  • coverOssId 必须是安全字符串 ID;没有文件可省略。

  • 额度 createRemaining <= 0 时阻止提交。

  • 创建响应必须有稳定 genealogyId、谱名和姓氏。

  • 跳转地址只能由响应 ID 产生:profile-family-home.html?genealogyId=...

  • Step 2: 运行 RED

Run:

node --test tests/genealogy-entry-pages.test.js

Expected: FAIL,纯函数不存在。

  • Step 3: 最小实现纯函数

严格构造 AppGenealogyCreateBody,可选空值省略,不读取页面外字段。

  • Step 4: 运行 GREEN

Run:

node --test tests/genealogy-entry-pages.test.js
node --check public/js/genealogy-entry-pages.js

Expected: PASS。


Task 3: 开放创建家谱页面

Files:

  • Modify: profile-create-family.html
  • Modify: public/js/genealogy-entry-pages.js
  • Modify: tests/genealogy-entry-pages.test.js
  • Modify: tests/pending-pages.test.js
  • Modify: tests/security-upload-scope.test.js
  • Modify: tests/pc-scope.test.js

Interfaces:

  • Consumes: Task 1 和 Task 2、RegionPagesUploadPages

  • Produces: initGenealogyCreatePage()

  • Step 1: 写失败的页面测试

断言页面:

  • 不再包含 data-feature-status="pending"pending-pages.js

  • 加载 region-pages.jsmd5.jsupload-pages.jsgenealogy-entry-pages.js

  • 存在隐藏 coverOssId 与文件选择控件,不能手填 OSS ID。

  • 不存在 genealogyId/applyId/inviterUserId 输入。

  • 表单只包含后端创建 DTO 字段和地区选择辅助字段。

  • 创建按钮、状态区域和额度区域可由脚本控制。

  • Step 2: 运行 RED

Run:

node --test tests/genealogy-entry-pages.test.js tests/pending-pages.test.js tests/security-upload-scope.test.js tests/pc-scope.test.js

Expected: FAIL,页面仍 pending 且缺上传/初始化行为。

  • Step 3: 实现页面初始化和提交

初始化顺序:

  1. 校验登录态。
  2. 调用 genealogyQuota() 并展示真实额度。
  3. RegionPages 初始化三级地区。
  4. UploadPages 通过 data-upload-target 把封面上传结果写入隐藏 coverOssId
  5. 提交前同步表单、构造并校验 body。
  6. 使用 writePending 阻止重复提交。
  7. 调用 createGenealogy(body)
  8. 规范化响应并跳转到真实家谱主页。

401 清登录态;403 保留登录态;业务错误显示在表单状态区域。

  • Step 4: 运行 GREEN

Run:

node --test tests/genealogy-entry-pages.test.js tests/api-client-contract.test.js tests/pending-pages.test.js tests/security-upload-scope.test.js tests/pc-scope.test.js
node --check public/js/genealogy-entry-pages.js

Expected: PASS。


Task 4: 首批收口

Files:

  • Modify: docs/PC接口对接规划.md

  • Modify: docs/superpowers/plans/2026-07-29-genealogy-create-first-batch.md

  • Step 1: 更新契约和阶段状态

记录 AppGenealogyCreateBodyAppGenealogyVo、额度、权限、上传派生字段、加入申请 ApiClient 契约及仍未开放的加入 UI。

  • Step 2: 聚焦和全量验证

Run:

node --test tests/api-client-contract.test.js tests/genealogy-entry-pages.test.js tests/pending-pages.test.js tests/security-upload-scope.test.js tests/pc-scope.test.js
npm test
git -c safe.directory=D:/WorkSpace/Web/jiapu diff --check

Expected: 全部 PASS。

  • Step 3: 浏览器验证并报告

使用真实账号验证创建页登录态、额度、地区加载、无手填 ID、控制台错误和提交前校验。不得为测试消耗真实创建额度;除非用户明确授权,不执行最终创建写操作。