7.3 KiB
家族圈动态接口接入 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.openapi2.json 中已交付的 12 个家族圈动态接口接入既有动态页面,并保持未开发的家谱业务不调用不存在的接口。
Architecture: PC.openapi2.json 是接口唯一依据;ApiClient 提供一一对应的私有请求封装,feed-pages.js 只协调页面事件和已定义的接口方法。动态页从 URL 查询参数读取真实 genealogyId,不写入示例家谱 ID。
Tech Stack: 原生 JavaScript、Axios、Node LTS node:test、静态 HTML/CSS。
Global Constraints
- 所有新增或修改的注释使用清晰中文。
- 不删除现有页面和样式;不接入尚未出现在
PC.openapi2.json的业务。 - 不提交当前工作区:其中含用户已有的未提交修改。
- 动态读取响应目前只有通用
ListResult/PageResult,页面仅使用feedId与feedContent;后端返回缺少这两个字段时展示明确错误,不猜测字段名。
Task 1: 更新接口边界测试和动态请求测试
Files:
- Modify:
tests/api-client-contract.test.js - Modify:
tests/pc-scope.test.js - Create:
tests/feed-pages.test.js
Interfaces:
-
Consumes:
PC.openapi2.json的 12 个/genealogy/pc/genealogies/{genealogyId}/feeds操作。 -
Produces: 对客户端路径、HTTP 方法、请求体和页面请求体转换的自动化约束。
-
Step 1: 写入失败测试
test('家族圈动态方法使用文档定义的路径和请求体', async () => {
const calls = [];
const client = createClientWithRecorder(calls);
await client.createFeed(900001001, { feedContent: '今天上传一张老照片。' });
await client.feedCommentsPage(900001001, 7001, { pageNum: 1, pageSize: 10 });
assert.deepEqual(calls.map((call) => [call.method, call.url]), [
['post', '/genealogy/pc/genealogies/900001001/feeds'],
['get', '/genealogy/pc/genealogies/900001001/feeds/7001/comments/page']
]);
});
test('动态表单只构造 FamilyFeedBody 字段', () => {
assert.deepEqual(FeedPages.buildFeedBody({
feedContent: '家谱动态', mediaOssIds: '101,102', status: '0'
}), {
feedType: 'text', feedContent: '家谱动态', mediaOssIds: '101,102', status: '0'
});
});
- Step 2: 运行失败测试
Run: $env:Path = 'C:\\Program Files\\nodejs;' + $env:Path; npm.cmd test
Expected: 动态方法或 feed-pages.js 尚不存在导致失败。
- Step 3: 调整范围检查
assert.match(contract, /\/genealogy\/pc\/genealogies\/\{genealogyId\}\/feeds/);
assert.equal(read('profile-feed.html').includes('src="public/js/feed-pages.js"'), true);
assert.equal(read('profile-feed-edit.html').includes('src="public/js/feed-pages.js"'), true);
- Step 4: 重新运行测试,确认仍处于预期失败状态
Run: $env:Path = 'C:\\Program Files\\nodejs;' + $env:Path; npm.cmd test
Expected: 仅动态实现相关断言失败。
Task 2: 增加 12 个家族圈 API 方法
Files:
- Modify:
utils/ApiClient.js - Modify:
tests/api-client-contract.test.js
Interfaces:
-
Consumes:
genealogyId:number|string、feedId:number|string、commentId:number|string。 -
Produces:
feeds、feedsPage、feedDetail、createFeed、updateFeed、deleteFeed、likeFeed、unlikeFeed、feedComments、feedCommentsPage、createFeedComment、deleteFeedComment。 -
Step 1: 保持失败测试不变
await client.createFeed(900001001, { feedContent: '家谱动态' });
assert.equal(calls[0].url, '/genealogy/pc/genealogies/900001001/feeds');
assert.deepEqual(calls[0].data, { feedContent: '家谱动态' });
- Step 2: 实现最小路径构造
function feedPath(genealogyId, suffix) {
return '/genealogy/pc/genealogies/' + encodeURIComponent(genealogyId) + '/feeds' + suffix;
}
createFeed: function (genealogyId, body) {
return request('POST', feedPath(genealogyId, ''), { body: body });
}
- Step 3: 运行测试,确认通过
Run: $env:Path = 'C:\\Program Files\\nodejs;' + $env:Path; npm.cmd test
Expected: 动态客户端路径和请求体断言通过。
Task 3: 恢复动态页的真实交互
Files:
- Create:
public/js/feed-pages.js - Modify:
profile-feed.html - Modify:
profile-feed-edit.html - Modify:
tests/feed-pages.test.js
Interfaces:
-
Consumes:
GenealogyApi.defaultClient的 12 个动态方法和 URL 中的genealogyId、可选feedId。 -
Produces: 动态列表、发布/编辑、点赞/取消点赞、评论查看/发布/删除、动态删除事件。
-
Step 1: 使页面测试失败
assert.equal(FeedPages.getCurrentGenealogyId('?genealogyId=900001001'), '900001001');
assert.equal(FeedPages.getCurrentGenealogyId(''), '');
assert.equal(FeedPages.getFeedId({ feedId: 7001 }), '7001');
- Step 2: 实现页面数据转换和事件
function buildFeedBody(values) {
return {
feedType: 'text',
feedContent: String(values.feedContent || '').trim(),
mediaOssIds: trimOrUndefined(values.mediaOssIds),
status: trimOrUndefined(values.status)
};
}
列表只读取 feedId、feedContent,并在缺少其中任一字段时显示“动态响应缺少 feedId 或 feedContent,请联系后端补充 DTO”。编辑页以 feedId 查询详情并调用 updateFeed;列表操作调用点赞、取消点赞、评论、删除接口后重新加载当前页。
- Step 3: 挂载脚本和契约字段
<textarea id="feedContent" name="feedContent" required></textarea>
<script src="public/js/feed-pages.js"></script>
移除未在 FamilyFeedBody 中定义的“可见范围”提交字段;保持页面布局与既有视觉类名。
- Step 4: 运行测试,确认通过
Run: $env:Path = 'C:\\Program Files\\nodejs;' + $env:Path; npm.cmd test
Expected: feed-pages.test.js 和已有测试全部通过。
Task 4: 更新文档来源与最终验证
Files:
- Modify:
tests/pc-scope.test.js - Modify:
PC.openapi.yaml
Interfaces:
-
Consumes:
PC.openapi2.json的接口路径。 -
Produces: 明确标记旧 YAML 不再为接口源,并使静态检查以 JSON 为准。
-
Step 1: 写入失败检查
const contract = JSON.parse(read('PC.openapi2.json'));
assert.ok(contract.paths['/genealogy/pc/genealogies/{genealogyId}/feeds']);
- Step 2: 标记旧 YAML 失效
在 PC.openapi.yaml 文件首行写入中文说明:该文件不再作为代码或测试接口源,正式接口源为 PC.openapi2.json。不复制或手改 JSON 中未定义的动态响应 DTO。
- Step 3: 全量验证
Run: $env:Path = 'C:\\Program Files\\nodejs;' + $env:Path; npm.cmd test
Expected: 全部测试通过,且所有动态页面加载的脚本文件都存在。
Self-review
- 范围只覆盖最新文档已交付的家族圈动态接口,没有加入家谱创建、成员或世系树接口。
- 所有请求体字段来自
FamilyFeedBody或FamilyFeedCommentBody。 - 读取响应不使用历史字段兜底,不把未知字段猜成有效数据。
- 任何 URL 缺少
genealogyId的页面都会明确提示,不使用硬编码示例 ID。