@qilitt-mickey/vue3-temp-skill 1.1.11 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,331 +1,51 @@
1
1
  ---
2
2
  skill: api-check
3
- description: 前后端接口对接检查清单。在对接后端 API 或 AI 生成接口调用代码后,必须对照此清单验证接口契约的正确性,确保前后端数据流通畅。适用于接口联调、AI 生成 API 代码自检、本地 Mock 场景。
3
+ description: 前后端接口联调核对清单。对接后端或生成 API 后对照契约;写法细则见 http-api。
4
4
  scope: project
5
- tags: [api, backend, integration, contract, http, request, response, debug, checklist, mock]
5
+ tags: [api, backend, integration, contract, http, checklist, mock]
6
6
  ---
7
7
 
8
- # 前后端接口对接检查清单
8
+ # 前后端接口对接检查
9
9
 
10
- > **使用说明**:在对接后端 API 或 AI 生成接口调用代码后,逐项对照检查。确保前端调用方式与后端接口定义完全匹配,避免联调阶段反复返工。
11
- > **权威来源**:以仓库代码为准——`types/global.d.ts`(`Result` / 分页)、`src/utils/http.ts`、`src/api/**`、`mock/**`、`src/hooks/useTableSearch.ts`。
10
+ 写法与示例 → **`http-api`**。本文件只做联调核对。权威源:`types/global.d.ts`、`src/utils/http.ts`、`src/api/**`、`mock/**`、`useTableSearch`。
12
11
 
13
- ## 一、接口基本信息核对
12
+ ## 基本信息
14
13
 
15
- ### 必须确认
14
+ - [ ] 业务 path 与后端文档一致;忌把 `/mock/...` 当生产约定
15
+ - [ ] 真实 URL:`VITE_API_BASE_URL` + path;忌硬编码域名 / 虚构 `/api` 前缀
16
+ - [ ] 方法跟文档(允许 GET/POST);POST→`data`,GET→`params`
17
+ - [ ] Content-Type:默认 JSON;上传 `multipart/form-data`
18
+ - [ ] 认证头:`token` / `userCode`(拦截器注入)
19
+ - [ ] 加解密:`VITE_ENCODE_SWITCH`;无 `crypto: true`;GET 默认不加解密
16
20
 
17
- - [ ] **请求地址**:业务接口路径与后端文档一致;**禁止**把本地 Mock 前缀(如 `/mock/...`)当成前后端约定。
18
- - [ ] **域名来源**:真实接口使用 `import.meta.env.VITE_API_BASE_URL` 拼接业务 path,禁止硬编码域名。
19
- - [ ] **请求方法**:与后端接口文档一致即可。**允许 GET / POST**(项目未禁止 GET);常见业务写操作用 POST,查询/下载/签名等后端要求 GET 时用 GET。
20
- - [ ] **参数位置**:POST 业务体用 `data`;GET 查询串用 `params`。二者按方法匹配,不要混用错位置。
21
- - [ ] **Content-Type**:默认 `application/json`,文件上传使用 `multipart/form-data`。
22
- - [ ] **认证方式**:拦截器自动注入请求头 `token`、`userCode`(不是 `Authorization: Bearer`)。
23
- - [ ] **加解密**:由环境变量 `VITE_ENCODE_SWITCH` 全局控制(见 `src/utils/http.ts`),**没有**单请求 `crypto: true` 开关;GET 默认不走加解密。
21
+ ## 请求参数
24
22
 
25
- ### URL 约定(务必区分「真实联调」与「本地 Mock」)
23
+ - [ ] 驼峰字段与文档一致;必填已传
24
+ - [ ] `Long` / `BigDecimal` → `string`;日期格式与后端约定一致
25
+ - [ ] 分页入参:`pageNo`(从 1)/ `pageSize`
26
26
 
27
- ```typescript
28
- // ✅ 真实业务接口:环境变量 + 后端业务 path(示例,path 以接口文档为准)
29
- `${import.meta.env.VITE_API_BASE_URL}/console/common/attachment/list`
30
- `${import.meta.env.VITE_API_BASE_URL}/baseCode/search?uuid=${buildUUID()}`
27
+ ## 响应
31
28
 
32
- // ✅ 本地 Fake Server(vite-plugin-fake-server,目录 mock/)
33
- // 仅开发 Mock 使用,不是前后端规范前缀
34
- "/mock/login"
35
- "/mock/console/customerPortrait/queryCustomerRelation"
36
- "/get-table-list" // 部分 Fake Server 路径也可能不带 /mock 前缀
29
+ - [ ] `Result<T>`:`status === 200` / `statusText` / `data`
30
+ - [ ] 分页:`content` / `totalCount`(非 `list`/`total`)
31
+ - [ ] 可空字段类型含 `| null`;展示用可选链
37
32
 
38
- ```
33
+ ## 特殊场景
39
34
 
40
- 说明:
35
+ - [ ] 上传:`FormData` + `repeatRequest: true`(见 `http-api`)
36
+ - [ ] 下载:`responseType: "blob"` + `blobDown`
37
+ - [ ] 列表优先 `useTableSearch`;空列表 `content=[]`、`totalCount=0`
41
38
 
42
- 1. **`/mock/...`、部分裸路径**:服务本地 `mock/*.ts`(`defineFakeRoute`),用于后端未就绪时的前端开发。
43
- 2. **真实联调**:换成 `VITE_API_BASE_URL` + 后端真实 path;path 形态由后端文档决定,**不是**统一的 `/api` 前缀规范。
44
- 3. **方法以接口文档为准**:允许 GET;不要为了“统一 POST”去改后端已定义的 GET 接口。也勿无依据地套路径参数式 REST(如 `/users/:id`),除非文档就是这样定义。
39
+ ## Mock
45
40
 
46
- ## 二、请求参数核对
41
+ - [ ] 用根目录 `mock/` + `vite-plugin-fake-server`;回包符合 `Result<T>`
42
+ - [ ] 后端就绪后 API 改为真实 path,组件调用尽量不变
47
43
 
48
- ### 必须确认
44
+ ## 联调排查(短)
49
45
 
50
- - [ ] **参数位置**:POST → `data`(body);GET → `params`(query)。与方法匹配即可。
51
- - [ ] **字段命名**:前后端统一 **驼峰 camelCase**(如 `userName`、`userCode`、`pageNo`),与接口文档一致。
52
- - [ ] **字段类型**:字符串/数字/布尔/数组/对象,与后端定义匹配。
53
- - [ ] **必填字段**:所有后端标记为必填的字段,前端必须传递。
54
- - [ ] **默认值**:后端有默认值的字段,前端不传时使用后端默认值。
55
- - [ ] **枚举值**:状态码、类型码等枚举值与后端定义一致。
56
-
57
- ### 参数格式对照表
58
-
59
- | 后端 Java 类型 | 前端 TypeScript 类型 | 注意事项 |
60
- |---------------|---------------------|---------|
61
- | `String` | `string` | 空字符串 `""` 与 `null` 不同 |
62
- | `Integer` | `number` | 普通整型可用 number |
63
- | `Long` | `string` | 超过 `Number.MAX_SAFE_INTEGER` 会丢精度,统一用 `string` |
64
- | `Boolean` | `boolean` | `0/1` 与 `true/false` 需确认后端用哪种 |
65
- | `BigDecimal` | `string` | 金额类字段必须用 `string` 避免精度丢失 |
66
- | `Date` / `LocalDateTime` | `string` | 确认格式:`yyyy-MM-dd` 还是 `yyyy-MM-dd HH:mm:ss` |
67
- | `List<T>` | `T[]` | 确认数组元素的类型 |
68
- | `Map<String, Object>` | `Record<string, unknown>` | 尽量避免,要求后端定义明确结构 |
69
-
70
- ### 常见参数错误
71
-
72
- ```typescript
73
- import { http } from "@/utils/http";
74
-
75
- const base = import.meta.env.VITE_API_BASE_URL;
76
-
77
- // ❌ 错误:POST 却把业务参数放在 params
78
- http.request("post", `${base}/console/user/list`, { params: { pageNo: 1, pageSize: 10 } });
79
-
80
- // ✅ 正确:POST 业务参数放 data
81
- http.request("post", `${base}/console/user/list`, { data: { pageNo: 1, pageSize: 10 } });
82
-
83
- // ✅ 正确:后端约定 GET 时使用 get + params(项目允许)
84
- http.request("get", `${base}/console/common/downLoadTemplate`, {
85
- params: { fileName: "模板.xlsx" },
86
- responseType: "blob",
87
- });
88
-
89
- // ❌ 错误:写成全小写 username(本项目前后端约定驼峰)
90
- { username: "张三" }
91
-
92
- // ✅ 正确:驼峰命名,与后端字段一致
93
- { userName: "张三", userCode: "zhangsan" }
94
-
95
- // ❌ 错误:金额使用 number(精度丢失)
96
- { amount: 99999999.99 }
97
-
98
- // ✅ 正确:金额使用 string
99
- { amount: "99999999.99" }
100
-
101
- // ❌ 错误:分页字段名套用通用脚手架习惯
102
- { page: 1, pageSize: 10 } // 或 pageNum
103
-
104
- // ✅ 正确:本项目分页入参(见 QueryData / useTableSearch)
105
- { pageNo: 1, pageSize: 10 }
106
- ```
107
-
108
- ## 三、响应数据核对
109
-
110
- ### 必须确认
111
-
112
- - [ ] **响应结构**:后端返回全局 `Result<T>`(`types/global.d.ts`),成功判断用 **`status === 200`**,文案用 **`statusText`**。
113
- - [ ] **数据类型**:`data` 字段的类型与前端声明的泛型 `T` 一致(`data` 可能为 `null`)。
114
- - [ ] **列表结构**:分页列表标准为 `{ content, totalCount, pageNo, pageSize, pageCount? }`,**不是** `{ list, total }`。
115
- - [ ] **空值处理**:后端可能返回 `null` 的字段,前端类型要包含 `| null`,展示用可选链。
116
- - [ ] **嵌套结构**:复杂对象的嵌套层级与后端返回一致。
117
- - [ ] **日期格式**:后端返回的日期字符串格式,前端展示时是否需要格式化。
118
-
119
- ### 响应类型定义(与仓库一致)
120
-
121
- ```typescript
122
- // types/global.d.ts(权威定义,勿另造 success/code/message 结构)
123
- interface Result<T = unknown> {
124
- att?: unknown[];
125
- data?: T | null;
126
- exceptionName?: null;
127
- status?: number;
128
- statusText?: string;
129
- name?: string; // blob 下载等场景可能附带文件名
130
- }
131
-
132
- interface Data {
133
- pageNo?: number;
134
- pageSize?: number;
135
- pageCount?: number;
136
- totalCount?: number;
137
- content?: Content[];
138
- }
139
-
140
- // 业务示例
141
- interface UserInfo {
142
- id: string;
143
- userName: string; // 驼峰
144
- userCode: string;
145
- phone: string | null;
146
- createTime: string;
147
- }
148
-
149
- function getUserListApi(data: CombinedQueryData) {
150
- return http.request<Result<Data>>(
151
- "post",
152
- `${import.meta.env.VITE_API_BASE_URL}/console/user/list`,
153
- { data },
154
- );
155
- }
156
-
157
- // 组件中使用
158
- const res = await getUserListApi(query);
159
- if (res.status === 200) {
160
- const list = res.data?.content ?? [];
161
- const total = res.data?.totalCount ?? 0;
162
- }
163
- ```
164
-
165
- ### 常见响应处理错误
166
-
167
- ```typescript
168
- // ❌ 错误:按 success / message / code 解构(本项目没有这些字段)
169
- const { success, message } = await getUserListApi(params);
170
-
171
- // ✅ 正确:按 status / statusText / data 处理
172
- const res = await getUserListApi(params);
173
- if (res.status === 200) {
174
- const list = res.data?.content ?? [];
175
- }
176
-
177
- // ❌ 错误:当成 { list, total }
178
- const list = res.data.list;
179
- const total = res.data.total;
180
-
181
- // ✅ 正确:content + totalCount(useTableSearch 已按此约定解析)
182
- const list = res.data?.content ?? [];
183
- const total = res.data?.totalCount ?? 0;
184
-
185
- // ❌ 错误:没有处理 null
186
- <span>{{ user.phone.length }}</span>
187
-
188
- // ✅ 正确:可选链
189
- <span>{{ user.phone?.length ?? "-" }}</span>
190
- ```
191
-
192
- ## 四、特殊场景检查
193
-
194
- ### 文件上传
195
-
196
- - [ ] `Content-Type` 设置为 `multipart/form-data`。
197
- - [ ] 使用 `FormData` 对象传递文件。
198
- - [ ] 文件大小限制与后端配置一致。
199
- - [ ] 上传进度有 UI 反馈(如有)。
200
-
201
- ```typescript
202
- // ✅ 参考 src/api/common/index.ts getUploadUrl
203
- function uploadFileApi(file: File, path = "/documentInfo/uploadFile") {
204
- const formData = new FormData();
205
- formData.append("file", file);
206
- return http.request<Result<UploadFileResult>>(
207
- "post",
208
- `${import.meta.env.VITE_API_BASE_URL}${path}`,
209
- {
210
- data: formData,
211
- headers: { "Content-Type": "multipart/form-data" },
212
- },
213
- { repeatRequest: true },
214
- );
215
- }
216
- ```
217
-
218
- ### 文件下载/导出
219
-
220
- - [ ] `responseType` 设置为 `"blob"`。
221
- - [ ] 使用 `blobDown(data, name, response)`(`src/utils/utils.ts`)处理下载。
222
- - [ ] 文件名优先从响应头 `Content-Disposition` 解析;http 封装对 Blob 可能返回 `{ data, name }`。
223
- - [ ] 下载过程有 Loading 状态。
224
-
225
- ```typescript
226
- import { blobDown } from "@/utils/utils";
227
-
228
- async function handleExport() {
229
- loading.value = true;
230
- try {
231
- const res = await exportApi(queryParams); // responseType: "blob"
232
- blobDown(res.data, res.name || "导出数据.xlsx", res);
233
- } finally {
234
- loading.value = false;
235
- }
236
- }
237
- ```
238
-
239
- ### 加解密接口
240
-
241
- - [ ] 确认当前环境 `VITE_ENCODE_SWITCH`、`VITE_ENCODE_PUBKEY` / `VITE_ENCODE_PRIKEY` 已按对接要求配置。
242
- - [ ] 开关开启后,非 GET、非 FormData、非白名单接口由拦截器统一加解密;业务 API **不要**写不存在的 `crypto: true`。
243
- - [ ] 联调时注意:加密开启后控制台可能打印入参/回参明文,正式包需关闭调试输出。
244
-
245
- ### 分页接口
246
-
247
- - [ ] 入参:`pageNo`(从 **1** 开始)、`pageSize`。
248
- - [ ] 出参:`content`、`totalCount`、`pageNo`、`pageSize`(可选 `pageCount`)。
249
- - [ ] 列表页优先用 `useTableSearch`(内部已按上述字段对接)。
250
- - [ ] 空列表时 `totalCount` 为 0,`content` 为空数组 `[]`(不是 `null`)。
251
-
252
- ## 五、联调常见问题排查
253
-
254
- ### 请求发出去了但后端收不到参数
255
-
256
- - 检查参数是否放在了 `data` 中(不是 `params`)。
257
- - 检查 `Content-Type` 是否为 `application/json`。
258
- - 检查字段是否为驼峰,且与后端 `@RequestBody` 字段名一致。
259
- - 若开启了加解密,确认前后端密钥与开关一致。
260
-
261
- ### 后端返回数据但前端取不到
262
-
263
- - 检查是否按 `Result` 处理:`status` / `data` / `statusText`。
264
- - 检查分页是否用了 `content` / `totalCount`(不是 `list` / `total`)。
265
- - 检查是否误把 Mock 路径当成了真实地址(或反过来)。
266
-
267
- ### 跨域问题
268
-
269
- - 开发环境:检查 `build/server.ts` / Vite `server.proxy` 配置。
270
- - 生产环境:确认 Nginx 反向代理与 `VITE_API_BASE_URL` 一致。
271
- - 确认后端 CORS 允许前端域名。
272
-
273
- ### Token 相关
274
-
275
- - 请求头字段为 `token`、`userCode`(见 `src/utils/http.ts` 拦截器)。
276
- - 业务页按项目既有登录态逻辑处理失效场景,勿擅自改成 Bearer 方案。
277
-
278
- ## 六、接口 Mock 规范
279
-
280
- 后端未就绪时,使用项目根目录 **`mock/`** + `vite-plugin-fake-server`(`build/plugins/ViteMockServe.ts`),**不要**在 `src/api/mock/` 手写假 Promise 充当标准方案。
281
-
282
- ```typescript
283
- // mock/login.ts(权威写法)
284
- import { defineFakeRoute } from "vite-plugin-fake-server/client";
285
-
286
- export default defineFakeRoute([
287
- {
288
- url: "/mock/login",
289
- method: "post",
290
- response: ({ body }) => {
291
- // POST:从 body 取入参;GET:从 query 取入参
292
- return {
293
- att: [],
294
- data: {
295
- accessToken: "demo-token",
296
- userCode: body.userCode,
297
- userName: "系统默认管理员", // 驼峰
298
- },
299
- exceptionName: null,
300
- status: 200,
301
- statusText: "Success",
302
- };
303
- },
304
- },
305
- ]);
306
- ```
307
-
308
- 对应 API:
309
-
310
- ```typescript
311
- // src/api/login/index.ts
312
- export const getLogin = (data: LoginParams) => {
313
- return http.request<Result<UserData>>("post", "/mock/login", { data });
314
- };
315
- ```
316
-
317
- ### Mock 约定
318
-
319
- 1. Mock 回包必须符合 `Result<T>`:`status` / `statusText` / `data`(不是 `success` / `code` / `message`)。
320
- 2. 字段名、类型与真实后端契约一致(驼峰;分页用 `content` / `totalCount`)。
321
- 3. API 函数路径可先指向 Mock;后端就绪后改为 `VITE_API_BASE_URL` + 真实 path,组件调用尽量不变。
322
- 4. Mock 文件放在项目根 `mock/`,按模块拆分(如 `mock/login.ts`、`mock/table.ts`)。
323
- 5. 开关与插件:`VITE_USE_MOCK` + `ViteFakeServerPlugin`(`include: 'mock'`)。
324
-
325
- ## 快速自检流程
326
-
327
- 1. **拿到后端接口文档后**:核对真实 path、方法、参数/响应结构;确认不是 Mock 专用路径。
328
- 2. **编写 API 函数时**:`import { http } from "@/utils/http"`;参数放 `data`;返回 `Result<T>`;URL 用 `VITE_API_BASE_URL`(或明确的 Mock 路径)。
329
- 3. **字段与分页**:驼峰命名;列表用 `pageNo`/`pageSize` → `content`/`totalCount`。
330
- 4. **组件中调用时**:判断 `status === 200`,取 `data`,做好空值防护;列表优先 `useTableSearch`。
331
- 5. **联调时**:打开 Network,对比请求 URL/Body/响应与文档;有问题按第五节排查。
46
+ | 现象 | 检查 |
47
+ |------|------|
48
+ | 后端收不到参 | `data` vs `params`;Content-Type;驼峰;加解密密钥 |
49
+ | 前端取不到数 | `status`/`data`;分页字段名;Mock vs 真实 URL |
50
+ | 跨域 | Vite proxy / Nginx / CORS |
51
+ | Token | 请求头是否为 `token`、`userCode` |