Files
zkxw/openspec/changes/zkxw-engineering-standards/specs/coding-conventions/spec.md
T
2026-05-23 21:27:10 +08:00

96 lines
5.5 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.
## ADDED Requirements
### Requirement: 最小必要改动
同一功能或缺陷修复的代码变更 SHALL 仅包含完成任务所必需的修改;不得在同一提交中进行无关重构、大范围格式化或与需求无关的文件挪动。
#### Scenario: 修复单接口校验
- **WHEN** 修复某一接口字段校验
- **THEN** diff SHALL 主要限于该接口、对应 schema 与必要测试,而不包含同模块无关重命名
### Requirement: Web 管理端工程约定
`web-admin` SHALL 遵循 `AGENTS.md` 中的栈与工具约定:包管理使用 pnpm;格式化以 Prettier(单引号、无分号、2 空格等)为准;ESLint/Stylelint 规则与仓库配置一致;Vue 与 Element Plus 依赖自动导入策略时,新增全局组件 SHALL 遵循既有 `unplugin` 配置而非随意手写重复导入(除非文件类型要求)。
#### Scenario: 提交前检查
- **WHEN** 提交 `web-admin` 源码
- **THEN** 贡献者 SHALL 在本地或通过 CI 运行与仓库一致的 lint/format 门禁
### Requirement: 后端工程约定
`backend` SHALL 使用 Python 3.9 与既有 FastAPI、SQLAlchemy、Pydantic v2 模式;新增领域逻辑 SHALL 优先落在 `app/services/` 与 `app/crud/`,路由层保持薄;配置 SHALL 通过 `pydantic-settings` 与 `.env` 系列文件管理。
#### Scenario: 新增业务接口
- **WHEN** 新增一组管理端 API
- **THEN** 路由 SHALL 放入 `app/api/` 合适模块,schema 放入 `app/schemas/`,数据库访问放入 `app/crud/` 或复用基类
### Requirement: 数据库脚本与迁移
涉及表结构变更时,维护者 SHALL 在 `docs/sql/` 中维护或更新与需求一致的 SQL 说明(全量基线导出为 `zkxw.sql`;增量变更可补充同目录下其他 `.sql`),并评估 Alembic/脚本与运行环境的同步(与 `AGENTS.md` 数据库变更约定一致)。
#### Scenario: 新增业务表
- **WHEN** 增加新表或字段
- **THEN** 仓库 SHALL 包含可复现的 schema 片段或迁移,且与 OpenSpec `database-conventions` 中的公共字段规则一致
### Requirement: 单文件行数上限
前端(`web-admin`)与后端(`backend`)的单个源码文件 SHALL 不超过 500 行。当文件因功能增长接近或超过此限制时,SHALL 将其拆分为多个职责单一的小文件(如:前端提取子组件、composable 或工具函数;后端按领域拆分 service、crud 模块或辅助函数)。配置文件、类型声明文件、SQL 脚本与自动生成文件不在此限制范围内。
#### Scenario: 前端页面文件增长
- **WHEN** 一个 Vue 组件文件超过 500 行
- **THEN** SHALL 将弹窗、复杂表格、可复用面板等拆分为独立子组件或 composable 函数,确保主入口文件在 500 行以内
#### Scenario: 后端模块文件增长
- **WHEN** 一个 Python 模块文件(api route、service、crud 等)超过 500 行
- **THEN** SHALL 按领域或功能边界拆分为多个子模块(如 `crud/production_task.py` → `crud/production_task.py` + `crud/production_task_step.py`),确保单个文件在 500 行以内
### Requirement: 提交说明可读性
提交信息 SHALL 使用完整句子说明「改了什么、为何」,并符合仓库 Conventional Commits / commitlint 类型约束。
#### Scenario: merge request
- **WHEN** 创建合并请求
- **THEN** 描述 SHALL 使评审者无需阅读聊天历史即可理解动机与风险
### Requirement: 前端 API 返回值消费约定
`web-admin` 的 axios 拦截器(`src/utils/http/index.ts`)已对响应做两层解包:`res.data.data` → 返回值即为后端 `data` 字段的内容。因此页面组件中消费 API 函数返回值时,SHALL NOT 再做 `{ data }` 解构或 `.data` 取值,SHALL 直接从返回值中读取业务字段。
#### Scenario: 调用列表 API
- **GIVEN** 后端返回 `{"code": 200, "data": {"list": [...], "total": 12}}`
- **WHEN** 页面调用 `const result = await fetchXxxList(params)`
- **THEN** `result` 已经是 `{"list": [...], "total": 12}`,SHALL 使用 `result.list`、`result.total`,SHALL NOT 写 `const { data } = await fetchXxxList()` 再从 `data.list` 取值
#### Scenario: 调用单条 API
- **GIVEN** 后端返回 `{"code": 200, "data": {"smsContent": "..."}}`
- **WHEN** 页面调用 `const result = await fetchGenerateSms(id)`
- **THEN** `result` 已经是 `{"smsContent": "..."}`,SHALL 使用 `result.smsContent`,SHALL NOT 写 `const { data } = await fetchGenerateSms()` 再从 `data.smsContent` 取值
#### Scenario: 新增 API 调用前确认返回值层级
- **WHEN** 编写新的页面消费 API 函数
- **THEN** 开发者 SHALL 先查看 `src/utils/http/index.ts` 第 420 行的 `return res.data.data as T`,确认拦截器已剥离 `{code, data}` 外层包装,消费端直接拿返回值即可
### Requirement: 前后端 HTTP 方法一致性
前端 API 函数的 HTTP 方法(GET / POST / PUT / DELETE)SHALL 与后端路由装饰器(`@router.get` / `@router.post` / `@router.put` / `@router.delete`)严格一致。有副作用的操作(创建、更新、状态变更、内容生成)SHALL 使用 POST 或 PUT。
#### Scenario: 新增 API 接口
- **WHEN** 后端定义 `@router.post("/generate-sms")`
- **THEN** 前端对应的 `fetchGenerateSms` SHALL 使用 `request.post()`,SHALL NOT 使用 `request.get()`
#### Scenario: 代码评审检查项
- **WHEN** 评审涉及前后端联调的变更
- **THEN** 评审者 SHALL 校验前端 `request.get/post/put/delete` 与后端 `@router.get/post/put/delete` 的方法一一匹配