# 前后端开发约束规范(abacus 动静分离微服务) > 版本:1.0(2026-08-19) · 权威来源:本文件(`docs/coding-standards.md`) > 适用范围:基于 `abacus-static-framework`(Vue 前端底座)与 `abacus.springboot.example`(Spring Boot Maven 微服务模板)开展的一切业务开发。 > 读者:**AI 智能体**(生成代码时强制遵守)与**团队全体成员**(评审与开发时共同遵循)。 --- ## 1. 规范目的与适用范围 ### 1.1 目的 1. **界面 → 代码**:用户可直接提供界面(原型图 / 截图 / 描述),由 AI 依据本规范生成前后端代码,无需逐条追问技术细节。 2. **统一约束**:团队所有成员在相同约束下开发,代码结构与风格一致,实现可预期的 Vibe Coding 工作流。 ### 1.2 边界(必须) | 端 | 只读共享区(不得修改) | 业务可写区(唯一开发位置) | |---|---|---| | 前端 | `abacus-static-framework/src/framework/**` | `abacus-static-framework/src/subsystem/**` | | 后端 | `abacus.springboot.example` 的 `pom.xml` / `assembly.xml` / `config/{dev,test,prod}/` 基础结构 | `src/main/java/abacus/springboot.<应用名>/**` + `src/main/resources/sql/**` + `doc/升级日志.md` | - **禁止**在 `src/framework/**` 内新增或修改代码;业务组件/工具无法复用标准件时,按 §4.6/§4.7 提交框架负责人评审后纳入框架,而非绕过。 - 前端框架升级不覆盖清单:`public`、`vite.config.ts`、`src/subsystem`。 ### 1.3 文档层级(单源化) - 本规范是**前后端共享约束的唯一权威**;各子项目 `.project.agents/docs/context/CONVENTIONS.md` 只写本仓库特有约定,共享内容一律以 `详见 ../../docs/coding-standards.md §N` 指针引用,**禁止复制正文**(防止文档漂移)。 --- ## 2. 动静分离架构总览 ``` [前端] Vue 3 源码 (src/subsystem/**) │ npm run build:prod ▼ vite outDir ──► [后端] 微服务工程 src/main/resources/html/vue/<应用名>/ │ │ mvn package(assembly.xml) ▼ 发布包 *-bin.zip(jar + doc + sql + html)──► 部署(Nginx / 容器托管 html,Java 进程提供 API) ``` - 前后端通过 **HTTP 接口**通信;开发期由 `vite.config.ts server.proxy` 反代到后端(代替 Nginx)。 - 后端通过 Nacos 注册/发现;接口文档 springdoc(OpenAPI);统一响应体由 abacus.commons 的 `ResultResponseBodyWrapper` 包装(`Application.java` 注册 `@Bean`,`abacus.responseExcludePath` 排除不包装的 URI)。 --- ## 3. APP_NAME 四处一致性(最高优先级,漏配静默失败) 新系统/新应用开发时,**应用名(APP_NAME)必须在以下四个位置一致**,任一处漏配即静默失败(启动正常但页面 404 / 接口不可达 / 路由不装配): | # | 位置 | 作用 | 示例 | |---|---|---|---| | ① | 后端 `bootstrap.yml` → `spring.application.name` | Nacos 注册名(须唯一) | `example` | | ② | 后端 `application.yml` → `abacus.controllerPackages` / `abacus.entitypackages` / `springdoc.packages-to-scan` 的**包前缀** | 框架装配 Controller / Entity / 接口文档扫描 | `abacus.springboot.example` | | ③ | 前端 `src/subsystem/api//*.ts` 的 **URL 首段** | 服务别名映射(§6.3) | `/example/xxx` | | ④ | 前端 `vite.config.ts` → `build.outDir` 的**目录名** | 构建产物输出到后端 html 目录 | `html/vue/example/` | 包前缀规范:`abacus.springboot.<应用名>.<层>`(分层见 §5.1)。 **排查表**(页面/接口异常时按症状定位): | 症状 | 优先检查 | |---|---| | 页面 404 / 菜单空白 | ④ outDir 目录名 ≠ 后端 html 实际加载目录;③ URL 首段错误 | | 接口 404 / 未装配 | ② 扫描包前缀未含新包;① Nacos 未注册 | | 接口 500 / 服务不可达 | ① 与 ③ 映射不一致(backendServices 找不到别名) | **必须**:AI 生成代码完成后执行"APP_NAME 四联检"(见 §7.3 检查清单第 1 项)。 --- ## 4. 前端开发规范(Vue 3 + TS + Vite + Element Plus + vxe-table + Pinia) ### 4.1 目录结构(`src/subsystem/**` 内) ``` src/subsystem/ ├── api/<服务别名>/ # 接口封装:按微服务名分目录,按 Controller 分 ts 文件 ├── router/dynamicRouter.ts # 菜单路由唯一注册点 ├── views/<一级菜单>/<二级菜单>/index.vue # 菜单页面,按一/二级菜单分目录 ├── extend/ # 框架扩展钩子(如初始化定时器、菜单徽章) ├── components/ # (业务需要时自建)子系统内部通用组件 ├── hooks/ # (自建)业务组合式函数 ├── store/ # (自建)业务状态机(Pinia) ├── styles/ # (自建)业务公共 css ├── types/ # (自建)业务公共类型 └── utils/ # (自建)业务工具函数与常量 ``` - 参考实现:`views/log/operationLog/index.vue`(列表页)、`views/document/dataDictionary/index.vue`(客户端分页)、`views/config/business/index.vue`(可编辑表格)、`views/document/interfacedoc/`(容器页 :is 切换 List/Detail)。 - `unplugin-auto-import` 已配置(vue/vue-router/@vueuse/core + Element Plus resolver):**禁止**手动 `import { ref, reactive } from 'vue'` 等自动导入项。 ### 4.2 命名 - 组件名:PascalCase,且必须与路由 `name` 一致(``)。 - 文件/目录:小写 + 短横线(kebab-case);views 目录用一级/二级菜单中文名或语义名。 - API 函数:`getXxx` / `saveXxx` / `deleteXxx` / `exportXxx`(动词+名词)。 - **禁止**语义为空的命名:`Manager` / `Helper` / `Util` / `Common` / `Misc` / `Tools`(工具类需用具体动词命名,如 `useTableQueryReload`)。 ### 4.3 API 封装(`api/<服务别名>/*.ts`) ```ts import request from '@/framework/utils/request'; // GET:查询,参数走 params export function getOperationLogs(params: any = {}) { return request({ url: '/sms/operationLogs', method: 'get', params }); } // POST:表单提交(urlencoded)或 JSON(默认) export function getAbacusAPIs(data: any = {}) { return request({ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, url: '/sms/document/abacusAPI/list', method: 'post', data }); } ``` - **必须**:`url` 首段为服务别名(§6.3 映射);默认参数 `params/data = {}`。 - **必须**:`status === 200` 时拦截器已自动解包 `data`,**业务代码禁止再取 `.data`**(直接使用返回值)。 - **禁止**:在组件内直接 `axios.get` / `fetch`;一律经 `request` 封装(自动携带 token / commonParam / 服务映射 / 错误提示)。 ### 4.4 页面模式(对应用户给出的界面) | 界面形态 | 标准实现 | |---|---| | 查询 + 列表 | `AbQueryForm`(fieldConfigs 配置式)+ `vxe-grid`(`gridDefaultProps` + `proxyConfig.ajax.query`) | | 服务端分页 | `clientPage: false`(默认,配 `pagerConfig`) | | 客户端分页 | `clientPage: true`(配 `tableDataCache` / `filterNameRef` / `useQueryAndClientPaging`) | | 新增/编辑表单 | `el-dialog` + `AbForm`(配置式) | | 详情 | `el-drawer` 或容器页 `:is` 切换 List/Detail 组件 | | 可编辑表格 | `editConfig: { trigger: 'dblclick', mode: 'row' }` + `editRender: { name: 'input' }` + `@edit-closed` 保存 | | 表内搜索 | `useInVxeGridSearch` | | 刷新/查询联动 | `useTableQueryReload` / `useQueryParamsHandle` | 列表页模板骨架: ```vue