Files
jiapu/docs/superpowers/plans/2026-07-29-genealogy-create-first-batch.md
T
2026-07-29 16:35:21 +08:00

259 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 家谱创建首批 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 白名单测试**
测试固定以下请求:
```js
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:
```powershell
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:
```powershell
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: 写失败的创建行为测试**
```js
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/2``joinMode` 只允许 `0/1/2`
- `coverOssId` 必须是安全字符串 ID;没有文件可省略。
- 额度 `createRemaining <= 0` 时阻止提交。
- 创建响应必须有稳定 `genealogyId`、谱名和姓氏。
- 跳转地址只能由响应 ID 产生:`profile-family-home.html?genealogyId=...`
- [ ] **Step 2: 运行 RED**
Run:
```powershell
node --test tests/genealogy-entry-pages.test.js
```
Expected: FAIL,纯函数不存在。
- [ ] **Step 3: 最小实现纯函数**
严格构造 `AppGenealogyCreateBody`,可选空值省略,不读取页面外字段。
- [ ] **Step 4: 运行 GREEN**
Run:
```powershell
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、`RegionPages``UploadPages`
- Produces: `initGenealogyCreatePage()`
- [ ] **Step 1: 写失败的页面测试**
断言页面:
- 不再包含 `data-feature-status="pending"``pending-pages.js`
- 加载 `region-pages.js``md5.js``upload-pages.js``genealogy-entry-pages.js`
- 存在隐藏 `coverOssId` 与文件选择控件,不能手填 OSS ID。
- 不存在 `genealogyId/applyId/inviterUserId` 输入。
- 表单只包含后端创建 DTO 字段和地区选择辅助字段。
- 创建按钮、状态区域和额度区域可由脚本控制。
- [ ] **Step 2: 运行 RED**
Run:
```powershell
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:
```powershell
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: 更新契约和阶段状态**
记录 `AppGenealogyCreateBody``AppGenealogyVo`、额度、权限、上传派生字段、加入申请 ApiClient 契约及仍未开放的加入 UI。
- [ ] **Step 2: 聚焦和全量验证**
Run:
```powershell
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、控制台错误和提交前校验。不得为测试消耗真实创建额度;除非用户明确授权,不执行最终创建写操作。