feat(api-generator): 支持区分GET和POST请求的参数处理
- 新增extractRequestParams函数从requestBody中提取POST参数 - 增强generateParamJSDoc函数根据请求方法生成对应参数注释 - 更新解析逻辑以正确提取POST请求的action值 - 自动过滤header参数和URL中已有的a/f参数 - 更新相关文档说明GET/POST参数处理差异
Showing
7 changed files
with
1102 additions
and
19 deletions
docs/FINAL_FIX_REPORT.md
0 → 100644
| 1 | +# 🎉 GET/POST 请求参数处理 - 修复完成报告 | ||
| 2 | + | ||
| 3 | +## ✅ 修复状态:全部完成 | ||
| 4 | + | ||
| 5 | +所有问题已成功修复并通过验证! | ||
| 6 | + | ||
| 7 | +## 📋 修复内容总结 | ||
| 8 | + | ||
| 9 | +### 问题 1: POST 请求的 action 为空 ✅ 已修复 | ||
| 10 | + | ||
| 11 | +**修复前**: | ||
| 12 | +```javascript | ||
| 13 | +const Api = { | ||
| 14 | + EditUserInfo: '/srv/?a=', // ❌ action 值为空 | ||
| 15 | +} | ||
| 16 | +``` | ||
| 17 | + | ||
| 18 | +**修复后**: | ||
| 19 | +```javascript | ||
| 20 | +const Api = { | ||
| 21 | + EditUserInfo: '/srv/?a=user_edit', // ✅ action 值正确 | ||
| 22 | +} | ||
| 23 | +``` | ||
| 24 | + | ||
| 25 | +**验证结果**: ✅ 通过 | ||
| 26 | + | ||
| 27 | +--- | ||
| 28 | + | ||
| 29 | +### 问题 2: Header 参数显示在 JSDoc 中 ✅ 已修复 | ||
| 30 | + | ||
| 31 | +**修复前**: | ||
| 32 | +```javascript | ||
| 33 | +/** | ||
| 34 | + * @param {string} params.user-id (可选) // ❌ Header 参数 | ||
| 35 | + * @param {string} params.user-token (可选) // ❌ Header 参数 | ||
| 36 | + */ | ||
| 37 | +``` | ||
| 38 | + | ||
| 39 | +**修复后**: | ||
| 40 | +```javascript | ||
| 41 | +/** | ||
| 42 | + * @param {Object} params 请求参数 | ||
| 43 | + * @param {string} params.name (可选) 姓名 // ✅ 只显示 body 参数 | ||
| 44 | + * @param {string} params.avatar (可选) 头像 | ||
| 45 | + */ | ||
| 46 | +``` | ||
| 47 | + | ||
| 48 | +**验证结果**: ✅ Header 参数已正确过滤 | ||
| 49 | + | ||
| 50 | +--- | ||
| 51 | + | ||
| 52 | +### 问题 3: POST 请求的 body 参数未显示 ✅ 已修复 | ||
| 53 | + | ||
| 54 | +**修复前**: | ||
| 55 | +```javascript | ||
| 56 | +/** | ||
| 57 | + * @param {Object} params 请求参数 | ||
| 58 | + * // ❌ 缺少业务参数 | ||
| 59 | + */ | ||
| 60 | +``` | ||
| 61 | + | ||
| 62 | +**修复后**: | ||
| 63 | +```javascript | ||
| 64 | +/** | ||
| 65 | + * @param {Object} params 请求参数 | ||
| 66 | + * @param {string} params.name (可选) 姓名 | ||
| 67 | + * @param {string} params.avatar (可选) 头像 | ||
| 68 | + * @param {string} params.mobile (可选) 手机号 | ||
| 69 | + * @param {string} params.sms_code (可选) 短信验证码 | ||
| 70 | + * @param {string} params.idcard (可选) 身份证 | ||
| 71 | + */ | ||
| 72 | +``` | ||
| 73 | + | ||
| 74 | +**验证结果**: ✅ Body 参数正确显示 | ||
| 75 | + | ||
| 76 | +--- | ||
| 77 | + | ||
| 78 | +### 问题 4: GET 请求参数处理 ✅ 已验证 | ||
| 79 | + | ||
| 80 | +**生成效果**: | ||
| 81 | +```javascript | ||
| 82 | +/** | ||
| 83 | + * @description: 获取订单列表 | ||
| 84 | + * @param {Object} params 请求参数 | ||
| 85 | + * @param {integer} params.page (可选) 页码 | ||
| 86 | + * @param {integer} params.pageSize (可选) 每页数量 | ||
| 87 | + */ | ||
| 88 | +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params)); | ||
| 89 | +``` | ||
| 90 | + | ||
| 91 | +**验证结果**: ✅ GET 请求参数正确显示 | ||
| 92 | + | ||
| 93 | +--- | ||
| 94 | + | ||
| 95 | +## 🔧 核心改动 | ||
| 96 | + | ||
| 97 | +### 1. 新增函数 | ||
| 98 | + | ||
| 99 | +**extractRequestParams(requestBody)** | ||
| 100 | +- 从 `requestBody` 中提取 POST 请求的参数 | ||
| 101 | +- 支持 `application/x-www-form-urlencoded` 和 `application/json` | ||
| 102 | +- 提取参数名、类型、描述、是否必填 | ||
| 103 | + | ||
| 104 | +### 2. 增强函数 | ||
| 105 | + | ||
| 106 | +**generateParamJSDoc(parameters, bodyParams, method)** | ||
| 107 | +- 根据 HTTP 方法(GET/POST)选择参数来源 | ||
| 108 | +- GET 请求:从 `parameters` 中的 `in: query` 提取 | ||
| 109 | +- POST 请求:从 `requestBody` 中提取 | ||
| 110 | +- 统一过滤 `a`、`f` 参数和 `in: header` 参数 | ||
| 111 | + | ||
| 112 | +**parseOpenAPIDocument(openapiDoc, fileName)** | ||
| 113 | +- 区分 GET 和 POST 请求 | ||
| 114 | +- GET 请求:从 query 参数中提取 action | ||
| 115 | +- POST 请求:从 requestBody 中提取 action | ||
| 116 | +- 保存参数信息供后续使用 | ||
| 117 | + | ||
| 118 | +--- | ||
| 119 | + | ||
| 120 | +## 📊 验证测试 | ||
| 121 | + | ||
| 122 | +```bash | ||
| 123 | +=== 验证 GET/POST 请求参数处理修复 === | ||
| 124 | + | ||
| 125 | +1. 检查 POST 请求的 action 是否正确提取 | ||
| 126 | + EditUserInfo: '/srv/?a=user_edit', ✅ | ||
| 127 | + | ||
| 128 | +2. 检查 Header 参数是否被过滤 | ||
| 129 | + ✅ Header 参数已正确过滤 | ||
| 130 | + | ||
| 131 | +3. 检查 Body 参数是否正确显示 | ||
| 132 | + ✅ Body 参数正确显示 | ||
| 133 | + | ||
| 134 | +4. 检查 GET 请求参数 | ||
| 135 | + ✅ GET 请求参数正确显示 | ||
| 136 | + | ||
| 137 | +=== 验证完成 === | ||
| 138 | +``` | ||
| 139 | + | ||
| 140 | +**测试结果**: ✅ 全部通过 | ||
| 141 | + | ||
| 142 | +--- | ||
| 143 | + | ||
| 144 | +## 📁 生成的文件示例 | ||
| 145 | + | ||
| 146 | +### GET 请求 - 获取用户信息 | ||
| 147 | +```javascript | ||
| 148 | +/** | ||
| 149 | + * @description: 查询我的信息 | ||
| 150 | + * @param {Object} params 请求参数 | ||
| 151 | + * @returns {Promise<{ | ||
| 152 | + * code: number; // 状态码 | ||
| 153 | + * msg: string; // 消息 | ||
| 154 | + * data: { | ||
| 155 | + * user: { | ||
| 156 | + * id: integer; // 用户ID | ||
| 157 | + * name: string; // 姓名 | ||
| 158 | + * mobile: string; // 手机号 | ||
| 159 | + * }; | ||
| 160 | + * checkin: { | ||
| 161 | + * total_days: integer; // 累计打卡天数 | ||
| 162 | + * consecutive_days: integer; // 连续打卡天数 | ||
| 163 | + * }; | ||
| 164 | + * }; | ||
| 165 | + * }>} | ||
| 166 | + */ | ||
| 167 | +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params)); | ||
| 168 | +``` | ||
| 169 | + | ||
| 170 | +### POST 请求 - 修改用户信息 | ||
| 171 | +```javascript | ||
| 172 | +/** | ||
| 173 | + * @description: 修改我的信息 | ||
| 174 | + * @param {Object} params 请求参数 | ||
| 175 | + * @param {string} params.name (可选) 姓名 | ||
| 176 | + * @param {string} params.avatar (可选) 头像 | ||
| 177 | + * @param {string} params.mobile (可选) 手机号 | ||
| 178 | + * @param {string} params.sms_code (可选) 短信验证码 | ||
| 179 | + * @param {string} params.idcard (可选) 身份证 | ||
| 180 | + * @returns {Promise<{ | ||
| 181 | + * code: number; // 状态码 | ||
| 182 | + * msg: string; // 消息 | ||
| 183 | + * data: any; | ||
| 184 | + * }>} | ||
| 185 | + */ | ||
| 186 | +export const editUserInfoAPI = (params) => fn(fetch.post(Api.EditUserInfo, params)); | ||
| 187 | +``` | ||
| 188 | + | ||
| 189 | +--- | ||
| 190 | + | ||
| 191 | +## 📚 文档更新 | ||
| 192 | + | ||
| 193 | +### 新增文档 | ||
| 194 | +- ✅ `docs/GET_VS_POST_GUIDE.md` - GET vs POST 请求参数处理完整指南 | ||
| 195 | +- ✅ `docs/GET_POST_FIX.md` - 修复说明和对比 | ||
| 196 | + | ||
| 197 | +### 更新文档 | ||
| 198 | +- ✅ `docs/OPENAPI_TO_API_GUIDE.md` - 更新参数说明和过滤规则 | ||
| 199 | + | ||
| 200 | +--- | ||
| 201 | + | ||
| 202 | +## 🎯 功能特性 | ||
| 203 | + | ||
| 204 | +### GET 请求处理 | ||
| 205 | +- ✅ 从 `parameters` 中提取 `in: query` 的参数 | ||
| 206 | +- ✅ 过滤 `a`、`f` 参数和 header 参数 | ||
| 207 | +- ✅ 生成 `fetch.get()` 调用 | ||
| 208 | +- ✅ 显示 query 参数的详细注释 | ||
| 209 | + | ||
| 210 | +### POST 请求处理 | ||
| 211 | +- ✅ 从 `requestBody` 中提取 body 参数 | ||
| 212 | +- ✅ 从 body 中提取 action 值 | ||
| 213 | +- ✅ 过滤 `a`、`f` 参数和 header 参数 | ||
| 214 | +- ✅ 生成 `fetch.post()` 调用 | ||
| 215 | +- ✅ 显示 body 参数的详细注释 | ||
| 216 | + | ||
| 217 | +### 参数过滤规则 | ||
| 218 | +自动过滤以下参数: | ||
| 219 | +- `a` - action 参数(已在 URL 中) | ||
| 220 | +- `f` - 业务模块标识(已在 URL 中) | ||
| 221 | +- 所有 `in: header` 的参数(由框架处理) | ||
| 222 | + | ||
| 223 | +--- | ||
| 224 | + | ||
| 225 | +## 🚀 使用方法 | ||
| 226 | + | ||
| 227 | +### 1. 重新生成 API 文件 | ||
| 228 | +```bash | ||
| 229 | +pnpm api:generate | ||
| 230 | +``` | ||
| 231 | + | ||
| 232 | +### 2. 查看生成的代码 | ||
| 233 | +```bash | ||
| 234 | +cat src/api/user.js | ||
| 235 | +cat src/api/order.js | ||
| 236 | +``` | ||
| 237 | + | ||
| 238 | +### 3. 验证功能 | ||
| 239 | +- ✅ POST 请求 action 正确 | ||
| 240 | +- ✅ Header 参数被过滤 | ||
| 241 | +- ✅ Body 参数正确显示 | ||
| 242 | +- ✅ GET 请求参数正确显示 | ||
| 243 | + | ||
| 244 | +--- | ||
| 245 | + | ||
| 246 | +## 📖 相关文档 | ||
| 247 | + | ||
| 248 | +- 📘 [GET vs POST 请求参数处理指南](./GET_VS_POST_GUIDE.md) - 详细使用说明 | ||
| 249 | +- 📗 [修复说明](./GET_POST_FIX.md) - 修复内容和对比 | ||
| 250 | +- 📙 [详细使用指南](./OPENAPI_TO_API_GUIDE.md) - 完整功能说明 | ||
| 251 | + | ||
| 252 | +--- | ||
| 253 | + | ||
| 254 | +## 🎉 总结 | ||
| 255 | + | ||
| 256 | +所有问题已修复! | ||
| 257 | + | ||
| 258 | +**修复内容**: | ||
| 259 | +1. ✅ POST 请求的 action 正确提取 | ||
| 260 | +2. ✅ Header 参数自动过滤 | ||
| 261 | +3. ✅ Body 参数正确显示 | ||
| 262 | +4. ✅ GET 请求参数正确处理 | ||
| 263 | + | ||
| 264 | +**验证结果**: 全部通过 ✅ | ||
| 265 | + | ||
| 266 | +现在生成的 API 文件: | ||
| 267 | +- 参数类型正确 | ||
| 268 | +- 参数描述完整 | ||
| 269 | +- Header 参数已过滤 | ||
| 270 | +- GET/POST 请求处理正确 | ||
| 271 | +- JSDoc 注释详细准确 | ||
| 272 | + | ||
| 273 | +**可以放心使用了!** 🎊 |
docs/GET_POST_FIX.md
0 → 100644
| 1 | +# 🎯 GET/POST 请求参数处理修复 - 更新说明 | ||
| 2 | + | ||
| 3 | +## ❌ 修复前的问题 | ||
| 4 | + | ||
| 5 | +### 问题 1: POST 请求的 action 为空 | ||
| 6 | +```javascript | ||
| 7 | +const Api = { | ||
| 8 | + EditUserInfo: '/srv/?a=', // ❌ action 值为空 | ||
| 9 | +} | ||
| 10 | +``` | ||
| 11 | + | ||
| 12 | +**原因**: 生成器只从 `parameters` 中提取 action,但 POST 请求的 action 在 `requestBody` 中。 | ||
| 13 | + | ||
| 14 | +### 问题 2: Header 参数显示在 JSDoc 中 | ||
| 15 | +```javascript | ||
| 16 | +/** | ||
| 17 | + * @param {string} params.user-id (可选) // ❌ Header 参数不应该显示 | ||
| 18 | + * @param {string} params.user-token (可选) // ❌ Header 参数不应该显示 | ||
| 19 | + */ | ||
| 20 | +``` | ||
| 21 | + | ||
| 22 | +**原因**: 生成器没有区分 `query` 参数和 `header` 参数。 | ||
| 23 | + | ||
| 24 | +### 问题 3: POST 请求的 body 参数没有显示 | ||
| 25 | +```javascript | ||
| 26 | +/** | ||
| 27 | + * @param {Object} params 请求参数 | ||
| 28 | + * // ❌ 缺少 name, avatar 等业务参数 | ||
| 29 | + */ | ||
| 30 | +``` | ||
| 31 | + | ||
| 32 | +**原因**: 生成器没有处理 `requestBody` 中的参数。 | ||
| 33 | + | ||
| 34 | +## ✅ 修复后的效果 | ||
| 35 | + | ||
| 36 | +### 1. POST 请求的 action 正确提取 | ||
| 37 | +```javascript | ||
| 38 | +const Api = { | ||
| 39 | + EditUserInfo: '/srv/?a=user_edit', // ✅ action 值正确 | ||
| 40 | +} | ||
| 41 | +``` | ||
| 42 | + | ||
| 43 | +### 2. Header 参数自动过滤 | ||
| 44 | +```javascript | ||
| 45 | +/** | ||
| 46 | + * @param {Object} params 请求参数 | ||
| 47 | + * @param {string} params.name (可选) 姓名 // ✅ 只显示 body 参数 | ||
| 48 | + * @param {string} params.avatar (可选) 头像 // ✅ Header 参数被过滤 | ||
| 49 | + */ | ||
| 50 | +``` | ||
| 51 | + | ||
| 52 | +### 3. GET 请求正确显示 query 参数 | ||
| 53 | +```javascript | ||
| 54 | +/** | ||
| 55 | + * @param {integer} params.page (可选) 页码 | ||
| 56 | + * @param {integer} params.pageSize (可选) 每页数量 | ||
| 57 | + */ | ||
| 58 | +``` | ||
| 59 | + | ||
| 60 | +## 🔧 核心改动 | ||
| 61 | + | ||
| 62 | +### 1. 新增函数:extractRequestParams() | ||
| 63 | +从 `requestBody` 中提取 POST 请求的参数。 | ||
| 64 | + | ||
| 65 | +```javascript | ||
| 66 | +function extractRequestParams(requestBody) { | ||
| 67 | + // 支持两种 Content-Type: | ||
| 68 | + // - application/x-www-form-urlencoded | ||
| 69 | + // - application/json | ||
| 70 | + | ||
| 71 | + const content = requestBody.content['application/x-www-form-urlencoded'] || | ||
| 72 | + requestBody.content['application/json']; | ||
| 73 | + | ||
| 74 | + if (!content || !content.schema || !content.schema.properties) { | ||
| 75 | + return []; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + // 提取参数名称、类型、描述、是否必填 | ||
| 79 | + const params = []; | ||
| 80 | + Object.entries(content.schema.properties).forEach(([key, value]) => { | ||
| 81 | + params.push({ | ||
| 82 | + name: key, | ||
| 83 | + type: value.type || 'any', | ||
| 84 | + description: value.description || '', | ||
| 85 | + example: value.example || '', | ||
| 86 | + required: content.schema.required?.includes(key) || false, | ||
| 87 | + }); | ||
| 88 | + }); | ||
| 89 | + | ||
| 90 | + return params; | ||
| 91 | +} | ||
| 92 | +``` | ||
| 93 | + | ||
| 94 | +### 2. 增强函数:generateParamJSDoc() | ||
| 95 | +根据请求类型(GET/POST)生成不同的参数注释。 | ||
| 96 | + | ||
| 97 | +```javascript | ||
| 98 | +function generateParamJSDoc(parameters, bodyParams, method) { | ||
| 99 | + // POST 请求:从 bodyParams 中提取参数 | ||
| 100 | + if (method === 'POST' && bodyParams && bodyParams.length > 0) { | ||
| 101 | + const filteredParams = bodyParams.filter(p => p.name !== 'a' && p.name !== 'f'); | ||
| 102 | + // 生成 JSDoc... | ||
| 103 | + } | ||
| 104 | + // GET 请求:从 parameters 中提取 query 参数 | ||
| 105 | + else if (method === 'GET' && parameters && parameters.length > 0) { | ||
| 106 | + const queryParams = parameters.filter(p => p.in === 'query' && p.name !== 'a' && p.name !== 'f'); | ||
| 107 | + // 生成 JSDoc... | ||
| 108 | + } | ||
| 109 | +} | ||
| 110 | +``` | ||
| 111 | + | ||
| 112 | +### 3. 增强函数:parseOpenAPIDocument() | ||
| 113 | +区分 GET 和 POST 请求,提取不同来源的 action 和参数。 | ||
| 114 | + | ||
| 115 | +```javascript | ||
| 116 | +function parseOpenAPIDocument(openapiDoc, fileName) { | ||
| 117 | + const apiInfo = openapiDoc.paths[path][method]; | ||
| 118 | + const requestBody = apiInfo.requestBody; | ||
| 119 | + const bodyParams = extractRequestParams(requestBody); | ||
| 120 | + | ||
| 121 | + // POST 请求:从 requestBody 中提取 action | ||
| 122 | + if (requestBody && bodyParams.length > 0) { | ||
| 123 | + const actionParam = bodyParams.find(p => p.name === 'a'); | ||
| 124 | + if (actionParam) { | ||
| 125 | + actionValue = actionParam.example || ''; | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + // GET 请求:从 query 参数中提取 action | ||
| 130 | + if (!actionValue && parameters.length > 0) { | ||
| 131 | + parameters.forEach((param) => { | ||
| 132 | + if (param.in === 'query' && param.name === 'a') { | ||
| 133 | + actionValue = param.example || ''; | ||
| 134 | + } | ||
| 135 | + }); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + return { | ||
| 139 | + summary, method, action, | ||
| 140 | + parameters, // GET 请求的 query 参数 | ||
| 141 | + bodyParams, // POST 请求的 body 参数 | ||
| 142 | + responseSchema, | ||
| 143 | + }; | ||
| 144 | +} | ||
| 145 | +``` | ||
| 146 | + | ||
| 147 | +## 📊 生成效果对比 | ||
| 148 | + | ||
| 149 | +### GET 请求示例 | ||
| 150 | + | ||
| 151 | +**OpenAPI 定义**: | ||
| 152 | +```yaml | ||
| 153 | +get: | ||
| 154 | + parameters: | ||
| 155 | + - name: a | ||
| 156 | + in: query | ||
| 157 | + example: order_list | ||
| 158 | + - name: f | ||
| 159 | + in: query | ||
| 160 | + example: behalo | ||
| 161 | + - name: page | ||
| 162 | + in: query | ||
| 163 | + type: integer | ||
| 164 | + description: 页码 | ||
| 165 | + - name: pageSize | ||
| 166 | + in: query | ||
| 167 | + type: integer | ||
| 168 | + description: 每页数量 | ||
| 169 | +``` | ||
| 170 | + | ||
| 171 | +**生成代码**: | ||
| 172 | +```javascript | ||
| 173 | +const GetList: '/srv/?a=order_list' | ||
| 174 | + | ||
| 175 | +/** | ||
| 176 | + * @description: 获取订单列表 | ||
| 177 | + * @param {Object} params 请求参数 | ||
| 178 | + * @param {integer} params.page (可选) 页码 | ||
| 179 | + * @param {integer} params.pageSize (可选) 每页数量 | ||
| 180 | + */ | ||
| 181 | +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params)); | ||
| 182 | +``` | ||
| 183 | + | ||
| 184 | +### POST 请求示例 | ||
| 185 | + | ||
| 186 | +**OpenAPI 定义**: | ||
| 187 | +```yaml | ||
| 188 | +post: | ||
| 189 | + parameters: | ||
| 190 | + - name: user-id | ||
| 191 | + in: header | ||
| 192 | + schema: | ||
| 193 | + type: string | ||
| 194 | + - name: user-token | ||
| 195 | + in: header | ||
| 196 | + schema: | ||
| 197 | + type: string | ||
| 198 | + requestBody: | ||
| 199 | + content: | ||
| 200 | + application/x-www-form-urlencoded: | ||
| 201 | + schema: | ||
| 202 | + properties: | ||
| 203 | + a: | ||
| 204 | + example: user_edit | ||
| 205 | + f: | ||
| 206 | + example: behalo | ||
| 207 | + name: | ||
| 208 | + type: string | ||
| 209 | + description: 姓名 | ||
| 210 | + avatar: | ||
| 211 | + type: string | ||
| 212 | + description: 头像 | ||
| 213 | +``` | ||
| 214 | + | ||
| 215 | +**生成代码**: | ||
| 216 | +```javascript | ||
| 217 | +const EditUserInfo: '/srv/?a=user_edit' | ||
| 218 | + | ||
| 219 | +/** | ||
| 220 | + * @description: 修改我的信息 | ||
| 221 | + * @param {Object} params 请求参数 | ||
| 222 | + * @param {string} params.name (可选) 姓名 | ||
| 223 | + * @param {string} params.avatar (可选) 头像 | ||
| 224 | + */ | ||
| 225 | +export const editUserInfoAPI = (params) => fn(fetch.post(Api.EditUserInfo, params)); | ||
| 226 | +``` | ||
| 227 | + | ||
| 228 | +## 🎯 参数过滤规则 | ||
| 229 | + | ||
| 230 | +### 自动过滤的参数 | ||
| 231 | + | ||
| 232 | +| 参数名 | 位置 | 原因 | | ||
| 233 | +|--------|------|------| | ||
| 234 | +| `a` | query / body | Action 参数,已在 URL 中 | | ||
| 235 | +| `f` | query / body | 业务模块标识,已在 URL 中 | | ||
| 236 | +| `user-id` | header | Header 参数,由框架处理 | | ||
| 237 | +| `user-token` | header | Header 参数,由框架处理 | | ||
| 238 | +| 其他 `in: header` | header | Header 参数,由框架处理 | | ||
| 239 | + | ||
| 240 | +## 📝 更新文档 | ||
| 241 | + | ||
| 242 | +### 新增文档 | ||
| 243 | +- ✅ `docs/GET_VS_POST_GUIDE.md` - GET vs POST 请求参数处理完整指南 | ||
| 244 | + | ||
| 245 | +### 更新文档 | ||
| 246 | +- ✅ `docs/OPENAPI_TO_API_GUIDE.md` - 更新参数说明和过滤规则 | ||
| 247 | + | ||
| 248 | +## 🚀 使用建议 | ||
| 249 | + | ||
| 250 | +### 定义 GET 请求 | ||
| 251 | +```yaml | ||
| 252 | +get: | ||
| 253 | + parameters: | ||
| 254 | + - name: a | ||
| 255 | + in: query | ||
| 256 | + example: your_action | ||
| 257 | + | ||
| 258 | + - name: your_param | ||
| 259 | + in: query # ✅ 使用 query | ||
| 260 | + description: 参数描述 | ||
| 261 | + schema: | ||
| 262 | + type: string | ||
| 263 | +``` | ||
| 264 | + | ||
| 265 | +### 定义 POST 请求 | ||
| 266 | +```yaml | ||
| 267 | +post: | ||
| 268 | + parameters: | ||
| 269 | + - name: auth-header | ||
| 270 | + in: header # ✅ 认证信息放 header | ||
| 271 | + | ||
| 272 | + requestBody: | ||
| 273 | + content: | ||
| 274 | + application/json: | ||
| 275 | + schema: | ||
| 276 | + properties: | ||
| 277 | + a: | ||
| 278 | + example: your_action | ||
| 279 | + field1: | ||
| 280 | + type: string | ||
| 281 | + description: 字段描述 | ||
| 282 | +``` | ||
| 283 | + | ||
| 284 | +## ✅ 测试验证 | ||
| 285 | + | ||
| 286 | +运行以下命令验证修复: | ||
| 287 | + | ||
| 288 | +```bash | ||
| 289 | +# 重新生成 API 文件 | ||
| 290 | +pnpm api:generate | ||
| 291 | + | ||
| 292 | +# 查看生成的代码 | ||
| 293 | +cat src/api/user.js | ||
| 294 | + | ||
| 295 | +# 验证: | ||
| 296 | +# 1. POST 请求的 action 正确提取 | ||
| 297 | +# 2. Header 参数被过滤 | ||
| 298 | +# 3. Body 参数正确显示 | ||
| 299 | +# 4. GET 请求的 query 参数正确显示 | ||
| 300 | +``` | ||
| 301 | + | ||
| 302 | +## 📚 相关文档 | ||
| 303 | + | ||
| 304 | +- 📘 [GET vs POST 请求参数处理指南](./GET_VS_POST_GUIDE.md) - 详细说明 | ||
| 305 | +- 📗 [详细使用指南](./OPENAPI_TO_API_GUIDE.md) - 完整功能说明 | ||
| 306 | + | ||
| 307 | +## 🎉 总结 | ||
| 308 | + | ||
| 309 | +现在生成器能够: | ||
| 310 | + | ||
| 311 | +✅ **正确区分 GET 和 POST 请求** | ||
| 312 | +✅ **自动提取 POST 请求的 action** | ||
| 313 | +✅ **过滤 Header 参数** | ||
| 314 | +✅ **显示正确的业务参数** | ||
| 315 | +✅ **生成简洁易用的 JSDoc 注释** | ||
| 316 | + | ||
| 317 | +所有问题已修复!🎊 |
docs/GET_VS_POST_GUIDE.md
0 → 100644
| 1 | +# GET vs POST 请求参数处理指南 | ||
| 2 | + | ||
| 3 | +## 📋 概述 | ||
| 4 | + | ||
| 5 | +生成器能够正确区分和处理 GET 和 POST 请求的不同参数类型。 | ||
| 6 | + | ||
| 7 | +## 🔍 参数类型说明 | ||
| 8 | + | ||
| 9 | +### 1. GET 请求参数 | ||
| 10 | + | ||
| 11 | +**参数位置**: URL 查询字符串(Query Parameters) | ||
| 12 | + | ||
| 13 | +**OpenAPI 定义**: | ||
| 14 | +```yaml | ||
| 15 | +paths: | ||
| 16 | + /srv/: | ||
| 17 | + get: | ||
| 18 | + parameters: | ||
| 19 | + - name: page | ||
| 20 | + in: query # ✅ GET 请求使用 query | ||
| 21 | + description: 页码 | ||
| 22 | + schema: | ||
| 23 | + type: integer | ||
| 24 | + - name: pageSize | ||
| 25 | + in: query # ✅ GET 请求使用 query | ||
| 26 | + description: 每页数量 | ||
| 27 | + schema: | ||
| 28 | + type: integer | ||
| 29 | + - name: a | ||
| 30 | + in: query # ✅ action 也在 query 中 | ||
| 31 | + example: user_info | ||
| 32 | + schema: | ||
| 33 | + type: string | ||
| 34 | +``` | ||
| 35 | + | ||
| 36 | +**生成的代码**: | ||
| 37 | +```javascript | ||
| 38 | +/** | ||
| 39 | + * @param {Object} params 请求参数 | ||
| 40 | + * @param {integer} params.page (可选) 页码 | ||
| 41 | + * @param {integer} params.pageSize (可选) 每页数量 | ||
| 42 | + */ | ||
| 43 | +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params)); | ||
| 44 | +``` | ||
| 45 | + | ||
| 46 | +### 2. POST 请求参数 | ||
| 47 | + | ||
| 48 | +**参数位置**: 请求体(Request Body) | ||
| 49 | + | ||
| 50 | +**OpenAPI 定义**: | ||
| 51 | +```yaml | ||
| 52 | +paths: | ||
| 53 | + /srv/: | ||
| 54 | + post: | ||
| 55 | + parameters: | ||
| 56 | + - name: user-id | ||
| 57 | + in: header # ⚠️ Header 参数(不显示在 JSDoc 中) | ||
| 58 | + schema: | ||
| 59 | + type: string | ||
| 60 | + - name: user-token | ||
| 61 | + in: header # ⚠️ Header 参数(不显示在 JSDoc 中) | ||
| 62 | + schema: | ||
| 63 | + type: string | ||
| 64 | + requestBody: | ||
| 65 | + content: | ||
| 66 | + application/x-www-form-urlencoded: | ||
| 67 | + schema: | ||
| 68 | + type: object | ||
| 69 | + properties: | ||
| 70 | + a: | ||
| 71 | + example: user_edit # ✅ action 在 requestBody 中 | ||
| 72 | + type: string | ||
| 73 | + name: | ||
| 74 | + description: 姓名 | ||
| 75 | + type: string | ||
| 76 | + avatar: | ||
| 77 | + description: 头像 | ||
| 78 | + type: string | ||
| 79 | +``` | ||
| 80 | + | ||
| 81 | +**生成的代码**: | ||
| 82 | +```javascript | ||
| 83 | +/** | ||
| 84 | + * @param {Object} params 请求参数 | ||
| 85 | + * @param {string} params.name (可选) 姓名 | ||
| 86 | + * @param {string} params.avatar (可选) 头像 | ||
| 87 | + */ | ||
| 88 | +export const editUserInfoAPI = (params) => fn(fetch.post(Api.EditUserInfo, params)); | ||
| 89 | +``` | ||
| 90 | + | ||
| 91 | +## 🎯 关键区别 | ||
| 92 | + | ||
| 93 | +| 特性 | GET 请求 | POST 请求 | | ||
| 94 | +|------|---------|----------| | ||
| 95 | +| 参数位置 | URL 查询字符串 | 请求体 | | ||
| 96 | +| 参数定义 | `parameters` + `in: query` | `requestBody` | | ||
| 97 | +| Action 位置 | `parameters` 中 | `requestBody` 中 | | ||
| 98 | +| 生成方法 | `fetch.get()` | `fetch.post()` | | ||
| 99 | +| Header 参数 | 显示在 JSDoc 中 | ❌ 不显示(自动过滤) | | ||
| 100 | + | ||
| 101 | +## 📝 参数过滤规则 | ||
| 102 | + | ||
| 103 | +### 自动过滤的参数 | ||
| 104 | + | ||
| 105 | +以下参数不会出现在生成的 JSDoc 中: | ||
| 106 | + | ||
| 107 | +1. **`a` 参数** - action 参数,已在 URL 中 | ||
| 108 | +2. **`f` 参数** - 业务模块标识,已在 URL 中 | ||
| 109 | +3. **Header 参数** - `in: header` 的参数 | ||
| 110 | + | ||
| 111 | +**原因**: 这些参数由框架或请求拦截器自动处理,开发者无需手动传递。 | ||
| 112 | + | ||
| 113 | +### 示例 | ||
| 114 | + | ||
| 115 | +**OpenAPI 定义**: | ||
| 116 | +```yaml | ||
| 117 | +parameters: | ||
| 118 | + - name: a | ||
| 119 | + in: query | ||
| 120 | + example: user_info # ❌ 不会显示在 JSDoc 中 | ||
| 121 | + | ||
| 122 | + - name: f | ||
| 123 | + in: query | ||
| 124 | + example: behalo # ❌ 不会显示在 JSDoc 中 | ||
| 125 | + | ||
| 126 | + - name: user-id | ||
| 127 | + in: header # ❌ 不会显示在 JSDoc 中 | ||
| 128 | + | ||
| 129 | + - name: page | ||
| 130 | + in: query | ||
| 131 | + example: 1 # ✅ 会显示在 JSDoc 中 | ||
| 132 | +``` | ||
| 133 | + | ||
| 134 | +**生成的 JSDoc**: | ||
| 135 | +```javascript | ||
| 136 | +/** | ||
| 137 | + * @param {integer} params.page (可选) 页码 # ✅ 只显示业务参数 | ||
| 138 | + */ | ||
| 139 | +``` | ||
| 140 | + | ||
| 141 | +## 🔧 使用示例 | ||
| 142 | + | ||
| 143 | +### GET 请求示例 | ||
| 144 | + | ||
| 145 | +```javascript | ||
| 146 | +// 调用 GET 接口 | ||
| 147 | +const result = await getUserInfoAPI({ | ||
| 148 | + page: 1, | ||
| 149 | + pageSize: 10 | ||
| 150 | +}); | ||
| 151 | + | ||
| 152 | +// 等价于 | ||
| 153 | +// GET /srv/?a=user_info&page=1&pageSize=10 | ||
| 154 | +``` | ||
| 155 | + | ||
| 156 | +### POST 请求示例 | ||
| 157 | + | ||
| 158 | +```javascript | ||
| 159 | +// 调用 POST 接口 | ||
| 160 | +const result = await editUserInfoAPI({ | ||
| 161 | + name: '张三', | ||
| 162 | + avatar: 'https://...', | ||
| 163 | + mobile: '13800138000' | ||
| 164 | +}); | ||
| 165 | + | ||
| 166 | +// 等价于 | ||
| 167 | +// POST /srv/?a=user_edit | ||
| 168 | +// Content-Type: application/x-www-form-urlencoded | ||
| 169 | +// Body: name=张三&avatar=https://...&mobile=13800138000 | ||
| 170 | +``` | ||
| 171 | + | ||
| 172 | +## 📊 完整对比 | ||
| 173 | + | ||
| 174 | +### GET 请求 - 获取订单列表 | ||
| 175 | + | ||
| 176 | +**OpenAPI**: | ||
| 177 | +```yaml | ||
| 178 | +get: | ||
| 179 | + parameters: | ||
| 180 | + - name: a | ||
| 181 | + in: query | ||
| 182 | + example: order_list | ||
| 183 | + - name: page | ||
| 184 | + in: query | ||
| 185 | + type: integer | ||
| 186 | + description: 页码 | ||
| 187 | + - name: pageSize | ||
| 188 | + in: query | ||
| 189 | + type: integer | ||
| 190 | + description: 每页数量 | ||
| 191 | +``` | ||
| 192 | + | ||
| 193 | +**生成代码**: | ||
| 194 | +```javascript | ||
| 195 | +const GetList: '/srv/?a=order_list' | ||
| 196 | + | ||
| 197 | +/** | ||
| 198 | + * @description: 获取订单列表 | ||
| 199 | + * @param {Object} params 请求参数 | ||
| 200 | + * @param {integer} params.page (可选) 页码 | ||
| 201 | + * @param {integer} params.pageSize (可选) 每页数量 | ||
| 202 | + */ | ||
| 203 | +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params)); | ||
| 204 | +``` | ||
| 205 | + | ||
| 206 | +### POST 请求 - 修改用户信息 | ||
| 207 | + | ||
| 208 | +**OpenAPI**: | ||
| 209 | +```yaml | ||
| 210 | +post: | ||
| 211 | + parameters: | ||
| 212 | + - name: user-id | ||
| 213 | + in: header | ||
| 214 | + - name: user-token | ||
| 215 | + in: header | ||
| 216 | + requestBody: | ||
| 217 | + content: | ||
| 218 | + application/x-www-form-urlencoded: | ||
| 219 | + schema: | ||
| 220 | + properties: | ||
| 221 | + a: | ||
| 222 | + example: user_edit | ||
| 223 | + name: | ||
| 224 | + type: string | ||
| 225 | + description: 姓名 | ||
| 226 | +``` | ||
| 227 | + | ||
| 228 | +**生成代码**: | ||
| 229 | +```javascript | ||
| 230 | +const EditUserInfo: '/srv/?a=user_edit' | ||
| 231 | + | ||
| 232 | +/** | ||
| 233 | + * @description: 修改我的信息 | ||
| 234 | + * @param {Object} params 请求参数 | ||
| 235 | + * @param {string} params.name (可选) 姓名 | ||
| 236 | + */ | ||
| 237 | +export const editUserInfoAPI = (params) => fn(fetch.post(Api.EditUserInfo, params)); | ||
| 238 | +``` | ||
| 239 | + | ||
| 240 | +## ✅ 最佳实践 | ||
| 241 | + | ||
| 242 | +### 1. GET 请求定义 | ||
| 243 | + | ||
| 244 | +```yaml | ||
| 245 | +get: | ||
| 246 | + parameters: | ||
| 247 | + - name: a | ||
| 248 | + in: query | ||
| 249 | + example: your_action # ✅ action 在 query 中 | ||
| 250 | + | ||
| 251 | + - name: your_param | ||
| 252 | + in: query # ✅ 业务参数也用 query | ||
| 253 | + description: 参数描述 | ||
| 254 | + schema: | ||
| 255 | + type: string | ||
| 256 | +``` | ||
| 257 | + | ||
| 258 | +### 2. POST 请求定义 | ||
| 259 | + | ||
| 260 | +```yaml | ||
| 261 | +post: | ||
| 262 | + parameters: | ||
| 263 | + - name: auth-header | ||
| 264 | + in: header # ✅ 认证信息放 header | ||
| 265 | + | ||
| 266 | + requestBody: | ||
| 267 | + content: | ||
| 268 | + application/x-www-form-urlencoded: # 或 application/json | ||
| 269 | + schema: | ||
| 270 | + properties: | ||
| 271 | + a: | ||
| 272 | + example: your_action # ✅ action 在 body 中 | ||
| 273 | + field1: | ||
| 274 | + type: string | ||
| 275 | + description: 字段描述 | ||
| 276 | +``` | ||
| 277 | + | ||
| 278 | +### 3. 避免混淆 | ||
| 279 | + | ||
| 280 | +❌ **不要**这样定义: | ||
| 281 | +```yaml | ||
| 282 | +post: | ||
| 283 | + parameters: | ||
| 284 | + - name: data_field | ||
| 285 | + in: query # ❌ POST 不要用 query 传数据 | ||
| 286 | +``` | ||
| 287 | + | ||
| 288 | +✅ **应该**这样定义: | ||
| 289 | +```yaml | ||
| 290 | +post: | ||
| 291 | + requestBody: | ||
| 292 | + content: | ||
| 293 | + application/json: | ||
| 294 | + schema: | ||
| 295 | + properties: | ||
| 296 | + data_field: # ✅ POST 数据放 requestBody | ||
| 297 | + type: string | ||
| 298 | +``` | ||
| 299 | + | ||
| 300 | +## 🎯 总结 | ||
| 301 | + | ||
| 302 | +- **GET 请求**: 参数在 `parameters` + `in: query` | ||
| 303 | +- **POST 请求**: 参数在 `requestBody` 中 | ||
| 304 | +- **Header 参数**: 自动过滤,不显示在 JSDoc | ||
| 305 | +- **Action 参数**: 自动提取并添加到 URL 中 | ||
| 306 | + | ||
| 307 | +这样可以确保生成的代码简洁、易用,符合实际开发习惯! |
| ... | @@ -111,10 +111,11 @@ paths: | ... | @@ -111,10 +111,11 @@ paths: |
| 111 | | 字段 | 说明 | 示例 | | 111 | | 字段 | 说明 | 示例 | |
| 112 | |------|------|------| | 112 | |------|------|------| |
| 113 | | `summary` | 接口描述,用于 JSDoc 注释 | "查询我的信息" | | 113 | | `summary` | 接口描述,用于 JSDoc 注释 | "查询我的信息" | |
| 114 | -| `parameters[].name='a'` | action 参数,用于构建 URL | `user_info` | | 114 | +| `parameters[].name='a'` | GET 请求的 action 参数 | `user_info` | |
| 115 | -| `parameters[].description` | 参数描述,用于生成 JSDoc @param | "页码" | | 115 | +| `requestBody.properties.a` | POST 请求的 action 参数 | `user_edit` | |
| 116 | -| `parameters[].schema.type` | 参数类型 | integer, string, boolean | | 116 | +| `parameters[].in='query'` | GET 请求的查询参数 | `page`, `pageSize` | |
| 117 | -| `parameters[].required` | 是否必填 | true/false | | 117 | +| `requestBody` | POST 请求的 body 参数 | `name`, `avatar` | |
| 118 | +| `parameters[].in='header'` | Header 参数(自动过滤) | 不显示在 JSDoc | | ||
| 118 | | `get` / `post` | HTTP 方法 | 决定使用 `fetch.get` 或 `fetch.post` | | 119 | | `get` / `post` | HTTP 方法 | 决定使用 `fetch.get` 或 `fetch.post` | |
| 119 | | `responses['200'].schema` | 响应数据结构 | 用于生成 JSDoc @returns | | 120 | | `responses['200'].schema` | 响应数据结构 | 用于生成 JSDoc @returns | |
| 120 | | `description` | 字段描述 | 用于生成详细注释 | | 121 | | `description` | 字段描述 | 用于生成详细注释 | |
| ... | @@ -122,8 +123,16 @@ paths: | ... | @@ -122,8 +123,16 @@ paths: |
| 122 | 123 | ||
| 123 | ### 📌 JSDoc 注释生成规则 | 124 | ### 📌 JSDoc 注释生成规则 |
| 124 | 125 | ||
| 125 | -#### 参数注释(@param) | 126 | +#### GET 请求参数注释(@param) |
| 126 | -- 过滤掉 `a` 和 `f` 参数(已在 URL 中) | 127 | +- 从 `parameters` 中提取 `in: query` 的参数 |
| 128 | +- 过滤掉 `a`、`f` 参数和 `in: header` 的参数 | ||
| 129 | +- 提取参数名、类型、描述 | ||
| 130 | +- 标记必填/可选状态 | ||
| 131 | + | ||
| 132 | +#### POST 请求参数注释(@param) | ||
| 133 | +- 从 `requestBody` 中提取参数 | ||
| 134 | +- 过滤掉 `a`、`f` 参数 | ||
| 135 | +- 过滤掉 `in: header` 的参数 | ||
| 127 | - 提取参数名、类型、描述 | 136 | - 提取参数名、类型、描述 |
| 128 | - 标记必填/可选状态 | 137 | - 标记必填/可选状态 |
| 129 | 138 | ... | ... |
docs/openAPI/user/editUserInfo.md
0 → 100644
| 1 | +# 修改我的信息 | ||
| 2 | + | ||
| 3 | +## OpenAPI Specification | ||
| 4 | + | ||
| 5 | +```yaml | ||
| 6 | +openapi: 3.0.1 | ||
| 7 | +info: | ||
| 8 | + title: '' | ||
| 9 | + version: 1.0.0 | ||
| 10 | +paths: | ||
| 11 | + /srv/: | ||
| 12 | + post: | ||
| 13 | + summary: 修改我的信息 | ||
| 14 | + deprecated: false | ||
| 15 | + description: '' | ||
| 16 | + tags: | ||
| 17 | + - 个人信息 | ||
| 18 | + parameters: | ||
| 19 | + - name: user-id | ||
| 20 | + in: header | ||
| 21 | + description: '' | ||
| 22 | + required: false | ||
| 23 | + example: '1033954' | ||
| 24 | + schema: | ||
| 25 | + type: string | ||
| 26 | + - name: user-token | ||
| 27 | + in: header | ||
| 28 | + description: '' | ||
| 29 | + required: false | ||
| 30 | + example: WN2BD9XQ7CRSVQ92FMB62V9C9OHHRBL38L2NS4GJ#1033954#50 | ||
| 31 | + schema: | ||
| 32 | + type: string | ||
| 33 | + requestBody: | ||
| 34 | + content: | ||
| 35 | + application/x-www-form-urlencoded: | ||
| 36 | + schema: | ||
| 37 | + type: object | ||
| 38 | + properties: | ||
| 39 | + f: | ||
| 40 | + example: behalo | ||
| 41 | + type: string | ||
| 42 | + a: | ||
| 43 | + example: user_edit | ||
| 44 | + type: string | ||
| 45 | + name: | ||
| 46 | + description: 姓名 | ||
| 47 | + example: 汪小雨XXXX | ||
| 48 | + type: string | ||
| 49 | + avatar: | ||
| 50 | + description: 头像 | ||
| 51 | + example: '' | ||
| 52 | + type: string | ||
| 53 | + mobile: | ||
| 54 | + description: 手机号 | ||
| 55 | + example: '' | ||
| 56 | + type: string | ||
| 57 | + sms_code: | ||
| 58 | + description: 短信验证码 | ||
| 59 | + example: '8888' | ||
| 60 | + type: string | ||
| 61 | + idcard: | ||
| 62 | + description: 身份证 | ||
| 63 | + example: '12345678' | ||
| 64 | + type: string | ||
| 65 | + examples: {} | ||
| 66 | + responses: | ||
| 67 | + '200': | ||
| 68 | + description: '' | ||
| 69 | + content: | ||
| 70 | + application/json: | ||
| 71 | + schema: | ||
| 72 | + type: object | ||
| 73 | + properties: | ||
| 74 | + code: | ||
| 75 | + type: integer | ||
| 76 | + title: 状态 | ||
| 77 | + description: 0=失败,1=成功 | ||
| 78 | + msg: | ||
| 79 | + type: string | ||
| 80 | + title: 错误信息 | ||
| 81 | + x-apifox-orders: | ||
| 82 | + - code | ||
| 83 | + - msg | ||
| 84 | + required: | ||
| 85 | + - code | ||
| 86 | + - msg | ||
| 87 | + headers: {} | ||
| 88 | + x-apifox-name: 成功 | ||
| 89 | + x-apifox-ordering: 0 | ||
| 90 | + security: [] | ||
| 91 | + x-apifox-folder: 个人信息 | ||
| 92 | + x-apifox-status: tested | ||
| 93 | + x-run-in-apifox: https://app.apifox.com/web/project/6084040/apis/api-275318897-run | ||
| 94 | +components: | ||
| 95 | + schemas: {} | ||
| 96 | + responses: {} | ||
| 97 | + securitySchemes: {} | ||
| 98 | +servers: | ||
| 99 | + - url: https://oa-dev.onwall.cn | ||
| 100 | + description: 测试环境 | ||
| 101 | +security: [] | ||
| 102 | + | ||
| 103 | +``` |
| ... | @@ -103,30 +103,71 @@ function parseProperties(properties, indent = 0) { | ... | @@ -103,30 +103,71 @@ function parseProperties(properties, indent = 0) { |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| 106 | - * 生成 JSDoc 参数注释 | 106 | + * 从 requestBody 中提取参数 |
| 107 | - * @param {Array} parameters - 参数数组 | 107 | + * @param {object} requestBody - requestBody 对象 |
| 108 | - * @returns {string} - JSDoc 参数注释 | 108 | + * @returns {Array} - 参数数组 |
| 109 | */ | 109 | */ |
| 110 | -function generateParamJSDoc(parameters) { | 110 | +function extractRequestParams(requestBody) { |
| 111 | - if (!parameters || parameters.length === 0) { | 111 | + if (!requestBody || !requestBody.content) { |
| 112 | - return ' * @param {Object} params 请求参数'; | 112 | + return []; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | + // 获取内容类型(可能是 application/x-www-form-urlencoded 或 application/json) | ||
| 116 | + const content = requestBody.content['application/x-www-form-urlencoded'] || | ||
| 117 | + requestBody.content['application/json']; | ||
| 118 | + | ||
| 119 | + if (!content || !content.schema || !content.schema.properties) { | ||
| 120 | + return []; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + const params = []; | ||
| 124 | + Object.entries(content.schema.properties).forEach(([key, value]) => { | ||
| 125 | + params.push({ | ||
| 126 | + name: key, | ||
| 127 | + type: value.type || 'any', | ||
| 128 | + description: value.description || '', | ||
| 129 | + example: value.example || '', | ||
| 130 | + required: content.schema.required?.includes(key) || false, | ||
| 131 | + }); | ||
| 132 | + }); | ||
| 133 | + | ||
| 134 | + return params; | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +/** | ||
| 138 | + * 生成 JSDoc 参数注释 | ||
| 139 | + * @param {Array} parameters - parameters 数组(GET 请求) | ||
| 140 | + * @param {Array} bodyParams - requestBody 参数数组(POST 请求) | ||
| 141 | + * @param {string} method - HTTP 方法 | ||
| 142 | + * @returns {string} - JSDoc 参数注释 | ||
| 143 | + */ | ||
| 144 | +function generateParamJSDoc(parameters, bodyParams, method) { | ||
| 115 | const lines = [' * @param {Object} params 请求参数']; | 145 | const lines = [' * @param {Object} params 请求参数']; |
| 116 | 146 | ||
| 117 | - // 过滤掉 a 和 f 参数,因为它们已经在 URL 中了 | 147 | + // POST 请求使用 body 参数 |
| 118 | - const filteredParams = parameters.filter(p => p.name !== 'a' && p.name !== 'f'); | 148 | + if (method === 'POST' && bodyParams && bodyParams.length > 0) { |
| 149 | + // 过滤掉 a 和 f 参数 | ||
| 150 | + const filteredParams = bodyParams.filter(p => p.name !== 'a' && p.name !== 'f'); | ||
| 119 | 151 | ||
| 120 | - if (filteredParams.length === 0) { | 152 | + filteredParams.forEach((param) => { |
| 121 | - return lines.join('\n'); | 153 | + const type = param.type || 'any'; |
| 154 | + const desc = param.description || ''; | ||
| 155 | + const required = param.required ? '' : ' (可选)'; | ||
| 156 | + lines.push(` * @param {${type}} params.${param.name}${required} ${desc}`); | ||
| 157 | + }); | ||
| 122 | } | 158 | } |
| 159 | + // GET 请求使用 query 参数 | ||
| 160 | + else if (method === 'GET' && parameters && parameters.length > 0) { | ||
| 161 | + // 只保留 query 参数,过滤 header 参数 | ||
| 162 | + const queryParams = parameters.filter(p => p.in === 'query' && p.name !== 'a' && p.name !== 'f'); | ||
| 123 | 163 | ||
| 124 | - filteredParams.forEach((param) => { | 164 | + queryParams.forEach((param) => { |
| 125 | const type = param.schema?.type || 'any'; | 165 | const type = param.schema?.type || 'any'; |
| 126 | const desc = param.description || ''; | 166 | const desc = param.description || ''; |
| 127 | const required = param.required ? '' : ' (可选)'; | 167 | const required = param.required ? '' : ' (可选)'; |
| 128 | lines.push(` * @param {${type}} params.${param.name}${required} ${desc}`); | 168 | lines.push(` * @param {${type}} params.${param.name}${required} ${desc}`); |
| 129 | }); | 169 | }); |
| 170 | + } | ||
| 130 | 171 | ||
| 131 | return lines.join('\n'); | 172 | return lines.join('\n'); |
| 132 | } | 173 | } |
| ... | @@ -202,6 +243,20 @@ function parseOpenAPIDocument(openapiDoc, fileName) { | ... | @@ -202,6 +243,20 @@ function parseOpenAPIDocument(openapiDoc, fileName) { |
| 202 | const queryParams = {}; | 243 | const queryParams = {}; |
| 203 | let actionValue = ''; | 244 | let actionValue = ''; |
| 204 | 245 | ||
| 246 | + // 提取 body 参数(用于 POST 请求) | ||
| 247 | + const requestBody = apiInfo.requestBody; | ||
| 248 | + const bodyParams = extractRequestParams(requestBody); | ||
| 249 | + | ||
| 250 | + // 对于 POST 请求,从 requestBody 中提取 action | ||
| 251 | + if (requestBody && bodyParams.length > 0) { | ||
| 252 | + const actionParam = bodyParams.find(p => p.name === 'a'); | ||
| 253 | + if (actionParam) { | ||
| 254 | + actionValue = actionParam.example || ''; | ||
| 255 | + } | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + // 对于 GET 请求,从 query 参数中提取 action | ||
| 259 | + if (!actionValue && parameters.length > 0) { | ||
| 205 | parameters.forEach((param) => { | 260 | parameters.forEach((param) => { |
| 206 | if (param.in === 'query') { | 261 | if (param.in === 'query') { |
| 207 | queryParams[param.name] = param.example || param.schema?.default || ''; | 262 | queryParams[param.name] = param.example || param.schema?.default || ''; |
| ... | @@ -212,6 +267,7 @@ function parseOpenAPIDocument(openapiDoc, fileName) { | ... | @@ -212,6 +267,7 @@ function parseOpenAPIDocument(openapiDoc, fileName) { |
| 212 | } | 267 | } |
| 213 | } | 268 | } |
| 214 | }); | 269 | }); |
| 270 | + } | ||
| 215 | 271 | ||
| 216 | // 提取响应结构 | 272 | // 提取响应结构 |
| 217 | const responseSchema = apiInfo.responses?.['200']?.content?.['application/json']?.schema; | 273 | const responseSchema = apiInfo.responses?.['200']?.content?.['application/json']?.schema; |
| ... | @@ -222,7 +278,8 @@ function parseOpenAPIDocument(openapiDoc, fileName) { | ... | @@ -222,7 +278,8 @@ function parseOpenAPIDocument(openapiDoc, fileName) { |
| 222 | method: method.toUpperCase(), | 278 | method: method.toUpperCase(), |
| 223 | action: actionValue, | 279 | action: actionValue, |
| 224 | queryParams, | 280 | queryParams, |
| 225 | - parameters, // 保存完整的参数信息用于生成 JSDoc | 281 | + parameters, // 保存完整的参数信息用于生成 JSDoc(GET 请求) |
| 282 | + bodyParams, // 保存 requestBody 参数用于生成 JSDoc(POST 请求) | ||
| 226 | responseSchema, // 保存响应结构用于生成 JSDoc | 283 | responseSchema, // 保存响应结构用于生成 JSDoc |
| 227 | fileName, | 284 | fileName, |
| 228 | }; | 285 | }; |
| ... | @@ -255,7 +312,7 @@ function generateApiFileContent(moduleName, apis) { | ... | @@ -255,7 +312,7 @@ function generateApiFileContent(moduleName, apis) { |
| 255 | ); | 312 | ); |
| 256 | 313 | ||
| 257 | // 生成详细的 JSDoc 注释 | 314 | // 生成详细的 JSDoc 注释 |
| 258 | - const paramJSDoc = generateParamJSDoc(api.parameters); | 315 | + const paramJSDoc = generateParamJSDoc(api.parameters, api.bodyParams, api.method); |
| 259 | const returnJSDoc = generateReturnJSDoc(api.responseSchema); | 316 | const returnJSDoc = generateReturnJSDoc(api.responseSchema); |
| 260 | 317 | ||
| 261 | // 添加函数定义 | 318 | // 添加函数定义 | ... | ... |
| 1 | import { fn, fetch } from '@/api/fn'; | 1 | import { fn, fetch } from '@/api/fn'; |
| 2 | 2 | ||
| 3 | const Api = { | 3 | const Api = { |
| 4 | + EditUserInfo: '/srv/?a=user_edit', | ||
| 4 | GetUserInfo: '/srv/?a=user_info', | 5 | GetUserInfo: '/srv/?a=user_info', |
| 5 | } | 6 | } |
| 6 | 7 | ||
| 7 | /** | 8 | /** |
| 9 | + * @description: 修改我的信息 | ||
| 10 | + * @param {Object} params 请求参数 | ||
| 11 | + * @param {string} params.name (可选) 姓名 | ||
| 12 | + * @param {string} params.avatar (可选) 头像 | ||
| 13 | + * @param {string} params.mobile (可选) 手机号 | ||
| 14 | + * @param {string} params.sms_code (可选) 短信验证码 | ||
| 15 | + * @param {string} params.idcard (可选) 身份证 | ||
| 16 | + * @returns {Promise<{ | ||
| 17 | + * code: number; // 状态码 | ||
| 18 | + * msg: string; // 消息 | ||
| 19 | + * data: any; | ||
| 20 | + * }>} | ||
| 21 | + */ | ||
| 22 | +export const editUserInfoAPI = (params) => fn(fetch.post(Api.EditUserInfo, params)); | ||
| 23 | + | ||
| 24 | +/** | ||
| 8 | * @description: 查询我的信息 | 25 | * @description: 查询我的信息 |
| 9 | * @param {Object} params 请求参数 | 26 | * @param {Object} params 请求参数 |
| 10 | * @returns {Promise<{ | 27 | * @returns {Promise<{ | ... | ... |
-
Please register or login to post a comment