whistle.mock-plugins 1.2.2-beta.10 → 1.2.2-beta.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whistle.mock-plugins",
3
- "version": "1.2.2-beta.10",
3
+ "version": "1.2.2-beta.11",
4
4
  "description": "Whistle 插件,用于快速创建 API 模拟数据",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -209,111 +209,6 @@ const ResponseContentEditor = ({
209
209
  updateActiveResponseParamMatchers(currentMatchers);
210
210
  };
211
211
 
212
- // 渲染入参匹配规则编辑区域
213
- const renderParamMatchersSection = () => {
214
- // 整个接口中是否有任意响应含有匹配规则
215
- const anyHasMatchers = responses.some(
216
- r => r.paramMatchers && Array.isArray(r.paramMatchers) && r.paramMatchers.length > 0
217
- );
218
- const currentHasMatchers = activeResponse.paramMatchers && activeResponse.paramMatchers.length > 0;
219
- // 只有当接口中存在规则时,无规则的响应才叫"兜底"
220
- const isFallback = anyHasMatchers && !currentHasMatchers;
221
-
222
- return (
223
- <div style={{
224
- marginBottom: '16px',
225
- border: '1px solid #e8e8e8',
226
- borderRadius: '6px',
227
- padding: '12px',
228
- background: '#fafafa'
229
- }}>
230
- <div style={{
231
- display: 'flex',
232
- alignItems: 'center',
233
- justifyContent: 'space-between',
234
- marginBottom: '10px'
235
- }}>
236
- <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
237
- <FilterOutlined style={{ color: '#1890ff' }} />
238
- <label style={{ fontSize: '12px', color: '#333', fontWeight: 'bold' }}>
239
- 入参匹配规则
240
- </label>
241
- {currentHasMatchers ? (
242
- <Tag color="blue" style={{ fontSize: '11px', lineHeight: '18px', padding: '0 6px' }}>
243
- {activeResponse.paramMatchers.length}条
244
- </Tag>
245
- ) : isFallback ? (
246
- <Tag color="default" style={{ fontSize: '11px', lineHeight: '18px', padding: '0 6px' }}>
247
- 兜底响应
248
- </Tag>
249
- ) : null}
250
- </div>
251
- <Button
252
- type="dashed"
253
- size="small"
254
- icon={<PlusCircleOutlined />}
255
- onClick={handleAddMatcher}
256
- style={{ fontSize: '12px' }}
257
- >
258
- 添加规则
259
- </Button>
260
- </div>
261
-
262
- {isFallback && (
263
- <div style={{
264
- color: '#999',
265
- fontSize: '12px',
266
- textAlign: 'center',
267
- padding: '8px 0'
268
- }}>
269
- 无匹配规则,当其他响应均不匹配时作为兜底返回
270
- </div>
271
- )}
272
-
273
- {activeResponse.paramMatchers && activeResponse.paramMatchers.map((matcher, index) => (
274
- <Row key={index} gutter={8} style={{ marginBottom: '8px' }} align="middle">
275
- <Col span={8}>
276
- <Input
277
- size="small"
278
- placeholder="参数路径,如 data.type"
279
- value={matcher.paramPath}
280
- onChange={(e) => handleMatcherChange(index, 'paramPath', e.target.value)}
281
- />
282
- </Col>
283
- <Col span={5}>
284
- <Select
285
- size="small"
286
- style={{ width: '100%' }}
287
- value={matcher.matchType || 'exact'}
288
- onChange={(val) => handleMatcherChange(index, 'matchType', val)}
289
- >
290
- <Option value="exact">精确匹配</Option>
291
- <Option value="contains">包含</Option>
292
- <Option value="regex">正则</Option>
293
- </Select>
294
- </Col>
295
- <Col span={9}>
296
- <Input
297
- size="small"
298
- placeholder="期望值"
299
- value={matcher.paramValue}
300
- onChange={(e) => handleMatcherChange(index, 'paramValue', e.target.value)}
301
- />
302
- </Col>
303
- <Col span={2} style={{ textAlign: 'center' }}>
304
- <Tooltip title="删除此规则">
305
- <MinusCircleOutlined
306
- style={{ color: '#ff4d4f', cursor: 'pointer', fontSize: '16px' }}
307
- onClick={() => handleDeleteMatcher(index)}
308
- />
309
- </Tooltip>
310
- </Col>
311
- </Row>
312
- ))}
313
- </div>
314
- );
315
- };
316
-
317
212
  // 格式化JSON内容
318
213
  const formatJsonContent = () => {
319
214
  if (!activeResponse || !activeResponse.content) {
@@ -643,7 +538,99 @@ const ResponseContentEditor = ({
643
538
  </div>
644
539
 
645
540
  {/* 入参匹配规则编辑区域 */}
646
- {activeResponse && renderParamMatchersSection()}
541
+ {activeResponse && (
542
+ <div style={{
543
+ marginBottom: '16px',
544
+ border: '1px solid #e8e8e8',
545
+ borderRadius: '6px',
546
+ padding: '12px',
547
+ background: '#fafafa'
548
+ }}>
549
+ <div style={{
550
+ display: 'flex',
551
+ alignItems: 'center',
552
+ justifyContent: 'space-between',
553
+ marginBottom: '10px'
554
+ }}>
555
+ <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
556
+ <FilterOutlined style={{ color: '#1890ff' }} />
557
+ <label style={{ fontSize: '12px', color: '#333', fontWeight: 'bold' }}>
558
+ 入参匹配规则
559
+ </label>
560
+ {activeResponse.paramMatchers && activeResponse.paramMatchers.length > 0 ? (
561
+ <Tag color="blue" style={{ fontSize: '11px', lineHeight: '18px', padding: '0 6px' }}>
562
+ {activeResponse.paramMatchers.length}条
563
+ </Tag>
564
+ ) : (
565
+ <Tag color="default" style={{ fontSize: '11px', lineHeight: '18px', padding: '0 6px' }}>
566
+ 兜底响应
567
+ </Tag>
568
+ )}
569
+ </div>
570
+ <Button
571
+ type="dashed"
572
+ size="small"
573
+ icon={<PlusCircleOutlined />}
574
+ onClick={handleAddMatcher}
575
+ style={{ fontSize: '12px' }}
576
+ >
577
+ 添加规则
578
+ </Button>
579
+ </div>
580
+
581
+ {(!activeResponse.paramMatchers || activeResponse.paramMatchers.length === 0) && (
582
+ <div style={{
583
+ color: '#999',
584
+ fontSize: '12px',
585
+ textAlign: 'center',
586
+ padding: '8px 0'
587
+ }}>
588
+ 无匹配规则,当其他响应均不匹配时作为兜底返回
589
+ </div>
590
+ )}
591
+
592
+ {activeResponse.paramMatchers && activeResponse.paramMatchers.map((matcher, index) => (
593
+ <Row key={index} gutter={8} style={{ marginBottom: '8px' }} align="middle">
594
+ <Col span={8}>
595
+ <Input
596
+ size="small"
597
+ placeholder="参数路径,如 data.type"
598
+ value={matcher.paramPath}
599
+ onChange={(e) => handleMatcherChange(index, 'paramPath', e.target.value)}
600
+ />
601
+ </Col>
602
+ <Col span={5}>
603
+ <Select
604
+ size="small"
605
+ style={{ width: '100%' }}
606
+ value={matcher.matchType || 'exact'}
607
+ onChange={(val) => handleMatcherChange(index, 'matchType', val)}
608
+ >
609
+ <Option value="exact">精确匹配</Option>
610
+ <Option value="contains">包含</Option>
611
+ <Option value="regex">正则</Option>
612
+ </Select>
613
+ </Col>
614
+ <Col span={9}>
615
+ <Input
616
+ size="small"
617
+ placeholder="期望值"
618
+ value={matcher.paramValue}
619
+ onChange={(e) => handleMatcherChange(index, 'paramValue', e.target.value)}
620
+ />
621
+ </Col>
622
+ <Col span={2} style={{ textAlign: 'center' }}>
623
+ <Tooltip title="删除此规则">
624
+ <MinusCircleOutlined
625
+ style={{ color: '#ff4d4f', cursor: 'pointer', fontSize: '16px' }}
626
+ onClick={() => handleDeleteMatcher(index)}
627
+ />
628
+ </Tooltip>
629
+ </Col>
630
+ </Row>
631
+ ))}
632
+ </div>
633
+ )}
647
634
 
648
635
  {/* 响应内容编辑区域 */}
649
636
  {activeResponse && (
@@ -302,17 +302,7 @@ const InterfaceManagement = () => {
302
302
  let activeResponseId = '';
303
303
 
304
304
  if (record.responses && Array.isArray(record.responses) && record.responses.length > 0) {
305
- responses = record.responses.map(r => ({
306
- ...r,
307
- paramMatchers: r.paramMatchers || []
308
- }));
309
- // 向后兼容:旧数据接口级 paramMatchers 迁移到第一个响应
310
- if (
311
- record.paramMatchers && Array.isArray(record.paramMatchers) && record.paramMatchers.length > 0 &&
312
- responses.every(r => !r.paramMatchers || r.paramMatchers.length === 0)
313
- ) {
314
- responses[0] = { ...responses[0], paramMatchers: record.paramMatchers };
315
- }
305
+ responses = record.responses;
316
306
  activeResponseId = record.activeResponseId || responses[0].id;
317
307
  } else if (record.responseContent) {
318
308
  // 兼容旧数据格式,创建默认响应
@@ -512,22 +502,13 @@ const InterfaceManagement = () => {
512
502
  }
513
503
 
514
504
  // 构建接口数据 - 在编辑模式下,确保关键字段不丢失
515
- // responses 隐藏字段可能被 Input 序列化为字符串,需要解析还原
516
- let responsesValue = values.responses;
517
- if (typeof responsesValue === 'string') {
518
- try { responsesValue = JSON.parse(responsesValue); } catch (e) { responsesValue = []; }
519
- }
520
- if (!Array.isArray(responsesValue)) {
521
- responsesValue = editingInterface ? editingInterface.responses : [];
522
- }
523
-
524
505
  const interfaceData = {
525
506
  name: values.name || (editingInterface ? editingInterface.name : ''),
526
507
  group: groupValue || (editingInterface ? editingInterface.group : '') || '', // 确保group不为undefined
527
508
  urlPattern: values.pattern || (editingInterface ? editingInterface.urlPattern : ''),
528
509
  proxyType: values.proxyType || (editingInterface ? editingInterface.proxyType : 'response'),
529
510
  featureId: selectedFeatureId,
530
- responses: responsesValue,
511
+ responses: values.responses || (editingInterface ? editingInterface.responses : []),
531
512
  activeResponseId: values.activeResponseId || (editingInterface ? editingInterface.activeResponseId : null),
532
513
  httpStatus: parseInt(values.statusCode, 10) || (editingInterface ? editingInterface.httpStatus : 200), // 转换为数字
533
514
  contentType: values.contentType || (editingInterface ? editingInterface.contentType : 'application/json; charset=utf-8'),
@@ -835,26 +816,8 @@ const InterfaceManagement = () => {
835
816
  const hasSmartMatch = record.responses.some(
836
817
  r => r.paramMatchers && Array.isArray(r.paramMatchers) && r.paramMatchers.length > 0
837
818
  );
819
+ const fallbackResp = record.responses.find(r => r.id === activeResponseId) || record.responses[0];
838
820
 
839
- // 场景一:所有响应都没有规则 → 显示 Select 快捷切换
840
- if (!hasSmartMatch) {
841
- return (
842
- <Select
843
- value={activeResponseId || record.responses[0]?.id}
844
- style={{ width: '100%' }}
845
- size="small"
846
- onChange={(value) => handleResponseSwitch(record.id, value)}
847
- >
848
- {record.responses.map(resp => (
849
- <Option key={resp.id} value={resp.id}>
850
- {resp.name}
851
- </Option>
852
- ))}
853
- </Select>
854
- );
855
- }
856
-
857
- // 场景二/三:有响应含规则 → 显示 Tag 摘要
858
821
  const tooltipContent = (
859
822
  <div style={{ maxWidth: 260 }}>
860
823
  {record.responses.map((resp) => {
@@ -891,9 +854,19 @@ const InterfaceManagement = () => {
891
854
 
892
855
  return (
893
856
  <Tooltip title={tooltipContent} placement="left">
894
- <Tag color="blue" style={{ cursor: 'default' }}>
895
- 智能匹配 · {total}个响应
896
- </Tag>
857
+ {hasSmartMatch ? (
858
+ <Tag color="blue" style={{ cursor: 'default' }}>
859
+ 智能匹配 · {total}个响应
860
+ </Tag>
861
+ ) : total > 1 ? (
862
+ <Tag color="orange" style={{ cursor: 'default' }}>
863
+ 手动切换 · {total}个响应
864
+ </Tag>
865
+ ) : (
866
+ <span style={{ color: '#999', fontSize: '12px' }}>
867
+ {fallbackResp?.name || '1个响应'}
868
+ </span>
869
+ )}
897
870
  </Tooltip>
898
871
  );
899
872
  },