whistle.mock-plugins 1.1.3-dev.7 → 1.1.3-dev.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whistle.mock-plugins",
3
- "version": "1.1.3-dev.7",
3
+ "version": "1.1.3-dev.9",
4
4
  "description": "Whistle 插件,用于快速创建 API 模拟数据",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -679,10 +679,40 @@ const InterfaceManagement = () => {
679
679
  },
680
680
  render: (group) => {
681
681
  if (!group) {
682
- return <span style={{ color: '#999', fontStyle: 'italic' }}>未分组</span>;
682
+ return (
683
+ <span style={{
684
+ color: '#a0aec0',
685
+ fontStyle: 'italic',
686
+ fontSize: '12px'
687
+ }}>
688
+ 未分组
689
+ </span>
690
+ );
683
691
  }
684
692
  return (
685
- <Tag color="blue" style={{ cursor: 'pointer' }} onClick={() => setSelectedGroup(group)}>
693
+ <Tag
694
+ style={{
695
+ cursor: 'pointer',
696
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
697
+ border: 'none',
698
+ borderRadius: '12px',
699
+ color: '#ffffff',
700
+ fontWeight: '600',
701
+ fontSize: '11px',
702
+ padding: '2px 8px',
703
+ boxShadow: '0 2px 4px rgba(102, 126, 234, 0.3)',
704
+ transition: 'all 0.2s ease'
705
+ }}
706
+ onClick={() => setSelectedGroup(group)}
707
+ onMouseEnter={(e) => {
708
+ e.target.style.transform = 'translateY(-1px)';
709
+ e.target.style.boxShadow = '0 4px 8px rgba(102, 126, 234, 0.4)';
710
+ }}
711
+ onMouseLeave={(e) => {
712
+ e.target.style.transform = 'translateY(0)';
713
+ e.target.style.boxShadow = '0 2px 4px rgba(102, 126, 234, 0.3)';
714
+ }}
715
+ >
686
716
  {group}
687
717
  </Tag>
688
718
  );
@@ -702,11 +732,31 @@ const InterfaceManagement = () => {
702
732
  width: 120,
703
733
  render: (text) => {
704
734
  const proxyType = proxyTypes.find(item => item.value === text);
735
+ const color = proxyType?.color || '#999';
736
+ const label = proxyType?.label || text;
737
+
705
738
  return (
706
- <Badge
707
- color={proxyType?.color || '#999'}
708
- text={proxyType?.label || text}
709
- />
739
+ <span
740
+ style={{
741
+ display: 'inline-flex',
742
+ alignItems: 'center',
743
+ padding: '4px 10px',
744
+ borderRadius: '12px',
745
+ fontSize: '12px',
746
+ fontWeight: '600',
747
+ backgroundColor: color === '#1890ff' ? '#ebf8ff' :
748
+ color === '#52c41a' ? '#f0fff4' :
749
+ color === '#faad14' ? '#fffbf0' : '#f5f5f5',
750
+ color: color === '#1890ff' ? '#3182ce' :
751
+ color === '#52c41a' ? '#38a169' :
752
+ color === '#faad14' ? '#d69e2e' : '#718096',
753
+ border: `1px solid ${color === '#1890ff' ? '#bee3f8' :
754
+ color === '#52c41a' ? '#c6f6d5' :
755
+ color === '#faad14' ? '#feebc8' : '#e2e8f0'}`
756
+ }}
757
+ >
758
+ {label}
759
+ </span>
710
760
  );
711
761
  },
712
762
  },
@@ -730,13 +780,22 @@ const InterfaceManagement = () => {
730
780
  return (
731
781
  <Select
732
782
  value={activeResponseId || record.responses[0]?.id}
733
- style={{ width: '100%' }}
783
+ style={{
784
+ width: '100%',
785
+ borderRadius: '6px'
786
+ }}
734
787
  onChange={(value) => handleResponseSwitch(record.id, value)}
735
788
  disabled={record.proxyType !== 'response'}
789
+ size="small"
736
790
  >
737
791
  {record.responses.map(resp => (
738
792
  <Option key={resp.id} value={resp.id}>
739
- {resp.name}
793
+ <span style={{
794
+ fontSize: '12px',
795
+ fontWeight: '500'
796
+ }}>
797
+ {resp.name}
798
+ </span>
740
799
  </Option>
741
800
  ))}
742
801
  </Select>
@@ -914,18 +973,28 @@ const InterfaceManagement = () => {
914
973
  width: 180,
915
974
  render: (_, record) => (
916
975
  <div className="action-buttons">
917
- <Button
918
- type="text"
919
- icon={<EditOutlined />}
920
- onClick={() => handleEditInterface(record)}
921
- />
976
+ <Tooltip title="编辑接口">
977
+ <Button
978
+ type="text"
979
+ icon={<EditOutlined />}
980
+ onClick={() => handleEditInterface(record)}
981
+ aria-label="编辑接口"
982
+ />
983
+ </Tooltip>
922
984
  <Popconfirm
923
985
  title="确定要删除此接口吗?"
924
986
  onConfirm={() => handleDeleteInterface(record.id)}
925
987
  okText="确定"
926
988
  cancelText="取消"
927
989
  >
928
- <Button type="text" danger icon={<DeleteOutlined />} />
990
+ <Tooltip title="删除接口">
991
+ <Button
992
+ type="text"
993
+ danger
994
+ icon={<DeleteOutlined />}
995
+ aria-label="删除接口"
996
+ />
997
+ </Tooltip>
929
998
  </Popconfirm>
930
999
  </div>
931
1000
  ),
@@ -1013,10 +1082,16 @@ const InterfaceManagement = () => {
1013
1082
  <Dropdown
1014
1083
  overlay={
1015
1084
  <Menu
1016
- selectedKeys={selectedGroup ? [selectedGroup] : []}
1017
- onClick={({ key }) => setSelectedGroup(key === selectedGroup ? null : key)}
1085
+ selectedKeys={selectedGroup ? [selectedGroup] : ['ALL_GROUPS']}
1086
+ onClick={({ key }) => {
1087
+ if (key === 'ALL_GROUPS') {
1088
+ setSelectedGroup(null);
1089
+ } else {
1090
+ setSelectedGroup(key === selectedGroup ? null : key);
1091
+ }
1092
+ }}
1018
1093
  >
1019
- <Menu.Item key={null}>全部分组</Menu.Item>
1094
+ <Menu.Item key="ALL_GROUPS">全部分组</Menu.Item>
1020
1095
  {groups.map(group => (
1021
1096
  <Menu.Item key={group}>
1022
1097
  {group} ({interfaces.filter(item => item.group === group).length})
@@ -1043,57 +1118,6 @@ const InterfaceManagement = () => {
1043
1118
  loading={interfacesLoading}
1044
1119
  />
1045
1120
  </Tooltip>
1046
-
1047
- <Popover
1048
- title="自定义显示列"
1049
- trigger="click"
1050
- open={columnConfigVisible}
1051
- onOpenChange={handleColumnConfigToggle}
1052
- content={
1053
- <div style={{ width: 280 }}>
1054
- <div style={{ marginBottom: 12 }}>
1055
- <Space>
1056
- <Button size="small" onClick={handleSelectAllColumns}>
1057
- 全选
1058
- </Button>
1059
- <Button size="small" onClick={handleResetColumns}>
1060
- 重置
1061
- </Button>
1062
- </Space>
1063
- </div>
1064
- <Checkbox.Group
1065
- value={tableConfig.visibleColumns || COLUMN_CONFIG.map(col => col.key)}
1066
- onChange={handleColumnConfigChange}
1067
- style={{ width: '100%' }}
1068
- >
1069
- <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
1070
- {COLUMN_CONFIG.map(col => (
1071
- <Checkbox
1072
- key={col.key}
1073
- value={col.key}
1074
- disabled={col.required}
1075
- style={{
1076
- width: '100%',
1077
- color: col.required ? '#999' : undefined
1078
- }}
1079
- >
1080
- {col.title}
1081
- {col.required && (
1082
- <span style={{ color: '#999', fontSize: '12px', marginLeft: 4 }}>
1083
- (必须)
1084
- </span>
1085
- )}
1086
- </Checkbox>
1087
- ))}
1088
- </div>
1089
- </Checkbox.Group>
1090
- </div>
1091
- }
1092
- >
1093
- <Button icon={<SettingOutlined />} size="small">
1094
- 列设置
1095
- </Button>
1096
- </Popover>
1097
1121
 
1098
1122
  <Button
1099
1123
  type="primary"
@@ -1196,6 +1220,69 @@ const InterfaceManagement = () => {
1196
1220
  </Popconfirm>
1197
1221
  </Space>
1198
1222
  )}
1223
+
1224
+ {/* 列设置按钮 */}
1225
+ <Popover
1226
+ title="自定义显示列"
1227
+ trigger="click"
1228
+ open={columnConfigVisible}
1229
+ onOpenChange={handleColumnConfigToggle}
1230
+ content={
1231
+ <div style={{ width: 280 }}>
1232
+ <div style={{ marginBottom: 12 }}>
1233
+ <Space>
1234
+ <Button size="small" onClick={handleSelectAllColumns}>
1235
+ 全选
1236
+ </Button>
1237
+ <Button size="small" onClick={handleResetColumns}>
1238
+ 重置
1239
+ </Button>
1240
+ </Space>
1241
+ </div>
1242
+ <Checkbox.Group
1243
+ value={tableConfig.visibleColumns || COLUMN_CONFIG.map(col => col.key)}
1244
+ onChange={handleColumnConfigChange}
1245
+ style={{ width: '100%' }}
1246
+ >
1247
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
1248
+ {COLUMN_CONFIG.map(col => (
1249
+ <Checkbox
1250
+ key={col.key}
1251
+ value={col.key}
1252
+ disabled={col.required}
1253
+ style={{
1254
+ width: '100%',
1255
+ color: col.required ? '#999' : undefined
1256
+ }}
1257
+ >
1258
+ {col.title}
1259
+ {col.required && (
1260
+ <span style={{ color: '#999', fontSize: '12px', marginLeft: 4 }}>
1261
+ (必须)
1262
+ </span>
1263
+ )}
1264
+ </Checkbox>
1265
+ ))}
1266
+ </div>
1267
+ </Checkbox.Group>
1268
+ </div>
1269
+ }
1270
+ >
1271
+ <Tooltip title="自定义显示列">
1272
+ <Button
1273
+ icon={<SettingOutlined />}
1274
+ type="text"
1275
+ size="middle"
1276
+ className="column-settings-btn"
1277
+ style={{
1278
+ marginLeft: (selectedRowKeys.length > 0 || selectedGroup) ? 16 : 0,
1279
+ color: '#666'
1280
+ }}
1281
+ >
1282
+ 列设置
1283
+ </Button>
1284
+ </Tooltip>
1285
+ </Popover>
1199
1286
  </div>
1200
1287
  </div>
1201
1288
  </Card>
@@ -15,10 +15,6 @@
15
15
  --transition-time: 0.3s;
16
16
  }
17
17
 
18
- .interface-management-container {
19
- padding: 24px;
20
- background: #f5f7fa;
21
- }
22
18
 
23
19
  /* 统一控制台 */
24
20
  .interface-control-panel {
@@ -111,6 +107,120 @@
111
107
  font-size: 13px;
112
108
  }
113
109
 
110
+ /* 列设置按钮 */
111
+ .column-settings-btn {
112
+ transition: all 0.2s ease;
113
+ border-radius: 6px;
114
+ }
115
+
116
+ .column-settings-btn:hover {
117
+ background-color: #f5f5f5;
118
+ color: var(--primary-color) !important;
119
+ }
120
+
121
+ .column-settings-btn:active {
122
+ background-color: #e6f7ff;
123
+ }
124
+
125
+ /* 接口名称样式优化 */
126
+ .interface-name {
127
+ font-weight: 600;
128
+ font-size: 14px;
129
+ color: #2d3748;
130
+ display: block;
131
+ line-height: 1.4;
132
+ }
133
+
134
+ /* 状态码样式优化 */
135
+ .status-success {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ padding: 4px 10px;
139
+ border-radius: 12px;
140
+ font-size: 12px;
141
+ font-weight: 600;
142
+ background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
143
+ color: #ffffff;
144
+ box-shadow: 0 2px 4px rgba(72, 187, 120, 0.3);
145
+ }
146
+
147
+ .status-warning {
148
+ display: inline-flex;
149
+ align-items: center;
150
+ padding: 4px 10px;
151
+ border-radius: 12px;
152
+ font-size: 12px;
153
+ font-weight: 600;
154
+ background: linear-gradient(135deg, #ed8936 0%, #dd6b20 100%);
155
+ color: #ffffff;
156
+ box-shadow: 0 2px 4px rgba(237, 137, 54, 0.3);
157
+ }
158
+
159
+ .status-error {
160
+ display: inline-flex;
161
+ align-items: center;
162
+ padding: 4px 10px;
163
+ border-radius: 12px;
164
+ font-size: 12px;
165
+ font-weight: 600;
166
+ background: linear-gradient(135deg, #f56565 0%, #e53e3e 100%);
167
+ color: #ffffff;
168
+ box-shadow: 0 2px 4px rgba(245, 101, 101, 0.3);
169
+ }
170
+
171
+ /* 延迟状态样式 */
172
+ .delay-active {
173
+ color: #ed8936;
174
+ font-weight: 600;
175
+ font-size: 12px;
176
+ }
177
+
178
+ .delay-inactive {
179
+ color: #a0aec0;
180
+ font-size: 12px;
181
+ }
182
+
183
+ /* 无响应数据样式 */
184
+ .no-response {
185
+ color: #a0aec0;
186
+ font-style: italic;
187
+ font-size: 12px;
188
+ }
189
+
190
+ /* 操作按钮区域优化 */
191
+ .action-buttons {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 8px;
195
+ }
196
+
197
+ .action-buttons .ant-btn {
198
+ border-radius: 6px;
199
+ display: flex;
200
+ align-items: center;
201
+ justify-content: center;
202
+ transition: all 0.2s ease;
203
+ }
204
+
205
+ .action-buttons .ant-btn:hover {
206
+ transform: translateY(-1px);
207
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
208
+ }
209
+
210
+ .action-buttons .ant-btn[aria-label*="编辑"] {
211
+ color: #3182ce;
212
+ }
213
+
214
+ .action-buttons .ant-btn[aria-label*="编辑"]:hover {
215
+ background-color: #ebf8ff;
216
+ border-color: #3182ce;
217
+ }
218
+
219
+ .action-buttons .ant-btn.ant-btn-dangerous:hover {
220
+ background-color: #fed7d7;
221
+ border-color: #e53e3e;
222
+ }
223
+
114
224
  /* 旧版样式兼容 */
115
225
  .interface-header-card {
116
226
  margin-bottom: 16px;
@@ -281,15 +391,67 @@
281
391
  }
282
392
 
283
393
  /* 表格样式增强 */
394
+ .interface-table {
395
+ border-radius: 8px;
396
+ overflow: hidden;
397
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
398
+ border: 1px solid #f0f2f5;
399
+ }
400
+
284
401
  .interface-table th {
285
- background-color: #f5f7fa !important;
402
+ background: linear-gradient(135deg, #fafbfc 0%, #f5f6fa 100%) !important;
286
403
  font-weight: 600;
287
- padding: 12px 16px !important;
288
- color: #333;
404
+ padding: 16px 16px !important;
405
+ color: #4a5568;
406
+ font-size: 13px;
407
+ letter-spacing: 0.5px;
408
+ text-transform: uppercase;
409
+ border-bottom: 2px solid #e2e8f0 !important;
410
+ position: relative;
411
+ }
412
+
413
+ .interface-table th::after {
414
+ content: '';
415
+ position: absolute;
416
+ bottom: 0;
417
+ left: 0;
418
+ right: 0;
419
+ height: 1px;
420
+ background: linear-gradient(90deg, transparent, #4299e1, transparent);
289
421
  }
290
422
 
291
423
  .interface-table td {
292
- padding: 12px 16px !important;
424
+ padding: 20px 16px !important;
425
+ vertical-align: middle;
426
+ border-bottom: 1px solid #f7fafc !important;
427
+ transition: all 0.2s ease;
428
+ }
429
+
430
+ .interface-table tbody tr {
431
+ transition: all 0.2s ease;
432
+ background-color: #ffffff;
433
+ }
434
+
435
+ .interface-table tbody tr:nth-child(even) {
436
+ background-color: #fafbfc;
437
+ }
438
+
439
+ .interface-table tbody tr:hover {
440
+ background-color: #edf2f7 !important;
441
+ transform: translateY(-1px);
442
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
443
+ }
444
+
445
+ .interface-table tbody tr:hover td {
446
+ border-bottom-color: #e2e8f0 !important;
447
+ }
448
+
449
+ .interface-table tbody tr.ant-table-row-selected {
450
+ background-color: #ebf8ff !important;
451
+ }
452
+
453
+ .interface-table tbody tr.ant-table-row-selected:hover {
454
+ background-color: #bee3f8 !important;
293
455
  }
294
456
 
295
457
  /* 卡片视图样式 */
@@ -677,13 +839,29 @@
677
839
  .url-pattern {
678
840
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
679
841
  word-break: break-all;
680
- padding: 4px 8px;
681
- background: #f5f5f5;
682
- border-radius: 4px;
842
+ padding: 6px 12px;
843
+ background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%);
844
+ border: 1px solid #e2e8f0;
845
+ border-radius: 6px;
683
846
  display: inline-block;
684
847
  max-width: 100%;
685
848
  overflow: hidden;
686
849
  text-overflow: ellipsis;
850
+ font-size: 12px;
851
+ color: #2d3748;
852
+ position: relative;
853
+ }
854
+
855
+ .url-pattern::before {
856
+ content: 'URL';
857
+ position: absolute;
858
+ top: -6px;
859
+ left: 8px;
860
+ background: #ffffff;
861
+ padding: 0 4px;
862
+ font-size: 10px;
863
+ color: #718096;
864
+ font-weight: 600;
687
865
  }
688
866
 
689
867
  /* 接口状态开关 */