whistle.mock-plugins 1.1.3-dev.6 → 1.1.3-dev.8

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.6",
3
+ "version": "1.1.3-dev.8",
4
4
  "description": "Whistle 插件,用于快速创建 API 模拟数据",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -10,12 +10,12 @@ import AppLayout from '../components/AppLayout';
10
10
  import {
11
11
  Table, Button, Modal, Form, Input, Select, message, Switch,
12
12
  Popconfirm, Alert, Space, Card, Badge, Tooltip, Row, Col,
13
- Popover, Checkbox, Tag, Input as AntInput, Radio, Drawer
13
+ Popover, Checkbox, Tag, Input as AntInput, Radio, Drawer, Dropdown, Menu
14
14
  } from 'antd';
15
15
  import {
16
16
  PlusOutlined, EditOutlined, DeleteOutlined,
17
17
  FileTextOutlined, PlusCircleOutlined, SettingOutlined,
18
- SearchOutlined, FilterOutlined, ReloadOutlined
18
+ SearchOutlined, FilterOutlined, ReloadOutlined, DownOutlined
19
19
  } from '@ant-design/icons';
20
20
  import '../styles/interface-management.css';
21
21
  import axios from 'axios';
@@ -976,15 +976,15 @@ const InterfaceManagement = () => {
976
976
  重构后版本 V2
977
977
  </div>
978
978
 
979
- <Card className="interface-header-card">
980
- <div className="interface-management-header">
981
- <div className="feature-selector-container">
979
+ <Card className="interface-control-panel">
980
+ <div className="control-panel-header">
981
+ <div className="control-left">
982
982
  <div className="feature-selector">
983
983
  <span>功能模块:</span>
984
984
  <Select
985
985
  value={selectedFeatureId}
986
986
  onChange={handleSelectFeature}
987
- style={{ width: 240 }}
987
+ style={{ width: 200 }}
988
988
  placeholder="选择功能模块"
989
989
  loading={featuresLoading}
990
990
  dropdownMatchSelectWidth={false}
@@ -1005,13 +1005,42 @@ const InterfaceManagement = () => {
1005
1005
  onSearch={handleSearch}
1006
1006
  value={searchValue}
1007
1007
  onChange={(e) => setSearchValue(e.target.value)}
1008
- style={{ width: 250, marginLeft: 16 }}
1008
+ style={{ width: 220, marginLeft: 12 }}
1009
1009
  enterButton={<SearchOutlined />}
1010
1010
  allowClear
1011
1011
  />
1012
+
1013
+ <Dropdown
1014
+ overlay={
1015
+ <Menu
1016
+ selectedKeys={selectedGroup ? [selectedGroup] : ['ALL_GROUPS']}
1017
+ onClick={({ key }) => {
1018
+ if (key === 'ALL_GROUPS') {
1019
+ setSelectedGroup(null);
1020
+ } else {
1021
+ setSelectedGroup(key === selectedGroup ? null : key);
1022
+ }
1023
+ }}
1024
+ >
1025
+ <Menu.Item key="ALL_GROUPS">全部分组</Menu.Item>
1026
+ {groups.map(group => (
1027
+ <Menu.Item key={group}>
1028
+ {group} ({interfaces.filter(item => item.group === group).length})
1029
+ </Menu.Item>
1030
+ ))}
1031
+ </Menu>
1032
+ }
1033
+ trigger={['click']}
1034
+ disabled={groups.length === 0}
1035
+ >
1036
+ <Button style={{ marginLeft: 12 }} icon={<FilterOutlined />}>
1037
+ {selectedGroup ? `分组: ${selectedGroup}` : '分组筛选'}
1038
+ <DownOutlined />
1039
+ </Button>
1040
+ </Dropdown>
1012
1041
  </div>
1013
1042
 
1014
- <div className="interface-actions">
1043
+ <div className="control-right">
1015
1044
  <Space>
1016
1045
  <Tooltip title="刷新数据">
1017
1046
  <Button
@@ -1026,132 +1055,46 @@ const InterfaceManagement = () => {
1026
1055
  icon={<PlusOutlined />}
1027
1056
  onClick={handleAddInterface}
1028
1057
  disabled={!selectedFeatureId || selectedFeature?.active === false}
1029
- className="add-interface-button"
1030
1058
  >
1031
1059
  添加接口
1032
1060
  </Button>
1033
1061
  </Space>
1034
1062
  </div>
1035
1063
  </div>
1036
- </Card>
1037
-
1038
- {!features.length && (
1039
- <Alert
1040
- message="未找到功能模块"
1041
- description="请先在模拟数据页面创建功能模块,然后再添加接口"
1042
- type="warning"
1043
- showIcon
1044
- style={{ marginBottom: 16 }}
1045
- />
1046
- )}
1047
-
1048
- {selectedFeature?.active === false && (
1049
- <Alert
1050
- message="功能模块已禁用"
1051
- description="当前功能模块已被禁用,所有关联接口不会生效。您可以在模拟数据页面启用此功能模块。"
1052
- type="warning"
1053
- showIcon
1054
- style={{ marginBottom: 16 }}
1055
- />
1056
- )}
1057
-
1058
- {/* 分组筛选和操作区域 */}
1059
- <Card className="filter-card" bordered={false}>
1060
- <div className="filter-header">
1061
- <div className="filter-title">
1062
- <FilterOutlined /> 分组筛选
1063
- </div>
1064
- {selectedGroup && (
1065
- <Button
1066
- type="link"
1067
- onClick={() => setSelectedGroup(null)}
1068
- size="small"
1069
- >
1070
- 清除筛选
1071
- </Button>
1072
- )}
1073
- </div>
1074
-
1075
- <div className="group-tags-container">
1076
- {groups.length === 0 ? (
1077
- <div className="empty-groups">暂无分组</div>
1078
- ) : (
1079
- <div className="group-tags">
1080
- {groups.map(group => (
1081
- <Tag
1082
- key={group}
1083
- color={selectedGroup === group ? "blue" : "default"}
1084
- onClick={() => setSelectedGroup(group === selectedGroup ? null : group)}
1085
- className={`group-tag ${selectedGroup === group ? 'active' : ''}`}
1086
- >
1087
- {group} ({interfaces.filter(item => item.group === group).length})
1088
- </Tag>
1089
- ))}
1090
- </div>
1091
- )}
1092
- </div>
1093
1064
 
1094
- {selectedGroup && (
1095
- <div className="group-actions">
1096
- <Popconfirm
1097
- title={`确定要启用分组 "${selectedGroup}" 中的所有接口吗?`}
1098
- onConfirm={() => handleBatchToggleActive(true)}
1099
- okText="确定"
1100
- cancelText="取消"
1101
- >
1102
- <Button
1103
- type="primary"
1104
- size="small"
1105
- loading={groupActionLoading}
1106
- >
1107
- 批量启用
1108
- </Button>
1109
- </Popconfirm>
1110
-
1111
- <Popconfirm
1112
- title={`确定要禁用分组 "${selectedGroup}" 中的所有接口吗?`}
1113
- onConfirm={() => handleBatchToggleActive(false)}
1114
- okText="确定"
1115
- cancelText="取消"
1116
- >
1117
- <Button
1118
- danger
1119
- size="small"
1120
- loading={groupActionLoading}
1121
- >
1122
- 批量禁用
1123
- </Button>
1124
- </Popconfirm>
1125
- </div>
1126
- )}
1127
- </Card>
1128
-
1129
- {/* 接口列表状态栏 */}
1130
- <Card className="list-header-card" bordered={false}>
1131
- <div className="list-header">
1132
- <div className="list-header-info">
1133
- <div className="feature-info">
1134
- <span className="label">功能模块:</span>
1135
- <span className="value">{selectedFeature?.name}</span>
1065
+ {/* 统计和批量操作行 */}
1066
+ <div className="control-panel-stats">
1067
+ <div className="stats-left">
1068
+ <Space size="large">
1069
+ <span className="stat-item">
1070
+ <span className="stat-label">功能模块:</span>
1071
+ <span className="stat-value">{selectedFeature?.name}</span>
1072
+ </span>
1073
+
1136
1074
  {selectedGroup && (
1137
- <Tag color="blue" className="group-badge">{selectedGroup}</Tag>
1138
- )}
1139
- </div>
1140
- <div className="interface-stats">
1141
- {searchValue ? (
1142
- <Badge
1143
- count={`搜索"${searchValue}" - ${filteredInterfaces.length}个结果`}
1144
- style={{ backgroundColor: '#108ee9' }}
1145
- />
1146
- ) : (
1147
- <Badge
1148
- count={`共 ${filteredInterfaces.length} 个接口`}
1149
- style={{ backgroundColor: '#52c41a' }}
1150
- />
1075
+ <span className="stat-item">
1076
+ <span className="stat-label">分组:</span>
1077
+ <Tag color="blue">{selectedGroup}</Tag>
1078
+ </span>
1151
1079
  )}
1152
- </div>
1080
+
1081
+ <span className="stat-item">
1082
+ {searchValue ? (
1083
+ <Badge
1084
+ count={`搜索"${searchValue}" - ${filteredInterfaces.length}个结果`}
1085
+ style={{ backgroundColor: '#108ee9' }}
1086
+ />
1087
+ ) : (
1088
+ <Badge
1089
+ count={`共 ${filteredInterfaces.length} 个接口`}
1090
+ style={{ backgroundColor: '#52c41a' }}
1091
+ />
1092
+ )}
1093
+ </span>
1094
+ </Space>
1153
1095
  </div>
1154
- <div className="batch-actions">
1096
+
1097
+ <div className="stats-right">
1155
1098
  {selectedRowKeys.length > 0 && (
1156
1099
  <Space>
1157
1100
  <span className="selected-count">
@@ -1175,72 +1118,127 @@ const InterfaceManagement = () => {
1175
1118
  </Popconfirm>
1176
1119
  </Space>
1177
1120
  )}
1121
+
1122
+ {selectedGroup && (
1123
+ <Space style={{ marginLeft: selectedRowKeys.length > 0 ? 16 : 0 }}>
1124
+ <Popconfirm
1125
+ title={`确定要启用分组 "${selectedGroup}" 中的所有接口吗?`}
1126
+ onConfirm={() => handleBatchToggleActive(true)}
1127
+ okText="确定"
1128
+ cancelText="取消"
1129
+ >
1130
+ <Button
1131
+ type="primary"
1132
+ size="small"
1133
+ loading={groupActionLoading}
1134
+ >
1135
+ 分组启用
1136
+ </Button>
1137
+ </Popconfirm>
1138
+ <Popconfirm
1139
+ title={`确定要禁用分组 "${selectedGroup}" 中的所有接口吗?`}
1140
+ onConfirm={() => handleBatchToggleActive(false)}
1141
+ okText="确定"
1142
+ cancelText="取消"
1143
+ >
1144
+ <Button
1145
+ danger
1146
+ size="small"
1147
+ loading={groupActionLoading}
1148
+ >
1149
+ 分组禁用
1150
+ </Button>
1151
+ </Popconfirm>
1152
+ </Space>
1153
+ )}
1154
+
1155
+ {/* 列设置按钮 */}
1156
+ <Popover
1157
+ title="自定义显示列"
1158
+ trigger="click"
1159
+ open={columnConfigVisible}
1160
+ onOpenChange={handleColumnConfigToggle}
1161
+ content={
1162
+ <div style={{ width: 280 }}>
1163
+ <div style={{ marginBottom: 12 }}>
1164
+ <Space>
1165
+ <Button size="small" onClick={handleSelectAllColumns}>
1166
+ 全选
1167
+ </Button>
1168
+ <Button size="small" onClick={handleResetColumns}>
1169
+ 重置
1170
+ </Button>
1171
+ </Space>
1172
+ </div>
1173
+ <Checkbox.Group
1174
+ value={tableConfig.visibleColumns || COLUMN_CONFIG.map(col => col.key)}
1175
+ onChange={handleColumnConfigChange}
1176
+ style={{ width: '100%' }}
1177
+ >
1178
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
1179
+ {COLUMN_CONFIG.map(col => (
1180
+ <Checkbox
1181
+ key={col.key}
1182
+ value={col.key}
1183
+ disabled={col.required}
1184
+ style={{
1185
+ width: '100%',
1186
+ color: col.required ? '#999' : undefined
1187
+ }}
1188
+ >
1189
+ {col.title}
1190
+ {col.required && (
1191
+ <span style={{ color: '#999', fontSize: '12px', marginLeft: 4 }}>
1192
+ (必须)
1193
+ </span>
1194
+ )}
1195
+ </Checkbox>
1196
+ ))}
1197
+ </div>
1198
+ </Checkbox.Group>
1199
+ </div>
1200
+ }
1201
+ >
1202
+ <Tooltip title="自定义显示列">
1203
+ <Button
1204
+ icon={<SettingOutlined />}
1205
+ type="text"
1206
+ size="middle"
1207
+ className="column-settings-btn"
1208
+ style={{
1209
+ marginLeft: (selectedRowKeys.length > 0 || selectedGroup) ? 16 : 0,
1210
+ color: '#666'
1211
+ }}
1212
+ >
1213
+ 列设置
1214
+ </Button>
1215
+ </Tooltip>
1216
+ </Popover>
1178
1217
  </div>
1179
1218
  </div>
1180
1219
  </Card>
1220
+
1221
+ {!features.length && (
1222
+ <Alert
1223
+ message="未找到功能模块"
1224
+ description="请先在模拟数据页面创建功能模块,然后再添加接口"
1225
+ type="warning"
1226
+ showIcon
1227
+ style={{ marginBottom: 16 }}
1228
+ />
1229
+ )}
1230
+
1231
+ {selectedFeature?.active === false && (
1232
+ <Alert
1233
+ message="功能模块已禁用"
1234
+ description="当前功能模块已被禁用,所有关联接口不会生效。您可以在模拟数据页面启用此功能模块。"
1235
+ type="warning"
1236
+ showIcon
1237
+ style={{ marginBottom: 16 }}
1238
+ />
1239
+ )}
1240
+
1181
1241
 
1182
- {/* 列配置区域 */}
1183
- <div style={{
1184
- marginBottom: 16,
1185
- display: 'flex',
1186
- justifyContent: 'flex-end',
1187
- alignItems: 'center'
1188
- }}>
1189
- <Popover
1190
- title="自定义显示列"
1191
- trigger="click"
1192
- open={columnConfigVisible}
1193
- onOpenChange={handleColumnConfigToggle}
1194
- content={
1195
- <div style={{ width: 280 }}>
1196
- <div style={{ marginBottom: 12 }}>
1197
- <Space>
1198
- <Button size="small" onClick={handleSelectAllColumns}>
1199
- 全选
1200
- </Button>
1201
- <Button size="small" onClick={handleResetColumns}>
1202
- 重置
1203
- </Button>
1204
- </Space>
1205
- </div>
1206
- <Checkbox.Group
1207
- value={tableConfig.visibleColumns || COLUMN_CONFIG.map(col => col.key)}
1208
- onChange={handleColumnConfigChange}
1209
- style={{ width: '100%' }}
1210
- >
1211
- <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
1212
- {COLUMN_CONFIG.map(col => (
1213
- <Checkbox
1214
- key={col.key}
1215
- value={col.key}
1216
- disabled={col.required}
1217
- style={{
1218
- width: '100%',
1219
- color: col.required ? '#999' : undefined
1220
- }}
1221
- >
1222
- {col.title}
1223
- {col.required && (
1224
- <span style={{ color: '#999', fontSize: '12px', marginLeft: 4 }}>
1225
- (必须)
1226
- </span>
1227
- )}
1228
- </Checkbox>
1229
- ))}
1230
- </div>
1231
- </Checkbox.Group>
1232
- </div>
1233
- }
1234
- >
1235
- <Button
1236
- icon={<SettingOutlined />}
1237
- size="small"
1238
- type="text"
1239
- >
1240
- 列设置
1241
- </Button>
1242
- </Popover>
1243
- </div>
1244
1242
 
1245
1243
  <Card className="list-container-card" bordered={false} bodyStyle={{ padding: 0 }}>
1246
1244
  <div className="interface-list-container">
@@ -15,38 +15,40 @@
15
15
  --transition-time: 0.3s;
16
16
  }
17
17
 
18
- .interface-management-container {
19
- padding: 24px;
20
- background: #f5f7fa;
21
- }
22
18
 
23
- /* 顶部功能区域 */
24
- .interface-header-card {
19
+ /* 统一控制台 */
20
+ .interface-control-panel {
25
21
  margin-bottom: 16px;
26
22
  border-radius: 12px;
27
23
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
28
24
  overflow: hidden;
29
25
  }
30
26
 
31
- .interface-management-header {
27
+ .control-panel-header {
32
28
  display: flex;
33
29
  justify-content: space-between;
34
30
  align-items: center;
35
31
  padding: 8px 0;
32
+ border-bottom: 1px solid #f0f0f0;
36
33
  }
37
34
 
38
- .feature-selector-container {
35
+ .control-left {
39
36
  display: flex;
40
37
  align-items: center;
41
38
  flex-wrap: wrap;
42
- gap: 12px;
39
+ gap: 8px;
40
+ }
41
+
42
+ .control-right {
43
+ display: flex;
44
+ align-items: center;
43
45
  }
44
46
 
45
47
  .feature-selector {
46
48
  display: flex;
47
49
  align-items: center;
48
50
  background: #f9f9f9;
49
- padding: 8px 16px;
51
+ padding: 6px 12px;
50
52
  border-radius: var(--border-radius);
51
53
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
52
54
  transition: all var(--transition-time);
@@ -57,9 +59,89 @@
57
59
  }
58
60
 
59
61
  .feature-selector span {
60
- margin-right: 12px;
62
+ margin-right: 8px;
61
63
  font-weight: 600;
62
64
  color: var(--text-secondary);
65
+ font-size: 14px;
66
+ }
67
+
68
+ .control-panel-stats {
69
+ display: flex;
70
+ justify-content: space-between;
71
+ align-items: center;
72
+ padding: 12px 0 8px 0;
73
+ min-height: 40px;
74
+ }
75
+
76
+ .stats-left {
77
+ display: flex;
78
+ align-items: center;
79
+ flex-wrap: wrap;
80
+ }
81
+
82
+ .stats-right {
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 12px;
86
+ }
87
+
88
+ .stat-item {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ font-size: 14px;
92
+ }
93
+
94
+ .stat-label {
95
+ color: var(--text-secondary);
96
+ margin-right: 6px;
97
+ }
98
+
99
+ .stat-value {
100
+ font-weight: 600;
101
+ color: var(--font-color);
102
+ }
103
+
104
+ .selected-count {
105
+ font-weight: 600;
106
+ color: var(--primary-color);
107
+ font-size: 13px;
108
+ }
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-header-card {
127
+ margin-bottom: 16px;
128
+ border-radius: 12px;
129
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
130
+ overflow: hidden;
131
+ }
132
+
133
+ .interface-management-header {
134
+ display: flex;
135
+ justify-content: space-between;
136
+ align-items: center;
137
+ padding: 8px 0;
138
+ }
139
+
140
+ .feature-selector-container {
141
+ display: flex;
142
+ align-items: center;
143
+ flex-wrap: wrap;
144
+ gap: 12px;
63
145
  }
64
146
 
65
147
  .interface-actions {