hookehuyr

feat(api-generator): 新增 OpenAPI 转 API 文档生成器及相关文档

- 新增核心生成器脚本,支持从 OpenAPI 文档自动生成 JavaScript API 文件
- 添加详细 JSDoc 注释生成功能,包含完整的参数和返回值类型定义
- 新增示例页面和完整使用文档,提供快速上手指南
- 集成到项目构建流程,添加 npm 命令和路由配置
- 安装所需依赖并更新相关配置文件
1 { 1 {
2 "permissions": { 2 "permissions": {
3 "allow": [ 3 "allow": [
4 - "Bash(pandoc:*)" 4 + "Bash(pandoc:*)",
5 + "Bash(npx skills --help:*)",
6 + "Bash(pnpm add:*)",
7 + "Bash(pnpm api:generate:*)",
8 + "Bash(node:*)",
9 + "Bash(ls:*)"
5 ] 10 ]
6 } 11 }
7 } 12 }
......
...@@ -11,3 +11,4 @@ pnpm-debug.log* ...@@ -11,3 +11,4 @@ pnpm-debug.log*
11 .env.local 11 .env.local
12 .env.*.local 12 .env.*.local
13 unpackage/ 13 unpackage/
14 +.history/
......
1 +# 🚀 OpenAPI 转 API 文档生成器
2 +
3 +> 从 OpenAPI 文档自动生成标准化的 JavaScript API 接口文件
4 +
5 +## ✨ 特性
6 +
7 +- 📁 **自动扫描** - 递归扫描 `docs/openAPI` 目录结构
8 +- 📝 **YAML 解析** - 解析 OpenAPI 3.x 规范的 Markdown 文档
9 +- 🔄 **命名转换** - 自动转换为驼峰命名和帕斯卡命名
10 +- 📦 **模块化** - 按文件夹自动生成独立的 API 模块文件
11 +-**即插即用** - 一条命令完成所有转换
12 +- 🎯 **详细注释** - 自动生成完整的 JSDoc 注释,包含参数类型和返回值结构
13 +
14 +## 📦 快速开始
15 +
16 +### 1. 安装依赖
17 +
18 +```bash
19 +pnpm install
20 +```
21 +
22 +### 2. 创建 OpenAPI 文档
23 +
24 +`docs/openAPI/` 目录下创建模块和接口文档:
25 +
26 +```bash
27 +mkdir -p docs/openAPI/user
28 +```
29 +
30 +编辑 `docs/openAPI/user/getUserInfo.md`
31 +
32 +```markdown
33 +# 查询我的信息
34 +
35 +## OpenAPI Specification
36 +
37 +\```yaml
38 +openapi: 3.0.1
39 +info:
40 + title: ''
41 + version: 1.0.0
42 +paths:
43 + /srv/:
44 + get:
45 + summary: 查询我的信息
46 + tags:
47 + - 个人信息
48 + parameters:
49 + - name: a
50 + in: query
51 + example: user_info
52 + - name: f
53 + in: query
54 + example: behalo
55 + responses:
56 + '200':
57 + description: 成功
58 + content:
59 + application/json:
60 + schema:
61 + properties:
62 + data:
63 + properties:
64 + user:
65 + type: object
66 + properties:
67 + id:
68 + type: integer
69 + description: 用户ID
70 + name:
71 + type: string
72 + description: 姓名
73 +\```
74 +```
75 +
76 +### 3. 生成 API 文件
77 +
78 +```bash
79 +pnpm api:generate
80 +```
81 +
82 +输出:
83 +```
84 +✅ 找到 1 个模块: user
85 +✅ 生成文件: src/api/user.js
86 +```
87 +
88 +**生成的文件包含详细的 JSDoc 注释**
89 +- ✅ 参数类型和描述
90 +- ✅ 返回值完整类型定义
91 +- ✅ 嵌套对象结构
92 +- ✅ 数组类型支持
93 +
94 +### 4. 使用生成的 API
95 +
96 +```javascript
97 +import { getUserInfoAPI } from '@/api/user';
98 +
99 +const result = await getUserInfoAPI();
100 +console.log(result.data);
101 +```
102 +
103 +## 📂 项目结构
104 +
105 +```
106 +docs/openAPI/ # OpenAPI 文档源目录
107 +├── user/ # 模块目录
108 +│ └── getUserInfo.md # 接口文档
109 +└── order/ # 模块目录
110 + ├── getList.md
111 + └── getDetail.md
112 +
113 +scripts/ # 生成器脚本
114 +├── generateApiFromOpenAPI.js # 核心生成器
115 +├── test-generate.js # 测试脚本
116 +└── QUICKSTART.md # 快速开始指南
117 +
118 +src/api/ # 生成的 API 文件
119 +├── user.js # 自动生成 ✨
120 +└── order.js # 自动生成 ✨
121 +
122 +docs/ # 文档
123 +├── OPENAPI_TO_API_GUIDE.md # 详细指南
124 +├── API_USAGE_EXAMPLES.md # 使用示例
125 +└── IMPLEMENTATION_SUMMARY.md # 实现总结
126 +```
127 +
128 +## 🎯 核心功能
129 +
130 +### 1. 自动扫描目录
131 +
132 +```javascript
133 +// 扫描 docs/openAPI 目录
134 +// 识别第一级文件夹为模块名
135 +// 识别文件夹内的 .md 文件为接口文档
136 +```
137 +
138 +### 2. 解析 OpenAPI 规范
139 +
140 +```yaml
141 +# 提取以下字段:
142 +- summary: 接口描述
143 +- parameters: 请求参数
144 +- a: action 值
145 +- get/post: HTTP 方法
146 +```
147 +
148 +### 3. 生成标准化代码
149 +
150 +```javascript
151 +// 输入: user/getUserInfo.md
152 +// 输出:
153 +const Api = {
154 + GetUserInfo: '/srv/?a=user_info',
155 +}
156 +
157 +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params));
158 +```
159 +
160 +## 📋 命令列表
161 +
162 +```bash
163 +# 生成 API 文件
164 +pnpm api:generate
165 +
166 +# 测试生成的文件
167 +node scripts/test-generate.js
168 +
169 +# 启动开发服务器
170 +pnpm dev:weapp
171 +```
172 +
173 +## 🔧 自定义配置
174 +
175 +### 修改输出目录
176 +
177 +编辑 `scripts/generateApiFromOpenAPI.js`:
178 +
179 +```javascript
180 +const outputDir = path.resolve(__dirname, '../src/api');
181 +// 改为其他目录
182 +```
183 +
184 +### 修改命名规则
185 +
186 +编辑命名转换函数:
187 +
188 +```javascript
189 +function toCamelCase(str) {
190 + // 自定义转换逻辑
191 +}
192 +
193 +function toPascalCase(str) {
194 + // 自定义转换逻辑
195 +}
196 +```
197 +
198 +### 修改生成模板
199 +
200 +编辑 `generateApiFileContent()` 函数。
201 +
202 +## 📖 使用示例
203 +
204 +### 基础用法
205 +
206 +```javascript
207 +import { getUserInfoAPI } from '@/api/user';
208 +
209 +const result = await getUserInfoAPI();
210 +if (result.code === 1) {
211 + console.log(result.data);
212 +}
213 +```
214 +
215 +### 结合 Pinia Store
216 +
217 +```javascript
218 +// stores/user.js
219 +import { defineStore } from 'pinia';
220 +import { getUserInfoAPI } from '@/api/user';
221 +
222 +export const useUserStore = defineStore('user', {
223 + actions: {
224 + async fetchUserInfo() {
225 + const result = await getUserInfoAPI();
226 + if (result.code === 1) {
227 + this.userInfo = result.data;
228 + }
229 + },
230 + },
231 +});
232 +```
233 +
234 +### 在 Vue 组件中使用
235 +
236 +```vue
237 +<script setup>
238 +import { ref } from 'vue';
239 +import { getUserInfoAPI } from '@/api/user';
240 +
241 +const userInfo = ref(null);
242 +
243 +const fetchUserInfo = async () => {
244 + const result = await getUserInfoAPI();
245 + if (result.code === 1) {
246 + userInfo.value = result.data;
247 + }
248 +};
249 +</script>
250 +```
251 +
252 +## 🎨 演示页面
253 +
254 +访问演示页面查看实际效果:
255 +
256 +```bash
257 +# 启动开发服务器
258 +pnpm dev:weapp
259 +
260 +# 访问路径
261 +pages/examples/api-demo/index
262 +```
263 +
264 +演示页面包含:
265 +- ✅ 用户信息接口示例
266 +- ✅ 订单列表接口示例
267 +- ✅ 订单详情接口示例
268 +- ✅ 完整的错误处理
269 +- ✅ 加载状态展示
270 +
271 +## 📚 文档
272 +
273 +- 📖 [详细使用指南](./docs/OPENAPI_TO_API_GUIDE.md) - 完整的功能说明
274 +-[快速开始指南](./scripts/QUICKSTART.md) - 快速上手教程
275 +- 💡 [API 使用示例](./docs/API_USAGE_EXAMPLES.md) - 实际使用案例
276 +- 📊 [实现总结](./docs/IMPLEMENTATION_SUMMARY.md) - 技术实现细节
277 +- 🎯 [JSDoc 生成指南](./docs/JSDOC_GENERATION_GUIDE.md) - 详细注释生成规则
278 +
279 +## ✅ 测试结果
280 +
281 +| 测试用例 | 状态 | 说明 |
282 +|---------|------|------|
283 +| 单接口生成 | ✅ 通过 | 单个文件成功生成 |
284 +| 批量接口生成 | ✅ 通过 | 多个接口批量生成 |
285 +| 多模块生成 | ✅ 通过 | 不同模块独立生成 |
286 +| 格式验证 | ✅ 通过 | 生成的代码格式正确 |
287 +
288 +## 🎯 最佳实践
289 +
290 +1. **保持文档同步** - 修改接口后及时更新 OpenAPI 文档
291 +2. **统一命名规范** - 使用驼峰命名文件名
292 +3. **模块化组织** - 相关接口放在同一模块下
293 +4. **版本控制** - 将生成的 API 文件提交到 Git
294 +5. **代码审查** - 生成后检查代码是否符合预期
295 +
296 +## 🔍 常见问题
297 +
298 +### Q: 如何添加新接口?
299 +
300 +A: 在对应模块目录下创建新的 `.md` 文件,运行 `pnpm api:generate`
301 +
302 +### Q: 如何添加新模块?
303 +
304 +A: 创建新的模块文件夹,添加接口文档,运行生成命令
305 +
306 +### Q: 生成的文件可以手动修改吗?
307 +
308 +A: 不建议,每次运行生成命令会覆盖已生成的文件
309 +
310 +### Q: 如何修改生成格式?
311 +
312 +A: 编辑 `scripts/generateApiFromOpenAPI.js` 中的相关函数
313 +
314 +## 🚧 后续规划
315 +
316 +- [ ] TypeScript 类型定义生成
317 +- [ ] Mock 数据自动生成
318 +- [ ] Watch 模式监听文件变化
319 +- [ ] 增量生成(只生成修改过的文件)
320 +- [ ] 可视化配置界面
321 +
322 +## 📞 获取帮助
323 +
324 +遇到问题?
325 +
326 +1. 查看 [详细使用指南](./docs/OPENAPI_TO_API_GUIDE.md)
327 +2. 查看 [API 使用示例](./docs/API_USAGE_EXAMPLES.md)
328 +3. 运行 `node scripts/test-generate.js` 诊断问题
329 +
330 +## 📄 许可证
331 +
332 +MIT
333 +
334 +---
335 +
336 +**现在就开始使用,简化你的 API 开发流程!** 🎉
1 +# API 使用示例
2 +
3 +本文档展示如何使用从 OpenAPI 文档自动生成的 API 接口。
4 +
5 +## 📦 导入 API
6 +
7 +```javascript
8 +// 导入特定模块的 API
9 +import { getUserInfoAPI } from '@/api/user';
10 +```
11 +
12 +## 🔧 基础用法
13 +
14 +### 示例 1: 简单调用
15 +
16 +```javascript
17 +import { getUserInfoAPI } from '@/api/user';
18 +
19 +// 在组件中使用
20 +export default {
21 + setup() {
22 + const fetchUserInfo = async () => {
23 + try {
24 + const result = await getUserInfoAPI({ id: 123 });
25 +
26 + if (result.code === 1) {
27 + console.log('用户信息:', result.data);
28 + } else {
29 + console.error('获取失败:', result.msg);
30 + }
31 + } catch (error) {
32 + console.error('请求异常:', error);
33 + }
34 + };
35 +
36 + return { fetchUserInfo };
37 + }
38 +}
39 +```
40 +
41 +### 示例 2: 结合 Pinia Store
42 +
43 +```javascript
44 +// src/stores/user.js
45 +import { defineStore } from 'pinia';
46 +import { getUserInfoAPI } from '@/api/user';
47 +
48 +export const useUserStore = defineStore('user', {
49 + state: () => ({
50 + userInfo: null,
51 + isLoading: false,
52 + }),
53 +
54 + actions: {
55 + async fetchUserInfo() {
56 + this.isLoading = true;
57 + try {
58 + const result = await getUserInfoAPI();
59 + if (result.code === 1) {
60 + this.userInfo = result.data;
61 + }
62 + } catch (error) {
63 + console.error('获取用户信息失败:', error);
64 + } finally {
65 + this.isLoading = false;
66 + }
67 + },
68 + },
69 +});
70 +```
71 +
72 +### 示例 3: 在 Vue 3 Composition API 中使用
73 +
74 +```vue
75 +<template>
76 + <view>
77 + <nut-button @click="handleGetUserInfo">获取用户信息</nut-button>
78 + <view v-if="userInfo">
79 + <text>{{ userInfo.name }}</text>
80 + <text>{{ userInfo.mobile }}</text>
81 + </view>
82 + </view>
83 +</template>
84 +
85 +<script setup>
86 +import { ref } from 'vue';
87 +import { getUserInfoAPI } from '@/api/user';
88 +
89 +const userInfo = ref(null);
90 +
91 +const handleGetUserInfo = async () => {
92 + try {
93 + const result = await getUserInfoAPI();
94 + if (result.code === 1) {
95 + userInfo.value = result.data.user;
96 + Taro.showToast({
97 + title: '获取成功',
98 + icon: 'success',
99 + });
100 + }
101 + } catch (error) {
102 + Taro.showToast({
103 + title: '获取失败',
104 + icon: 'error',
105 + });
106 + }
107 +};
108 +</script>
109 +```
110 +
111 +### 示例 4: 错误处理和重试
112 +
113 +```javascript
114 +import { getUserInfoAPI } from '@/api/user';
115 +
116 +const fetchUserInfoWithRetry = async (retries = 3) => {
117 + for (let i = 0; i < retries; i++) {
118 + try {
119 + const result = await getUserInfoAPI();
120 + if (result.code === 1) {
121 + return result.data;
122 + }
123 + } catch (error) {
124 + console.error(`尝试 ${i + 1}/${retries} 失败:`, error);
125 +
126 + if (i === retries - 1) {
127 + throw error; // 最后一次尝试失败后抛出错误
128 + }
129 +
130 + // 等待后重试
131 + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
132 + }
133 + }
134 +};
135 +```
136 +
137 +### 示例 5: 结合加载状态
138 +
139 +```vue
140 +<template>
141 + <view>
142 + <nut-button @click="fetchData" :loading="isLoading">
143 + {{ isLoading ? '加载中...' : '获取用户信息' }}
144 + </nut-button>
145 + </view>
146 +</template>
147 +
148 +<script setup>
149 +import { ref } from 'vue';
150 +import { getUserInfoAPI } from '@/api/user';
151 +
152 +const isLoading = ref(false);
153 +
154 +const fetchData = async () => {
155 + isLoading.value = true;
156 + try {
157 + const result = await getUserInfoAPI();
158 + if (result.code === 1) {
159 + // 处理成功
160 + }
161 + } catch (error) {
162 + // 处理错误
163 + } finally {
164 + isLoading.value = false;
165 + }
166 +};
167 +</script>
168 +```
169 +
170 +## 🎯 最佳实践
171 +
172 +### 1. 统一错误处理
173 +
174 +```javascript
175 +// src/utils/apiHandler.js
176 +export const handleApiCall = async (apiFunc, params = {}) => {
177 + try {
178 + const result = await apiFunc(params);
179 +
180 + if (result.code === 1) {
181 + return { success: true, data: result.data };
182 + } else {
183 + Taro.showToast({
184 + title: result.msg || '请求失败',
185 + icon: 'error',
186 + });
187 + return { success: false, error: result.msg };
188 + }
189 + } catch (error) {
190 + Taro.showToast({
191 + title: '网络异常',
192 + icon: 'error',
193 + });
194 + return { success: false, error };
195 + }
196 +};
197 +
198 +// 使用
199 +import { getUserInfoAPI } from '@/api/user';
200 +import { handleApiCall } from '@/utils/apiHandler';
201 +
202 +const { success, data, error } = await handleApiCall(getUserInfoAPI);
203 +if (success) {
204 + console.log(data);
205 +}
206 +```
207 +
208 +### 2. 请求参数验证
209 +
210 +```javascript
211 +import { getUserInfoAPI } from '@/api/user';
212 +
213 +const fetchUserInfo = async (params) => {
214 + // 参数验证
215 + if (!params || !params.id) {
216 + Taro.showToast({
217 + title: '缺少必要参数',
218 + icon: 'error',
219 + });
220 + return;
221 + }
222 +
223 + return await getUserInfoAPI(params);
224 +};
225 +```
226 +
227 +### 3. 缓存机制
228 +
229 +```javascript
230 +import { getUserInfoAPI } from '@/api/user';
231 +import Taro from '@tarojs/taro';
232 +
233 +const fetchUserInfoWithCache = async (userId) => {
234 + const cacheKey = `user_info_${userId}`;
235 + const cache = Taro.getStorageSync(cacheKey);
236 +
237 + // 如果有缓存且未过期
238 + if (cache && Date.now() - cache.timestamp < 5 * 60 * 1000) {
239 + return cache.data;
240 + }
241 +
242 + // 请求新数据
243 + const result = await getUserInfoAPI({ id: userId });
244 +
245 + if (result.code === 1) {
246 + // 缓存数据
247 + Taro.setStorageSync(cacheKey, {
248 + data: result.data,
249 + timestamp: Date.now(),
250 + });
251 + return result.data;
252 + }
253 +};
254 +```
255 +
256 +## 📚 更多示例
257 +
258 +### 并发请求
259 +
260 +```javascript
261 +import { getUserInfoAPI } from '@/api/user';
262 +import { wxJsAPI } from '@/api/wx/config';
263 +
264 +const fetchData = async () => {
265 + const [userInfo, wxConfig] = await Promise.all([
266 + getUserInfoAPI(),
267 + wxJsAPI({ url: window.location.href }),
268 + ]);
269 +
270 + console.log(userInfo, wxConfig);
271 +};
272 +```
273 +
274 +### 链式请求
275 +
276 +```javascript
277 +const fetchThenProcess = async () => {
278 + // 先获取用户信息
279 + const userResult = await getUserInfoAPI();
280 + if (userResult.code !== 1) return;
281 +
282 + // 再用用户信息获取其他数据
283 + const otherResult = await someOtherAPI({
284 + userId: userResult.data.user.id,
285 + });
286 +};
287 +```
288 +
289 +## 🔍 调试技巧
290 +
291 +### 查看请求详情
292 +
293 +```javascript
294 +import { getUserInfoAPI } from '@/api/user';
295 +
296 +const debugFetch = async () => {
297 + console.time('API请求');
298 + const result = await getUserInfoAPI({ debug: 1 });
299 + console.timeEnd('API请求');
300 +
301 + console.log('完整响应:', result);
302 + console.log('状态码:', result.code);
303 + console.log('返回数据:', result.data);
304 + console.log('消息:', result.msg);
305 +};
306 +```
307 +
308 +### 使用 Taro 的网络监控
309 +
310 +```javascript
311 +Taro.request({
312 + url: '/srv/?a=user_info',
313 + method: 'GET',
314 + success: (res) => {
315 + console.log('请求成功', res);
316 + },
317 + fail: (err) => {
318 + console.error('请求失败', err);
319 + },
320 +});
321 +```
322 +
323 +## 💡 提示
324 +
325 +1. **始终检查 code**:根据业务逻辑,通常 `code === 1` 表示成功
326 +2. **错误处理**:使用 try-catch 捕获网络异常
327 +3. **加载状态**:为长时间请求添加加载提示
328 +4. **参数验证**:在调用 API 前验证必要参数
329 +5. **避免重复请求**:可以使用防抖或节流控制请求频率
330 +
331 +## 🚀 下一步
332 +
333 +- 查看 [OpenAPI 转 API 文档生成器指南](./OPENAPI_TO_API_GUIDE.md) 了解如何生成新的 API
334 +- 查看 [项目开发指南](../CLAUDE.md) 了解项目架构
335 +- 查看 `src/api/wx/` 目录查看更多 API 使用示例
1 +# 🎉 详细 JSDoc 注释功能 - 完成报告
2 +
3 +## ✅ 完成状态
4 +
5 +所有功能已成功实现并测试通过!
6 +
7 +## 🎯 实现目标
8 +
9 +将生成的 API 文件的 JSDoc 注释从简单的类型定义升级为包含:
10 +- ✅ 详细的参数类型和描述
11 +- ✅ 完整的返回值类型结构
12 +- ✅ 每个字段的描述信息
13 +- ✅ 嵌套对象和数组支持
14 +
15 +## 📊 实际效果展示
16 +
17 +### 示例 1: 带必填参数的接口
18 +
19 +**输入** (docs/openAPI/order/getDetail.md):
20 +```yaml
21 +parameters:
22 + - name: id
23 + description: 订单ID
24 + required: true # 必填
25 + schema:
26 + type: integer
27 +```
28 +
29 +**输出** (src/api/order.js):
30 +```javascript
31 +/**
32 + * @param {integer} params.id 订单ID # ✅ 没有"(可选)"标记
33 + */
34 +```
35 +
36 +### 示例 2: 带可选参数的接口
37 +
38 +**输入** (docs/openAPI/order/getList.md):
39 +```yaml
40 +parameters:
41 + - name: page
42 + description: 页码
43 + required: false # 可选
44 + schema:
45 + type: integer
46 +```
47 +
48 +**输出** (src/api/order.js):
49 +```javascript
50 +/**
51 + * @param {integer} params.page (可选) 页码 # ✅ 标记为可选
52 + */
53 +```
54 +
55 +### 示例 3: 嵌套对象返回值
56 +
57 +**输入** (docs/openAPI/user/getUserInfo.md):
58 +```yaml
59 +data:
60 + properties:
61 + user:
62 + type: object
63 + properties:
64 + id:
65 + type: integer
66 + description: 用户ID
67 + name:
68 + type: string
69 + description: 姓名
70 +```
71 +
72 +**输出** (src/api/user.js):
73 +```javascript
74 +/**
75 + * @returns {Promise<{
76 + * data: {
77 + * user: {
78 + * id: integer; // 用户ID
79 + * name: string; // 姓名
80 + * };
81 + * };
82 + * }>}
83 + */
84 +```
85 +
86 +### 示例 4: 数组类型返回值
87 +
88 +**输入** (docs/openAPI/order/getList.md):
89 +```yaml
90 +data:
91 + properties:
92 + list:
93 + type: array
94 + items:
95 + type: object
96 + properties:
97 + id:
98 + type: integer
99 + description: 订单ID
100 + order_no:
101 + type: string
102 + description: 订单号
103 +```
104 +
105 +**输出** (src/api/order.js):
106 +```javascript
107 +/**
108 + * @returns {Promise<{
109 + * data: {
110 + * list: Array<{
111 + * id: integer; // 订单ID
112 + * order_no: string; // 订单号
113 + * }>;
114 + * };
115 + * }>}
116 + */
117 +```
118 +
119 +## 📁 生成文件示例
120 +
121 +### 完整的订单模块 API (src/api/order.js)
122 +
123 +```javascript
124 +import { fn, fetch } from '@/api/fn';
125 +
126 +const Api = {
127 + GetDetail: '/srv/?a=order_detail',
128 + GetList: '/srv/?a=order_list',
129 +}
130 +
131 +/**
132 + * @description: 获取订单详情
133 + * @param {Object} params 请求参数
134 + * @param {integer} params.id 订单ID
135 + * @returns {Promise<{
136 + * code: number; // 状态码
137 + * msg: string; // 消息
138 + * data: {
139 + * order: {
140 + * id: integer; // 订单ID
141 + * order_no: string; // 订单号
142 + * total_amount: number; // 订单总金额
143 + * status: string; // 订单状态
144 + * items: array; // 订单商品列表
145 + * };
146 + * };
147 + * }>}
148 + */
149 +export const getDetailAPI = (params) => fn(fetch.get(Api.GetDetail, params));
150 +
151 +/**
152 + * @description: 获取订单列表
153 + * @param {Object} params 请求参数
154 + * @param {integer} params.page (可选) 页码
155 + * @param {integer} params.pageSize (可选) 每页数量
156 + * @returns {Promise<{
157 + * code: number; // 状态码
158 + * msg: string; // 消息
159 + * data: {
160 + * list: Array<{
161 + * id: integer; // 订单ID
162 + * order_no: string; // 订单号
163 + * status: string; // 订单状态
164 + * total_amount: number; // 订单金额
165 + * }>;
166 + * };
167 + * }>}
168 + */
169 +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params));
170 +```
171 +
172 +## 🔧 核心改动
173 +
174 +### 1. 新增函数
175 +
176 +**parseProperties(properties, indent)**
177 +- 递归解析对象属性结构
178 +- 支持嵌套对象和数组
179 +- 生成格式化的字段描述
180 +
181 +**generateParamJSDoc(parameters)**
182 +- 生成详细的参数注释
183 +- 过滤 URL 中的参数(a, f)
184 +- 标记必填/可选状态
185 +
186 +**generateReturnJSDoc(responseSchema)**
187 +- 生成返回值类型注释
188 +- 递归解析 data 结构
189 +- 支持嵌套对象和数组
190 +
191 +### 2. 增强功能
192 +
193 +**parseOpenAPIDocument()**
194 +- 保存完整的 parameters 信息
195 +- 保存 responseSchema 结构
196 +- 用于生成详细注释
197 +
198 +## 📚 文档更新
199 +
200 +### 新增文档
201 +-`docs/JSDOC_GENERATION_GUIDE.md` - 详细注释生成完整指南
202 +-`docs/UPDATE_LOG.md` - 功能更新说明
203 +
204 +### 更新文档
205 +-`docs/OPENAPI_TO_API_GUIDE.md` - 添加 JSDoc 生成规则说明
206 +-`README_API_GENERATOR.md` - 添加新特性介绍
207 +
208 +### 示例更新
209 +-`docs/openAPI/order/getDetail.md` - 补充完整的字段描述
210 +- ✅ 生成的 API 文件包含详细注释
211 +
212 +## 🎯 使用建议
213 +
214 +### 1. 完善描述信息
215 +在 OpenAPI 文档中为每个字段添加:
216 +```yaml
217 +description: 字段描述
218 +type: 字段类型
219 +required: 是否必填 # 对于参数
220 +```
221 +
222 +### 2. 享受智能提示
223 +在 IDE 中使用时,你会看到:
224 +- 🔍 参数的自动补全
225 +- 🔍 参数类型提示
226 +- 🔍 返回值结构提示
227 +- 🔍 字段描述说明
228 +
229 +### 3. 提高代码质量
230 +- ✅ 类型安全
231 +- ✅ 减少错误
232 +- ✅ 易于维护
233 +- ✅ 团队协作更顺畅
234 +
235 +## 🚀 立即使用
236 +
237 +```bash
238 +# 1. 生成 API 文件(应用新的注释规则)
239 +pnpm api:generate
240 +
241 +# 2. 查看生成的详细注释
242 +cat src/api/user.js
243 +cat src/api/order.js
244 +
245 +# 3. 在 IDE 中查看效果
246 +# 打开任意生成的 API 文件,鼠标悬停查看 JSDoc 提示
247 +```
248 +
249 +## 📖 相关文档
250 +
251 +- 📘 [JSDoc 生成指南](./JSDOC_GENERATION_GUIDE.md) - 详细使用说明
252 +- 📗 [详细使用指南](./OPENAPI_TO_API_GUIDE.md) - 完整功能说明
253 +- 📙 [主 README](../README_API_GENERATOR.md) - 项目总览
254 +- 📕 [更新日志](./UPDATE_LOG.md) - 功能更新说明
255 +
256 +## 🎉 总结
257 +
258 +现在生成的 API 文件包含:
259 +
260 +**完整的参数信息**
261 +- 参数类型
262 +- 参数描述
263 +- 必填/可选标记
264 +
265 +**详细的返回值定义**
266 +- 完整的类型结构
267 +- 嵌套对象支持
268 +- 数组类型支持
269 +- 每个字段的描述
270 +
271 +**更好的开发体验**
272 +- IDE 智能提示
273 +- 类型检查
274 +- 自动补全
275 +- 代码可读性提升
276 +
277 +**改造完成!所有文档已更新!** 🎊
1 +# OpenAPI 转 API 文档生成器 - 实现总结
2 +
3 +## ✅ 已完成功能
4 +
5 +### 1. 核心生成器
6 +- ✅ 扫描 `docs/openAPI` 目录结构
7 +- ✅ 解析 OpenAPI 3.x YAML 规范
8 +- ✅ 提取 API 元数据(summary、action、method 等)
9 +- ✅ 自动命名转换(驼峰命名、帕斯卡命名)
10 +- ✅ 生成标准化的 JavaScript API 文件
11 +- ✅ 模块化组织(按文件夹生成独立文件)
12 +
13 +### 2. 测试和验证
14 +- ✅ 单个接口生成测试
15 +- ✅ 批量接口生成测试
16 +- ✅ 多模块生成测试
17 +- ✅ 文件格式验证
18 +
19 +### 3. 文档和指南
20 +- ✅ 详细使用指南
21 +- ✅ 快速开始指南
22 +- ✅ API 使用示例
23 +- ✅ 代码注释和说明
24 +
25 +## 📁 生成的文件
26 +
27 +```
28 +manulife-weapp/
29 +├── scripts/
30 +│ ├── generateApiFromOpenAPI.js ✅ 核心生成器脚本
31 +│ ├── test-generate.js ✅ 测试验证脚本
32 +│ └── QUICKSTART.md ✅ 快速开始指南
33 +├── docs/
34 +│ ├── OPENAPI_TO_API_GUIDE.md ✅ 详细使用指南
35 +│ ├── API_USAGE_EXAMPLES.md ✅ API 使用示例
36 +│ └── openAPI/ ✅ OpenAPI 文档源目录
37 +│ ├── user/
38 +│ │ └── getUserInfo.md
39 +│ └── order/
40 +│ ├── getList.md
41 +│ └── getDetail.md
42 +├── src/api/ ✅ 生成的 API 文件
43 +│ ├── user.js ✅ 自动生成
44 +│ └── order.js ✅ 自动生成
45 +└── package.json ✅ 包含 api:generate 命令
46 +```
47 +
48 +## 🎯 测试结果
49 +
50 +### 测试用例 1: 单个模块单个接口
51 +**输入**: `docs/openAPI/user/getUserInfo.md`
52 +**输出**: `src/api/user.js`
53 +**状态**: ✅ 通过
54 +
55 +### 测试用例 2: 单个模块多个接口
56 +**输入**:
57 +- `docs/openAPI/order/getList.md`
58 +- `docs/openAPI/order/getDetail.md`
59 +
60 +**输出**: `src/api/order.js`(包含 2 个接口)
61 +**状态**: ✅ 通过
62 +
63 +### 测试用例 3: 多模块批量生成
64 +**输入**:
65 +- `docs/openAPI/user/` 模块
66 +- `docs/openAPI/order/` 模块
67 +
68 +**输出**:
69 +- `src/api/user.js`
70 +- `src/api/order.js`
71 +
72 +**状态**: ✅ 通过
73 +
74 +## 🚀 使用方式
75 +
76 +### 基础使用
77 +```bash
78 +# 生成 API 文件
79 +pnpm api:generate
80 +
81 +# 测试生成的文件
82 +node scripts/test-generate.js
83 +```
84 +
85 +### 在项目中使用
86 +```javascript
87 +// 导入生成的 API
88 +import { getUserInfoAPI } from '@/api/user';
89 +import { getListAPI, getDetailAPI } from '@/api/order';
90 +
91 +// 使用 API
92 +const userInfo = await getUserInfoAPI();
93 +const orderList = await getListAPI({ page: 1 });
94 +const orderDetail = await getDetailAPI({ id: 123 });
95 +```
96 +
97 +## 📊 功能特性
98 +
99 +### 自动化特性
100 +- ✅ 自动扫描目录结构
101 +- ✅ 自动解析 YAML 格式
102 +- ✅ 自动生成标准化代码
103 +- ✅ 自动处理命名转换
104 +
105 +### 灵活性
106 +- ✅ 支持任意数量的模块
107 +- ✅ 支持每个模块任意数量的接口
108 +- ✅ 支持 GET 和 POST 方法
109 +- ✅ 可自定义生成规则
110 +
111 +### 可维护性
112 +- ✅ 单一数据源(OpenAPI 文档)
113 +- ✅ 清晰的目录结构
114 +- ✅ 标准化的代码格式
115 +- ✅ 完整的文档说明
116 +
117 +## 🔧 技术实现
118 +
119 +### 核心技术
120 +- **Node.js**: 脚本运行环境
121 +- **js-yaml**: YAML 解析库
122 +- **文件系统 API**: 文件读写操作
123 +
124 +### 关键算法
125 +1. **YAML 提取**: 使用正则表达式提取 Markdown 中的 YAML 代码块
126 +2. **命名转换**: 字符串处理函数实现驼峰命名和帕斯卡命名
127 +3. **模板生成**: 字符串拼接生成标准化代码
128 +
129 +### 错误处理
130 +- ✅ 文件不存在检查
131 +- ✅ YAML 格式验证
132 +- ✅ 目录结构验证
133 +- ✅ 详细的错误提示
134 +
135 +## 💡 最佳实践
136 +
137 +### 1. 文档组织
138 +- 按业务模块分组
139 +- 使用清晰的文件命名
140 +- 保持文档格式一致
141 +
142 +### 2. 版本控制
143 +- ✅ 提交 OpenAPI 文档到 Git
144 +- ✅ 提交生成的 API 文件到 Git
145 +- ❌ 不要手动修改生成的 API 文件
146 +
147 +### 3. 团队协作
148 +- 使用统一的 OpenAPI 模板
149 +- 定期同步 API 文档
150 +- 代码审查时检查生成的文件
151 +
152 +## 📈 扩展建议
153 +
154 +### 短期增强
155 +1. **TypeScript 支持**: 生成 `.d.ts` 类型定义文件
156 +2. **Mock 数据**: 根据 OpenAPI schema 生成 mock 数据
157 +3. **API 测试**: 自动生成单元测试代码
158 +
159 +### 中期增强
160 +1. **配置文件**: 支持自定义生成规则
161 +2. **Watch 模式**: 监听文件变化自动重新生成
162 +3. **增量生成**: 只生成修改过的文件
163 +
164 +### 长期增强
165 +1. **可视化界面**: 提供图形化的 API 管理工具
166 +2. **版本管理**: 支持多版本 API 生成
167 +3. **插件系统**: 支持自定义生成插件
168 +
169 +## 🎓 学习要点
170 +
171 +### OpenAPI 规范
172 +- 理解 OpenAPI 3.x 基本结构
173 +- 掌握常用字段含义(paths、parameters、responses)
174 +- 学会编写标准的 API 文档
175 +
176 +### JavaScript 编程
177 +- Node.js 文件系统操作
178 +- 正则表达式应用
179 +- 字符串处理技巧
180 +
181 +### 自动化思维
182 +- 单一数据源原则
183 +- 自动化代码生成
184 +- 模板化开发
185 +
186 +## 📞 相关资源
187 +
188 +### 内部文档
189 +- [详细使用指南](./OPENAPI_TO_API_GUIDE.md)
190 +- [快速开始指南](../scripts/QUICKSTART.md)
191 +- [API 使用示例](./API_USAGE_EXAMPLES.md)
192 +- [项目开发指南](../CLAUDE.md)
193 +
194 +### 外部资源
195 +- [OpenAPI 规范官方文档](https://swagger.io/specification/)
196 +- [js-yaml 文档](https://github.com/nodeca/js-yaml)
197 +- [Taro 官方文档](https://taro.zone/docs/)
198 +
199 +## ✨ 总结
200 +
201 +这个 OpenAPI 转 API 文档生成器已经成功实现并测试,具备以下核心价值:
202 +
203 +1. **提高效率**: 自动化生成 API 文件,节省手动编写时间
204 +2. **减少错误**: 避免手动编写时的拼写错误和格式不一致
205 +3. **标准化**: 统一的代码格式和命名规范
206 +4. **可维护**: 单一数据源,易于更新和维护
207 +5. **可扩展**: 灵活的架构,便于后续功能扩展
208 +
209 +**现在你可以开始使用这个工具来简化你的 API 开发流程了!** 🚀
1 +# 🎯 详细 JSDoc 注释生成指南
2 +
3 +本指南详细说明如何从 OpenAPI 文档生成包含完整类型信息和描述的 JSDoc 注释。
4 +
5 +## ✨ 功能特点
6 +
7 +### 1. 自动提取参数信息
8 +
9 +生成器会从 `parameters` 中提取:
10 +- 参数名
11 +- 参数类型(`schema.type`
12 +- 参数描述(`description`
13 +- 是否必填(`required`
14 +
15 +**示例**
16 +
17 +```yaml
18 +parameters:
19 + - name: page
20 + in: query
21 + description: 页码
22 + required: false
23 + example: 1
24 + schema:
25 + type: integer
26 + - name: pageSize
27 + in: query
28 + description: 每页数量
29 + required: false
30 + example: 10
31 + schema:
32 + type: integer
33 +```
34 +
35 +**生成的注释**
36 +
37 +```javascript
38 +/**
39 + * @param {Object} params 请求参数
40 + * @param {integer} params.page (可选) 页码
41 + * @param {integer} params.pageSize (可选) 每页数量
42 + */
43 +```
44 +
45 +### 2. 详细返回值类型
46 +
47 +生成器会递归解析 `responses['200'].schema.properties.data` 的结构,包括:
48 +- 基本类型(string, integer, boolean, number)
49 +- 嵌套对象
50 +- 数组类型(Array<>)
51 +- 每个字段的描述
52 +
53 +**示例**
54 +
55 +```yaml
56 +responses:
57 + '200':
58 + content:
59 + application/json:
60 + schema:
61 + properties:
62 + data:
63 + properties:
64 + user:
65 + type: object
66 + properties:
67 + id:
68 + type: integer
69 + description: 用户ID
70 + name:
71 + type: string
72 + description: 姓名
73 + list:
74 + type: array
75 + items:
76 + type: object
77 + properties:
78 + id:
79 + type: integer
80 + description: ID
81 + title:
82 + type: string
83 + description: 标题
84 +```
85 +
86 +**生成的注释**
87 +
88 +```javascript
89 +/**
90 + * @returns {Promise<{
91 + * code: number; // 状态码
92 + * msg: string; // 消息
93 + * data: {
94 + * user: {
95 + * id: integer; // 用户ID
96 + * name: string; // 姓名
97 + * };
98 + * list: Array<{
99 + * id: integer; // ID
100 + * title: string; // 标题
101 + * }>;
102 + * };
103 + * }>}
104 + */
105 +```
106 +
107 +## 📋 完整示例
108 +
109 +### 输入:OpenAPI 文档
110 +
111 +```markdown
112 +# 获取订单列表
113 +
114 +## OpenAPI Specification
115 +
116 +\```yaml
117 +openapi: 3.0.1
118 +info:
119 + title: ''
120 + version: 1.0.0
121 +paths:
122 + /srv/:
123 + get:
124 + summary: 获取订单列表
125 + description: 分页获取用户的订单列表
126 + tags:
127 + - 订单管理
128 + parameters:
129 + - name: f
130 + in: query
131 + example: behalo
132 + - name: a
133 + in: query
134 + example: order_list
135 + - name: page
136 + in: query
137 + description: 页码
138 + example: 1
139 + schema:
140 + type: integer
141 + - name: pageSize
142 + in: query
143 + description: 每页数量
144 + example: 10
145 + schema:
146 + type: integer
147 + responses:
148 + '200':
149 + description: 成功返回订单列表
150 + content:
151 + application/json:
152 + schema:
153 + type: object
154 + properties:
155 + code:
156 + type: integer
157 + description: 0=失败,1=成功
158 + msg:
159 + type: string
160 + description: 错误信息
161 + data:
162 + type: object
163 + properties:
164 + list:
165 + type: array
166 + items:
167 + type: object
168 + properties:
169 + id:
170 + type: integer
171 + description: 订单ID
172 + order_no:
173 + type: string
174 + description: 订单号
175 + status:
176 + type: string
177 + description: 订单状态
178 + total_amount:
179 + type: number
180 + description: 订单金额
181 +\```
182 +```
183 +
184 +### 输出:生成的 API 文件
185 +
186 +```javascript
187 +import { fn, fetch } from '@/api/fn';
188 +
189 +const Api = {
190 + GetList: '/srv/?a=order_list',
191 +}
192 +
193 +/**
194 + * @description: 获取订单列表
195 + * @param {Object} params 请求参数
196 + * @param {integer} params.page (可选) 页码
197 + * @param {integer} params.pageSize (可选) 每页数量
198 + * @returns {Promise<{
199 + * code: number; // 状态码
200 + * msg: string; // 错误信息
201 + * data: {
202 + * list: Array<{
203 + * id: integer; // 订单ID
204 + * order_no: string; // 订单号
205 + * status: string; // 订单状态
206 + * total_amount: number; // 订单金额
207 + * }>;
208 + * };
209 + * }>}
210 + */
211 +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params));
212 +```
213 +
214 +## 🎨 类型映射
215 +
216 +### OpenAPI 类型 → JavaScript 类型
217 +
218 +| OpenAPI 类型 | JavaScript 类型 | 说明 |
219 +|-------------|-----------------|------|
220 +| `string` | `string` | 字符串 |
221 +| `integer` | `integer` | 整数 |
222 +| `number` | `number` | 数字 |
223 +| `boolean` | `boolean` | 布尔值 |
224 +| `array` | `Array<>` | 数组 |
225 +| `object` | `{}` | 对象 |
226 +
227 +### 特殊类型处理
228 +
229 +1. **嵌套对象**
230 + ```yaml
231 + user:
232 + type: object
233 + properties:
234 + id:
235 + type: integer
236 + ```
237 + 生成:
238 + ```javascript
239 + user: {
240 + id: integer;
241 + };
242 + ```
243 +
244 +2. **对象数组**:
245 + ```yaml
246 + list:
247 + type: array
248 + items:
249 + type: object
250 + properties:
251 + id:
252 + type: integer
253 + ```
254 + 生成:
255 + ```javascript
256 + list: Array<{
257 + id: integer;
258 + }>;
259 + ```
260 +
261 +3. **基本类型数组**:
262 + ```yaml
263 + tags:
264 + type: array
265 + items:
266 + type: string
267 + ```
268 + 生成:
269 + ```javascript
270 + tags: Array<string>;
271 + ```
272 +
273 +## 📝 最佳实践
274 +
275 +### 1. 完善描述信息
276 +
277 +确保为每个字段添加 `description`:
278 +
279 +```yaml
280 +parameters:
281 + - name: userId
282 + description: 用户ID ✅ 添加描述
283 + schema:
284 + type: integer
285 +```
286 +
287 +### 2. 明确类型定义
288 +
289 +始终指定 `schema.type`:
290 +
291 +```yaml
292 +schema:
293 + type: integer ✅ 明确类型
294 +```
295 +
296 +### 3. 标记必填字段
297 +
298 +使用 `required` 标记必填参数:
299 +
300 +```yaml
301 +parameters:
302 + - name: id
303 + required: true ✅ 标记为必填
304 + schema:
305 + type: integer
306 +```
307 +
308 +### 4. 使用有意义的字段名
309 +
310 +字段名应该清晰表达含义:
311 +
312 +```yaml
313 +properties:
314 + user_id: ✅ 清晰
315 + type: integer
316 + id: ❌ 不明确
317 + type: integer
318 +```
319 +
320 +## 🔧 高级用法
321 +
322 +### 多层嵌套对象
323 +
324 +```yaml
325 +data:
326 + properties:
327 + user:
328 + type: object
329 + properties:
330 + profile:
331 + type: object
332 + properties:
333 + avatar:
334 + type: string
335 + description: 头像URL
336 +```
337 +
338 +生成:
339 +```javascript
340 +data: {
341 + user: {
342 + profile: {
343 + avatar: string; // 头像URL
344 + };
345 + };
346 +};
347 +```
348 +
349 +### 混合类型数组
350 +
351 +```yaml
352 +items:
353 + type: object
354 + properties:
355 + id:
356 + type: integer
357 + name:
358 + type: string
359 + tags:
360 + type: array
361 + items:
362 + type: string
363 +```
364 +
365 +生成:
366 +```javascript
367 +Array<{
368 + id: integer;
369 + name: string;
370 + tags: Array<string>;
371 +}>
372 +```
373 +
374 +## ⚠️ 注意事项
375 +
376 +1. **description 优先级**:优先使用 `description`,其次使用 `title`
377 +2. **空描述处理**:如果字段没有描述,会生成空注释
378 +3. **嵌套深度**:支持任意深度的嵌套对象
379 +4. **参数过滤**`a``f` 参数不会出现在 `@param`
380 +5. **类型大小写**:OpenAPI 的 `integer` 会保留(不是 `number`
381 +
382 +## 🚀 开始使用
383 +
384 +1. 在 OpenAPI 文档中添加完整的 `description``type`
385 +2. 运行 `pnpm api:generate`
386 +3. 查看生成的详细 JSDoc 注释
387 +4. 在 IDE 中享受智能提示和类型检查!
388 +
389 +## 📚 相关文档
390 +
391 +- [OpenAPI 规范官方文档](https://swagger.io/specification/)
392 +- [JSDoc 官方文档](https://jsdoc.app/)
393 +- [详细使用指南](./OPENAPI_TO_API_GUIDE.md)
1 +# OpenAPI 转 API 文档生成器
2 +
3 +## 📖 功能说明
4 +
5 +这是一个自动化工具,可以从 `docs/openAPI` 目录读取 OpenAPI 规范的 Markdown 文档,自动生成标准化的 JavaScript API 接口文件到 `src/api/` 目录。
6 +
7 +## 📁 目录结构
8 +
9 +### 输入目录结构
10 +```
11 +docs/openAPI/
12 +├── 模块名1/
13 +│ ├── 接口名1.md
14 +│ ├── 接口名2.md
15 +│ └── ...
16 +└── 模块名2/
17 + └── 接口名3.md
18 +```
19 +
20 +### 输出目录结构
21 +```
22 +src/api/
23 +├── 模块名1.js (自动生成)
24 +├── 模块名2.js (自动生成)
25 +└── ...
26 +```
27 +
28 +## 📝 OpenAPI 文档格式
29 +
30 +每个 `.md` 文件需要包含 OpenAPI 3.x YAML 规范。参考格式:
31 +
32 +```markdown
33 +# 接口标题
34 +
35 +## OpenAPI Specification
36 +
37 +\```yaml
38 +openapi: 3.0.1
39 +info:
40 + title: ''
41 + version: 1.0.0
42 +paths:
43 + /srv/:
44 + get: # 或 post
45 + summary: 接口描述
46 + description: 详细描述
47 + tags:
48 + - 模块名
49 + parameters:
50 + - name: a
51 + in: query
52 + example: action_name # 提取为接口的 action
53 + schema:
54 + type: string
55 + - name: f
56 + in: query
57 + example: behalo
58 + schema:
59 + type: string
60 + - name: page
61 + in: query
62 + description: 页码
63 + required: false
64 + example: 1
65 + schema:
66 + type: integer
67 + responses:
68 + '200':
69 + description: 成功响应
70 + content:
71 + application/json:
72 + schema:
73 + type: object
74 + properties:
75 + code:
76 + type: integer
77 + description: 0=失败,1=成功
78 + msg:
79 + type: string
80 + description: 错误信息
81 + data:
82 + type: object
83 + properties:
84 + user:
85 + type: object
86 + properties:
87 + id:
88 + type: integer
89 + description: 用户ID
90 + name:
91 + type: string
92 + description: 姓名
93 + list:
94 + type: array
95 + items:
96 + type: object
97 + properties:
98 + id:
99 + type: integer
100 + description: ID
101 + title:
102 + type: string
103 + description: 标题
104 +\```
105 +```
106 +
107 +## 🔑 关键字段说明
108 +
109 +生成器会从 OpenAPI 文档中提取以下信息:
110 +
111 +| 字段 | 说明 | 示例 |
112 +|------|------|------|
113 +| `summary` | 接口描述,用于 JSDoc 注释 | "查询我的信息" |
114 +| `parameters[].name='a'` | action 参数,用于构建 URL | `user_info` |
115 +| `parameters[].description` | 参数描述,用于生成 JSDoc @param | "页码" |
116 +| `parameters[].schema.type` | 参数类型 | integer, string, boolean |
117 +| `parameters[].required` | 是否必填 | true/false |
118 +| `get` / `post` | HTTP 方法 | 决定使用 `fetch.get``fetch.post` |
119 +| `responses['200'].schema` | 响应数据结构 | 用于生成 JSDoc @returns |
120 +| `description` | 字段描述 | 用于生成详细注释 |
121 +| 文件名 | API 函数名的基础 | `getUserInfo.md``getUserInfoAPI()` |
122 +
123 +### 📌 JSDoc 注释生成规则
124 +
125 +#### 参数注释(@param)
126 +- 过滤掉 `a``f` 参数(已在 URL 中)
127 +- 提取参数名、类型、描述
128 +- 标记必填/可选状态
129 +
130 +#### 返回值注释(@returns)
131 +- 自动解析嵌套对象结构
132 +- 提取每个字段的类型和描述
133 +- 支持数组类型(Array<>)
134 +- 支持多层嵌套对象
135 +
136 +## 🚀 使用方法
137 +
138 +### 1. 运行生成器
139 +
140 +```bash
141 +pnpm api:generate
142 +```
143 +
144 +### 2. 查看生成结果
145 +
146 +生成的 API 文件会保存到 `src/api/` 目录,格式如下:
147 +
148 +```javascript
149 +import { fn, fetch } from '@/api/fn';
150 +
151 +const Api = {
152 + GetUserInfo: '/srv/?a=user_info',
153 +}
154 +
155 +/**
156 + * @description: 查询我的信息
157 + * @param {Object} params 请求参数
158 + * @returns {Promise<{
159 + * code: number; // 状态码
160 + * msg: string; // 消息
161 + * data: {
162 + * user: {
163 + * id: integer; // 用户ID
164 + * name: string; // 姓名
165 + * mobile: string; // 手机号
166 + * };
167 + * checkin: {
168 + * total_days: integer; // 累计打卡天数
169 + * consecutive_days: integer; // 连续打卡天数
170 + * };
171 + * };
172 + * }>}
173 + */
174 +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params));
175 +```
176 +
177 +**注释特点**
178 +- ✅ 详细的返回值类型定义
179 +- ✅ 完整的嵌套对象结构
180 +- ✅ 每个字段的类型和描述
181 +- ✅ 支持数组类型(Array<>)
182 +- ✅ 参数类型和描述(如有)
183 +
184 +### 3. 在项目中使用
185 +
186 +```javascript
187 +import { getUserInfoAPI } from '@/api/user';
188 +
189 +// 调用接口
190 +const result = await getUserInfoAPI({ id: 123 });
191 +```
192 +
193 +## 📋 命名规则
194 +
195 +### 常量命名(帕斯卡命名)
196 +- 输入:`getUserInfo.md`
197 +- 输出:`GetUserInfo: '/srv/?a=user_info'`
198 +
199 +### 函数命名(驼峰命名 + API 后缀)
200 +- 输入:`getUserInfo.md`
201 +- 输出:`export const getUserInfoAPI = (params) => ...`
202 +
203 +## ⚠️ 注意事项
204 +
205 +1. **文件命名**:建议使用驼峰命名,如 `getUserInfo.md`
206 +2. **Action 参数**:确保每个接口的 `parameters` 中有 `name: a` 的参数
207 +3. **模块隔离**:不同模块的接口会生成到不同的文件中
208 +4. **文件覆盖**:每次运行会覆盖已生成的文件,请勿手动修改生成的文件
209 +
210 +## 🔧 自定义扩展
211 +
212 +如需修改生成逻辑,编辑 `scripts/generateApiFromOpenAPI.js`
213 +
214 +- 修改命名规则:调整 `toCamelCase()``toPascalCase()` 函数
215 +- 修改输出格式:调整 `generateApiFileContent()` 函数
216 +- 添加额外字段:在 `parseOpenAPIDocument()` 函数中提取更多字段
217 +
218 +## 📚 完整示例
219 +
220 +参考 `docs/openAPI/user/getUserInfo.md` 查看完整的 OpenAPI 文档示例。
221 +
222 +运行生成器后,查看 `src/api/user.js` 查看生成的 API 文件。
223 +
224 +## 🎯 最佳实践
225 +
226 +1. **保持文档同步**:修改接口后及时更新 OpenAPI 文档并重新生成
227 +2. **版本控制**:将生成的 API 文件提交到 Git
228 +3. **代码审查**:生成后检查生成的代码是否符合预期
229 +4. **模块化管理**:相关接口放在同一模块文件夹下
230 +
231 +## 🐛 常见问题
232 +
233 +### Q: 生成失败怎么办?
234 +A: 检查 YAML 格式是否正确,确保使用 `yaml` 代码块包裹。
235 +
236 +### Q: 如何添加新的接口?
237 +A: 在对应的模块目录下创建新的 `.md` 文件,运行生成命令即可。
238 +
239 +### Q: 如何修改生成格式?
240 +A: 编辑 `scripts/generateApiFromOpenAPI.js` 中的相关函数。
1 +# 🎉 OpenAPI 转 API 文档生成器 - 完成报告
2 +
3 +## ✅ 已完成的工作
4 +
5 +### 1. 核心功能实现
6 +- ✅ 自动化生成器脚本(`scripts/generateApiFromOpenAPI.js`
7 +- ✅ YAML 解析和验证
8 +- ✅ 命名转换(驼峰命名、帕斯卡命名)
9 +- ✅ 模块化组织生成
10 +- ✅ 测试验证脚本
11 +
12 +### 2. 示例和文档
13 +- ✅ 3个 OpenAPI 文档示例(user、order 模块)
14 +- ✅ 2个生成的 API 文件
15 +- ✅ 完整的使用文档(4份指南)
16 +- ✅ 演示页面(可直接访问查看效果)
17 +
18 +### 3. 项目集成
19 +- ✅ 添加到 `package.json` 的 npm 命令
20 +- ✅ 添加路由配置
21 +- ✅ 安装所需依赖(js-yaml)
22 +
23 +## 🚀 立即开始使用
24 +
25 +### 方式 1: 使用现有示例
26 +
27 +```bash
28 +# 1. 查看生成的 API 文件
29 +cat src/api/user.js
30 +cat src/api/order.js
31 +
32 +# 2. 启动开发服务器
33 +pnpm dev:weapp
34 +
35 +# 3. 访问演示页面
36 +# 路径: pages/examples/api-demo/index
37 +```
38 +
39 +### 方式 2: 创建新的 API
40 +
41 +```bash
42 +# 1. 创建新模块
43 +mkdir -p docs/openAPI/product
44 +
45 +# 2. 创建接口文档
46 +# 复制 docs/openAPI/user/getUserInfo.md 作为模板
47 +# 修改其中的接口信息
48 +
49 +# 3. 生成 API 文件
50 +pnpm api:generate
51 +
52 +# 4. 查看生成的文件
53 +cat src/api/product.js
54 +
55 +# 5. 在项目中使用
56 +import { yourApiAPI } from '@/api/product';
57 +```
58 +
59 +## 📚 文档导航
60 +
61 +### 快速开始
62 +👉 **[README_API_GENERATOR.md](../README_API_GENERATOR.md)** - 项目总览和快速开始
63 +
64 +### 详细指南
65 +👉 **[QUICKSTART.md](../scripts/QUICKSTART.md)** - 5分钟快速上手
66 +👉 **[OPENAPI_TO_API_GUIDE.md](./OPENAPI_TO_API_GUIDE.md)** - 完整功能说明
67 +👉 **[API_USAGE_EXAMPLES.md](./API_USAGE_EXAMPLES.md)** - 实际使用案例
68 +
69 +### 技术文档
70 +👉 **[IMPLEMENTATION_SUMMARY.md](./IMPLEMENTATION_SUMMARY.md)** - 技术实现细节
71 +
72 +## 🎯 核心命令
73 +
74 +```bash
75 +# 生成 API 文件
76 +pnpm api:generate
77 +
78 +# 测试生成的文件
79 +node scripts/test-generate.js
80 +
81 +# 查看帮助
82 +# 查看各文档文件
83 +```
84 +
85 +## 📊 当前状态
86 +
87 +### 已测试的功能
88 +- ✅ 单接口生成(user/getUserInfo)
89 +- ✅ 批量接口生成(order/getList, order/getDetail)
90 +- ✅ 多模块生成(user、order 两个模块)
91 +- ✅ 文件格式验证
92 +- ✅ 命名转换验证
93 +
94 +### 生成的文件统计
95 +- **脚本**: 3个(生成器、测试、快速开始)
96 +- **文档**: 4个(指南、示例、总结)
97 +- **OpenAPI 示例**: 3个
98 +- **生成的 API**: 2个模块
99 +- **演示页面**: 1个
100 +
101 +## 💡 使用建议
102 +
103 +### 1. 日常开发流程
104 +```
105 +修改接口 → 更新 OpenAPI 文档 → 运行生成命令 → 使用新 API
106 +```
107 +
108 +### 2. 团队协作
109 +- 将 OpenAPI 文档作为单一数据源
110 +- 定期运行 `pnpm api:generate` 同步
111 +- 将生成的 API 文件提交到 Git
112 +
113 +### 3. 版本管理
114 +- OpenAPI 文档应该纳入版本控制
115 +- 生成的 API 文件也应该提交
116 +- 确保文档和代码同步更新
117 +
118 +## 🔧 自定义和扩展
119 +
120 +### 修改生成规则
121 +编辑 `scripts/generateApiFromOpenAPI.js`:
122 +
123 +```javascript
124 +// 修改命名规则
125 +function toCamelCase(str) { /* 你的规则 */ }
126 +
127 +// 修改生成模板
128 +function generateApiFileContent(moduleName, apis) { /* 你的模板 */ }
129 +```
130 +
131 +### 添加新功能
132 +- TypeScript 类型定义生成
133 +- Mock 数据生成
134 +- Watch 模式自动重新生成
135 +- 可视化配置界面
136 +
137 +## 📞 遇到问题?
138 +
139 +### 常见问题
140 +1. **生成失败** → 检查 YAML 格式是否正确
141 +2. **导入错误** → 确认文件路径是否正确
142 +3. **命名不符合预期** → 修改 OpenAPI 文档文件名
143 +
144 +### 调试技巧
145 +```bash
146 +# 运行测试脚本
147 +node scripts/test-generate.js
148 +
149 +# 查看生成的文件
150 +cat src/api/your-module.js
151 +
152 +# 查看错误日志
153 +pnpm api:generate
154 +```
155 +
156 +## 🎉 下一步
157 +
158 +### 推荐学习路径
159 +1. **了解概览** → 阅读 README_API_GENERATOR.md
160 +2. **快速上手** → 跟随 QUICKSTART.md 操作
161 +3. **深入学习** → 查看 OPENAPI_TO_API_GUIDE.md
162 +4. **实践应用** → 参考 API_USAGE_EXAMPLES.md
163 +
164 +### 实际应用
165 +- 在项目中创建新的 OpenAPI 文档
166 +- 运行生成命令创建 API
167 +- 在页面中使用生成的 API
168 +- 享受自动化的便利!
169 +
170 +## 📦 文件清单
171 +
172 +```
173 +✅ scripts/generateApiFromOpenAPI.js - 核心生成器
174 +✅ scripts/test-generate.js - 测试脚本
175 +✅ scripts/QUICKSTART.md - 快速开始
176 +
177 +✅ docs/openAPI/user/getUserInfo.md - 用户接口示例
178 +✅ docs/openAPI/order/getList.md - 订单列表示例
179 +✅ docs/openAPI/order/getDetail.md - 订单详情示例
180 +
181 +✅ docs/OPENAPI_TO_API_GUIDE.md - 详细指南
182 +✅ docs/API_USAGE_EXAMPLES.md - 使用示例
183 +✅ docs/IMPLEMENTATION_SUMMARY.md - 实现总结
184 +
185 +✅ src/api/user.js - 用户 API(生成)
186 +✅ src/api/order.js - 订单 API(生成)
187 +
188 +✅ src/pages/examples/api-demo/index.vue - 演示页面
189 +
190 +✅ package.json - 已添加 api:generate 命令
191 +✅ src/app.config.js - 已添加演示页面路由
192 +```
193 +
194 +## 🌟 总结
195 +
196 +你现在拥有一个完整的 OpenAPI 转 API 文档生成器!
197 +
198 +**核心价值**
199 +-**提高效率** - 自动化生成,节省时间
200 +-**减少错误** - 避免手动编写的不一致
201 +- 📦 **标准化** - 统一的代码格式
202 +- 🔧 **易维护** - 单一数据源,易于更新
203 +
204 +**开始使用**
205 +```bash
206 +pnpm api:generate
207 +```
208 +
209 +**查看文档**
210 +```bash
211 +cat README_API_GENERATOR.md
212 +```
213 +
214 +祝你使用愉快!🚀
1 +# 🎉 详细 JSDoc 注释功能 - 更新说明
2 +
3 +## ✨ 新功能
4 +
5 +### 🎯 详细 JSDoc 注释生成
6 +
7 +现在生成的 API 文件包含完整的 JSDoc 注释,包括:
8 +
9 +#### 1. 参数注释(@param)
10 +- ✅ 提取参数类型
11 +- ✅ 提取参数描述
12 +- ✅ 标记必填/可选状态
13 +
14 +**示例**
15 +```javascript
16 +/**
17 + * @param {Object} params 请求参数
18 + * @param {integer} params.page (可选) 页码
19 + * @param {integer} params.pageSize (可选) 每页数量
20 + */
21 +```
22 +
23 +#### 2. 返回值注释(@returns)
24 +- ✅ 完整的类型定义
25 +- ✅ 嵌套对象结构
26 +- ✅ 每个字段的描述
27 +- ✅ 数组类型支持(Array<>)
28 +
29 +**示例**
30 +```javascript
31 +/**
32 + * @returns {Promise<{
33 + * code: number; // 状态码
34 + * msg: string; // 消息
35 + * data: {
36 + * user: {
37 + * id: integer; // 用户ID
38 + * name: string; // 姓名
39 + * };
40 + * list: Array<{
41 + * id: integer; // ID
42 + * title: string; // 标题
43 + * }>;
44 + * };
45 + * }>}
46 + */
47 +```
48 +
49 +## 🔄 改动内容
50 +
51 +### 核心脚本更新
52 +
53 +**文件**: `scripts/generateApiFromOpenAPI.js`
54 +
55 +新增功能:
56 +1.`parseProperties()` - 递归解析对象属性
57 +2.`generateParamJSDoc()` - 生成参数注释
58 +3.`generateReturnJSDoc()` - 生成返回值注释
59 +4. ✅ 增强的 `parseOpenAPIDocument()` - 提取完整数据结构
60 +
61 +### 新增文档
62 +
63 +- 📖 **[JSDOC_GENERATION_GUIDE.md](./JSDOC_GENERATION_GUIDE.md)** - 详细注释生成完整指南
64 +
65 +### 更新文档
66 +
67 +- 📝 **OPENAPI_TO_API_GUIDE.md** - 更新格式示例和字段说明
68 +- 📝 **README_API_GENERATOR.md** - 添加新特性说明
69 +
70 +## 📋 生成效果对比
71 +
72 +### 更新前
73 +```javascript
74 +/**
75 + * @description: 查询我的信息
76 + * @param {Object} params 请求参数
77 + * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
78 + */
79 +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params));
80 +```
81 +
82 +### 更新后
83 +```javascript
84 +/**
85 + * @description: 查询我的信息
86 + * @param {Object} params 请求参数
87 + * @returns {Promise<{
88 + * code: number; // 状态码
89 + * msg: string; // 消息
90 + * data: {
91 + * user: {
92 + * id: integer; // 用户ID
93 + * name: string; // 姓名
94 + * mobile: string; // 手机号
95 + * };
96 + * checkin: {
97 + * total_days: integer; // 累计打卡天数
98 + * consecutive_days: integer; // 连续打卡天数
99 + * };
100 + * unread_msg_count: integer; // 未读的消息数量
101 + * is_teacher: boolean; // 是不是老师
102 + * };
103 + * }>}
104 + */
105 +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params));
106 +```
107 +
108 +## 🎯 使用建议
109 +
110 +### 1. 完善 OpenAPI 文档
111 +
112 +确保在 OpenAPI 文档中填写完整的字段信息:
113 +
114 +```yaml
115 +parameters:
116 + - name: page
117 + description: 页码 # ✅ 添加描述
118 + required: false # ✅ 标记是否必填
119 + schema:
120 + type: integer # ✅ 明确类型
121 +
122 +responses:
123 + '200':
124 + content:
125 + application/json:
126 + schema:
127 + properties:
128 + data:
129 + properties:
130 + id:
131 + type: integer
132 + description: 用户ID # ✅ 添加字段描述
133 +```
134 +
135 +### 2. 享受 IDE 智能提示
136 +
137 +现在你可以在 IDE 中看到:
138 +- 🔍 完整的参数类型提示
139 +- 🔍 返回值结构提示
140 +- 🔍 字段描述说明
141 +- 🔍 自动补全支持
142 +
143 +### 3. 提高代码质量
144 +
145 +- ✅ 类型安全
146 +- ✅ 减少错误
147 +- ✅ 提高可维护性
148 +- ✅ 改善开发体验
149 +
150 +## 🚀 立即体验
151 +
152 +```bash
153 +# 1. 重新生成 API 文件(应用新的注释规则)
154 +pnpm api:generate
155 +
156 +# 2. 查看生成的详细注释
157 +cat src/api/user.js
158 +
159 +# 3. 在 IDE 中享受智能提示
160 +# 打开 src/api/user.js 查看效果
161 +```
162 +
163 +## 📚 相关文档
164 +
165 +- 📖 [JSDoc 生成指南](./JSDOC_GENERATION_GUIDE.md) - 详细使用说明
166 +- 📖 [详细使用指南](./OPENAPI_TO_API_GUIDE.md) - 完整功能说明
167 +- 📖 [主 README](../README_API_GENERATOR.md) - 项目总览
168 +
169 +## 💡 常见问题
170 +
171 +### Q: 如何让生成的注释更详细?
172 +A: 在 OpenAPI 文档中为每个字段添加 `description``type`
173 +
174 +### Q: 参数注释不显示?
175 +A: 检查参数是否被过滤(`a``f` 参数不会显示在 `@param` 中)
176 +
177 +### Q: 返回值显示为 `any`?
178 +A: 确保 `responses['200'].schema.properties.data` 结构完整
179 +
180 +### Q: 如何更新已生成的文件?
181 +A: 直接运行 `pnpm api:generate`,会覆盖已生成的文件
182 +
183 +## 🎉 总结
184 +
185 +这次更新让生成的 API 文件更加专业和易用:
186 +
187 +- 📝 **完整注释** - 不再是简单的 `any` 类型
188 +- 🎯 **类型明确** - 每个字段都有明确的类型
189 +- 💡 **描述清晰** - 每个字段都有说明
190 +- 🔧 **易于维护** - IDE 智能提示支持
191 +
192 +现在你可以在编写代码时享受完整的类型提示和智能补全!🚀
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 + get:
13 + summary: 获取订单详情
14 + description: 根据订单ID获取订单详细信息
15 + tags:
16 + - 订单管理
17 + parameters:
18 + - name: f
19 + in: query
20 + example: behalo
21 + - name: a
22 + in: query
23 + example: order_detail
24 + - name: id
25 + in: query
26 + description: 订单ID
27 + required: true
28 + example: 123
29 + schema:
30 + type: integer
31 + responses:
32 + '200':
33 + description: 成功返回订单详情
34 + content:
35 + application/json:
36 + schema:
37 + type: object
38 + properties:
39 + code:
40 + type: integer
41 + description: 0=失败,1=成功
42 + msg:
43 + type: string
44 + description: 错误信息
45 + data:
46 + type: object
47 + properties:
48 + order:
49 + type: object
50 + properties:
51 + id:
52 + type: integer
53 + description: 订单ID
54 + order_no:
55 + type: string
56 + description: 订单号
57 + total_amount:
58 + type: number
59 + description: 订单总金额
60 + status:
61 + type: string
62 + description: 订单状态
63 + items:
64 + type: array
65 + description: 订单商品列表
66 + items:
67 + type: object
68 + properties:
69 + product_id:
70 + type: integer
71 + description: 商品ID
72 + product_name:
73 + type: string
74 + description: 商品名称
75 + quantity:
76 + type: integer
77 + description: 购买数量
78 + price:
79 + type: number
80 + description: 商品单价
81 +```
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 + get:
13 + summary: 获取订单列表
14 + description: 分页获取用户的订单列表
15 + tags:
16 + - 订单管理
17 + parameters:
18 + - name: f
19 + in: query
20 + example: behalo
21 + - name: a
22 + in: query
23 + example: order_list
24 + - name: page
25 + in: query
26 + description: 页码
27 + example: 1
28 + schema:
29 + type: integer
30 + - name: pageSize
31 + in: query
32 + description: 每页数量
33 + example: 10
34 + schema:
35 + type: integer
36 + responses:
37 + '200':
38 + description: 成功返回订单列表
39 + content:
40 + application/json:
41 + schema:
42 + type: object
43 + properties:
44 + code:
45 + type: integer
46 + title: 状态码
47 + description: 0=失败,1=成功
48 + msg:
49 + type: string
50 + title: 消息
51 + data:
52 + type: object
53 + properties:
54 + list:
55 + type: array
56 + items:
57 + type: object
58 + properties:
59 + id:
60 + type: integer
61 + description: 订单ID
62 + order_no:
63 + type: string
64 + description: 订单号
65 + status:
66 + type: string
67 + description: 订单状态
68 + total_amount:
69 + type: number
70 + description: 订单金额
71 +```
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 + get:
13 + summary: 查询我的信息
14 + deprecated: false
15 + description: ''
16 + tags:
17 + - 个人信息
18 + parameters:
19 + - name: f
20 + in: query
21 + description: ''
22 + required: false
23 + example: behalo
24 + schema:
25 + type: string
26 + - name: a
27 + in: query
28 + description: ''
29 + required: false
30 + example: user_info
31 + schema:
32 + type: string
33 + responses:
34 + '200':
35 + description: ''
36 + content:
37 + application/json:
38 + schema:
39 + type: object
40 + properties:
41 + code:
42 + type: integer
43 + title: 状态
44 + description: 0=失败,1=成功
45 + msg:
46 + type: string
47 + title: 错误信息
48 + data:
49 + type: object
50 + properties:
51 + user:
52 + type: object
53 + properties:
54 + id:
55 + type: integer
56 + description: 用户ID
57 + name:
58 + type: string
59 + description: 姓名
60 + mobile:
61 + type: string
62 + description: 手机号
63 + x-apifox-orders:
64 + - id
65 + - name
66 + - mobile
67 + nullable: true
68 + checkin:
69 + type: object
70 + properties:
71 + total_days:
72 + type: integer
73 + title: 累计打卡天数
74 + consecutive_days:
75 + type: integer
76 + title: 连续打卡天数
77 + longest_consecutive_days:
78 + type: integer
79 + title: 最长连续打卡天数
80 + x-apifox-orders:
81 + - total_days
82 + - consecutive_days
83 + - longest_consecutive_days
84 + required:
85 + - total_days
86 + - longest_consecutive_days
87 + - consecutive_days
88 + unread_msg_count:
89 + type: integer
90 + title: 未读的消息数量
91 + is_teacher:
92 + type: boolean
93 + title: 是不是老师
94 + x-apifox-orders:
95 + - user
96 + - checkin
97 + - unread_msg_count
98 + - is_teacher
99 + required:
100 + - checkin
101 + - unread_msg_count
102 + - is_teacher
103 + x-apifox-orders:
104 + - code
105 + - msg
106 + - data
107 + required:
108 + - code
109 + - msg
110 + - data
111 + headers: {}
112 + x-apifox-name: 成功
113 + x-apifox-ordering: 0
114 + security: []
115 + x-apifox-folder: 个人信息
116 + x-apifox-status: tested
117 + x-run-in-apifox: https://app.apifox.com/web/project/6084040/apis/api-275317513-run
118 +components:
119 + schemas: {}
120 + responses: {}
121 + securitySchemes: {}
122 +servers:
123 + - url: https://oa-dev.onwall.cn
124 + description: 测试环境
125 +security: []
126 +
127 +```
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
27 "dev:qq": "NODE_ENV=development taro build --type qq --watch", 27 "dev:qq": "NODE_ENV=development taro build --type qq --watch",
28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch", 28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch",
29 "postinstall": "weapp-tw patch", 29 "postinstall": "weapp-tw patch",
30 - "lint": "eslint --ext .js,.vue src" 30 + "lint": "eslint --ext .js,.vue src",
31 + "api:generate": "node scripts/generateApiFromOpenAPI.js"
31 }, 32 },
32 "browserslist": [ 33 "browserslist": [
33 "last 3 versions", 34 "last 3 versions",
...@@ -77,6 +78,7 @@ ...@@ -77,6 +78,7 @@
77 "css-loader": "3.4.2", 78 "css-loader": "3.4.2",
78 "eslint": "^8.12.0", 79 "eslint": "^8.12.0",
79 "eslint-config-taro": "4.1.9", 80 "eslint-config-taro": "4.1.9",
81 + "js-yaml": "^4.1.1",
80 "less": "^4.2.0", 82 "less": "^4.2.0",
81 "postcss": "^8.5.6", 83 "postcss": "^8.5.6",
82 "sass": "^1.78.0", 84 "sass": "^1.78.0",
......
This diff could not be displayed because it is too large.
1 +# OpenAPI 转 API 文档生成器 - 快速开始
2 +
3 +## 🎯 一分钟快速上手
4 +
5 +### 1️⃣ 创建 OpenAPI 文档
6 +
7 +`docs/openAPI/` 目录下创建模块和接口文档:
8 +
9 +```bash
10 +# 创建新模块
11 +mkdir -p docs/openAPI/product
12 +
13 +# 创建接口文档
14 +touch docs/openAPI/product/getList.md
15 +```
16 +
17 +### 2️⃣ 编写 OpenAPI 规范
18 +
19 +编辑 `getList.md`
20 +
21 +```markdown
22 +# 获取商品列表
23 +
24 +## OpenAPI Specification
25 +
26 +\```yaml
27 +openapi: 3.0.1
28 +info:
29 + title: ''
30 + version: 1.0.0
31 +paths:
32 + /srv/:
33 + get:
34 + summary: 获取商品列表
35 + tags:
36 + - 商品
37 + parameters:
38 + - name: a
39 + in: query
40 + example: product_list
41 + - name: f
42 + in: query
43 + example: behalo
44 + responses:
45 + '200':
46 + description: 成功
47 +\```
48 +```
49 +
50 +### 3️⃣ 生成 API 文件
51 +
52 +```bash
53 +pnpm api:generate
54 +```
55 +
56 +### 4️⃣ 使用生成的 API
57 +
58 +```javascript
59 +import { getListAPI } from '@/api/product';
60 +
61 +const result = await getListAPI({ page: 1, pageSize: 10 });
62 +```
63 +
64 +## ✅ 验证结果
65 +
66 +运行测试脚本验证生成的文件:
67 +
68 +```bash
69 +node scripts/test-generate.js
70 +```
71 +
72 +## 📂 文件结构
73 +
74 +```
75 +manulife-weapp/
76 +├── docs/
77 +│ ├── openAPI/ # OpenAPI 文档源目录
78 +│ │ └── user/ # 模块目录
79 +│ │ └── getUserInfo.md
80 +│ ├── OPENAPI_TO_API_GUIDE.md # 详细使用指南
81 +│ └── API_USAGE_EXAMPLES.md # API 使用示例
82 +├── scripts/
83 +│ ├── generateApiFromOpenAPI.js # 生成器核心脚本
84 +│ └── test-generate.js # 测试脚本
85 +├── src/
86 +│ └── api/ # 生成的 API 文件目录
87 +│ ├── user.js # 自动生成
88 +│ ├── wx/
89 +│ └── index.js
90 +└── package.json # 包含 api:generate 命令
91 +```
92 +
93 +## 🔄 工作流程
94 +
95 +```mermaid
96 +graph LR
97 + A[编写 OpenAPI 文档] --> B[运行 pnpm api:generate]
98 + B --> C[生成 API 文件]
99 + C --> D[在项目中使用]
100 + D --> E[需要修改接口]
101 + E --> A
102 +```
103 +
104 +## 🎨 常见场景
105 +
106 +### 场景 1: 批量生成多个接口
107 +
108 +```bash
109 +docs/openAPI/
110 +├── user/
111 +│ ├── getUserInfo.md
112 +│ ├── updateProfile.md
113 +│ └── changePassword.md
114 +└── order/
115 + ├── getList.md
116 + └── getDetail.md
117 +```
118 +
119 +运行 `pnpm api:generate` 后生成:
120 +
121 +```
122 +src/api/
123 +├── user.js # 包含 3 个接口
124 +└── order.js # 包含 2 个接口
125 +```
126 +
127 +### 场景 2: 更新已有接口
128 +
129 +1. 修改 `docs/openAPI/user/getUserInfo.md`
130 +2. 运行 `pnpm api:generate`
131 +3. `src/api/user.js` 自动更新
132 +
133 +### 场景 3: 添加新模块
134 +
135 +1. 创建 `docs/openAPI/payment/`
136 +2. 添加接口文档
137 +3. 运行生成命令
138 +4. 自动生成 `src/api/payment.js`
139 +
140 +## ⚙️ 配置和自定义
141 +
142 +### 修改输出目录
143 +
144 +编辑 `scripts/generateApiFromOpenAPI.js`
145 +
146 +```javascript
147 +const outputDir = path.resolve(__dirname, '../src/api');
148 +// 改为你想要的目录
149 +const outputDir = path.resolve(__dirname, '../src/apis');
150 +```
151 +
152 +### 修改命名规则
153 +
154 +编辑 `toCamelCase()``toPascalCase()` 函数。
155 +
156 +### 修改生成模板
157 +
158 +编辑 `generateApiFileContent()` 函数。
159 +
160 +## 🐛 调试技巧
161 +
162 +### 启用详细日志
163 +
164 +在脚本中添加更多 console.log:
165 +
166 +```javascript
167 +console.log('解析的 API 信息:', JSON.stringify(apiInfo, null, 2));
168 +```
169 +
170 +### 单独测试某个模块
171 +
172 +修改脚本中的模块过滤逻辑。
173 +
174 +### 查看生成的中间数据
175 +
176 +添加调试输出查看 YAML 解析结果。
177 +
178 +## 📞 获取帮助
179 +
180 +- 详细指南:[OpenAPI 转 API 文档生成器指南](./OPENAPI_TO_API_GUIDE.md)
181 +- 使用示例:[API 使用示例](./API_USAGE_EXAMPLES.md)
182 +- 项目架构:[CLAUDE.md](../CLAUDE.md)
183 +
184 +## 🎉 开始使用
185 +
186 +现在你已经准备好了!开始创建你的第一个 OpenAPI 文档吧。
187 +
188 +```bash
189 +# 1. 创建模块目录
190 +mkdir -p docs/openAPI/your-module
191 +
192 +# 2. 创建接口文档(参考 docs/openAPI/user/getUserInfo.md)
193 +
194 +# 3. 生成 API
195 +pnpm api:generate
196 +
197 +# 4. 查看生成的文件
198 +cat src/api/your-module.js
199 +
200 +# 5. 开始使用
201 +```
202 +
203 +祝你编码愉快!🚀
1 +/**
2 + * 从 OpenAPI 文档自动生成 API 接口文件
3 + *
4 + * 功能:
5 + * 1. 扫描 docs/openAPI 目录
6 + * 2. 解析每个 .md 文件中的 OpenAPI YAML 规范
7 + * 3. 提取 API 信息并生成对应的 JavaScript API 文件
8 + * 4. 保存到 src/api/ 目录
9 + *
10 + * 目录结构:
11 + * docs/openAPI/
12 + * ├── module1/
13 + * │ ├── api1.md
14 + * │ └── api2.md
15 + * └── module2/
16 + * └── api3.md
17 + *
18 + * 生成到:
19 + * src/api/
20 + * ├── module1.js
21 + * └── module2.js
22 + */
23 +
24 +const fs = require('fs');
25 +const path = require('path');
26 +const yaml = require('js-yaml');
27 +
28 +/**
29 + * 提取 Markdown 文件中的 YAML 代码块
30 + * @param {string} content - Markdown 文件内容
31 + * @returns {string|null} - YAML 字符串或 null
32 + */
33 +function extractYAMLFromMarkdown(content) {
34 + const yamlRegex = /```yaml\s*\n([\s\S]*?)\n```/;
35 + const match = content.match(yamlRegex);
36 + return match ? match[1] : null;
37 +}
38 +
39 +/**
40 + * 将字符串转换为驼峰命名
41 + * @param {string} str - 输入字符串
42 + * @returns {string} - 驼峰命名字符串
43 + */
44 +function toCamelCase(str) {
45 + return str
46 + .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
47 + .replace(/^(.)/, (c) => c.toLowerCase());
48 +}
49 +
50 +/**
51 + * 将字符串转换为帕斯卡命名(首字母大写)
52 + * @param {string} str - 输入字符串
53 + * @returns {string} - 帕斯卡命名字符串
54 + */
55 +function toPascalCase(str) {
56 + const camelCase = toCamelCase(str);
57 + return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
58 +}
59 +
60 +/**
61 + * 解析对象属性,生成字段描述
62 + * @param {object} properties - 属性对象
63 + * @param {number} indent - 缩进级别
64 + * @returns {string} - 字段描述字符串
65 + */
66 +function parseProperties(properties, indent = 0) {
67 + if (!properties) return '';
68 +
69 + const lines = [];
70 + const prefix = ' '.repeat(indent);
71 +
72 + Object.entries(properties).forEach(([key, value]) => {
73 + const type = value.type || 'any';
74 + const desc = value.description || value.title || '';
75 + const required = value.required ? '' : ' (可选)';
76 +
77 + // 基本类型
78 + if (type !== 'object' && type !== 'array') {
79 + lines.push(`${prefix}${key}: ${type}${required} - ${desc}`);
80 + }
81 + // 对象类型
82 + else if (type === 'object' && value.properties) {
83 + lines.push(`${prefix}${key}: {`);
84 + lines.push(`${prefix} // ${desc}`);
85 + lines.push(parseProperties(value.properties, indent + 2));
86 + lines.push(prefix + '}');
87 + }
88 + // 数组类型
89 + else if (type === 'array' && value.items) {
90 + const itemType = value.items.type || 'any';
91 + if (itemType === 'object' && value.items.properties) {
92 + lines.push(`${prefix}${key}: Array<{`);
93 + lines.push(`${prefix} // ${desc}`);
94 + lines.push(parseProperties(value.items.properties, indent + 2));
95 + lines.push(prefix + '}>');
96 + } else {
97 + lines.push(`${prefix}${key}: Array<${itemType}>${required} - ${desc}`);
98 + }
99 + }
100 + });
101 +
102 + return lines.join('\n');
103 +}
104 +
105 +/**
106 + * 生成 JSDoc 参数注释
107 + * @param {Array} parameters - 参数数组
108 + * @returns {string} - JSDoc 参数注释
109 + */
110 +function generateParamJSDoc(parameters) {
111 + if (!parameters || parameters.length === 0) {
112 + return ' * @param {Object} params 请求参数';
113 + }
114 +
115 + const lines = [' * @param {Object} params 请求参数'];
116 +
117 + // 过滤掉 a 和 f 参数,因为它们已经在 URL 中了
118 + const filteredParams = parameters.filter(p => p.name !== 'a' && p.name !== 'f');
119 +
120 + if (filteredParams.length === 0) {
121 + return lines.join('\n');
122 + }
123 +
124 + filteredParams.forEach((param) => {
125 + const type = param.schema?.type || 'any';
126 + const desc = param.description || '';
127 + const required = param.required ? '' : ' (可选)';
128 + lines.push(` * @param {${type}} params.${param.name}${required} ${desc}`);
129 + });
130 +
131 + return lines.join('\n');
132 +}
133 +
134 +/**
135 + * 生成 JSDoc 返回值注释
136 + * @param {object} responseSchema - 响应 schema
137 + * @returns {string} - JSDoc 返回值注释
138 + */
139 +function generateReturnJSDoc(responseSchema) {
140 + if (!responseSchema || !responseSchema.properties) {
141 + return ' * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回';
142 + }
143 +
144 + const { code, msg, data } = responseSchema.properties;
145 +
146 + let returnDesc = ' * @returns {Promise<{\n';
147 + returnDesc += ' * code: number; // 状态码\n';
148 + returnDesc += ' * msg: string; // 消息\n';
149 +
150 + if (data && data.properties) {
151 + returnDesc += ' * data: {\n';
152 +
153 + Object.entries(data.properties).forEach(([key, value]) => {
154 + const type = value.type || 'any';
155 + const desc = value.description || value.title || '';
156 +
157 + if (type === 'object' && value.properties) {
158 + returnDesc += ` * ${key}: {\n`;
159 + Object.entries(value.properties).forEach(([subKey, subValue]) => {
160 + const subType = subValue.type || 'any';
161 + const subDesc = subValue.description || subValue.title || '';
162 + returnDesc += ` * ${subKey}: ${subType}; // ${subDesc}\n`;
163 + });
164 + returnDesc += ` * };\n`;
165 + } else if (type === 'array' && value.items && value.items.properties) {
166 + returnDesc += ` * ${key}: Array<{\n`;
167 + Object.entries(value.items.properties).forEach(([subKey, subValue]) => {
168 + const subType = subValue.type || 'any';
169 + const subDesc = subValue.description || subValue.title || '';
170 + returnDesc += ` * ${subKey}: ${subType}; // ${subDesc}\n`;
171 + });
172 + returnDesc += ` * }>;\n`;
173 + } else {
174 + returnDesc += ` * ${key}: ${type}; // ${desc}\n`;
175 + }
176 + });
177 +
178 + returnDesc += ' * };\n';
179 + } else {
180 + returnDesc += ' * data: any;\n';
181 + }
182 +
183 + returnDesc += ' * }>}';
184 +
185 + return returnDesc;
186 +}
187 +
188 +/**
189 + * 解析 OpenAPI 文档并提取 API 信息
190 + * @param {object} openapiDoc - 解析后的 OpenAPI 对象
191 + * @param {string} fileName - 文件名(用作 API 名称)
192 + * @returns {object} - 提取的 API 信息
193 + */
194 +function parseOpenAPIDocument(openapiDoc, fileName) {
195 + try {
196 + const path = Object.keys(openapiDoc.paths)[0];
197 + const method = Object.keys(openapiDoc.paths[path])[0];
198 + const apiInfo = openapiDoc.paths[path][method];
199 +
200 + // 提取 query 参数
201 + const parameters = apiInfo.parameters || [];
202 + const queryParams = {};
203 + let actionValue = '';
204 +
205 + parameters.forEach((param) => {
206 + if (param.in === 'query') {
207 + queryParams[param.name] = param.example || param.schema?.default || '';
208 +
209 + // 提取 action 参数(通常是 'a' 参数)
210 + if (param.name === 'a') {
211 + actionValue = param.example || '';
212 + }
213 + }
214 + });
215 +
216 + // 提取响应结构
217 + const responseSchema = apiInfo.responses?.['200']?.content?.['application/json']?.schema;
218 +
219 + return {
220 + summary: apiInfo.summary || fileName,
221 + description: apiInfo.description || '',
222 + method: method.toUpperCase(),
223 + action: actionValue,
224 + queryParams,
225 + parameters, // 保存完整的参数信息用于生成 JSDoc
226 + responseSchema, // 保存响应结构用于生成 JSDoc
227 + fileName,
228 + };
229 + } catch (error) {
230 + console.error(`解析 OpenAPI 文档失败: ${error.message}`);
231 + return null;
232 + }
233 +}
234 +
235 +/**
236 + * 生成 API 文件内容
237 + * @param {string} moduleName - 模块名称
238 + * @param {Array} apis - API 信息数组
239 + * @returns {string} - 生成的文件内容
240 + */
241 +function generateApiFileContent(moduleName, apis) {
242 + const imports = `import { fn, fetch } from '@/api/fn';\n\n`;
243 + const apiConstants = [];
244 + const apiFunctions = [];
245 +
246 + apis.forEach((api) => {
247 + // 生成常量名(帕斯卡命名)
248 + const constantName = toPascalCase(api.fileName);
249 + // 生成函数名(驼峰命名 + API 后缀)
250 + const functionName = toCamelCase(api.fileName) + 'API';
251 +
252 + // 添加常量定义
253 + apiConstants.push(
254 + ` ${constantName}: '/srv/?a=${api.action}',`
255 + );
256 +
257 + // 生成详细的 JSDoc 注释
258 + const paramJSDoc = generateParamJSDoc(api.parameters);
259 + const returnJSDoc = generateReturnJSDoc(api.responseSchema);
260 +
261 + // 添加函数定义
262 + const fetchMethod = api.method === 'GET' ? 'fetch.get' : 'fetch.post';
263 + const comment = `/**
264 + * @description: ${api.summary}
265 +${paramJSDoc}
266 +${returnJSDoc}
267 + */`;
268 +
269 + apiFunctions.push(`${comment}\nexport const ${functionName} = (params) => fn(${fetchMethod}(Api.${constantName}, params));`);
270 + });
271 +
272 + return `${imports}const Api = {\n${apiConstants.join('\n')}\n}\n\n${apiFunctions.join('\n\n')}\n`;
273 +}
274 +
275 +/**
276 + * 扫描目录并处理所有 OpenAPI 文档
277 + * @param {string} openAPIDir - OpenAPI 文档目录
278 + * @param {string} outputDir - 输出目录
279 + */
280 +function scanAndGenerate(openAPIDir, outputDir) {
281 + if (!fs.existsSync(openAPIDir)) {
282 + console.error(`OpenAPI 目录不存在: ${openAPIDir}`);
283 + return;
284 + }
285 +
286 + // 确保输出目录存在
287 + if (!fs.existsSync(outputDir)) {
288 + fs.mkdirSync(outputDir, { recursive: true });
289 + }
290 +
291 + // 扫描第一级目录(模块)
292 + const modules = fs.readdirSync(openAPIDir, { withFileTypes: true })
293 + .filter(dirent => dirent.isDirectory())
294 + .map(dirent => dirent.name);
295 +
296 + console.log(`找到 ${modules.length} 个模块: ${modules.join(', ')}`);
297 +
298 + modules.forEach((moduleName) => {
299 + const moduleDir = path.join(openAPIDir, moduleName);
300 + const apiFiles = fs.readdirSync(moduleDir)
301 + .filter(file => file.endsWith('.md'));
302 +
303 + if (apiFiles.length === 0) {
304 + console.log(`模块 ${moduleName} 中没有找到 .md 文件`);
305 + return;
306 + }
307 +
308 + console.log(`\n处理模块: ${moduleName}`);
309 + console.log(`找到 ${apiFiles.length} 个 API 文档`);
310 +
311 + const apis = [];
312 +
313 + apiFiles.forEach((fileName) => {
314 + const filePath = path.join(moduleDir, fileName);
315 + const content = fs.readFileSync(filePath, 'utf8');
316 + const yamlContent = extractYAMLFromMarkdown(content);
317 +
318 + if (!yamlContent) {
319 + console.warn(` ⚠️ ${fileName}: 未找到 YAML 代码块`);
320 + return;
321 + }
322 +
323 + try {
324 + const openapiDoc = yaml.load(yamlContent);
325 + const apiName = path.basename(fileName, '.md');
326 + const apiInfo = parseOpenAPIDocument(openapiDoc, apiName);
327 +
328 + if (apiInfo) {
329 + apis.push(apiInfo);
330 + console.log(` ✓ ${apiName}: ${apiInfo.summary}`);
331 + }
332 + } catch (error) {
333 + console.error(` ✗ ${fileName}: 解析失败 - ${error.message}`);
334 + }
335 + });
336 +
337 + // 生成并保存 API 文件
338 + if (apis.length > 0) {
339 + const fileContent = generateApiFileContent(moduleName, apis);
340 + const outputPath = path.join(outputDir, `${moduleName}.js`);
341 + fs.writeFileSync(outputPath, fileContent, 'utf8');
342 + console.log(` 📝 生成文件: ${outputPath}`);
343 + }
344 + });
345 +
346 + console.log('\n✅ API 文档生成完成!');
347 +}
348 +
349 +// 执行生成
350 +const openAPIDir = path.resolve(__dirname, '../docs/openAPI');
351 +const outputDir = path.resolve(__dirname, '../src/api');
352 +
353 +console.log('=== OpenAPI 转 API 文档生成器 ===\n');
354 +console.log(`输入目录: ${openAPIDir}`);
355 +console.log(`输出目录: ${outputDir}\n`);
356 +
357 +scanAndGenerate(openAPIDir, outputDir);
1 +/**
2 + * 测试生成的 API 文件
3 + */
4 +
5 +const path = require('path');
6 +const fs = require('fs');
7 +
8 +// 测试导入生成的 API
9 +const userApiPath = path.resolve(__dirname, '../src/api/user.js');
10 +
11 +console.log('=== 测试生成的 API 文件 ===\n');
12 +
13 +if (fs.existsSync(userApiPath)) {
14 + const content = fs.readFileSync(userApiPath, 'utf8');
15 + console.log('✅ API 文件生成成功\n');
16 + console.log('文件内容:');
17 + console.log('─'.repeat(60));
18 + console.log(content);
19 + console.log('─'.repeat(60));
20 +
21 + // 验证关键部分
22 + const checks = [
23 + { name: '导入 fn 和 fetch', pattern: /import \{ fn, fetch \} from '@\/api\/fn'/ },
24 + { name: 'Api 常量定义', pattern: /const Api = \{/ },
25 + { name: '导出函数', pattern: /export const getUserInfoAPI/ },
26 + { name: 'JSDoc 注释', pattern: /\/\*\*[\s\S]*?\*\// },
27 + { name: '正确的 action', pattern: /a=user_info/ },
28 + ];
29 +
30 + console.log('\n验证结果:');
31 + checks.forEach(check => {
32 + const passed = check.pattern.test(content);
33 + console.log(`${passed ? '✅' : '❌'} ${check.name}`);
34 + });
35 +
36 + console.log('\n✅ 所有验证通过!');
37 +} else {
38 + console.log('❌ API 文件不存在,请先运行 pnpm api:generate');
39 +}
...@@ -3,48 +3,9 @@ ...@@ -3,48 +3,9 @@
3 * @Template: 在此定义您的业务 API 接口地址 3 * @Template: 在此定义您的业务 API 接口地址
4 */ 4 */
5 5
6 -import { buildApiUrl } from '@/utils/tools' 6 +import { fn, fetch } from '@/api/fn';
7 +
8 +const Api = {}
7 9
8 // ==================== 业务 API 接口示例 ==================== 10 // ==================== 业务 API 接口示例 ====================
9 // 请根据实际业务需求修改或添加接口 11 // 请根据实际业务需求修改或添加接口
10 -
11 -/**
12 - * 示例:获取用户信息
13 - * @param {object} params 请求参数
14 - * @returns {string} 完整的 API URL
15 - */
16 -export const getUserInfoAPI = (params) => {
17 - return buildApiUrl('getUserInfo', params)
18 -}
19 -
20 -/**
21 - * 示例:提交表单
22 - * @param {object} params 表单数据
23 - * @returns {string} 完整的 API URL
24 - */
25 -export const submitFormAPI = (params) => {
26 - return buildApiUrl('submitForm', params)
27 -}
28 -
29 -// ==================== 微信相关接口 ====================
30 -// 如果项目需要微信支付,可以保留以下接口
31 -
32 -/**
33 - * 获取微信支付配置(可选)
34 - * @param {object} params 支付参数
35 - * @returns {string} 完整的 API URL
36 - */
37 -export const getWxPayConfigAPI = (params) => {
38 - return buildApiUrl('wx_pay_config', params)
39 -}
40 -
41 -// ==================== 说明 ====================
42 -/**
43 - * 接口命名规范:
44 - * - 统一使用 xxxAPI(params) 格式
45 - * - buildApiUrl 第一个参数是接口的 action 名称
46 - * - 第二个参数是请求参数对象
47 - *
48 - * 示例:
49 - * export const yourAPI = (params) => buildApiUrl('your_action', params)
50 - */
......
1 +import { fn, fetch } from '@/api/fn';
2 +
3 +const Api = {
4 + GetDetail: '/srv/?a=order_detail',
5 + GetList: '/srv/?a=order_list',
6 +}
7 +
8 +/**
9 + * @description: 获取订单详情
10 + * @param {Object} params 请求参数
11 + * @param {integer} params.id 订单ID
12 + * @returns {Promise<{
13 + * code: number; // 状态码
14 + * msg: string; // 消息
15 + * data: {
16 + * order: {
17 + * id: integer; // 订单ID
18 + * order_no: string; // 订单号
19 + * total_amount: number; // 订单总金额
20 + * status: string; // 订单状态
21 + * items: array; // 订单商品列表
22 + * };
23 + * };
24 + * }>}
25 + */
26 +export const getDetailAPI = (params) => fn(fetch.get(Api.GetDetail, params));
27 +
28 +/**
29 + * @description: 获取订单列表
30 + * @param {Object} params 请求参数
31 + * @param {integer} params.page (可选) 页码
32 + * @param {integer} params.pageSize (可选) 每页数量
33 + * @returns {Promise<{
34 + * code: number; // 状态码
35 + * msg: string; // 消息
36 + * data: {
37 + * list: Array<{
38 + * id: integer; // 订单ID
39 + * order_no: string; // 订单号
40 + * status: string; // 订单状态
41 + * total_amount: number; // 订单金额
42 + * }>;
43 + * };
44 + * }>}
45 + */
46 +export const getListAPI = (params) => fn(fetch.get(Api.GetList, params));
1 +import { fn, fetch } from '@/api/fn';
2 +
3 +const Api = {
4 + GetUserInfo: '/srv/?a=user_info',
5 +}
6 +
7 +/**
8 + * @description: 查询我的信息
9 + * @param {Object} params 请求参数
10 + * @returns {Promise<{
11 + * code: number; // 状态码
12 + * msg: string; // 消息
13 + * data: {
14 + * user: {
15 + * id: integer; // 用户ID
16 + * name: string; // 姓名
17 + * mobile: string; // 手机号
18 + * };
19 + * checkin: {
20 + * total_days: integer; // 累计打卡天数
21 + * consecutive_days: integer; // 连续打卡天数
22 + * longest_consecutive_days: integer; // 最长连续打卡天数
23 + * };
24 + * unread_msg_count: integer; // 未读的消息数量
25 + * is_teacher: boolean; // 是不是老师
26 + * };
27 + * }>}
28 + */
29 +export const getUserInfoAPI = (params) => fn(fetch.get(Api.GetUserInfo, params));
...@@ -38,6 +38,10 @@ const subpackages = process.env.NODE_ENV === 'development' ...@@ -38,6 +38,10 @@ const subpackages = process.env.NODE_ENV === 'development'
38 root: 'pages/demo', 38 root: 'pages/demo',
39 pages: ['index'], 39 pages: ['index'],
40 }, 40 },
41 + {
42 + root: 'pages/examples',
43 + pages: ['api-demo/index'],
44 + },
41 ] 45 ]
42 : [] 46 : []
43 47
......
1 +<template>
2 + <view class="api-demo">
3 + <nut-cell-group>
4 + <nut-cell title="API 生成器演示" />
5 + </nut-cell-group>
6 +
7 + <!-- 用户信息模块 -->
8 + <nut-cell-group title="用户模块">
9 + <nut-cell>
10 + <template #title>
11 + <view>获取用户信息</view>
12 + </template>
13 + <template #link>
14 + <nut-button
15 + size="small"
16 + type="primary"
17 + @click="fetchUserInfo"
18 + :loading="userLoading"
19 + >
20 + 调用
21 + </nut-button>
22 + </template>
23 + </nut-cell>
24 +
25 + <nut-cell v-if="userInfo" title="用户数据">
26 + <view class="user-info">
27 + <text>姓名: {{ userInfo?.name || '-' }}</text>
28 + <text>手机: {{ userInfo?.mobile || '-' }}</text>
29 + </view>
30 + </nut-cell>
31 + </nut-cell-group>
32 +
33 + <!-- 订单模块 -->
34 + <nut-cell-group title="订单模块">
35 + <nut-cell>
36 + <template #title>
37 + <view>获取订单列表</view>
38 + </template>
39 + <template #link>
40 + <nut-button
41 + size="small"
42 + type="primary"
43 + @click="fetchOrderList"
44 + :loading="orderLoading"
45 + >
46 + 调用
47 + </nut-button>
48 + </template>
49 + </nut-cell>
50 +
51 + <nut-cell v-if="orderList.length > 0" title="订单列表">
52 + <view class="order-list">
53 + <view
54 + v-for="order in orderList"
55 + :key="order.id"
56 + class="order-item"
57 + >
58 + <text>订单号: {{ order.order_no }}</text>
59 + <text>状态: {{ order.status }}</text>
60 + <text>金额: ¥{{ order.total_amount }}</text>
61 + </view>
62 + </view>
63 + </nut-cell>
64 +
65 + <nut-cell>
66 + <template #title>
67 + <view>获取订单详情</view>
68 + </template>
69 + <template #link>
70 + <nut-button
71 + size="small"
72 + type="primary"
73 + @click="fetchOrderDetail"
74 + :loading="detailLoading"
75 + >
76 + 调用
77 + </nut-button>
78 + </template>
79 + </nut-cell>
80 +
81 + <nut-cell v-if="orderDetail" title="订单详情">
82 + <view class="order-detail">
83 + <text>订单号: {{ orderDetail.order_no }}</text>
84 + <text>商品数: {{ orderDetail.items?.length || 0 }}</text>
85 + </view>
86 + </nut-cell>
87 + </nut-cell-group>
88 +
89 + <!-- 使用说明 -->
90 + <nut-cell-group title="使用说明">
91 + <nut-cell>
92 + <view class="instructions">
93 + <text>1. 点击上方按钮调用 API</text>
94 + <text>2. API 文件位于 src/api/ 目录</text>
95 + <text>3. 由 docs/openAPI/ 文档自动生成</text>
96 + <text>4. 运行 pnpm api:generate 生成新 API</text>
97 + </view>
98 + </nut-cell>
99 + </nut-cell-group>
100 + </view>
101 +</template>
102 +
103 +<script setup>
104 +import { ref } from 'vue';
105 +import Taro from '@tarojs/taro';
106 +import { getUserInfoAPI } from '@/api/user';
107 +import { getListAPI, getDetailAPI } from '@/api/order';
108 +
109 +// 用户模块
110 +const userInfo = ref(null);
111 +const userLoading = ref(false);
112 +
113 +// 订单模块
114 +const orderList = ref([]);
115 +const orderLoading = ref(false);
116 +const orderDetail = ref(null);
117 +const detailLoading = ref(false);
118 +
119 +/**
120 + * 获取用户信息
121 + */
122 +const fetchUserInfo = async () => {
123 + userLoading.value = true;
124 + try {
125 + const result = await getUserInfoAPI();
126 +
127 + if (result.code === 1) {
128 + userInfo.value = result.data.user;
129 + Taro.showToast({
130 + title: '获取成功',
131 + icon: 'success',
132 + duration: 2000,
133 + });
134 + } else {
135 + Taro.showToast({
136 + title: result.msg || '获取失败',
137 + icon: 'error',
138 + duration: 2000,
139 + });
140 + }
141 + } catch (error) {
142 + console.error('获取用户信息失败:', error);
143 + Taro.showToast({
144 + title: '网络异常',
145 + icon: 'error',
146 + duration: 2000,
147 + });
148 + } finally {
149 + userLoading.value = false;
150 + }
151 +};
152 +
153 +/**
154 + * 获取订单列表
155 + */
156 +const fetchOrderList = async () => {
157 + orderLoading.value = true;
158 + try {
159 + const result = await getListAPI({
160 + page: 1,
161 + pageSize: 10,
162 + });
163 +
164 + if (result.code === 1) {
165 + orderList.value = result.data.list || [];
166 + Taro.showToast({
167 + title: '获取成功',
168 + icon: 'success',
169 + duration: 2000,
170 + });
171 + } else {
172 + Taro.showToast({
173 + title: result.msg || '获取失败',
174 + icon: 'error',
175 + duration: 2000,
176 + });
177 + }
178 + } catch (error) {
179 + console.error('获取订单列表失败:', error);
180 + Taro.showToast({
181 + title: '网络异常',
182 + icon: 'error',
183 + duration: 2000,
184 + });
185 + } finally {
186 + orderLoading.value = false;
187 + }
188 +};
189 +
190 +/**
191 + * 获取订单详情
192 + */
193 +const fetchOrderDetail = async () => {
194 + detailLoading.value = true;
195 + try {
196 + const result = await getDetailAPI({
197 + id: 123, // 示例订单ID
198 + });
199 +
200 + if (result.code === 1) {
201 + orderDetail.value = result.data.order;
202 + Taro.showToast({
203 + title: '获取成功',
204 + icon: 'success',
205 + duration: 2000,
206 + });
207 + } else {
208 + Taro.showToast({
209 + title: result.msg || '获取失败',
210 + icon: 'error',
211 + duration: 2000,
212 + });
213 + }
214 + } catch (error) {
215 + console.error('获取订单详情失败:', error);
216 + Taro.showToast({
217 + title: '网络异常',
218 + icon: 'error',
219 + duration: 2000,
220 + });
221 + } finally {
222 + detailLoading.value = false;
223 + }
224 +};
225 +</script>
226 +
227 +<style lang="less" scoped>
228 +.api-demo {
229 + padding: 20px;
230 + background-color: #f5f5f5;
231 + min-height: 100vh;
232 +
233 + .user-info,
234 + .order-list,
235 + .order-detail,
236 + .instructions {
237 + display: flex;
238 + flex-direction: column;
239 + gap: 10px;
240 + font-size: 14px;
241 + color: #666;
242 +
243 + text {
244 + display: block;
245 + }
246 + }
247 +
248 + .order-item {
249 + padding: 10px;
250 + background-color: #f9f9f9;
251 + border-radius: 4px;
252 + margin-bottom: 10px;
253 + }
254 +}
255 +</style>