Files
amlhc/.planning/phases/01-omitted-number-analysis/01-03-PLAN.md
T
2026-04-21 23:02:15 +08:00

219 lines
9.3 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.
---
phase: 01
plan: 03
type: execute
wave: 2
depends_on: [01-01, 01-02]
files_modified:
- public/assets/js/backend/history.js
autonomous: false
requirements: [OMIT-02, OMIT-03, OMIT-04]
must_haves:
truths:
- "前后端联调通过:前端请求能正确到达后端接口并获取数据"
- "结果按遗漏期数从大到小正确渲染"
- "波色球着色与已有颜色映射一致"
artifacts:
- path: "public/assets/js/backend/history.js"
provides: "联调验证逻辑和边界情况处理"
contains: "history/missingNum"
key_links:
- from: "public/assets/js/backend/history.js"
to: "application/admin/controller/History.php::missingNum()"
via: "$.ajax GET history/missingNum?periods=X"
pattern: "history/missingNum"
- from: "public/assets/js/backend/history.js::renderMissingNum"
to: "后端返回 data[].omit"
via: "按 omit 降序渲染(后端已排序)"
pattern: "data\\[i\\]\\.omit"
---
<objective>
前后端联调验证:确保 history.js 的 AJAX 请求正确调用 history/missingNum 接口,结果按遗漏期数降序渲染,波色球着色与已有映射一致,并处理边界情况(无数据、加载失败、颜色映射未就绪)。
Purpose: 验证完整功能链路(per D-03: $.ajax 请求遗漏接口)
Output: 联调验证通过,边界情况处理完善
</objective>
<execution_context>
@D:/code/php/amlhc/.claude/get-shit-done/workflows/execute-plan.md
@D:/code/php/amlhc/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-omitted-number-analysis/01-RESEARCH.md
@D:/code/php/amlhc/public/assets/js/backend/history.jsplan 01-02 修改后的版本)
@D:/code/php/amlhc/application/admin/controller/History.phpplan 01-01 修改后的版本)
@D:/code/php/amlhc/application/admin/model/History.phpplan 01-01 修改后的版本)
</context>
<interfaces>
<!-- Key types and contracts from plans 01-01 and 01-02. -->
Backend endpoint (from plan 01-01):
```
GET /admin/history/missingNum?periods=X
Response success: {code: 1, msg: "查询成功", data: [{num: int, omit: int, color: string}, ...]}
Response error: {code: 0, msg: "期数范围必须在 1-100 之间"}
```
Frontend API (from plan 01-02):
```javascript
Controller.api.showMissingNumDialog() // opens Layer dialog
Controller.api.queryMissingNum(periods, layero) // initiates AJAX
Controller.api.renderMissingNum(data, periods, layero) // renders result grid
Controller.api.colorMapLoaded // boolean: color map ready flag
Controller.api.getColorByNum(num) // returns CSS color string
```
</interfaces>
<tasks>
<task type="auto" tdd="false">
<name>Task 1: 验证联调链路并完善边界情况处理</name>
<files>public/assets/js/backend/history.js</files>
<read_first>
- public/assets/js/backend/history.jsplan 01-02 修改后的完整文件)
- application/admin/controller/History.phpplan 01-01 修改后的控制器)
- application/admin/model/History.phpplan 01-01 修改后的模型)
</read_first>
<action>
检查 plan 01-02 创建的 JS 代码,确保以下边界情况已正确处理。如果已有则跳过,如果缺失则补充。
**边界情况 1:colorMap 未加载时的处理**
确认 queryMissingNum 方法在 colorMapLoaded === false 时,先调用 loadColorMap 等待完成再发起请求。代码应类似:
```javascript
queryMissingNum: function (periods, layero) {
if (!Controller.api.colorMapLoaded) {
Controller.api.loadColorMap(function () {
Controller.api._doQueryMissingNum(periods, layero);
});
} else {
Controller.api._doQueryMissingNum(periods, layero);
}
},
```
**边界情况 2:后端返回空数据(所有号码在最近 X 期都出现过)**
确认 renderMissingNum 方法在 data.length === 0 时显示友好提示而非空白:
```javascript
if (!data || data.length === 0) {
$('#missing-result', layero).html('<div class="alert alert-info">...</div>');
return;
}
```
**边界情况 3:AJAX 请求失败(网络错误、服务器 500)**
确认 _doQueryMissingNum 的 error 回调正确显示错误信息:
```javascript
error: function () {
$('#missing-result', layero).html('<div class="alert alert-danger">请求失败</div>');
}
```
**边界情况 4:波色球颜色兜底**
确认 renderMissingNum 中 getColorByNum 对未映射号码返回灰色 (#95a5a6)——这已在 getColorByNum 方法中实现,此处只需确保调用正确。
**边界情况 5:快速重复点击查询按钮**
在 _doQueryMissingNum 中,发起请求前禁用查询按钮,请求完成后恢复:
```javascript
var $btn = $('#btn-missing-query', layero);
$btn.prop('disabled', true);
$.ajax({
...
complete: function () {
$btn.prop('disabled', false);
}
});
```
如果上述边界情况在 plan 01-02 的代码中已经处理,本任务仅做验证性读取确认,不做修改。如果有缺失项,补充对应代码。
</action>
<acceptance_criteria>
- queryMissingNum 包含 `if (!Controller.api.colorMapLoaded)` 检查
- queryMissingNum 在 colorMapLoaded 为 false 时调用 `Controller.api.loadColorMap(function(){...})`
- renderMissingNum 包含 `data.length === 0` 的空数据处理分支
- _doQueryMissingNum 包含 error 回调函数
- _doQueryMissingNum 的 $.ajax 包含 complete 回调用于恢复按钮状态
- _doQueryMissingNum 在请求前设置 `$('#btn-missing-query', layero).prop('disabled', true)`
</acceptance_criteria>
<verify>
<automated>grep -c "colorMapLoaded\|data\.length === 0\|\.prop.*disabled\|complete:" public/assets/js/backend/history.js | awk '$1 >= 4'</automated>
</verify>
<done>所有边界情况(颜色映射未就绪、空数据、请求失败、按钮防重复点击、波色兜底)均已正确处理</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>Task 2: 人工验证完整功能链路</name>
<files>public/assets/js/backend/history.js, application/admin/controller/History.php, application/admin/model/History.php</files>
<what-built>
后端 missingNum 接口 + 前端弹窗 UI + AJAX 联调 + 边界情况处理
</what-built>
<how-to-verify>
按以下步骤在浏览器中验证(假设 admin 后台地址为 http://localhost/ByZjtVrKok.php):
1. **登录 admin 后台**,进入 history 页面
2. **检查按钮**:确认 toolbar 出现黄色"遗漏号码"按钮(带搜索图标)
3. **打开弹窗**:点击按钮,确认弹出 Layer 窗口,标题为"遗漏号码分析"
4. **检查弹窗内容**:确认有"查询期数:"标签、数字输入框(默认值 10)、查询按钮
5. **正常查询**:保持默认值 10,点击查询
- 确认出现"查询中..."加载提示(带 spinner
- 确认加载完成后显示结果网格:每个球显示号码(带颜色)+ 下方"遗漏 X 期"文字
- 确认结果从左到右按遗漏期数从大到小排列(最左边 omit 最大)
- 确认球的颜色与 history 表格中的波色球一致
6. **边界值测试**
- 输入 1 点击查询,确认返回结果
- 输入 100 点击查询,确认返回结果
- 输入 0 点击查询,确认显示错误提示"期数范围必须在 1-100 之间"
- 输入 200 点击查询,确认显示错误提示
7. **防重复点击**:点击查询按钮后,确认按钮变灰(disabled),请求完成后恢复可点击
8. **关闭弹窗**:点击弹窗外的遮罩区域,确认弹窗关闭
9. **重复打开**:再次点击"遗漏号码"按钮,确认弹窗正常打开且输入框恢复默认值 10
</how-to-verify>
<resume-signal>验证通过请回复"approved",如有问题请描述具体现象</resume-signal>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| AJAX response → DOM rendering | 后端返回的数据直接注入 DOM,需确保无 XSS 风险 |
| User rapid-click → multiple AJAX requests | 可能导致竞态条件或服务器负载 |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-01-07 | Tampering | renderMissingNum DOM 渲染 | mitigate | 使用 textContent/innerText 或 jQuery .text() 渲染号码数字,不使用 .html() 注入原始数据;球的颜色通过 style.backgroundColor 设置 |
| T-01-08 | Denial of Service | 快速重复点击 | mitigate | 请求期间禁用查询按钮(complete 回调恢复),防止并发请求 |
</threat_model>
<verification>
- 所有边界情况已在代码中处理(grep 验证通过)
- 人工验证 9 个步骤全部通过
- 无 JavaScript 控制台错误
- 后端无 PHP 错误日志
</verification>
<success_criteria>
- [ ] 前端 AJAX 请求正确调用后端 missingNum 接口
- [ ] 后端返回的 {num, omit, color} 数据正确渲染为波色球网格
- [ ] 结果按遗漏期数从大到小排列
- [ ] 波色球颜色与表格中一致
- [ ] 空数据时显示友好提示
- [ ] 参数超出范围时显示错误提示
- [ ] 请求期间按钮被禁用防止重复提交
- [ ] 点击遮罩可关闭弹窗
- [ ] 无 JavaScript 控制台错误
</success_criteria>
<output>
After completion, create `.planning/phases/01-omitted-number-analysis/01-03-SUMMARY.md`
</output>