whistle.mock-plugins 1.1.1-dev.14 → 1.1.1-dev.8
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/VERSION.md +0 -5
- package/app/cgi-bin/interfaces.js +0 -5
- package/app/public/js/index.js +1 -1
- package/lib/routes/interfaces.js +0 -171
- package/package.json +1 -1
- package/ui/src/pages/InterfaceManagement.js +11 -239
package/lib/routes/interfaces.js
CHANGED
|
@@ -23,7 +23,6 @@ const processInterfaceData = (data) => {
|
|
|
23
23
|
console.log('=== 开始处理接口数据 ===');
|
|
24
24
|
console.log('原始数据:', JSON.stringify({
|
|
25
25
|
name: result.name,
|
|
26
|
-
group: result.group, // 添加分组信息的日志
|
|
27
26
|
hasResponses: !!result.responses,
|
|
28
27
|
responsesType: typeof result.responses,
|
|
29
28
|
responsesLength: result.responses ? result.responses.length : 0,
|
|
@@ -109,7 +108,6 @@ const processInterfaceData = (data) => {
|
|
|
109
108
|
console.log('=== 处理后的最终接口数据 ===');
|
|
110
109
|
console.log('最终数据:', JSON.stringify({
|
|
111
110
|
name: result.name,
|
|
112
|
-
group: result.group, // 添加分组信息的日志
|
|
113
111
|
responsesLength: result.responses.length,
|
|
114
112
|
responses: result.responses,
|
|
115
113
|
activeResponseId: result.activeResponseId,
|
|
@@ -518,175 +516,6 @@ const initRouter = () => {
|
|
|
518
516
|
}
|
|
519
517
|
});
|
|
520
518
|
|
|
521
|
-
// 批量更新接口状态
|
|
522
|
-
router.patch('/interfaces', (req, res) => {
|
|
523
|
-
try {
|
|
524
|
-
const { active } = req.query;
|
|
525
|
-
const { featureId, group } = req.body;
|
|
526
|
-
|
|
527
|
-
if (active === undefined) {
|
|
528
|
-
return res.status(400).json({
|
|
529
|
-
code: 1,
|
|
530
|
-
message: '状态参数为必填项'
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (!featureId) {
|
|
535
|
-
return res.status(400).json({
|
|
536
|
-
code: 1,
|
|
537
|
-
message: '功能ID为必填项'
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// 检查功能是否存在
|
|
542
|
-
const featuresFile = path.join(DATA_DIR, 'features.json');
|
|
543
|
-
if (!fs.existsSync(featuresFile)) {
|
|
544
|
-
return res.status(404).json({
|
|
545
|
-
code: 1,
|
|
546
|
-
message: '功能不存在'
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
const features = fs.readJsonSync(featuresFile);
|
|
551
|
-
const feature = features.find(f => f.id === featureId);
|
|
552
|
-
if (!feature) {
|
|
553
|
-
return res.status(404).json({
|
|
554
|
-
code: 1,
|
|
555
|
-
message: '功能不存在'
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// 读取接口列表
|
|
560
|
-
const interfacesFile = path.join(DATA_DIR, `interfaces-${featureId}.json`);
|
|
561
|
-
if (!fs.existsSync(interfacesFile)) {
|
|
562
|
-
return res.status(404).json({
|
|
563
|
-
code: 1,
|
|
564
|
-
message: '接口列表不存在'
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
const interfaces = fs.readJsonSync(interfacesFile);
|
|
569
|
-
|
|
570
|
-
// 根据分组筛选要更新的接口
|
|
571
|
-
let updatedCount = 0;
|
|
572
|
-
const updatedInterfaces = interfaces.map(item => {
|
|
573
|
-
// 如果指定了分组,只更新该分组下的接口
|
|
574
|
-
if (group && item.group !== group) {
|
|
575
|
-
return item;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// 更新接口状态
|
|
579
|
-
if (item.active !== (active === 'true')) {
|
|
580
|
-
updatedCount++;
|
|
581
|
-
return {
|
|
582
|
-
...item,
|
|
583
|
-
active: active === 'true',
|
|
584
|
-
updatedAt: new Date().toISOString()
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
return item;
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
// 保存更新后的接口列表
|
|
592
|
-
fs.writeJsonSync(interfacesFile, updatedInterfaces, { spaces: 2 });
|
|
593
|
-
|
|
594
|
-
res.json({
|
|
595
|
-
code: 0,
|
|
596
|
-
message: `成功${active === 'true' ? '启用' : '禁用'} ${updatedCount} 个接口`,
|
|
597
|
-
data: { updatedCount }
|
|
598
|
-
});
|
|
599
|
-
} catch (err) {
|
|
600
|
-
console.error('批量更新接口状态失败:', err);
|
|
601
|
-
res.status(500).json({
|
|
602
|
-
code: 1,
|
|
603
|
-
message: '批量更新接口状态失败: ' + err.message
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
// 部分更新接口
|
|
609
|
-
router.patch('/interfaces/:id', (req, res) => {
|
|
610
|
-
try {
|
|
611
|
-
const { id } = req.params;
|
|
612
|
-
const updateData = req.body;
|
|
613
|
-
|
|
614
|
-
if (!id) {
|
|
615
|
-
return res.status(400).json({
|
|
616
|
-
code: 1,
|
|
617
|
-
message: '接口ID为必填项'
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// 检查功能是否存在
|
|
622
|
-
const featuresFile = path.join(DATA_DIR, 'features.json');
|
|
623
|
-
if (!fs.existsSync(featuresFile)) {
|
|
624
|
-
return res.status(404).json({
|
|
625
|
-
code: 1,
|
|
626
|
-
message: '功能不存在'
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
const features = fs.readJsonSync(featuresFile);
|
|
631
|
-
|
|
632
|
-
// 在所有功能模块中查找接口
|
|
633
|
-
let foundInterface = null;
|
|
634
|
-
let foundFeature = null;
|
|
635
|
-
let foundInterfaceIndex = -1;
|
|
636
|
-
let interfacesFile = '';
|
|
637
|
-
|
|
638
|
-
for (const feature of features) {
|
|
639
|
-
const featureInterfacesFile = path.join(DATA_DIR, `interfaces-${feature.id}.json`);
|
|
640
|
-
if (fs.existsSync(featureInterfacesFile)) {
|
|
641
|
-
const interfaces = fs.readJsonSync(featureInterfacesFile);
|
|
642
|
-
const index = interfaces.findIndex(item => item.id === id);
|
|
643
|
-
|
|
644
|
-
if (index !== -1) {
|
|
645
|
-
foundInterface = interfaces[index];
|
|
646
|
-
foundFeature = feature;
|
|
647
|
-
foundInterfaceIndex = index;
|
|
648
|
-
interfacesFile = featureInterfacesFile;
|
|
649
|
-
break;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
if (!foundInterface) {
|
|
655
|
-
return res.status(404).json({
|
|
656
|
-
code: 1,
|
|
657
|
-
message: '接口不存在'
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// 读取接口所在文件的所有接口
|
|
662
|
-
const interfaces = fs.readJsonSync(interfacesFile);
|
|
663
|
-
|
|
664
|
-
// 更新接口
|
|
665
|
-
const updatedInterface = {
|
|
666
|
-
...foundInterface,
|
|
667
|
-
...updateData,
|
|
668
|
-
updatedAt: new Date().toISOString()
|
|
669
|
-
};
|
|
670
|
-
|
|
671
|
-
interfaces[foundInterfaceIndex] = updatedInterface;
|
|
672
|
-
|
|
673
|
-
// 保存更新后的接口列表
|
|
674
|
-
fs.writeJsonSync(interfacesFile, interfaces, { spaces: 2 });
|
|
675
|
-
|
|
676
|
-
res.json({
|
|
677
|
-
code: 0,
|
|
678
|
-
message: '接口更新成功',
|
|
679
|
-
data: updatedInterface
|
|
680
|
-
});
|
|
681
|
-
} catch (err) {
|
|
682
|
-
console.error('更新接口失败:', err);
|
|
683
|
-
res.status(500).json({
|
|
684
|
-
code: 1,
|
|
685
|
-
message: '更新接口失败: ' + err.message
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
});
|
|
689
|
-
|
|
690
519
|
return router;
|
|
691
520
|
};
|
|
692
521
|
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import AppLayout from '../components/AppLayout';
|
|
|
4
4
|
import {
|
|
5
5
|
Table, Button, Modal, Form, Input, Select, message, Switch,
|
|
6
6
|
Popconfirm, Alert, Space, Card, Badge, Tooltip, Row, Col,
|
|
7
|
-
Popover, Checkbox
|
|
7
|
+
Popover, Checkbox
|
|
8
8
|
} from 'antd';
|
|
9
9
|
import {
|
|
10
10
|
PlusOutlined, EditOutlined, DeleteOutlined,
|
|
@@ -32,7 +32,6 @@ const { Option } = Select;
|
|
|
32
32
|
const COLUMN_CONFIG = [
|
|
33
33
|
{ key: 'active', title: '状态', required: true },
|
|
34
34
|
{ key: 'name', title: '名称', required: true },
|
|
35
|
-
{ key: 'group', title: '分组', required: false },
|
|
36
35
|
{ key: 'urlPattern', title: 'URL匹配规则', required: false },
|
|
37
36
|
{ key: 'proxyType', title: '处理方式', required: false },
|
|
38
37
|
{ key: 'currentResponse', title: '当前响应', required: false },
|
|
@@ -58,11 +57,6 @@ const InterfaceManagement = () => {
|
|
|
58
57
|
const [interfacesLoading, setInterfacesLoading] = useState(false);
|
|
59
58
|
const [selectedFeatureId, setSelectedFeatureId] = useState(null);
|
|
60
59
|
|
|
61
|
-
// 分组状态
|
|
62
|
-
const [groups, setGroups] = useState([]);
|
|
63
|
-
const [selectedGroup, setSelectedGroup] = useState(null);
|
|
64
|
-
const [groupActionLoading, setGroupActionLoading] = useState(false);
|
|
65
|
-
|
|
66
60
|
// 模态框状态
|
|
67
61
|
const [modalVisible, setModalVisible] = useState(false);
|
|
68
62
|
const [previewVisible, setPreviewVisible] = useState(false);
|
|
@@ -172,10 +166,6 @@ const InterfaceManagement = () => {
|
|
|
172
166
|
|
|
173
167
|
setInterfaces(processedInterfaces);
|
|
174
168
|
console.log('处理后的接口列表:', processedInterfaces);
|
|
175
|
-
console.log('接口分组信息:', processedInterfaces.map(item => ({ id: item.id, name: item.name, group: item.group })));
|
|
176
|
-
|
|
177
|
-
// 提取并更新分组列表
|
|
178
|
-
updateGroups(processedInterfaces);
|
|
179
169
|
} else {
|
|
180
170
|
console.warn('接口数据格式不正确:', response.data);
|
|
181
171
|
setInterfaces([]);
|
|
@@ -189,41 +179,6 @@ const InterfaceManagement = () => {
|
|
|
189
179
|
setInterfacesLoading(false);
|
|
190
180
|
}
|
|
191
181
|
};
|
|
192
|
-
|
|
193
|
-
// 提取并更新分组列表
|
|
194
|
-
const updateGroups = (interfaces) => {
|
|
195
|
-
// 从接口列表中提取所有分组
|
|
196
|
-
const groupSet = new Set();
|
|
197
|
-
interfaces.forEach(item => {
|
|
198
|
-
if (item.group) {
|
|
199
|
-
groupSet.add(item.group);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// 转换为数组并排序
|
|
204
|
-
const groupArray = Array.from(groupSet).sort();
|
|
205
|
-
setGroups(groupArray);
|
|
206
|
-
|
|
207
|
-
// 如果当前选中的分组不在列表中,重置选中的分组
|
|
208
|
-
if (selectedGroup && !groupArray.includes(selectedGroup)) {
|
|
209
|
-
setSelectedGroup(null);
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// 根据分组筛选接口
|
|
214
|
-
const getFilteredInterfaces = () => {
|
|
215
|
-
// 首先按功能模块筛选
|
|
216
|
-
const featureFiltered = interfaces.filter(item =>
|
|
217
|
-
!selectedFeatureId || item.featureId === selectedFeatureId
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
// 然后按分组筛选
|
|
221
|
-
if (selectedGroup) {
|
|
222
|
-
return featureFiltered.filter(item => item.group === selectedGroup);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return featureFiltered;
|
|
226
|
-
};
|
|
227
182
|
|
|
228
183
|
const handleAddInterface = () => {
|
|
229
184
|
if (!selectedFeatureId) {
|
|
@@ -251,8 +206,7 @@ const InterfaceManagement = () => {
|
|
|
251
206
|
activeResponseId: defaultResponseId,
|
|
252
207
|
httpMethod: 'ALL',
|
|
253
208
|
headerItems: [], // 初始化为空数组
|
|
254
|
-
paramMatchers: []
|
|
255
|
-
group: undefined // 确保分组字段为undefined,而不是空字符串
|
|
209
|
+
paramMatchers: [] // 初始化为空数组
|
|
256
210
|
});
|
|
257
211
|
|
|
258
212
|
setCurrentResponseId(defaultResponseId);
|
|
@@ -299,16 +253,9 @@ const InterfaceManagement = () => {
|
|
|
299
253
|
}));
|
|
300
254
|
}
|
|
301
255
|
|
|
302
|
-
// 处理分组值,确保它是字符串而不是数组
|
|
303
|
-
let groupValue = record.group;
|
|
304
|
-
if (Array.isArray(groupValue)) {
|
|
305
|
-
groupValue = groupValue.length > 0 ? groupValue[0] : undefined;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
256
|
// 设置表单值
|
|
309
257
|
form.setFieldsValue({
|
|
310
258
|
name: record.name,
|
|
311
|
-
group: groupValue || undefined, // 使用undefined而不是空字符串
|
|
312
259
|
pattern: record.urlPattern,
|
|
313
260
|
proxyType: record.proxyType || 'response',
|
|
314
261
|
statusCode: (record.httpStatus || record.statusCode || 200).toString(),
|
|
@@ -322,8 +269,6 @@ const InterfaceManagement = () => {
|
|
|
322
269
|
responseDelay: record.responseDelay ? record.responseDelay.toString() : '0'
|
|
323
270
|
});
|
|
324
271
|
|
|
325
|
-
console.log('编辑接口时设置的分组值:', groupValue);
|
|
326
|
-
|
|
327
272
|
setCurrentResponseId(activeResponseId);
|
|
328
273
|
setEditingInterface(record);
|
|
329
274
|
setModalVisible(true);
|
|
@@ -349,15 +294,12 @@ const InterfaceManagement = () => {
|
|
|
349
294
|
|
|
350
295
|
const handleToggleActive = async (id, currentActive) => {
|
|
351
296
|
try {
|
|
352
|
-
const response = await axios.patch(`/cgi-bin/interfaces
|
|
297
|
+
const response = await axios.patch(`/cgi-bin/interfaces?id=${id}`, {
|
|
353
298
|
active: !currentActive
|
|
354
299
|
});
|
|
355
300
|
if (response.data && response.data.code === 0) {
|
|
356
301
|
message.success(`接口${!currentActive ? '启用' : '禁用'}成功`);
|
|
357
302
|
fetchInterfaces();
|
|
358
|
-
|
|
359
|
-
// 刷新规则缓存
|
|
360
|
-
refreshCacheAfterUpdate();
|
|
361
303
|
} else {
|
|
362
304
|
throw new Error(response.data?.message || `接口${!currentActive ? '启用' : '禁用'}失败`);
|
|
363
305
|
}
|
|
@@ -383,16 +325,9 @@ const InterfaceManagement = () => {
|
|
|
383
325
|
});
|
|
384
326
|
}
|
|
385
327
|
|
|
386
|
-
// 处理分组值,确保它是字符串而不是数组
|
|
387
|
-
let groupValue = values.group;
|
|
388
|
-
if (Array.isArray(groupValue)) {
|
|
389
|
-
groupValue = groupValue.length > 0 ? groupValue[0] : '';
|
|
390
|
-
}
|
|
391
|
-
|
|
392
328
|
// 构建接口数据
|
|
393
329
|
const interfaceData = {
|
|
394
330
|
name: values.name,
|
|
395
|
-
group: groupValue || '', // 确保group不为undefined
|
|
396
331
|
urlPattern: values.pattern,
|
|
397
332
|
proxyType: values.proxyType,
|
|
398
333
|
featureId: selectedFeatureId,
|
|
@@ -405,8 +340,6 @@ const InterfaceManagement = () => {
|
|
|
405
340
|
active: true
|
|
406
341
|
};
|
|
407
342
|
|
|
408
|
-
console.log('提交的分组值:', groupValue);
|
|
409
|
-
|
|
410
343
|
// 根据代理类型添加不同字段
|
|
411
344
|
if (values.proxyType === 'redirect' || values.proxyType === 'url_redirect') {
|
|
412
345
|
interfaceData.targetUrl = values.targetUrl;
|
|
@@ -441,8 +374,6 @@ const InterfaceManagement = () => {
|
|
|
441
374
|
const response = await axios.post('/cgi-bin/interfaces', interfaceData);
|
|
442
375
|
if (response.data && response.data.code === 0) {
|
|
443
376
|
message.success('接口创建成功');
|
|
444
|
-
console.log('接口创建成功,返回数据:', response.data);
|
|
445
|
-
console.log('返回的接口数据中的分组信息:', response.data.data?.group);
|
|
446
377
|
setModalVisible(false);
|
|
447
378
|
fetchInterfaces();
|
|
448
379
|
|
|
@@ -529,7 +460,9 @@ const InterfaceManagement = () => {
|
|
|
529
460
|
}
|
|
530
461
|
};
|
|
531
462
|
|
|
532
|
-
const filteredInterfaces =
|
|
463
|
+
const filteredInterfaces = interfaces.filter(item =>
|
|
464
|
+
!selectedFeatureId || item.featureId === selectedFeatureId
|
|
465
|
+
);
|
|
533
466
|
|
|
534
467
|
// 处理表格变化(排序、分页)
|
|
535
468
|
const handleTableChange = (pagination, filters, sorter) => {
|
|
@@ -594,27 +527,6 @@ const InterfaceManagement = () => {
|
|
|
594
527
|
sorter: (a, b) => a.name.localeCompare(b.name),
|
|
595
528
|
render: (text) => <span className="interface-name">{text}</span>,
|
|
596
529
|
},
|
|
597
|
-
{
|
|
598
|
-
title: '分组',
|
|
599
|
-
dataIndex: 'group',
|
|
600
|
-
key: 'group',
|
|
601
|
-
width: 120,
|
|
602
|
-
sorter: (a, b) => {
|
|
603
|
-
const groupA = a.group || '';
|
|
604
|
-
const groupB = b.group || '';
|
|
605
|
-
return groupA.localeCompare(groupB);
|
|
606
|
-
},
|
|
607
|
-
render: (group) => {
|
|
608
|
-
if (!group) {
|
|
609
|
-
return <span style={{ color: '#999', fontStyle: 'italic' }}>未分组</span>;
|
|
610
|
-
}
|
|
611
|
-
return (
|
|
612
|
-
<Tag color="blue" style={{ cursor: 'pointer' }} onClick={() => setSelectedGroup(group)}>
|
|
613
|
-
{group}
|
|
614
|
-
</Tag>
|
|
615
|
-
);
|
|
616
|
-
},
|
|
617
|
-
},
|
|
618
530
|
{
|
|
619
531
|
title: 'URL匹配规则',
|
|
620
532
|
dataIndex: 'urlPattern',
|
|
@@ -863,28 +775,6 @@ const InterfaceManagement = () => {
|
|
|
863
775
|
const visibleColumns = tableConfig.visibleColumns || COLUMN_CONFIG.map(col => col.key);
|
|
864
776
|
const columns = allColumns.filter(col => visibleColumns.includes(col.key));
|
|
865
777
|
|
|
866
|
-
// 分组筛选和操作区域
|
|
867
|
-
const handleBatchToggleActive = async (active) => {
|
|
868
|
-
try {
|
|
869
|
-
setGroupActionLoading(true);
|
|
870
|
-
const response = await axios.patch(`/cgi-bin/interfaces?active=${active}`, {
|
|
871
|
-
featureId: selectedFeatureId,
|
|
872
|
-
group: selectedGroup
|
|
873
|
-
});
|
|
874
|
-
if (response.data && response.data.code === 0) {
|
|
875
|
-
message.success(`分组 "${selectedGroup}" 中的接口已成功${active ? '启用' : '禁用'}`);
|
|
876
|
-
fetchInterfaces();
|
|
877
|
-
} else {
|
|
878
|
-
throw new Error(response.data?.message || '批量操作失败');
|
|
879
|
-
}
|
|
880
|
-
} catch (error) {
|
|
881
|
-
console.error('批量操作失败:', error);
|
|
882
|
-
message.error(error.response?.data?.message || error.message || '批量操作失败');
|
|
883
|
-
} finally {
|
|
884
|
-
setGroupActionLoading(false);
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
|
|
888
778
|
return (
|
|
889
779
|
<AppLayout>
|
|
890
780
|
<div className="interface-management-container">
|
|
@@ -938,77 +828,6 @@ const InterfaceManagement = () => {
|
|
|
938
828
|
/>
|
|
939
829
|
)}
|
|
940
830
|
|
|
941
|
-
{/* 分组筛选和操作区域 */}
|
|
942
|
-
<div style={{
|
|
943
|
-
display: 'flex',
|
|
944
|
-
justifyContent: 'space-between',
|
|
945
|
-
alignItems: 'center',
|
|
946
|
-
marginBottom: 16,
|
|
947
|
-
padding: '12px 16px',
|
|
948
|
-
backgroundColor: '#f5f5f5',
|
|
949
|
-
borderRadius: '4px'
|
|
950
|
-
}}>
|
|
951
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
|
|
952
|
-
<span>分组筛选:</span>
|
|
953
|
-
<Select
|
|
954
|
-
value={selectedGroup}
|
|
955
|
-
onChange={value => setSelectedGroup(value)}
|
|
956
|
-
style={{ width: 200 }}
|
|
957
|
-
placeholder="选择分组"
|
|
958
|
-
allowClear
|
|
959
|
-
showSearch
|
|
960
|
-
loading={interfacesLoading}
|
|
961
|
-
>
|
|
962
|
-
{groups.map(group => (
|
|
963
|
-
<Option key={group} value={group}>{group}</Option>
|
|
964
|
-
))}
|
|
965
|
-
</Select>
|
|
966
|
-
{selectedGroup && (
|
|
967
|
-
<Button
|
|
968
|
-
type="link"
|
|
969
|
-
onClick={() => setSelectedGroup(null)}
|
|
970
|
-
size="small"
|
|
971
|
-
>
|
|
972
|
-
清除筛选
|
|
973
|
-
</Button>
|
|
974
|
-
)}
|
|
975
|
-
</div>
|
|
976
|
-
|
|
977
|
-
{selectedGroup && (
|
|
978
|
-
<div style={{ display: 'flex', gap: '8px' }}>
|
|
979
|
-
<Popconfirm
|
|
980
|
-
title={`确定要启用分组 "${selectedGroup}" 中的所有接口吗?`}
|
|
981
|
-
onConfirm={() => handleBatchToggleActive(true)}
|
|
982
|
-
okText="确定"
|
|
983
|
-
cancelText="取消"
|
|
984
|
-
>
|
|
985
|
-
<Button
|
|
986
|
-
type="primary"
|
|
987
|
-
size="small"
|
|
988
|
-
loading={groupActionLoading}
|
|
989
|
-
>
|
|
990
|
-
批量启用
|
|
991
|
-
</Button>
|
|
992
|
-
</Popconfirm>
|
|
993
|
-
|
|
994
|
-
<Popconfirm
|
|
995
|
-
title={`确定要禁用分组 "${selectedGroup}" 中的所有接口吗?`}
|
|
996
|
-
onConfirm={() => handleBatchToggleActive(false)}
|
|
997
|
-
okText="确定"
|
|
998
|
-
cancelText="取消"
|
|
999
|
-
>
|
|
1000
|
-
<Button
|
|
1001
|
-
danger
|
|
1002
|
-
size="small"
|
|
1003
|
-
loading={groupActionLoading}
|
|
1004
|
-
>
|
|
1005
|
-
批量禁用
|
|
1006
|
-
</Button>
|
|
1007
|
-
</Popconfirm>
|
|
1008
|
-
</div>
|
|
1009
|
-
)}
|
|
1010
|
-
</div>
|
|
1011
|
-
|
|
1012
831
|
{/* 接口列表状态栏 */}
|
|
1013
832
|
{filteredInterfaces.length > 0 && !interfacesLoading && (
|
|
1014
833
|
<div style={{
|
|
@@ -1024,11 +843,6 @@ const InterfaceManagement = () => {
|
|
|
1024
843
|
}}>
|
|
1025
844
|
<span>
|
|
1026
845
|
当前功能模块:<strong>{selectedFeature?.name}</strong>
|
|
1027
|
-
{selectedGroup && (
|
|
1028
|
-
<span style={{ marginLeft: 8 }}>
|
|
1029
|
-
| 分组:<Tag color="blue">{selectedGroup}</Tag>
|
|
1030
|
-
</span>
|
|
1031
|
-
)}
|
|
1032
846
|
</span>
|
|
1033
847
|
<span>
|
|
1034
848
|
共 {filteredInterfaces.length} 个接口,每页显示 {tableConfig.pageSize} 个
|
|
@@ -1143,7 +957,6 @@ const InterfaceManagement = () => {
|
|
|
1143
957
|
layout="vertical"
|
|
1144
958
|
initialValues={{
|
|
1145
959
|
name: '',
|
|
1146
|
-
group: '',
|
|
1147
960
|
pattern: '',
|
|
1148
961
|
proxyType: 'response',
|
|
1149
962
|
statusCode: '200',
|
|
@@ -1156,7 +969,7 @@ const InterfaceManagement = () => {
|
|
|
1156
969
|
responseDelay: '0'
|
|
1157
970
|
}}
|
|
1158
971
|
>
|
|
1159
|
-
{/*
|
|
972
|
+
{/* 基础信息表单项保持原样 */}
|
|
1160
973
|
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px' }}>
|
|
1161
974
|
<div style={{ flex: 1 }}>
|
|
1162
975
|
<Form.Item
|
|
@@ -1167,44 +980,6 @@ const InterfaceManagement = () => {
|
|
|
1167
980
|
<Input placeholder="请输入接口名称" />
|
|
1168
981
|
</Form.Item>
|
|
1169
982
|
</div>
|
|
1170
|
-
<div style={{ flex: 1 }}>
|
|
1171
|
-
<Form.Item
|
|
1172
|
-
name="group"
|
|
1173
|
-
label="分组"
|
|
1174
|
-
tooltip="为接口设置分组,便于管理和批量操作"
|
|
1175
|
-
>
|
|
1176
|
-
<Select
|
|
1177
|
-
placeholder="选择或创建分组"
|
|
1178
|
-
showSearch
|
|
1179
|
-
allowClear
|
|
1180
|
-
style={{ width: '100%' }}
|
|
1181
|
-
mode="tags"
|
|
1182
|
-
maxTagCount="responsive"
|
|
1183
|
-
maxTagTextLength={10}
|
|
1184
|
-
onChange={(value) => {
|
|
1185
|
-
// 如果值是数组(tags模式),只取第一个元素
|
|
1186
|
-
if (Array.isArray(value) && value.length > 0) {
|
|
1187
|
-
// 如果第一个元素是空字符串,则设置为undefined
|
|
1188
|
-
const groupValue = value[0] === '' ? undefined : value[0];
|
|
1189
|
-
form.setFieldsValue({ group: groupValue });
|
|
1190
|
-
}
|
|
1191
|
-
}}
|
|
1192
|
-
onInputKeyDown={(e) => {
|
|
1193
|
-
// 防止回车键提交表单
|
|
1194
|
-
if (e.key === 'Enter') {
|
|
1195
|
-
e.stopPropagation();
|
|
1196
|
-
}
|
|
1197
|
-
}}
|
|
1198
|
-
>
|
|
1199
|
-
{Array.from(new Set(interfaces.map(item => item.group).filter(Boolean))).map(group => (
|
|
1200
|
-
<Option key={group} value={group}>{group}</Option>
|
|
1201
|
-
))}
|
|
1202
|
-
</Select>
|
|
1203
|
-
</Form.Item>
|
|
1204
|
-
</div>
|
|
1205
|
-
</div>
|
|
1206
|
-
|
|
1207
|
-
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px' }}>
|
|
1208
983
|
<div style={{ flex: 1 }}>
|
|
1209
984
|
<Form.Item
|
|
1210
985
|
name="pattern"
|
|
@@ -1284,6 +1059,9 @@ const InterfaceManagement = () => {
|
|
|
1284
1059
|
/>
|
|
1285
1060
|
</Form.Item>
|
|
1286
1061
|
</div>
|
|
1062
|
+
</div>
|
|
1063
|
+
|
|
1064
|
+
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px' }}>
|
|
1287
1065
|
<div style={{ flex: 1 }}>
|
|
1288
1066
|
<Form.Item
|
|
1289
1067
|
name="proxyType"
|
|
@@ -1311,7 +1089,7 @@ const InterfaceManagement = () => {
|
|
|
1311
1089
|
const patternInput = document.querySelector('input[placeholder="根据选择的处理方式输入相应格式的URL"]');
|
|
1312
1090
|
if (patternInput) {
|
|
1313
1091
|
if (value === 'response') {
|
|
1314
|
-
patternInput.placeholder = "例如:/api/users,/api/users/*,/api
|
|
1092
|
+
patternInput.placeholder = "例如:/api/users,/api/users/*,/api\/users\/\d+/";
|
|
1315
1093
|
} else if (value === 'redirect') {
|
|
1316
1094
|
patternInput.placeholder = "例如:https://example.com/api";
|
|
1317
1095
|
} else if (value === 'url_redirect') {
|
|
@@ -1325,9 +1103,6 @@ const InterfaceManagement = () => {
|
|
|
1325
1103
|
</Select>
|
|
1326
1104
|
</Form.Item>
|
|
1327
1105
|
</div>
|
|
1328
|
-
</div>
|
|
1329
|
-
|
|
1330
|
-
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px' }}>
|
|
1331
1106
|
<div style={{ flex: 1 }}>
|
|
1332
1107
|
<Form.Item
|
|
1333
1108
|
name="httpMethod"
|
|
@@ -1341,9 +1116,6 @@ const InterfaceManagement = () => {
|
|
|
1341
1116
|
</Select>
|
|
1342
1117
|
</Form.Item>
|
|
1343
1118
|
</div>
|
|
1344
|
-
<div style={{ flex: 1 }}>
|
|
1345
|
-
{/* 这里可以留空或添加其他字段 */}
|
|
1346
|
-
</div>
|
|
1347
1119
|
</div>
|
|
1348
1120
|
|
|
1349
1121
|
{/* 根据proxyType显示不同的表单项 */}
|