feat(api): 添加帮助中心反馈系统和VIP服务功能

- 在ApiClient中新增submitFeedback、myFeedback、helpArticles、helpArticleDetail、
  siteArticles、promotions、vipPackages、createVipOrder、vipOrders等方法
- 添加帮助文章和站点资讯的参数验证逻辑
- 更新测试文件添加新的API方法测试用例
- 在HTML页面中添加反馈、帮助和VIP服务相关页面的脚本引用
- 更新加入家谱页面为完整的申请流程界面
- 修改资讯详情页面为站点资讯展示页面
- 更新AxiosRequestUtil中认证处理逻辑
- 添加世系树渲染的HTML生成函数用于页面复用
- 更新文档中的API契约说明和页面规划
This commit is contained in:
fizzleaf
2026-07-30 16:04:48 +08:00
parent fb1743aa2a
commit 309598bfa6
53 changed files with 6740 additions and 282 deletions
@@ -0,0 +1,249 @@
# VIP 套餐与订单 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:** 在服务中心开放 VIP 套餐查看、响应选项创建订单和我的订单刷新闭环,不制造支付或取消能力。
**Architecture:** `utils/ApiClient.js` 唯一拥有 `/genealogy/pc/vip/**` 的三个接口;新增 `vip-pages.js` 规范化套餐、家谱选项和订单,使用响应中的字符串 ID 构造 `AppVipOrderBody``profile-services.html` 作为唯一 VIP 页面,只提供套餐选择、可选家谱选择、创建订单和订单刷新。
**Tech Stack:** 静态 HTML、原生 JavaScript UMD、Axios、Node `node:test`
## Global Constraints
- 后端 `D:\WorkSpace\Java\Genealogy` 全程只读。
- 只调用 `GET /genealogy/pc/vip/packages``POST /genealogy/pc/vip/orders``GET /genealogy/pc/vip/orders`
- `packageId` 只能来自套餐响应;`genealogyId` 只能来自 `genealogiesMine()` 响应,不提供文本输入。
- 页面不提供未经确认的支付方式选择;请求省略 `payType`,由后端默认 `wechat`
- 不显示立即支付、模拟支付成功、取消订单、退款或关闭订单操作。
- 创建成功后重读订单列表并精确匹配同一 `orderId`
- 不展示 `appUserId`、用户手机号、内部原始 JSON。
---
### Task 1: ApiClient VIP 契约
**Files:**
- Modify: `utils/ApiClient.js`
- Modify: `tests/api-client-contract.test.js`
**Interfaces:**
- Produces: `vipPackages()``createVipOrder(body)``vipOrders()`
- [ ] **Step 1: 写失败契约测试**
```js
await client.vipPackages();
await client.createVipOrder({
packageId: '2062179707935264769',
genealogyId: '2062179707935264770',
payType: 'wechat',
appUserId: 'must-drop',
payStatus: 'must-drop'
});
await client.vipOrders();
assert.deepEqual(calls.map((config) => [config.method, config.url, config.data]), [
['get', '/genealogy/pc/vip/packages', undefined],
['post', '/genealogy/pc/vip/orders', {
packageId: '2062179707935264769',
genealogyId: '2062179707935264770',
payType: 'wechat'
}],
['get', '/genealogy/pc/vip/orders', undefined]
]);
```
- [ ] **Step 2: 运行 RED**
Run: `node --test tests/api-client-contract.test.js`
Expected: FAILVIP 方法不存在。
- [ ] **Step 3: 最小实现**
```js
vipPackages: function () {
return request('GET', '/genealogy/pc/vip/packages');
},
createVipOrder: function (body) {
return request('POST', '/genealogy/pc/vip/orders', {
body: pickDefined(body, ['packageId', 'genealogyId', 'payType'])
});
},
vipOrders: function () {
return request('GET', '/genealogy/pc/vip/orders');
}
```
- [ ] **Step 4: 运行 GREEN**
Run: `node --test tests/api-client-contract.test.js`
Expected: PASS。
---
### Task 2: 套餐、家谱选项和订单数据边界
**Files:**
- Create: `public/js/vip-pages.js`
- Create: `tests/vip-pages.test.js`
**Interfaces:**
- Produces:
- `normalizeVipPackage(item)`
- `normalizeVipPackages(data)`
- `normalizeGenealogyOption(item)`
- `buildVipOrderBody(values)`
- `validateVipOrderBody(body)`
- `normalizeVipOrder(item)`
- `normalizeVipOrders(data)`
- `renderVipPackages(data, selectedPackageId)`
- `renderGenealogyOptions(data)`
- `renderVipOrders(data)`
- [ ] **Step 1: 写失败纯行为测试**
使用完整 `VipPackageVo``VipOrderVo` 字面量断言:
- 套餐要求稳定字符串 `packageId`、非空名称、`packageType=vip/storage``durationUnit=permanent/day/month/year`、非负价格、`status=0`
- 停用套餐和不安全数字长 ID 不渲染;
- 家谱选项要求稳定字符串 `genealogyId` 和非空 `genealogyName`
- body 只保留 `packageId/genealogyId/payType`,页面默认构造不包含 `payType`
- 必须选择有效套餐;可选家谱必须是安全字符串 ID;若显式提供 `payType` 只允许已确认 `wechat`
- 订单要求稳定 `orderId/packageId`、订单号、套餐名、非负金额、`payStatus=0/1/2/3``status=0/1`
- 渲染不出现用户 ID、手机号、原始 JSON,不出现支付/取消/退款按钮。
- [ ] **Step 2: 运行 RED**
Run: `node --test tests/vip-pages.test.js`
Expected: FAIL,模块不存在。
- [ ] **Step 3: 最小实现纯函数**
支付状态:
```js
{ '0': '待支付', '1': '已支付', '2': '已关闭', '3': '已退款' }
```
套餐类型:
```js
{ vip: '会员套餐', storage: '存储扩容' }
```
套餐和订单金额保留后端字符串语义,不进行浮点运算。
- [ ] **Step 4: 运行 GREEN**
Run:
```powershell
node --test tests/vip-pages.test.js
node --check public/js/vip-pages.js
```
Expected: PASS。
---
### Task 3: 服务中心真实 VIP 闭环
**Files:**
- Modify: `profile-services.html`
- Modify: `public/js/vip-pages.js`
- Modify: `tests/vip-pages.test.js`
- Modify: `tests/pending-pages.test.js`
- Modify: `tests/pc-scope.test.js`
**Interfaces:**
- Produces: `initVipPage()``init()`
- [ ] **Step 1: 写失败页面行为测试**
断言:
- 服务中心不再 pending,加载 `vip-pages.js`
- 有套餐列表、只读选中提示、可选家谱下拉、订单表单、刷新订单和订单列表;
- 不存在 `packageId/genealogyId/orderId` 文本或数字输入;
- 不存在 `payType` 选择器以及支付、取消、退款、模拟成功按钮;
- 脚本并行读取套餐、我的家谱和订单;
- 创建后重读订单并精确匹配提交响应 `orderId`
- [ ] **Step 2: 运行 RED**
Run:
```powershell
node --test tests/vip-pages.test.js tests/pending-pages.test.js tests/pc-scope.test.js
```
Expected: FAIL,服务中心仍为 pending 且允许手填 ID。
- [ ] **Step 3: 实现页面初始化**
1. 401 跳转登录,403 保留登录态;
2. `Promise.all([vipPackages(), genealogiesMine(), vipOrders()])` 读取页面数据;
3. 点击套餐卡保存响应中的字符串 `packageId`
4. 家谱下拉只使用 `genealogiesMine()` 选项,空值表示不关联家谱;
5. 表单提交使用 `writePending` 锁;
6. 创建响应必须规范化;
7. 重读 `vipOrders()` 并找到同一 `orderId`
8. 刷新订单列表并展示“订单已创建;当前 PC 暂未开放在线支付”。
- [ ] **Step 4: 运行 GREEN**
Run:
```powershell
node --test tests/vip-pages.test.js tests/pending-pages.test.js tests/pc-scope.test.js
node --check public/js/vip-pages.js
```
Expected: PASS。
---
### Task 4: 导航、规划和收尾验证
**Files:**
- Modify: `profile.html`
- Modify: `docs/PC接口对接规划.md`
- Modify: `tests/stage6-navigation.test.js`
- Modify: `docs/superpowers/plans/2026-07-29-vip-packages-orders.md`
**Interfaces:**
- Consumes: Task 13 的 VIP 套餐与订单闭环。
- [ ] **Step 1: 写失败导航测试**
断言个人中心服务入口可进入 `profile-services.html`,服务页真实开放并且所有 VIP 业务都留在该唯一 owner 页面。
- [ ] **Step 2: 运行 RED**
Run: `node --test tests/stage6-navigation.test.js tests/pending-pages.test.js`
Expected: FAIL,服务页仍 pending 或未加载真实脚本。
- [ ] **Step 3: 更新规划**
记录 `AppVipOrderBody``VipPackageVo``VipOrderVo` 的字段来源、枚举、隐藏字段、写后重读和支付能力阻断;阶段 7 标记 VIP 批次完成。
- [ ] **Step 4: 聚焦和全量验证**
Run:
```powershell
node --test tests/vip-pages.test.js tests/api-client-contract.test.js tests/pending-pages.test.js tests/pc-scope.test.js tests/stage6-navigation.test.js
npm test
node --check public/js/vip-pages.js
git -c safe.directory=D:/WorkSpace/Web/jiapu diff --check
```
Expected: 全部 PASS。
- [ ] **Step 5: 浏览器只读验证**
真实登录态验证套餐、家谱下拉、订单空/有数据态、无伪支付动作和控制台错误。未经用户本轮明确授权,不创建真实订单。