whistle.mock-plugins 1.2.2-beta.8 → 1.2.2-beta.9
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
|
@@ -209,6 +209,111 @@ 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
|
+
|
|
212
317
|
// 格式化JSON内容
|
|
213
318
|
const formatJsonContent = () => {
|
|
214
319
|
if (!activeResponse || !activeResponse.content) {
|
|
@@ -538,99 +643,7 @@ const ResponseContentEditor = ({
|
|
|
538
643
|
</div>
|
|
539
644
|
|
|
540
645
|
{/* 入参匹配规则编辑区域 */}
|
|
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
|
-
)}
|
|
646
|
+
{activeResponse && renderParamMatchersSection()}
|
|
634
647
|
|
|
635
648
|
{/* 响应内容编辑区域 */}
|
|
636
649
|
{activeResponse && (
|
|
@@ -816,8 +816,26 @@ const InterfaceManagement = () => {
|
|
|
816
816
|
const hasSmartMatch = record.responses.some(
|
|
817
817
|
r => r.paramMatchers && Array.isArray(r.paramMatchers) && r.paramMatchers.length > 0
|
|
818
818
|
);
|
|
819
|
-
const fallbackResp = record.responses.find(r => r.id === activeResponseId) || record.responses[0];
|
|
820
819
|
|
|
820
|
+
// 场景一:所有响应都没有规则 → 显示 Select 快捷切换
|
|
821
|
+
if (!hasSmartMatch) {
|
|
822
|
+
return (
|
|
823
|
+
<Select
|
|
824
|
+
value={activeResponseId || record.responses[0]?.id}
|
|
825
|
+
style={{ width: '100%' }}
|
|
826
|
+
size="small"
|
|
827
|
+
onChange={(value) => handleResponseSwitch(record.id, value)}
|
|
828
|
+
>
|
|
829
|
+
{record.responses.map(resp => (
|
|
830
|
+
<Option key={resp.id} value={resp.id}>
|
|
831
|
+
{resp.name}
|
|
832
|
+
</Option>
|
|
833
|
+
))}
|
|
834
|
+
</Select>
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// 场景二/三:有响应含规则 → 显示 Tag 摘要
|
|
821
839
|
const tooltipContent = (
|
|
822
840
|
<div style={{ maxWidth: 260 }}>
|
|
823
841
|
{record.responses.map((resp) => {
|
|
@@ -854,19 +872,9 @@ const InterfaceManagement = () => {
|
|
|
854
872
|
|
|
855
873
|
return (
|
|
856
874
|
<Tooltip title={tooltipContent} placement="left">
|
|
857
|
-
{
|
|
858
|
-
|
|
859
|
-
|
|
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
|
-
)}
|
|
875
|
+
<Tag color="blue" style={{ cursor: 'default' }}>
|
|
876
|
+
智能匹配 · {total}个响应
|
|
877
|
+
</Tag>
|
|
870
878
|
</Tooltip>
|
|
871
879
|
);
|
|
872
880
|
},
|