diff --git a/docs/02-前端全局规范.md b/docs/02-前端全局规范.md index 752e65e..673a0c4 100644 --- a/docs/02-前端全局规范.md +++ b/docs/02-前端全局规范.md @@ -371,6 +371,137 @@ mock/*.ts 文件内容来源: - 大屏看板:独立深色主题(#0f0f1a背景/#1a1a2e卡片),样式文件 `styles/screen.scss` - 不引入Tailwind CSS +### Mock→API切换 Checklist(强制) + +联调切换时,开发者必须执行以下检查清单,逐项确认后才能声明切换完成: + +1. **全局搜索残留**: + - 搜索代码中所有 `mock-api` 字符串,确认零残留 + - 搜索所有 `/mock-api/` URL 引用,确认零残留 + +2. **逐调用点确认URL**: + - 搜索所有 `request.get(`、`request.post(`、`request.put(`、`request.delete(` 调用点 + - 输出完整清单(文件路径 + 行号 + URL) + - 逐个确认每个 URL 已从 Mock 风格切换为 RESTful 风格 + +3. **逐调用点确认HTTP方法**: + - 写操作(新增/编辑/删除/启停)必须使用正确的 RESTful 方法(POST/PUT/DELETE) + - 禁止写操作用 GET + - 禁止所有操作都用 POST(Mock 遗留) + +4. **对照API设计文档**: + - 打开 `docs/03-API接口设计.md` 的正式API列 + - 逐个端点确认前端调用 URL 和 Method 与文档一致 + +**检查模板:** + +``` +模块:设备管理 +切换日期:2026-04-XX + +| # | 前端方法 | 文件 | Mock URL | 正式 URL | HTTP Method | 已确认 | +|---|---------|------|---------|---------|-------------|--------| +| 1 | loadData | MachineListPage.vue | POST /mock-api/machine/list | GET /api/admin/machine | GET | ✅ | +| 2 | handleCreate | MachineListPage.vue | POST /mock-api/machine/create | POST /api/admin/machine | POST | ✅ | +| 3 | handleEdit | MachineListPage.vue | POST /mock-api/machine/update | PUT /api/admin/machine/{id} | PUT | ✅ | +| ... | ... | ... | ... | ... | ... | ... | +``` + +### RESTful 调用规范 + +1. **资源 ID 必须使用路径参数传递**: + +```typescript +// ✅ 正确:ID 在 URL 路径中 +request.get(`/api/admin/machine/${id}/status`) +request.put(`/api/admin/machine/${id}/toggle`) + +// ❌ 错误:ID 在 query 参数中 +request.get('/api/admin/machine/status', { params: { id } }) +``` + +2. **禁止自行编造后端不存在的接口**: + - 前端调用的每个 URL 必须在 `docs/03-API接口设计.md` 的正式API列中存在 + - 批量操作如果后端只提供单个操作接口,前端通过循环调用实现,不编造批量端点 + +3. **代码审查必检项**: + - 每个新增的 `request.xxx()` 调用,审查时必须对照 API 设计文档确认 URL 和 Method 正确 + +### el-pagination 使用规范 + +使用 `` 组件时,**必须同时**绑定以下事件: + +```vue + + + + +``` + +```vue + + + +``` + +**原因**:`v-model:current-page` 只是双向绑定数据,页码变化时不会自动调用 `loadData()`。必须通过 `@current-change` 和 `@size-change` 事件手动触发数据请求。 + +### 布尔字段类型规范 + +1. **TypeScript 接口中二元状态字段使用 `boolean` 类型**: + +```typescript +// ✅ 正确 +interface Machine { + isOnline: boolean + isEnabled: boolean +} + +// ❌ 错误 +interface Machine { + isOnline: number // 0/1 语义不明确 + isEnabled: number // 隐式转换碰巧正确但不可靠 +} +``` + +2. **后端返回 `int` 时的前端处理**:如果后端 DTO 暂时无法改为 `bool`(需协调),前端应在 API 响应拦截或数据转换层统一转为 `boolean`: + +```typescript +// 在 loadData 或 API 响应处理中 +const machine = { + ...raw, + isOnline: Boolean(raw.isOnline), + isEnabled: Boolean(raw.isEnabled), +} +``` + +3. **禁止在模板中使用 number 做隐式布尔判断**: + +```vue + + + + + +``` + ### 大屏独立规范 - 独立Layout:`ScreenLayout.vue`(全屏,无侧边栏/面包屑) diff --git a/docs/02-功能清单/03-界面变更执行规范.md b/docs/02-功能清单/03-界面变更执行规范.md index 5e88de4..8f7ac0a 100644 --- a/docs/02-功能清单/03-界面变更执行规范.md +++ b/docs/02-功能清单/03-界面变更执行规范.md @@ -92,3 +92,33 @@ AI助手执行任何界面变更前,只需读以下文件: - 禁止修改全局规范而不检查模块兼容性 - 禁止在页面文件中重复全局规范已有内容 - 禁止使用旧样式 `+---+` 画界面布局 + +--- + +## 六、逐字段验证测试规范(联调测试必读) + +联调测试时,以下三种场景必须执行逐字段验证,不能只验证"操作成功": + +### 1. 编辑测试(逐字段验证) + +对每个可编辑字段: +1. 记录原始值 → 修改为新值 → 保存 +2. 列表页验证:该字段对应的列显示新值 +3. 重新打开编辑弹窗:逐字段比对回填值是否为新值 +4. (推荐)通过 API 直接查询数据库,确认数据库中存储的值正确 + +### 2. 分页测试(数据变化验证) + +1. 记录当前页第一条数据的关键字段(如 device_code) +2. 切换到第2页 +3. 确认第一条数据的关键字段确实变了(不是同一批数据) +4. 切换回第1页 +5. 确认数据恢复为之前记录的值 + +### 3. 详情页测试(逐字段显示验证) + +对详情页每个展示字段: +1. 打开已知数据的详情页 +2. 逐字段检查:名称、编码、**关联名称**(车间名称、品牌名称、工人名称等)、IP、状态 +3. 空白/异常值不能跳过——如果某个字段显示为空,必须记录为 Bug +4. 特别关注外键关联的名称字段(ID 存在但 Name 为空 = Bug) diff --git a/docs/04-后端开发规范.md b/docs/04-后端开发规范.md index 7d99844..5136e94 100644 --- a/docs/04-后端开发规范.md +++ b/docs/04-后端开发规范.md @@ -657,6 +657,115 @@ public class MachineRepositoryTests : IDisposable | 删除测试来"通过"构建 | 禁止,必须修复 | | 忽略 `[Fact(Skip="...")]` | 禁止跳过测试 | +### 6.11 API端点实现对照表(强制) + +**适用时机**:每个模块的 Controller + Service 开发完成后、声明"模块完成"之前。 + +**规范要求:** + +1. 打开 `docs/03-API接口设计.md`,复制该模块的完整端点清单 +2. 在 `tests/CncService.Tests/Checklists/` 目录下创建对照清单文件,命名规则:`{模块名}-endpoints.md`,每行包含: + +``` +| 端点 | HTTP方法 | URL | Controller方法 | Service方法 | 测试方法 | 状态 | +|------|---------|-----|---------------|------------|---------|------| +| 机床列表 | GET | /api/admin/machine | GetList | GetList | GetList_xxx | ✅ | +| 机床详情 | GET | /api/admin/machine/{id} | GetById | GetById | GetById_xxx | ✅ | +| 机床状态 | GET | /api/admin/machine/{id}/status | GetStatus | GetStatus | GetStatus_xxx | ❌未实现 | +| ... | ... | ... | ... | ... | ... | ... | +``` + +3. **全部端点状态为 ✅ 时,才算模块开发完成** +4. 对照清单文件随测试文件一起提交到 Git + +**禁止行为:** +- 禁止只实现 CRUD 五件套(列表/详情/新增/编辑/删除)就声称模块完成,忽略设计文档中定义的子端点(如 status、production/today、production/trend、collect-records 等) +- 禁止"测了多少就覆盖多少"——覆盖率数字只统计已存在的方法 + +### 6.12 DTO断言完整性(强制) + +**规范要求:** + +1. GetById、GetDetail 等详情接口的测试,必须对 DTO 中的**每个字段**做断言 +2. 外键 ID 字段(如 `WorkshopId`)和关联名称字段(如 `WorkshopName`)**必须成对断言**: + +```csharp +// ✅ 正确:ID 和 Name 成对断言 +Assert.True(result.WorkshopId > 0); +Assert.NotNull(result.WorkshopName); +Assert.NotEmpty(result.WorkshopName); + +// ❌ 错误:只断言 ID,Name 为 null 也通过 +Assert.Equal(1, result.WorkshopId); +// WorkshopName 未断言 → null 也通过测试 +``` + +3. Controller 层测试同样必须对返回对象的每个字段做断言,不能只验证单个字段 + +**检查方法:** +- 写完测试后,数一下断言语句的数量,必须 ≥ DTO 的 public 属性数量 +- 如果 DTO 新增了字段,对应测试必须同步新增断言 + +### 6.13 布尔字段类型规范 + +**规范要求:** + +1. **C# DTO 层**:二元状态字段使用 `bool` 类型,不用 `int` + +```csharp +// ✅ 正确 +public bool IsEnabled { get; set; } +public bool IsOnline { get; set; } + +// ❌ 错误 +public int IsEnabled { get; set; } // 0/1 语义不明确 +``` + +2. **C# Entity 层**:如果 Dapper 映射需要,Entity 可以用 `int`/`sbyte`,但必须在 Repository 映射时转为 `bool` + +3. **测试断言**:布尔字段用 `Assert.True()`/`Assert.False()`,不用 `Assert.Equal(1, ...)`/`Assert.Equal(0, ...)` + +```csharp +// ✅ 正确 +Assert.True(result.IsEnabled); + +// ❌ 错误——与实现同源,如果实现用错了 int,测试也用 int,两者同错 +Assert.Equal(1, result.IsEnabled); +``` + +### 6.14 测试从需求文档编写(强制) + +**规范要求:** + +1. **写测试的输入顺序**: + - 第一步:打开 `docs/03-API接口设计.md`,列出该模块所有端点和业务规则 + - 第二步:根据端点清单和业务规则编写测试方法签名和断言 + - 第三步:运行测试,确认哪些通过、哪些失败(此时再检查实现是否遗漏) + +2. **禁止的行为**: + - 禁止看 Service/Controller 代码后补测试——这会导致"实现有什么就测什么",遗漏的功能永远不会被发现 + - 禁止只测试已存在的方法——API 设计文档中定义但未实现的方法,必须有对应的失败测试(标记为 TODO 或 `[Fact(Skip="端点未实现")]`) + +3. **新增端点时**:先更新 API 设计文档,再写测试(TDD 风格),最后写实现 + +### 6.15 覆盖率诚实声明 + +**规范要求:** + +1. 声明覆盖率时,必须附加以下免责说明: + +``` +覆盖率统计范围:仅覆盖已实现的 Controller/Service/Repository 方法。 +API 设计文档中定义但尚未实现的端点不在统计范围内。 +完整性请参照 API 端点实现对照表(见 6.11)。 +``` + +2. **禁止**只报一个数字(如"390个测试,100%方法覆盖")而不说明统计范围 + +3. 每个模块完成时,覆盖率报告必须与端点对照表一起呈现,两个指标缺一不可: + - 已实现方法的覆盖率(方法覆盖 + 分支覆盖) + - 已设计端点的实现率(已实现端点数 / 文档定义端点总数) + --- ## 七、依赖注入