whistle.mock-plugins 1.1.3-dev.9 → 1.2.0-beta.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.
@@ -520,24 +520,22 @@ const MockData = () => {
520
520
  return (
521
521
  <AppLayout>
522
522
  <div className="page-container">
523
- {/* V2版本标识 */}
524
- <div style={{
525
- position: 'absolute',
526
- top: '10px',
527
- right: '10px',
528
- backgroundColor: '#52c41a',
529
- color: 'white',
530
- padding: '4px 8px',
531
- borderRadius: '4px',
532
- fontSize: '12px',
533
- zIndex: 1000
534
- }}>
535
- V2版本
536
- </div>
537
-
538
523
  <div className="page-title-bar">
539
- <div>
540
- <h1 className="page-title">功能模块管理</h1>
524
+ <div className="title-section">
525
+ <div className="title-with-badge">
526
+ <h1 className="page-title">功能模块管理</h1>
527
+ <Badge
528
+ count="V2"
529
+ style={{
530
+ backgroundColor: '#52c41a',
531
+ fontSize: '12px',
532
+ height: '20px',
533
+ lineHeight: '20px',
534
+ borderRadius: '10px',
535
+ marginLeft: '12px'
536
+ }}
537
+ />
538
+ </div>
541
539
  <div className="page-description">
542
540
  创建和管理功能模块,为每个功能配置独立的接口
543
541
  </div>
@@ -561,117 +559,147 @@ const MockData = () => {
561
559
  </div>
562
560
  </div>
563
561
 
564
- {/* 排序和分页控制栏 */}
562
+ {/* 控制面板 */}
565
563
  {mockFeatures.length > 0 && !loading && (
566
- <div style={{
567
- marginBottom: 16,
568
- padding: '12px 16px',
569
- background: '#fafafa',
570
- borderRadius: '6px',
571
- display: 'flex',
572
- justifyContent: 'space-between',
573
- alignItems: 'center',
574
- flexWrap: 'wrap',
575
- gap: '8px'
576
- }}>
577
- <div style={{ display: 'flex', alignItems: 'center', gap: '12px', flexWrap: 'wrap' }}>
578
- <span style={{ fontSize: '14px', color: '#666' }}>
579
- <SortAscendingOutlined /> 排序:
580
- </span>
581
- <Select
582
- value={listConfig.sortBy}
583
- onChange={handleSortChange}
584
- style={{ width: 120 }}
585
- size="small"
586
- >
587
- <Select.Option value="name">名称</Select.Option>
588
- <Select.Option value="createdAt">创建时间</Select.Option>
589
- <Select.Option value="interfaceCount">接口数量</Select.Option>
590
- <Select.Option value="active">状态</Select.Option>
591
- </Select>
592
- <Select
593
- value={listConfig.sortOrder}
594
- onChange={handleSortOrderChange}
595
- style={{ width: 80 }}
596
- size="small"
597
- >
598
- <Select.Option value="ascend">升序</Select.Option>
599
- <Select.Option value="descend">降序</Select.Option>
600
- </Select>
601
- </div>
602
-
603
- <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
604
- <span style={{ fontSize: '14px', color: '#666' }}>每页显示:</span>
605
- <Select
606
- value={listConfig.pageSize}
607
- onChange={handlePageSizeChange}
608
- style={{ width: 80 }}
609
- size="small"
610
- >
611
- <Select.Option value={8}>8</Select.Option>
612
- <Select.Option value={12}>12</Select.Option>
613
- <Select.Option value={16}>16</Select.Option>
614
- <Select.Option value={24}>24</Select.Option>
615
- </Select>
616
- <span style={{ fontSize: '14px', color: '#999' }}>
617
- 共 {mockFeatures.length} 个功能模块
618
- </span>
619
- </div>
620
- </div>
564
+ <Card className="control-panel-card" style={{ marginBottom: 24 }}>
565
+ <Row gutter={[24, 16]} align="middle">
566
+ {/* 统计信息区域 */}
567
+ <Col xs={24} sm={12} md={8} lg={6}>
568
+ <div className="stats-section">
569
+ <div className="stats-item">
570
+ <span className="stats-number">{mockFeatures.length}</span>
571
+ <span className="stats-label">功能模块</span>
572
+ </div>
573
+ <div className="stats-item">
574
+ <span className="stats-number">
575
+ {mockFeatures.filter(f => f.active).length}
576
+ </span>
577
+ <span className="stats-label">已启用</span>
578
+ </div>
579
+ <div className="stats-item">
580
+ <span className="stats-number">
581
+ {mockFeatures.reduce((sum, f) => sum + (f.interfaceCount || 0), 0)}
582
+ </span>
583
+ <span className="stats-label">接口总数</span>
584
+ </div>
585
+ </div>
586
+ </Col>
587
+
588
+ {/* 排序控制区域 */}
589
+ <Col xs={24} sm={12} md={8} lg={9}>
590
+ <div className="sort-controls">
591
+ <div className="control-group">
592
+ <span className="control-label">
593
+ <SortAscendingOutlined /> 排序方式
594
+ </span>
595
+ <Select
596
+ value={listConfig.sortBy}
597
+ onChange={handleSortChange}
598
+ style={{ width: 120 }}
599
+ size="middle"
600
+ >
601
+ <Select.Option value="name">名称</Select.Option>
602
+ <Select.Option value="createdAt">创建时间</Select.Option>
603
+ <Select.Option value="interfaceCount">接口数量</Select.Option>
604
+ <Select.Option value="active">状态</Select.Option>
605
+ </Select>
606
+ <Select
607
+ value={listConfig.sortOrder}
608
+ onChange={handleSortOrderChange}
609
+ style={{ width: 80 }}
610
+ size="middle"
611
+ >
612
+ <Select.Option value="ascend">升序</Select.Option>
613
+ <Select.Option value="descend">降序</Select.Option>
614
+ </Select>
615
+ </div>
616
+ </div>
617
+ </Col>
618
+
619
+ {/* 分页控制区域 */}
620
+ <Col xs={24} sm={24} md={8} lg={9}>
621
+ <div className="pagination-controls">
622
+ <div className="control-group">
623
+ <span className="control-label">每页显示</span>
624
+ <Select
625
+ value={listConfig.pageSize}
626
+ onChange={handlePageSizeChange}
627
+ style={{ width: 80 }}
628
+ size="middle"
629
+ >
630
+ <Select.Option value={8}>8</Select.Option>
631
+ <Select.Option value={12}>12</Select.Option>
632
+ <Select.Option value={16}>16</Select.Option>
633
+ <Select.Option value={24}>24</Select.Option>
634
+ </Select>
635
+ <span className="page-info">
636
+ 第 {(listConfig.current - 1) * listConfig.pageSize + 1}-{Math.min(listConfig.current * listConfig.pageSize, mockFeatures.length)} 条
637
+ </span>
638
+ </div>
639
+ </div>
640
+ </Col>
641
+ </Row>
642
+ </Card>
621
643
  )}
622
644
 
623
- <div className="feature-list-container">
645
+ <Card className="feature-list-card">
624
646
  {loading ? (
625
- <div className="loading">
626
- <div className="loading-spinner"></div>
627
- <div>正在加载功能模块...</div>
647
+ <div className="loading-state">
648
+ <Spin size="large" />
649
+ <div className="loading-text">正在加载功能模块...</div>
628
650
  </div>
629
651
  ) : mockFeatures.length > 0 ? (
630
652
  <>
631
- <Row gutter={[16, 16]}>
653
+ <Row gutter={[20, 20]} className="feature-grid">
632
654
  {getPaginatedFeatures().map(feature => renderFeatureCard(feature))}
633
655
  </Row>
634
656
 
635
657
  {/* 分页组件 */}
636
658
  {mockFeatures.length > listConfig.pageSize && (
637
- <div style={{
638
- marginTop: 24,
639
- textAlign: 'center',
640
- padding: '16px',
641
- borderTop: '1px solid #f0f0f0'
642
- }}>
659
+ <div className="pagination-wrapper">
643
660
  <Pagination
644
661
  current={listConfig.current}
645
662
  pageSize={listConfig.pageSize}
646
663
  total={mockFeatures.length}
647
664
  onChange={handlePageChange}
648
665
  onShowSizeChange={handlePageChange}
649
- showSizeChanger={true}
666
+ showSizeChanger={false}
650
667
  showQuickJumper={true}
651
668
  showTotal={(total, range) =>
652
669
  `第 ${range[0]}-${range[1]} 条,共 ${total} 个功能模块`
653
670
  }
654
- pageSizeOptions={['8', '12', '16', '24']}
655
671
  size="default"
672
+ className="custom-pagination"
656
673
  />
657
674
  </div>
658
675
  )}
659
676
  </>
660
677
  ) : (
661
- <div className="empty-data">
662
- <div className="empty-icon">📂</div>
663
- <div className="empty-text">暂无功能,请点击"新建功能"按钮创建</div>
678
+ <Empty
679
+ className="custom-empty"
680
+ image={
681
+ <div className="empty-image">
682
+ <ApiOutlined style={{ fontSize: 64, color: '#d9d9d9' }} />
683
+ </div>
684
+ }
685
+ description={
686
+ <div className="empty-description">
687
+ <div className="empty-title">暂无功能模块</div>
688
+ <div className="empty-subtitle">创建您的第一个功能模块,开始管理接口</div>
689
+ </div>
690
+ }
691
+ >
664
692
  <div className="empty-actions">
665
- <button className="create-button" onClick={() => openModal()}>
693
+ <Button type="primary" icon={<PlusOutlined />} onClick={() => openModal()}>
666
694
  创建新功能
667
- </button>
668
- <button className="import-button-large" onClick={importFeatureConfig}>
669
- 导入已有功能
670
- </button>
695
+ </Button>
696
+ <Button icon={<ExportOutlined />} onClick={importFeatureConfig}>
697
+ 导入功能
698
+ </Button>
671
699
  </div>
672
- </div>
700
+ </Empty>
673
701
  )}
674
- </div>
702
+ </Card>
675
703
  </div>
676
704
 
677
705
  <Modal
@@ -16,6 +16,12 @@
16
16
  }
17
17
 
18
18
 
19
+ /* 页面容器 */
20
+ .interface-management-container {
21
+ padding: 24px;
22
+ min-height: calc(100vh - 120px);
23
+ }
24
+
19
25
  /* 统一控制台 */
20
26
  .interface-control-panel {
21
27
  margin-bottom: 16px;
@@ -107,120 +113,6 @@
107
113
  font-size: 13px;
108
114
  }
109
115
 
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
-
224
116
  /* 旧版样式兼容 */
225
117
  .interface-header-card {
226
118
  margin-bottom: 16px;
@@ -383,7 +275,7 @@
383
275
  .list-container-card {
384
276
  border-radius: 12px;
385
277
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
386
- margin-bottom: 24px;
278
+ margin-bottom: 40px;
387
279
  }
388
280
 
389
281
  .interface-list-container {
@@ -391,67 +283,19 @@
391
283
  }
392
284
 
393
285
  /* 表格样式增强 */
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
-
401
286
  .interface-table th {
402
- background: linear-gradient(135deg, #fafbfc 0%, #f5f6fa 100%) !important;
287
+ background-color: #f5f7fa !important;
403
288
  font-weight: 600;
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
+ padding: 12px 16px !important;
290
+ color: #333;
291
+ white-space: nowrap;
421
292
  }
422
293
 
423
294
  .interface-table td {
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;
295
+ padding: 12px 16px !important;
296
+ white-space: nowrap;
297
+ overflow: hidden;
298
+ text-overflow: ellipsis;
455
299
  }
456
300
 
457
301
  /* 卡片视图样式 */
@@ -802,33 +646,7 @@
802
646
  line-height: 1.6;
803
647
  }
804
648
 
805
- .interface-table {
806
- width: 100%;
807
- border-collapse: collapse;
808
- border-radius: var(--border-radius);
809
- overflow: hidden;
810
- box-shadow: var(--card-shadow);
811
- }
812
-
813
- .interface-table th,
814
- .interface-table td {
815
- padding: 16px;
816
- text-align: left;
817
- border-bottom: 1px solid var(--border-color);
818
- }
819
-
820
- .interface-table th {
821
- background-color: #fafafa;
822
- color: var(--text-secondary);
823
- font-weight: 600;
824
- font-size: 14px;
825
- text-transform: uppercase;
826
- letter-spacing: 0.5px;
827
- }
828
-
829
- .interface-table tr:hover {
830
- background-color: #f5f5f5;
831
- }
649
+ /* 重复的表格样式已移除,使用上面的统一定义 */
832
650
 
833
651
  .interface-table tr.inactive {
834
652
  color: var(--text-light);
@@ -838,30 +656,14 @@
838
656
 
839
657
  .url-pattern {
840
658
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
841
- word-break: break-all;
842
- padding: 6px 12px;
843
- background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%);
844
- border: 1px solid #e2e8f0;
845
- border-radius: 6px;
659
+ padding: 4px 8px;
660
+ background: #f5f5f5;
661
+ border-radius: 4px;
846
662
  display: inline-block;
847
- max-width: 100%;
663
+ max-width: 300px;
848
664
  overflow: hidden;
849
665
  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;
666
+ white-space: nowrap;
865
667
  }
866
668
 
867
669
  /* 接口状态开关 */
@@ -1315,4 +1117,138 @@
1315
1117
  .no-response {
1316
1118
  color: #999;
1317
1119
  font-style: italic;
1318
- }
1120
+ }
1121
+
1122
+ /* 内联列设置按钮样式 */
1123
+ .inline-column-settings-btn {
1124
+ display: flex;
1125
+ align-items: center;
1126
+ gap: 6px;
1127
+ padding: 4px 8px;
1128
+ border-radius: 4px;
1129
+ border: 1px solid #d9d9d9;
1130
+ background: #ffffff;
1131
+ color: #666;
1132
+ font-size: 12px;
1133
+ transition: all 0.2s ease;
1134
+ }
1135
+
1136
+ .inline-column-settings-btn:hover {
1137
+ border-color: #4096ff;
1138
+ background: #f0f9ff;
1139
+ color: #4096ff;
1140
+ }
1141
+
1142
+ .inline-column-settings-btn:active {
1143
+ border-color: #1677ff;
1144
+ background: #e6f4ff;
1145
+ }
1146
+
1147
+ /* 接口弹窗样式 */
1148
+ .interface-modal .ant-modal-header {
1149
+ border-bottom: 1px solid #f0f0f0;
1150
+ padding: 16px 24px;
1151
+ margin-bottom: 0;
1152
+ }
1153
+
1154
+ .interface-modal .ant-modal-body {
1155
+ padding: 0;
1156
+ }
1157
+
1158
+ .interface-modal .ant-card {
1159
+ border: 1px solid #e8e8e8;
1160
+ border-radius: 8px;
1161
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
1162
+ }
1163
+
1164
+ .interface-modal .ant-card-head {
1165
+ background: #fafafa;
1166
+ border-bottom: 1px solid #f0f0f0;
1167
+ padding: 0 20px;
1168
+ min-height: 48px;
1169
+ }
1170
+
1171
+ .interface-modal .ant-card-head-title {
1172
+ font-size: 14px;
1173
+ font-weight: 600;
1174
+ color: #262626;
1175
+ padding: 12px 0;
1176
+ }
1177
+
1178
+ .interface-modal .ant-form-item-label > label {
1179
+ font-size: 13px;
1180
+ font-weight: 500;
1181
+ color: #434343;
1182
+ }
1183
+
1184
+ .interface-modal .ant-form-item {
1185
+ margin-bottom: 16px;
1186
+ }
1187
+
1188
+ .interface-modal .ant-input,
1189
+ .interface-modal .ant-select-selector {
1190
+ border-radius: 6px;
1191
+ border: 1px solid #d9d9d9;
1192
+ }
1193
+
1194
+ .interface-modal .ant-input:focus,
1195
+ .interface-modal .ant-select-focused .ant-select-selector {
1196
+ border-color: #4096ff;
1197
+ box-shadow: 0 0 0 2px rgba(64, 150, 255, 0.1);
1198
+ }
1199
+
1200
+ /* 接口弹窗中的折叠面板样式 */
1201
+ .interface-modal .ant-collapse {
1202
+ background: transparent;
1203
+ border: none;
1204
+ }
1205
+
1206
+ .interface-modal .ant-collapse-item {
1207
+ margin-bottom: 16px;
1208
+ background: #ffffff;
1209
+ border: 1px solid #e8e8e8;
1210
+ border-radius: 8px;
1211
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
1212
+ }
1213
+
1214
+ .interface-modal .ant-collapse-header {
1215
+ background: #fafafa;
1216
+ border-bottom: 1px solid #f0f0f0;
1217
+ border-radius: 8px 8px 0 0 !important;
1218
+ padding: 16px 20px !important;
1219
+ font-size: 14px;
1220
+ font-weight: 600;
1221
+ color: #262626;
1222
+ }
1223
+
1224
+ .interface-modal .ant-collapse-content {
1225
+ border-top: none;
1226
+ background: #ffffff;
1227
+ border-radius: 0 0 8px 8px;
1228
+ }
1229
+
1230
+ .interface-modal .ant-collapse-content-box {
1231
+ padding: 20px;
1232
+ }
1233
+
1234
+ .interface-modal .ant-collapse-arrow {
1235
+ color: #666 !important;
1236
+ font-size: 12px !important;
1237
+ }
1238
+
1239
+ /* 参数匹配规则帮助按钮样式 */
1240
+ .interface-modal .ant-popover-inner-content {
1241
+ padding: 12px;
1242
+ }
1243
+
1244
+ .interface-modal .ant-popover-title {
1245
+ font-weight: 600;
1246
+ color: #262626;
1247
+ padding: 8px 12px;
1248
+ border-bottom: 1px solid #f0f0f0;
1249
+ }
1250
+
1251
+ /* 分页器样式 */
1252
+ .interface-table .ant-pagination-options {
1253
+ margin-right: 16px;
1254
+ }