whistle.mock-plugins 1.1.3-dev.17 → 1.1.3-dev.19

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.17",
3
+ "version": "1.1.3-dev.19",
4
4
  "description": "Whistle 插件,用于快速创建 API 模拟数据",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -1318,7 +1318,11 @@ const InterfaceManagement = () => {
1318
1318
  }}
1319
1319
  >
1320
1320
  <Collapse
1321
- defaultActiveKey={editingInterface ? ['3'] : ['1', '2', '3']}
1321
+ defaultActiveKey={
1322
+ editingInterface
1323
+ ? (editingInterface.proxyType === 'response' ? ['3'] : ['1', '2'])
1324
+ : ['1', '2', '3']
1325
+ }
1322
1326
  style={{ marginBottom: '16px' }}
1323
1327
  ghost
1324
1328
  >
@@ -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
@@ -14,23 +14,138 @@
14
14
  border-bottom: 1px solid #f0f0f0;
15
15
  }
16
16
 
17
+ /* 页面标题区域样式 */
18
+ .title-section {
19
+ flex: 1;
20
+ }
21
+
22
+ .title-with-badge {
23
+ display: flex;
24
+ align-items: center;
25
+ margin-bottom: 8px;
26
+ }
27
+
28
+ .page-title {
29
+ margin: 0 !important;
30
+ font-size: 24px;
31
+ font-weight: 600;
32
+ color: #262626;
33
+ line-height: 1.2;
34
+ }
35
+
36
+ .page-description {
37
+ color: #8c8c8c;
38
+ font-size: 14px;
39
+ line-height: 1.5;
40
+ margin: 0;
41
+ }
42
+
43
+ /* 控制面板卡片样式 */
44
+ .control-panel-card {
45
+ border-radius: 12px;
46
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
47
+ border: 1px solid #f0f0f0;
48
+ }
49
+
50
+ .control-panel-card .ant-card-body {
51
+ padding: 20px 24px;
52
+ }
53
+
54
+ /* 统计信息区域 */
55
+ .stats-section {
56
+ display: flex;
57
+ gap: 24px;
58
+ align-items: center;
59
+ }
60
+
61
+ .stats-item {
62
+ display: flex;
63
+ flex-direction: column;
64
+ align-items: center;
65
+ text-align: center;
66
+ }
67
+
68
+ .stats-number {
69
+ font-size: 24px;
70
+ font-weight: 600;
71
+ color: #1890ff;
72
+ line-height: 1;
73
+ margin-bottom: 4px;
74
+ }
75
+
76
+ .stats-label {
77
+ font-size: 12px;
78
+ color: #8c8c8c;
79
+ line-height: 1;
80
+ }
81
+
82
+ /* 控制组样式 */
83
+ .control-group {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 12px;
87
+ flex-wrap: wrap;
88
+ }
89
+
90
+ .control-label {
91
+ font-size: 14px;
92
+ color: #595959;
93
+ white-space: nowrap;
94
+ font-weight: 500;
95
+ }
96
+
97
+ .control-label .anticon {
98
+ margin-right: 6px;
99
+ color: #1890ff;
100
+ }
101
+
102
+ .page-info {
103
+ font-size: 13px;
104
+ color: #8c8c8c;
105
+ white-space: nowrap;
106
+ }
107
+
108
+ /* 功能列表卡片样式 */
109
+ .feature-list-card {
110
+ border-radius: 12px;
111
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
112
+ border: 1px solid #f0f0f0;
113
+ min-height: 400px;
114
+ }
115
+
116
+ .feature-list-card .ant-card-body {
117
+ padding: 24px;
118
+ }
119
+
120
+ .feature-grid {
121
+ min-height: 300px;
122
+ }
123
+
17
124
  .feature-card {
18
125
  position: relative;
19
- transition: all 0.3s;
126
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
20
127
  height: 100%;
21
128
  display: flex;
22
129
  flex-direction: column;
23
- border-radius: 8px;
130
+ border-radius: 12px;
24
131
  overflow: hidden;
25
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
132
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
133
+ border: 1px solid #f0f0f0;
26
134
  cursor: pointer;
135
+ background: #ffffff;
136
+ }
137
+
138
+ .feature-card:hover {
139
+ transform: translateY(-4px);
140
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
141
+ border-color: #d9d9d9;
27
142
  }
28
143
 
29
144
  .feature-card:active {
30
145
  transform: translateY(-2px);
31
146
  }
32
147
 
33
- /* 添加卡片点击提示 */
148
+ /* 添加卡片悬浮效果 */
34
149
  .feature-card::before {
35
150
  content: '';
36
151
  position: absolute;
@@ -38,9 +153,9 @@
38
153
  left: 0;
39
154
  right: 0;
40
155
  bottom: 0;
41
- background: linear-gradient(135deg, rgba(24, 144, 255, 0.02), rgba(24, 144, 255, 0.05));
156
+ background: linear-gradient(135deg, rgba(24, 144, 255, 0.02), rgba(24, 144, 255, 0.04));
42
157
  opacity: 0;
43
- transition: opacity 0.3s;
158
+ transition: opacity 0.3s ease;
44
159
  pointer-events: none;
45
160
  z-index: 1;
46
161
  }
@@ -53,11 +168,33 @@
53
168
  .feature-card .ant-card-body {
54
169
  position: relative;
55
170
  z-index: 2;
171
+ padding: 20px;
56
172
  }
57
173
 
58
174
  .feature-card .ant-card-actions {
59
175
  position: relative;
60
176
  z-index: 2;
177
+ border-top: 1px solid #f0f0f0;
178
+ background: #fafafa;
179
+ }
180
+
181
+ .feature-card .ant-card-actions li {
182
+ transition: all 0.2s ease;
183
+ }
184
+
185
+ .feature-card .ant-card-actions li:hover {
186
+ background: #f0f0f0;
187
+ }
188
+
189
+ /* 不活跃功能卡片样式 */
190
+ .feature-card.inactive-feature {
191
+ opacity: 0.7;
192
+ filter: grayscale(0.3);
193
+ }
194
+
195
+ .feature-card.inactive-feature:hover {
196
+ opacity: 0.9;
197
+ filter: grayscale(0.1);
61
198
  }
62
199
 
63
200
  .feature-card-content {
@@ -797,29 +934,71 @@ input:checked + .slider:before {
797
934
  }
798
935
 
799
936
  /* 加载中样式 */
800
- .loading {
937
+ /* 加载状态样式 */
938
+ .loading-state {
801
939
  display: flex;
802
940
  flex-direction: column;
803
941
  align-items: center;
804
942
  justify-content: center;
805
943
  height: 300px;
944
+ gap: 16px;
945
+ }
946
+
947
+ .loading-text {
806
948
  color: #8c8c8c;
807
949
  font-size: 16px;
808
950
  }
809
951
 
810
- .loading-spinner {
811
- border: 4px solid #f3f3f3;
812
- border-top: 4px solid #1890ff;
813
- border-radius: 50%;
814
- width: 40px;
815
- height: 40px;
816
- animation: spin 2s linear infinite;
952
+ /* 空状态样式 */
953
+ .custom-empty {
954
+ padding: 60px 20px;
955
+ }
956
+
957
+ .empty-image {
817
958
  margin-bottom: 16px;
818
959
  }
819
960
 
820
- @keyframes spin {
821
- 0% { transform: rotate(0deg); }
822
- 100% { transform: rotate(360deg); }
961
+ .empty-description {
962
+ margin-bottom: 24px;
963
+ }
964
+
965
+ .empty-title {
966
+ font-size: 16px;
967
+ font-weight: 500;
968
+ color: #262626;
969
+ margin-bottom: 8px;
970
+ }
971
+
972
+ .empty-subtitle {
973
+ font-size: 14px;
974
+ color: #8c8c8c;
975
+ line-height: 1.5;
976
+ }
977
+
978
+ .empty-actions {
979
+ display: flex;
980
+ gap: 12px;
981
+ justify-content: center;
982
+ flex-wrap: wrap;
983
+ }
984
+
985
+ /* 分页组件样式 */
986
+ .pagination-wrapper {
987
+ margin-top: 32px;
988
+ padding-top: 24px;
989
+ border-top: 1px solid #f0f0f0;
990
+ display: flex;
991
+ justify-content: center;
992
+ }
993
+
994
+ .custom-pagination {
995
+ display: flex;
996
+ justify-content: center;
997
+ }
998
+
999
+ .custom-pagination .ant-pagination-total-text {
1000
+ color: #8c8c8c;
1001
+ font-size: 14px;
823
1002
  }
824
1003
 
825
1004
  /* 响应式调整 */
@@ -828,18 +1007,32 @@ input:checked + .slider:before {
828
1007
  padding: 16px;
829
1008
  }
830
1009
 
831
- .page-header {
1010
+ .page-title-bar {
832
1011
  flex-direction: column;
833
1012
  align-items: flex-start;
1013
+ gap: 16px;
834
1014
  }
835
1015
 
836
- .header-actions {
837
- margin-top: 16px;
1016
+ .page-actions {
838
1017
  width: 100%;
1018
+ justify-content: flex-start;
1019
+ }
1020
+
1021
+ .stats-section {
1022
+ justify-content: space-around;
1023
+ gap: 16px;
1024
+ }
1025
+
1026
+ .control-group {
1027
+ justify-content: flex-start;
839
1028
  }
840
1029
 
841
- .add-button, .import-button {
842
- flex: 1;
1030
+ .control-panel-card .ant-card-body {
1031
+ padding: 16px;
1032
+ }
1033
+
1034
+ .feature-list-card .ant-card-body {
1035
+ padding: 16px;
843
1036
  }
844
1037
 
845
1038
  .feature-card-content {
@@ -853,6 +1046,51 @@ input:checked + .slider:before {
853
1046
  .cancel-button, .submit-button {
854
1047
  width: 100%;
855
1048
  }
1049
+
1050
+ .empty-actions {
1051
+ flex-direction: column;
1052
+ align-items: center;
1053
+ }
1054
+
1055
+ .empty-actions .ant-btn {
1056
+ width: 200px;
1057
+ }
1058
+ }
1059
+
1060
+ @media (max-width: 576px) {
1061
+ .stats-section {
1062
+ flex-direction: column;
1063
+ gap: 12px;
1064
+ align-items: stretch;
1065
+ }
1066
+
1067
+ .stats-item {
1068
+ flex-direction: row;
1069
+ justify-content: space-between;
1070
+ align-items: center;
1071
+ padding: 8px 12px;
1072
+ background: #fafafa;
1073
+ border-radius: 6px;
1074
+ }
1075
+
1076
+ .stats-number {
1077
+ font-size: 20px;
1078
+ }
1079
+
1080
+ .stats-label {
1081
+ font-size: 13px;
1082
+ }
1083
+
1084
+ .control-group {
1085
+ flex-direction: column;
1086
+ align-items: flex-start;
1087
+ gap: 8px;
1088
+ }
1089
+
1090
+ .page-info {
1091
+ order: -1;
1092
+ font-weight: 500;
1093
+ }
856
1094
  }
857
1095
 
858
1096
  /* 修复功能模块状态标记(ribbon)与按钮的重叠问题 */