同一功能或缺陷修复的代码变更 SHALL 仅包含完成任务所必需的修改;不得在同一提交中进行无关重构、大范围格式化或与需求无关的文件挪动。
web-admin SHALL 遵循 AGENTS.md 中的栈与工具约定:包管理使用 pnpm;格式化以 Prettier(单引号、无分号、2 空格等)为准;ESLint/Stylelint 规则与仓库配置一致;Vue 与 Element Plus 依赖自动导入策略时,新增全局组件 SHALL 遵循既有 unplugin 配置而非随意手写重复导入(除非文件类型要求)。
web-admin 源码backend SHALL 使用 Python 3.9 与既有 FastAPI、SQLAlchemy、Pydantic v2 模式;新增领域逻辑 SHALL 优先落在 app/services/ 与 app/crud/,路由层保持薄;配置 SHALL 通过 pydantic-settings 与 .env 系列文件管理。
app/api/ 合适模块,schema 放入 app/schemas/,数据库访问放入 app/crud/ 或复用基类app/api/** 中从请求体 body: XxxBody 读取字段时,SHALL 使用 app/schemas/** 里定义的 Python 属性名(多为 snake_case),SHALL NOT 使用 JSON camelCase 的 Field(alias=...) 字符串作为 body.xxx(例如 SHALL NOT 写 body.createTimeRange)。传 CRUD 时优先 body.model_dump(exclude_unset=True)。
完整约定、字段对照表与反例 EC-API-001 见 api-conventions §「JSON 字段命名(前后端 camelCase 对齐)」及 §「常见错误案例(API / Pydantic)」。
app/crud/,且 Schema 中 view_mode 的 alias 为 viewModeview_mode=body.view_mode,SHALL NOT 写 view_mode=body.viewMode本仓库门户默认租户编号 SHALL 为 shanxia2.0,与 OpenSpec database-conventions 中 DDL 默认值一致。
| 层级 | 约定 |
|---|---|
| 配置 | app/core/config.py 中 DEFAULT_TENANT_NO SHALL 为 "shanxia2.0";本地/部署 .env、.env.example SHALL 提供 DEFAULT_TENANT_NO=shanxia2.0 |
| ORM | app/models/ 中含 tenant_no 的 Column SHALL 使用 default="shanxia2.0"(sys_tenant.tenant_no 除外,其为租户编码主字段) |
| CRUD / 服务 | 无登录上下文或需门户默认租户时(如 Web 登录按 user_no 查用户、新建实体未从 JWT 注入租户),SHALL 使用 settings.DEFAULT_TENANT_NO,SHALL NOT 硬编码 zkxw |
| 写入 | 业务写入 SHALL 将 tenant_no 设为当前用户租户;未显式赋值且由 ORM/服务端默认填充时,SHALL 落库为 shanxia2.0 |
app/models/ 为业务表增加 tenant_no 字段default="shanxia2.0",并与 docs/sql/ 中对应表的 DEFAULT 'shanxia2.0' 一致user_crud.get_by_user_no 等按账号解析用户的入口且未传入 tenant_nosettings.DEFAULT_TENANT_NO(shanxia2.0),与库中 sys_user.tenant_no 一致default="zkxw" 或 DEFAULT_TENANT_NO=zkxw;若发现历史 zkxw 数据,SHALL 通过 docs/sql/ 迁移脚本统一而非在代码中保留旧默认涉及表结构变更时,维护者 SHALL 在 docs/sql/ 中维护或更新与需求一致的 SQL 说明(全量基线导出为 shanxia2.0.sql;增量变更可补充同目录下其他 .sql),并评估 Alembic/脚本与运行环境的同步(与 AGENTS.md 数据库变更约定一致);含 tenant_no 的表 SHALL 符合 database-conventions 默认租户 shanxia2.0 约定。
database-conventions 中的公共字段规则一致前端(web-admin)与后端(backend)的单个源码文件 SHALL 不超过 500 行。当文件因功能增长接近或超过此限制时,SHALL 将其拆分为多个职责单一的小文件(如:前端提取子组件、composable 或工具函数;后端按领域拆分 service、crud 模块或辅助函数)。配置文件、类型声明文件、SQL 脚本与自动生成文件不在此限制范围内。
crud/production_task.py → crud/production_task.py + crud/production_task_step.py),确保单个文件在 500 行以内提交信息 SHALL 使用完整句子说明「改了什么、为何」,并符合仓库 Conventional Commits / commitlint 类型约束。
web-admin 的 axios 拦截器(src/utils/http/index.ts)已对响应做两层解包:res.data.data → 返回值即为后端 data 字段的内容。因此页面组件中消费 API 函数返回值时,SHALL NOT 再做 { data } 解构或 .data 取值,SHALL 直接从返回值中读取业务字段。
{"code": 200, "data": {"list": [...], "total": 12}}const result = await fetchXxxList(params)result 已经是 {"list": [...], "total": 12},SHALL 使用 result.list、result.total,SHALL NOT 写 const { data } = await fetchXxxList() 再从 data.list 取值{"code": 200, "data": {"smsContent": "..."}}const result = await fetchGenerateSms(id)result 已经是 {"smsContent": "..."},SHALL 使用 result.smsContent,SHALL NOT 写 const { data } = await fetchGenerateSms() 再从 data.smsContent 取值src/utils/http/index.ts 第 420 行的 return res.data.data as T,确认拦截器已剥离 {code, data} 外层包装,消费端直接拿返回值即可前端 API 函数 SHALL 统一使用 request.post() 调用后端接口(文件上传下载除外),与后端统一 POST 路由规范保持一致(详见 api-conventions spec「统一 POST 接口」)。
@router.post("/products/list")fetchProductList SHALL 使用 request.post({ url: '/web/crm/products/list', data: params })request.post() 与后端 @router.post() 一一匹配,SHALL NOT 出现 request.get() / request.put() / request.delete() 调用业务接口将已有系统(CRM、报销、地磅等)的业务模块迁移到 shanxia2.0 框架时,SHALL 严格遵循以下约束,防止功能蔓延:
web-admin 调用 responseType: 'blob' 的接口(CRM Excel 导出、导入模板下载等)时,axios 封装(src/utils/http/index.ts)SHALL:
Content-Type 为 xlsx/octet-stream 等非 JSON 时,SHALL 跳过 JSON 业务码(code === 200)校验,直接返回 Blob。application/json(如 openpyxl 未安装、code: 500)时,SHALL 解析 JSON 并走统一错误抛出,SHALL NOT 将错误 JSON 当作文件下载。request() 在 responseType: 'blob' 时 SHALL 返回 res.data(Blob 本身),SHALL NOT 返回 res.data.data。showErrorMessage: false,由页面 catch 展示「导出失败」,避免与全局 showError 重复。exportClue 使用 responseType: 'blob' 且后端返回 xlsx 流HttpError,页面 SHALL 能通过 URL.createObjectURL 触发下载{ "code": 500, "message": "..." } 且 HTTP 状态仍为 200catch 并提示失败,SHALL NOT 下载损坏的「伪 xlsx」文件