AGILE TEAM
Skip to content

Skill ②:接口约定(api-contract)

基于《页面清单》为每个页面生成 api.md 文件,放在页面目录下(和 index.vue 同级)。

双重作用:

  1. 前端 — data.ts 中 API_CONFIG 的 URL 和字段名直接基于 api.md
  2. 后端 — 拿到 api.md 直接出接口(Controller + Service + Entity),字段名一致,联调零成本

URL 命名规范

/[服务缩写]/[资源名CamelCase]/[操作]
服务缩写含义示例
pm生产管理/pm/omptMillPlanOrder/list
mmwr精整作业/mmwr/mmwrTechFinish/queryTechList
mmsm炼钢管理/mmsm/mmsmRsltLadleUse/list
sale销售管理/sale/saleOrder/list
hrms人力资源/hrms/hrmsEmployee/list
base基础数据/base/cmUserGroup/list

标准操作集

操作方法URL 后缀说明
分页列表POST/list基类 super({ url: { list } }) 自动调用
单条查询GET/getById?id=xxxgetAction(API_CONFIG.getById, { id })
新增POST/savepostAction(API_CONFIG.save, formData)
编辑POST/updatepostAction(API_CONFIG.update, formData)
删除POST/remove基类 super({ url: { remove } }) + this.remove(id)
导出GET/exportgetAction(API_CONFIG.export, params)

业务操作命名规范

非标准 CRUD 操作按以下约定命名,URL 后缀使用动词原形(camelCase):

操作方法URL 后缀请求说明
提交审批POST/submit{ id }{ ids: [] }
审批通过POST/approve{ id, opinion? }
审批驳回POST/reject{ id, opinion }
撤回POST/withdraw{ id } 撤回已提交的单据
启用/禁用POST/changeStatus{ id, status }
转化POST/convert{ id } 临时→正式(如临时客户→正式)
下发POST/release{ id } 计划/工单下发执行
关闭POST/close{ id } 关闭订单/计划
作废POST/cancel{ id } 作废单据
批量操作POST/batchXxx/batchSubmit/batchRemove
子表查询POST/queryXxxList/queryDetailList,主从表场景

命名原则:/[服务缩写]/[资源名]/[动作],动作用英文动词原形,不用中文拼音,不加 do / handle 前缀。

统一响应结构(基于真实后端契约)

⚠️ 重要:本项目后端响应外壳为 { code, message, data }result),成功码为 2000非 200)。

1. 分页查询响应

json
{
  "code": 2000,
  "message": "操作成功",
  "data": {
    "records": [{ /* Entity 字段 */ }],
    "total": 100,
    "current": 1,
    "size": 20,
    "pages": 5,
    "countId": null,
    "maxLimit": null,
    "orders": [],
    "searchCount": true
  }
}
data 字段类型说明
recordsarray当前页数据列表
totalnumber总记录数
currentnumber当前页码
sizenumber每页条数
pagesnumber总页数
countIdanyMyBatis-Plus 分页计数 ID(前端忽略)
maxLimitany最大单页限制(前端忽略)
ordersarray排序条件回传(前端忽略)
searchCountboolean是否执行总数查询(前端忽略)

前端 BaseTable / AbstractPageQueryHook 已自动适配:取 data.records 渲染、data.total 设分页。无需在 data.ts 中处理。

2. 单条 / 非分页查询响应

json
{ "code": 2000, "message": "操作成功", "data": { /* Entity 单对象 */ } }

3. 增删改响应

json
{ "code": 2000, "message": "操作成功", "data": true }

4. 失败响应

json
{ "code": 4001, "message": "参数缺失:customerName 不能为空", "data": null }
code 范围含义
2000成功
4xxx客户端错误(参数/权限/校验)
5xxx服务端错误
401 / 403网关层未登录 / 无权限(统一拦截)

业务代码不需要关心 code 判断,request.ts 拦截器统一处理:非 2000 自动 Promise.reject + Toast 提示。业务代码 .then() 拿到的就是 data 字段内容。

字段命名

规范说明
前端camelCase所有请求/响应字段名
后端snake_case数据库字段,Jackson 自动转驼峰

生成产物:api.md 模板

每个页面目录下生成一个 api.md,包含:

markdown
# 接口约定 - [页面中文名]

> 页面路径:`src/views/[域]/[模块]/[子模块]/[目录]/`
> 服务缩写:[pm / mmwr / sale / ...]
> 资源名:[camelCase 实体名]
> 状态:🟡 待后端确认

---

## API_CONFIG

```typescript
export const API_CONFIG = {
  list: "/[服务缩写]/[资源名]/list",
  remove: "/[服务缩写]/[资源名]/remove",
  getById: "/[服务缩写]/[资源名]/getById",
  save: "/[服务缩写]/[资源名]/save",
  update: "/[服务缩写]/[资源名]/update",
  export: "/[服务缩写]/[资源名]/export",
} as const;

实体定义

字段名与 data.ts 中 queryDef/columnsDef 使用的字段名完全一致

字段名类型说明必填字典(logicValue)备注
idstring主键自动-后端生成
[field1]string[说明]-
[statusField]string[状态][dictCode]前端 logicValue 对应
[dateField]string[日期]-YYYY-MM-DD
createTimestring创建时间自动-YYYY-MM-DD HH:mm:ss

接口清单

1. 分页查询

POST /[服务缩写]/[资源名]/list

响应外壳{ code: 2000, message, data: { records, total, current, size, pages, ... } }

2. 详情查询

GET /[服务缩写]/[资源名]/getById?id=xxx

响应外壳{ code: 2000, message, data: {...} }

3. 新增 / 编辑 / 删除

(省略,按标准操作集)


数据字典

dictCode(logicValue)用途出现位置
[dictCode][说明]queryDef / columnsDef / form

## 联调注意

1. **响应外壳**:`{ code, message, data }`,成功 `code: 2000`(非 200,非 result)
2. 前端字段全部 camelCase,后端 JSON 序列化输出 camelCase
3. 时间字段统一 `YYYY-MM-DD HH:mm:ss`
4. 大数字 ID 后端转字符串(雪花 ID 超过 JS Number 精度)
5. 分页参数前端传 `current` / `size`(基类自动处理),后端响应 `data.records` / `data.total`
6. 枚举字段前端传 value,后端可返回 `[field]Label` 辅助展示,或前端自行通过 `logicValue` 字典翻译
7. 业务代码 `.then(res => res)` 拿到的就是 `data` 字段(拦截器已剥外壳)

## 状态标记

- 🟡 待后端确认 — 刚生成
- 🟢 已确认 — 双方对齐,可编码
- 🔴 有变更 — 需双方同步

---

## 标准对话示例

### 示例 1:批量生成流水线

你:基于 reports/PROTOTYPE_SCAN_客户管理_20260426.md,帮我生成全部页面的 api.md。 AI:[Pre-flight] 批量模式,共 7 页 ├─ src/views/mmwr/customer-archive/api.md ✅ ├─ src/views/mmwr/customer-detail/api.md ✅ └─ ... 共 7 个 api.md 已生成,状态均为 🟡 待后端确认


### 示例 2:单页生成 + 变更标记

你:客户档案页的"状态"字段后端已确认用 custStatus,不是 status,帮我更新 api.md。 AI:已更新 src/views/mmwr/customer-archive/api.md 字段 status → custStatus,状态 🟡 → 🟢(已确认)


## 常见踩坑

| 现象 | 原因 | 解法 |
|------|------|------|
| ai.md 与 data.ts 字段名不一致 | page-codegen 没读 api.md 直接生成 | 触发时明确"读取 api.md 生成 data.ts" |
| 同一接口在多页面定义不一致 | 共用接口未抽取到公共层 | 抽取到 src/api/common/,各页面 import |
| 后端改了字段 AI 不知道 | api.md 没有同步标记 | 每次联调后修改 api.md 状态标记 |

## FAQ

**Q:必须先有 page-spec JSON 吗?**  
A:推荐,但也可直接口述需求让 AI 生成 api.md 草稿,后续校验。

**Q:api.md 和后端 Swagger 有没有关系?**  
A:目前独立维护,v2.4 计划支持从 Swagger/OpenAPI 自动生成 api.md。

**Q:前端自己能决定字段名吗?**  
A:查询参数前端可建议,响应体字段名需与后端对齐后再编码。

You may not distribute, modify, or sell this software without permission.