@tuoyuan/gateway-api-select-config 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +605 -0
- package/dist/gateway-api-select-config.css +3 -0
- package/dist/gateway-api-select-config.es.js +1767 -0
- package/dist/gateway-api-select-config.umd.js +28 -0
- package/package.json +60 -0
- package/src/components/ApiConfig.vue +2264 -0
- package/src/components/SchemaFieldEditor.vue +572 -0
- package/src/index.js +70 -0
- package/src/utils/dataExtractor.js +359 -0
- package/src/utils/dataFilters.js +300 -0
- package/src/utils/reqMappingUtils.js +147 -0
- package/src/utils/schemaUtils.js +197 -0
- package/src/utils/treeUtils.js +134 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 API Config Component
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
# API Config Component
|
|
2
|
+
|
|
3
|
+
网关接口配置组件 - 可视化配置 API 接口数据映射
|
|
4
|
+
|
|
5
|
+
## 简介
|
|
6
|
+
|
|
7
|
+
**API Config Component** 是一个基于 Vue 3 的可视化配置组件,用于配置网关 API 接口的数据映射规则。
|
|
8
|
+
|
|
9
|
+
### 核心功能
|
|
10
|
+
|
|
11
|
+
1. **选择 API 接口** - 从树形结构中选择目标接口
|
|
12
|
+
2. **配置入参映射** - 支持固定值、模板字符串、函数三种模式
|
|
13
|
+
3. **配置输出结构** - 定义字段提取路径和格式化规则
|
|
14
|
+
4. **输出标准配置** - 生成可存储、可解析的 JSON 配置
|
|
15
|
+
|
|
16
|
+
### 应用场景
|
|
17
|
+
|
|
18
|
+
- 网关接口数据适配
|
|
19
|
+
- 多数据源统一输出格式
|
|
20
|
+
- 动态表单/表格数据源配置
|
|
21
|
+
- 低代码平台数据源配置
|
|
22
|
+
|
|
23
|
+
## 特性
|
|
24
|
+
|
|
25
|
+
- 🎯 **可视化配置** - 通过界面操作完成复杂的数据映射
|
|
26
|
+
- 🌲 **树形 API 选择** - 支持多层级分类和搜索
|
|
27
|
+
- 🔍 **智能过滤** - 支持 include/exclude 模式过滤 API
|
|
28
|
+
- 🎨 **灵活的入参配置** - 固定值/模板字符串/函数三种模式
|
|
29
|
+
- 📋 **Schema 驱动** - 基于 JSON Schema 定义输出结构
|
|
30
|
+
- 🎛️ **字段格式化** - 支持日期、数字、货币等格式化
|
|
31
|
+
- 💾 **标准输出** - 输出标准 JSON 配置
|
|
32
|
+
- 🔄 **自动推断** - Schema 不完整时自动返回完整数据
|
|
33
|
+
|
|
34
|
+
## 安装
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install api-config-component
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
或
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
yarn add api-config-component
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
或
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm add api-config-component
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 快速开始
|
|
53
|
+
|
|
54
|
+
### 最简单的使用方式
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<template>
|
|
58
|
+
<ApiConfig
|
|
59
|
+
:api-loader="loadApiList"
|
|
60
|
+
@save="handleSave"
|
|
61
|
+
/>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<script setup>
|
|
65
|
+
import { ApiConfig } from 'api-config-component';
|
|
66
|
+
import 'api-config-component/dist/style.css';
|
|
67
|
+
|
|
68
|
+
// 加载 API 列表
|
|
69
|
+
const loadApiList = async () => {
|
|
70
|
+
const response = await fetch('/api/gateway/list');
|
|
71
|
+
return response.json();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// 保存配置
|
|
75
|
+
const handleSave = (config) => {
|
|
76
|
+
console.log('保存的配置:', config);
|
|
77
|
+
// 将配置保存到后端
|
|
78
|
+
};
|
|
79
|
+
</script>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 使用工具函数测试配置
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<template>
|
|
86
|
+
<ApiConfig
|
|
87
|
+
:api-loader="loadApiList"
|
|
88
|
+
@save="handleSave"
|
|
89
|
+
/>
|
|
90
|
+
</template>
|
|
91
|
+
|
|
92
|
+
<script setup>
|
|
93
|
+
import { ApiConfig, extractDataBySchema, executeReqMapping } from 'api-config-component';
|
|
94
|
+
import 'api-config-component/dist/style.css';
|
|
95
|
+
|
|
96
|
+
const loadApiList = async () => {
|
|
97
|
+
// 加载 API 列表
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const handleSave = async (config) => {
|
|
101
|
+
// 1. 执行入参映射
|
|
102
|
+
const params = executeReqMapping(config.reqMapping, {
|
|
103
|
+
pageNum: 1,
|
|
104
|
+
pageSize: 100
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 2. 调用 API
|
|
108
|
+
const response = await fetch(config.apiPath, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
body: JSON.stringify(params)
|
|
111
|
+
});
|
|
112
|
+
const data = await response.json();
|
|
113
|
+
|
|
114
|
+
// 3. 提取数据
|
|
115
|
+
const result = extractDataBySchema(data, config.res_schema);
|
|
116
|
+
|
|
117
|
+
console.log('提取后的数据:', result);
|
|
118
|
+
};
|
|
119
|
+
</script>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## API 文档
|
|
123
|
+
|
|
124
|
+
### Props
|
|
125
|
+
|
|
126
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
127
|
+
|------|------|------|--------|------|
|
|
128
|
+
| apiLoader | Function | 是* | null | 自定义 API 列表加载函数 |
|
|
129
|
+
| apiListUrl | String | 是* | '' | 网关 API 列表接口地址 |
|
|
130
|
+
| resSchema | Object | 否 | null | 输出数据结构模板(JSON Schema) |
|
|
131
|
+
| includePattern | Array | 否 | [] | 只显示匹配规则的 API,支持通配符 `*` |
|
|
132
|
+
| excludePattern | Array | 否 | [] | 排除匹配规则的 API |
|
|
133
|
+
| initialConfig | Object | 否 | null | 初始配置(编辑模式) |
|
|
134
|
+
|
|
135
|
+
**注意**:`apiLoader` 和 `apiListUrl` 至少需要提供一个。
|
|
136
|
+
|
|
137
|
+
### Events
|
|
138
|
+
|
|
139
|
+
| 事件名 | 参数 | 说明 |
|
|
140
|
+
|--------|------|------|
|
|
141
|
+
| save | config: Object | 保存配置时触发,返回完整配置对象 |
|
|
142
|
+
| change | { api, config, resSchema } | 配置变化时触发 |
|
|
143
|
+
|
|
144
|
+
### 导出的工具函数
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
import {
|
|
148
|
+
ApiConfig, // 组件
|
|
149
|
+
extractDataBySchema, // 根据 schema 提取数据
|
|
150
|
+
executeReqMapping, // 执行入参映射
|
|
151
|
+
extractOutputFields, // 提取输出字段信息
|
|
152
|
+
formatConfig // 格式化配置显示
|
|
153
|
+
} from 'api-config-component';
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### extractDataBySchema(data, schema)
|
|
157
|
+
|
|
158
|
+
根据 res_schema 从原始数据中提取字段。
|
|
159
|
+
|
|
160
|
+
**参数:**
|
|
161
|
+
- `data` - 原始数据对象
|
|
162
|
+
- `schema` - res_schema 配置
|
|
163
|
+
|
|
164
|
+
**返回:** 提取后的数据
|
|
165
|
+
|
|
166
|
+
**示例:**
|
|
167
|
+
```javascript
|
|
168
|
+
const data = {
|
|
169
|
+
code: 10000,
|
|
170
|
+
msg: '成功',
|
|
171
|
+
data: {
|
|
172
|
+
list: [
|
|
173
|
+
{ id: 1, name: '张三' },
|
|
174
|
+
{ id: 2, name: '李四' }
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const schema = {
|
|
180
|
+
type: 'object',
|
|
181
|
+
x_path: '@.data.list',
|
|
182
|
+
items: {
|
|
183
|
+
type: 'object',
|
|
184
|
+
properties: {
|
|
185
|
+
id: { type: 'integer', x_path: '@.id' },
|
|
186
|
+
name: { type: 'string', x_path: '@.name' }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const result = extractDataBySchema(data, schema);
|
|
192
|
+
// 结果:[{ id: 1, name: '张三' }, { id: 2, name: '李四' }]
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### executeReqMapping(reqMapping, context)
|
|
196
|
+
|
|
197
|
+
执行入参映射,将模板变量替换为实际值。
|
|
198
|
+
|
|
199
|
+
**参数:**
|
|
200
|
+
- `reqMapping` - 入参映射配置
|
|
201
|
+
- `context` - 上下文数据对象
|
|
202
|
+
|
|
203
|
+
**返回:** 执行后的参数对象
|
|
204
|
+
|
|
205
|
+
**示例:**
|
|
206
|
+
```javascript
|
|
207
|
+
const reqMapping = {
|
|
208
|
+
page_no: '${pageNum}',
|
|
209
|
+
page_size: '${pageSize}',
|
|
210
|
+
keyword: '${searchText}'
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const context = {
|
|
214
|
+
pageNum: 1,
|
|
215
|
+
pageSize: 100,
|
|
216
|
+
searchText: 'test'
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const params = executeReqMapping(reqMapping, context);
|
|
220
|
+
// 结果:{ page_no: 1, page_size: 100, keyword: 'test' }
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## 使用示例
|
|
224
|
+
|
|
225
|
+
### 示例 1:列表接口配置
|
|
226
|
+
|
|
227
|
+
```vue
|
|
228
|
+
<template>
|
|
229
|
+
<ApiConfig
|
|
230
|
+
:api-loader="loadApiList"
|
|
231
|
+
:include-pattern="['*.get_list', '*.query*']"
|
|
232
|
+
:exclude-pattern="['*.add', '*.remove', '*.delete']"
|
|
233
|
+
@save="handleSave"
|
|
234
|
+
/>
|
|
235
|
+
</template>
|
|
236
|
+
|
|
237
|
+
<script setup>
|
|
238
|
+
import { ApiConfig } from 'api-config-component';
|
|
239
|
+
import 'api-config-component/dist/style.css';
|
|
240
|
+
|
|
241
|
+
const loadApiList = async () => {
|
|
242
|
+
const response = await fetch('/api/gateway/list');
|
|
243
|
+
return response.json();
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const handleSave = (config) => {
|
|
247
|
+
console.log('保存的配置:', config);
|
|
248
|
+
// 保存到后端
|
|
249
|
+
fetch('/api/config/save', {
|
|
250
|
+
method: 'POST',
|
|
251
|
+
body: JSON.stringify(config)
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
</script>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 示例 2:树形结构配置
|
|
258
|
+
|
|
259
|
+
```vue
|
|
260
|
+
<template>
|
|
261
|
+
<ApiConfig
|
|
262
|
+
:api-loader="loadApiList"
|
|
263
|
+
:include-pattern="['*.get_tree', '*.get_list']"
|
|
264
|
+
@save="handleSave"
|
|
265
|
+
/>
|
|
266
|
+
</template>
|
|
267
|
+
|
|
268
|
+
<script setup>
|
|
269
|
+
import { ApiConfig } from 'api-config-component';
|
|
270
|
+
import 'api-config-component/dist/style.css';
|
|
271
|
+
|
|
272
|
+
const loadApiList = async () => {
|
|
273
|
+
// 加载 API 列表
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const handleSave = (config) => {
|
|
277
|
+
console.log('保存配置', config);
|
|
278
|
+
};
|
|
279
|
+
</script>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 示例 3:编辑已有配置
|
|
283
|
+
|
|
284
|
+
```vue
|
|
285
|
+
<template>
|
|
286
|
+
<ApiConfig
|
|
287
|
+
:api-loader="loadApiList"
|
|
288
|
+
:initial-config="existingConfig"
|
|
289
|
+
@save="handleSave"
|
|
290
|
+
/>
|
|
291
|
+
</template>
|
|
292
|
+
|
|
293
|
+
<script setup>
|
|
294
|
+
import { ref } from 'vue';
|
|
295
|
+
import { ApiConfig } from 'api-config-component';
|
|
296
|
+
import 'api-config-component/dist/style.css';
|
|
297
|
+
|
|
298
|
+
const existingConfig = ref({
|
|
299
|
+
apiPath: '/api/news/list',
|
|
300
|
+
reqMapping: {
|
|
301
|
+
page_no: '${pageNum}',
|
|
302
|
+
page_size: '${pageSize}'
|
|
303
|
+
},
|
|
304
|
+
res_schema: {
|
|
305
|
+
type: 'object',
|
|
306
|
+
x_path: '@.data.list',
|
|
307
|
+
items: {
|
|
308
|
+
type: 'object',
|
|
309
|
+
properties: {
|
|
310
|
+
id: { type: 'integer', x_path: '@.id' },
|
|
311
|
+
title: { type: 'string', x_path: '@.title' }
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const loadApiList = async () => {
|
|
318
|
+
// 加载 API 列表
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const handleSave = (config) => {
|
|
322
|
+
console.log('更新配置', config);
|
|
323
|
+
};
|
|
324
|
+
</script>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## 配置输出格式
|
|
328
|
+
|
|
329
|
+
组件保存后输出标准 JSON 配置:
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"apiPath": "/api/news/list",
|
|
334
|
+
"reqMapping": {
|
|
335
|
+
"page_no": "${pageNum}",
|
|
336
|
+
"page_size": "${pageSize}",
|
|
337
|
+
"keyword": "${searchText}"
|
|
338
|
+
},
|
|
339
|
+
"res_schema": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"x_path": "@.data.list",
|
|
342
|
+
"items": {
|
|
343
|
+
"type": "object",
|
|
344
|
+
"properties": {
|
|
345
|
+
"id": {
|
|
346
|
+
"type": "integer",
|
|
347
|
+
"x_path": "@.id",
|
|
348
|
+
"format": ""
|
|
349
|
+
},
|
|
350
|
+
"title": {
|
|
351
|
+
"type": "string",
|
|
352
|
+
"x_path": "@.title",
|
|
353
|
+
"format": ""
|
|
354
|
+
},
|
|
355
|
+
"publishTime": {
|
|
356
|
+
"type": "string",
|
|
357
|
+
"x_path": "@.publish_time",
|
|
358
|
+
"format": "YYYY-MM-DD HH:mm:ss"
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## 入参配置模式
|
|
367
|
+
|
|
368
|
+
### 1. 固定值模式
|
|
369
|
+
|
|
370
|
+
直接使用固定值:
|
|
371
|
+
|
|
372
|
+
```json
|
|
373
|
+
{
|
|
374
|
+
"page_no": 1,
|
|
375
|
+
"page_size": 100,
|
|
376
|
+
"need_total": true
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 2. 模板字符串模式
|
|
381
|
+
|
|
382
|
+
使用 `${变量名}` 引用上下文变量:
|
|
383
|
+
|
|
384
|
+
```json
|
|
385
|
+
{
|
|
386
|
+
"page_no": "${pageNum}",
|
|
387
|
+
"page_size": "${pageSize}",
|
|
388
|
+
"keyword": "${searchText}"
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**不带引号的写法**(推荐,自动保持类型):
|
|
393
|
+
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"page_no": ${pageNum},
|
|
397
|
+
"page_size": ${pageSize}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### 3. 函数模式
|
|
402
|
+
|
|
403
|
+
使用箭头函数进行复杂计算:
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
{
|
|
407
|
+
"page_no": "(ctx) => Number(ctx.pageNum) || 1",
|
|
408
|
+
"page_size": "(ctx) => Math.min(ctx.pageSize, 100)",
|
|
409
|
+
"keyword": "(ctx) => ctx.searchText?.trim() || ''"
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## 字段格式化
|
|
414
|
+
|
|
415
|
+
支持多种格式化类型:
|
|
416
|
+
|
|
417
|
+
### 日期格式
|
|
418
|
+
|
|
419
|
+
- `YYYY-MM-DD` - 2024-01-01
|
|
420
|
+
- `YYYY-MM-DD HH:mm:ss` - 2024-01-01 12:00:00
|
|
421
|
+
- `YYYY/MM/DD` - 2024/01/01
|
|
422
|
+
- `timestamp` - 时间戳(毫秒)
|
|
423
|
+
- `timestamp_s` - 时间戳(秒)
|
|
424
|
+
|
|
425
|
+
### 数字格式
|
|
426
|
+
|
|
427
|
+
- `number` - 数字
|
|
428
|
+
- `integer` - 整数
|
|
429
|
+
- `currency` - 货币(¥1,234.56)
|
|
430
|
+
- `percent` - 百分比(12.34%)
|
|
431
|
+
|
|
432
|
+
### 通用格式
|
|
433
|
+
|
|
434
|
+
- `string` - 字符串
|
|
435
|
+
- `boolean` - 布尔值
|
|
436
|
+
- `json` - JSON 字符串
|
|
437
|
+
|
|
438
|
+
## Schema 自动推断
|
|
439
|
+
|
|
440
|
+
当 API 的 `res_schema` 不完整(`properties` 为空)时,组件会自动推断并返回完整的原始数据。
|
|
441
|
+
|
|
442
|
+
**示例:**
|
|
443
|
+
|
|
444
|
+
如果 API 的 schema 是:
|
|
445
|
+
```json
|
|
446
|
+
{
|
|
447
|
+
"type": "object",
|
|
448
|
+
"properties": {
|
|
449
|
+
"data": {
|
|
450
|
+
"type": "object",
|
|
451
|
+
"properties": {}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
组件会自动:
|
|
458
|
+
1. 检测到 `data.properties` 为空
|
|
459
|
+
2. 推测数据路径为 `@.data.list`
|
|
460
|
+
3. 直接返回 `data.list` 的完整数据
|
|
461
|
+
|
|
462
|
+
## API 树数据格式
|
|
463
|
+
|
|
464
|
+
API 列表应返回以下格式:
|
|
465
|
+
|
|
466
|
+
```javascript
|
|
467
|
+
[
|
|
468
|
+
{
|
|
469
|
+
id: '1', // 节点 ID
|
|
470
|
+
name: '系统管理', // 节点名称
|
|
471
|
+
isLeaf: false, // 是否叶子节点
|
|
472
|
+
expanded: false, // 是否展开
|
|
473
|
+
children: [ // 子节点
|
|
474
|
+
{
|
|
475
|
+
id: '1-1',
|
|
476
|
+
name: '获取用户列表',
|
|
477
|
+
apiPath: '/api/system/user/get_list', // API 路径
|
|
478
|
+
isLeaf: true,
|
|
479
|
+
_raw: { // 原始数据(包含 req_schema、res_schema)
|
|
480
|
+
req_schema: { /* ... */ },
|
|
481
|
+
res_schema: { /* ... */ }
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
]
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
或者使用 `funcs` 数组(会自动转换为 `children`):
|
|
490
|
+
|
|
491
|
+
```javascript
|
|
492
|
+
[
|
|
493
|
+
{
|
|
494
|
+
id: '1',
|
|
495
|
+
name: '系统管理',
|
|
496
|
+
funcs: [ // 接口列表
|
|
497
|
+
{
|
|
498
|
+
id: '1-1',
|
|
499
|
+
name: '获取用户列表',
|
|
500
|
+
tag: 'system.user.get_list',
|
|
501
|
+
req_schema: { /* ... */ },
|
|
502
|
+
res_schema: { /* ... */ }
|
|
503
|
+
}
|
|
504
|
+
]
|
|
505
|
+
}
|
|
506
|
+
]
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## 过滤规则
|
|
510
|
+
|
|
511
|
+
### includePattern
|
|
512
|
+
|
|
513
|
+
只显示匹配的 API:
|
|
514
|
+
|
|
515
|
+
```vue
|
|
516
|
+
<ApiConfig
|
|
517
|
+
:include-pattern="['*.get_list', '*.query*', 'system.*']"
|
|
518
|
+
/>
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### excludePattern
|
|
522
|
+
|
|
523
|
+
排除匹配的 API:
|
|
524
|
+
|
|
525
|
+
```vue
|
|
526
|
+
<ApiConfig
|
|
527
|
+
:exclude-pattern="['*.add', '*.remove', '*.delete', '*.update']"
|
|
528
|
+
/>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### 通配符规则
|
|
532
|
+
|
|
533
|
+
- `*` - 匹配任意字符
|
|
534
|
+
- `*.get_list` - 匹配所有以 `.get_list` 结尾的 API
|
|
535
|
+
- `system.*` - 匹配所有以 `system.` 开头的 API
|
|
536
|
+
- `*user*` - 匹配包含 `user` 的 API
|
|
537
|
+
|
|
538
|
+
## 开发
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
# 安装依赖
|
|
542
|
+
npm install
|
|
543
|
+
|
|
544
|
+
# 启动开发服务器
|
|
545
|
+
npm run dev
|
|
546
|
+
|
|
547
|
+
# 构建库
|
|
548
|
+
npm run build
|
|
549
|
+
|
|
550
|
+
# 预览
|
|
551
|
+
npm run preview
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## 浏览器支持
|
|
555
|
+
|
|
556
|
+
- Chrome >= 87
|
|
557
|
+
- Firefox >= 78
|
|
558
|
+
- Safari >= 14
|
|
559
|
+
- Edge >= 88
|
|
560
|
+
|
|
561
|
+
## 常见问题
|
|
562
|
+
|
|
563
|
+
### 1. 如何处理 Schema 不完整的 API?
|
|
564
|
+
|
|
565
|
+
组件会自动检测并使用自动推断模式,直接返回完整的原始数据。
|
|
566
|
+
|
|
567
|
+
### 2. 模板变量的类型如何保持?
|
|
568
|
+
|
|
569
|
+
使用不带引号的写法:`{"page_no": ${pageNum}}`,会自动保持原始类型。
|
|
570
|
+
|
|
571
|
+
### 3. 如何自定义 API 加载逻辑?
|
|
572
|
+
|
|
573
|
+
使用 `apiLoader` prop 提供自定义加载函数:
|
|
574
|
+
|
|
575
|
+
```javascript
|
|
576
|
+
const loadApiList = async () => {
|
|
577
|
+
const response = await fetch('/your-api');
|
|
578
|
+
return response.json();
|
|
579
|
+
};
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### 4. 如何测试配置是否正确?
|
|
583
|
+
|
|
584
|
+
使用导出的工具函数:
|
|
585
|
+
|
|
586
|
+
```javascript
|
|
587
|
+
import { extractDataBySchema, executeReqMapping } from 'api-config-component';
|
|
588
|
+
|
|
589
|
+
// 执行入参映射
|
|
590
|
+
const params = executeReqMapping(config.reqMapping, context);
|
|
591
|
+
|
|
592
|
+
// 调用 API 获取数据
|
|
593
|
+
const data = await callApi(config.apiPath, params);
|
|
594
|
+
|
|
595
|
+
// 提取数据
|
|
596
|
+
const result = extractDataBySchema(data, config.res_schema);
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## License
|
|
600
|
+
|
|
601
|
+
MIT
|
|
602
|
+
|
|
603
|
+
## 贡献
|
|
604
|
+
|
|
605
|
+
欢迎提交 Issue 和 Pull Request!
|