whistle.mock-plugins 1.0.0

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.
Files changed (68) hide show
  1. package/API.md +247 -0
  2. package/README.md +91 -0
  3. package/app/cgi-bin/features.js +285 -0
  4. package/app/cgi-bin/index.js +31 -0
  5. package/app/cgi-bin/interfaces.js +409 -0
  6. package/app/cgi-bin/logs.js +151 -0
  7. package/app/cgi-bin/test-interface.js +152 -0
  8. package/app/public/index.html +1 -0
  9. package/app/public/js/index.js +2 -0
  10. package/app/public/js/index.js.LICENSE.txt +150 -0
  11. package/app/util/index.js +24 -0
  12. package/index.html +52 -0
  13. package/initialize.js +32 -0
  14. package/lib/dataManager.js +500 -0
  15. package/lib/index.js +3 -0
  16. package/lib/models.js +64 -0
  17. package/lib/routes/features.js +213 -0
  18. package/lib/routes/interfaces.js +304 -0
  19. package/lib/routes/proxy.js +239 -0
  20. package/lib/ruleManager.js +551 -0
  21. package/lib/rules-server.js +267 -0
  22. package/lib/server.js +805 -0
  23. package/lib/storage.js +16 -0
  24. package/lib/ui-server.js +68 -0
  25. package/package.json +51 -0
  26. package/public/bundle.js +2 -0
  27. package/public/bundle.js.LICENSE.txt +38 -0
  28. package/public/index.html +1 -0
  29. package/public/plugin.mock-plugin.html +14 -0
  30. package/rules.txt +22 -0
  31. package/test/rulesServer.test.js +120 -0
  32. package/ui/src/App.css +173 -0
  33. package/ui/src/App.js +24 -0
  34. package/ui/src/components/AppLayout.js +149 -0
  35. package/ui/src/components/FeatureCard.js +53 -0
  36. package/ui/src/components/Layout.js +94 -0
  37. package/ui/src/components/MainNav.js +42 -0
  38. package/ui/src/components/PageContainer.js +16 -0
  39. package/ui/src/index.html +11 -0
  40. package/ui/src/index.js +43 -0
  41. package/ui/src/pages/FileProxy.js +235 -0
  42. package/ui/src/pages/FilesPage.js +292 -0
  43. package/ui/src/pages/Home.js +128 -0
  44. package/ui/src/pages/HomePage.js +195 -0
  45. package/ui/src/pages/InterfaceManagement.js +829 -0
  46. package/ui/src/pages/InterfacePage.js +342 -0
  47. package/ui/src/pages/MockData.js +472 -0
  48. package/ui/src/pages/Settings.js +192 -0
  49. package/ui/src/pages/SettingsPage.js +165 -0
  50. package/ui/src/pages/UrlRedirect.js +225 -0
  51. package/ui/src/pages/Welcome.js +155 -0
  52. package/ui/src/services/api.js +186 -0
  53. package/ui/src/styles/app-layout.css +337 -0
  54. package/ui/src/styles/feature-card.css +172 -0
  55. package/ui/src/styles/file-proxy.css +301 -0
  56. package/ui/src/styles/global.css +224 -0
  57. package/ui/src/styles/home.css +123 -0
  58. package/ui/src/styles/index.css +419 -0
  59. package/ui/src/styles/interface-management.css +694 -0
  60. package/ui/src/styles/layout.css +159 -0
  61. package/ui/src/styles/logs-page.css +427 -0
  62. package/ui/src/styles/main-nav.css +52 -0
  63. package/ui/src/styles/mock-data.css +850 -0
  64. package/ui/src/styles/page-container.css +11 -0
  65. package/ui/src/styles/settings.css +208 -0
  66. package/ui/src/styles/url-redirect.css +279 -0
  67. package/ui/src/styles/welcome.css +282 -0
  68. package/webpack.config.js +49 -0
@@ -0,0 +1,159 @@
1
+ .app-layout {
2
+ display: flex;
3
+ flex-direction: column;
4
+ min-height: 100vh;
5
+ }
6
+
7
+ .app-header {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: space-between;
11
+ padding: 0 20px;
12
+ height: 60px;
13
+ background-color: #fff;
14
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
15
+ z-index: 10;
16
+ }
17
+
18
+ .app-logo {
19
+ display: flex;
20
+ align-items: center;
21
+ font-size: 1.5rem;
22
+ font-weight: bold;
23
+ color: #2c3e50;
24
+ }
25
+
26
+ .app-logo img {
27
+ height: 32px;
28
+ margin-right: 10px;
29
+ }
30
+
31
+ .search-bar {
32
+ flex: 1;
33
+ max-width: 400px;
34
+ margin: 0 20px;
35
+ position: relative;
36
+ }
37
+
38
+ .search-bar input {
39
+ width: 100%;
40
+ padding: 8px 12px;
41
+ padding-left: 35px;
42
+ border: 1px solid #ddd;
43
+ border-radius: 4px;
44
+ font-size: 14px;
45
+ }
46
+
47
+ .search-bar::before {
48
+ content: '🔍';
49
+ position: absolute;
50
+ left: 10px;
51
+ top: 8px;
52
+ color: #aaa;
53
+ }
54
+
55
+ .action-buttons {
56
+ display: flex;
57
+ gap: 10px;
58
+ }
59
+
60
+ .action-btn {
61
+ padding: 8px 12px;
62
+ background-color: #3498db;
63
+ color: white;
64
+ border: none;
65
+ border-radius: 4px;
66
+ cursor: pointer;
67
+ transition: background-color 0.2s;
68
+ }
69
+
70
+ .action-btn:hover {
71
+ background-color: #2980b9;
72
+ }
73
+
74
+ .app-main {
75
+ display: flex;
76
+ flex: 1;
77
+ }
78
+
79
+ .app-sidebar {
80
+ width: 240px;
81
+ background-color: #fff;
82
+ box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05);
83
+ padding: 20px 0;
84
+ display: flex;
85
+ flex-direction: column;
86
+ min-height: calc(100vh - 60px);
87
+ }
88
+
89
+ .sidebar-header {
90
+ padding: 0 20px 15px;
91
+ border-bottom: 1px solid #eee;
92
+ font-weight: bold;
93
+ font-size: 1.1rem;
94
+ }
95
+
96
+ .feature-list {
97
+ list-style: none;
98
+ margin-top: 15px;
99
+ }
100
+
101
+ .feature-item {
102
+ padding: 10px 20px;
103
+ display: flex;
104
+ justify-content: space-between;
105
+ align-items: center;
106
+ cursor: pointer;
107
+ transition: background-color 0.2s;
108
+ }
109
+
110
+ .feature-item:hover {
111
+ background-color: #f0f7ff;
112
+ }
113
+
114
+ .feature-item.active {
115
+ background-color: #e6f7ff;
116
+ border-right: 3px solid #1890ff;
117
+ }
118
+
119
+ .feature-name {
120
+ flex: 1;
121
+ }
122
+
123
+ .feature-count {
124
+ font-size: 12px;
125
+ padding: 2px 8px;
126
+ background-color: #eee;
127
+ border-radius: 10px;
128
+ }
129
+
130
+ .add-feature-btn {
131
+ margin: 20px;
132
+ padding: 8px 12px;
133
+ background-color: #f0f7ff;
134
+ color: #1890ff;
135
+ border: 1px dashed #1890ff;
136
+ border-radius: 4px;
137
+ width: calc(100% - 40px);
138
+ text-align: center;
139
+ cursor: pointer;
140
+ transition: all 0.2s;
141
+ }
142
+
143
+ .add-feature-btn:hover {
144
+ background-color: #e6f7ff;
145
+ }
146
+
147
+ .sidebar-footer {
148
+ margin-top: auto;
149
+ padding: 15px 20px;
150
+ font-size: 12px;
151
+ color: #999;
152
+ border-top: 1px solid #eee;
153
+ }
154
+
155
+ .app-content {
156
+ flex: 1;
157
+ padding: 20px;
158
+ overflow-y: auto;
159
+ }
@@ -0,0 +1,427 @@
1
+ .logs-page-container {
2
+ width: 100%;
3
+ }
4
+
5
+ .filter-card {
6
+ border-radius: 8px;
7
+ }
8
+
9
+ .filter-container {
10
+ display: flex;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ flex-wrap: wrap;
14
+ gap: 16px;
15
+ }
16
+
17
+ .filter-item {
18
+ margin-bottom: 0 !important;
19
+ }
20
+
21
+ .filter-count {
22
+ margin-left: 8px;
23
+ }
24
+
25
+ .logs-summary {
26
+ display: flex;
27
+ align-items: center;
28
+ white-space: nowrap;
29
+ }
30
+
31
+ .table-container {
32
+ border-radius: 8px;
33
+ overflow: hidden;
34
+ }
35
+
36
+ .time-column {
37
+ display: flex;
38
+ flex-direction: column;
39
+ }
40
+
41
+ .time-value {
42
+ font-weight: 500;
43
+ color: rgba(0, 0, 0, 0.85);
44
+ }
45
+
46
+ .date-small {
47
+ font-size: 12px;
48
+ color: rgba(0, 0, 0, 0.45);
49
+ margin-top: 2px;
50
+ }
51
+
52
+ .url-column {
53
+ max-width: 300px;
54
+ overflow: hidden;
55
+ text-overflow: ellipsis;
56
+ white-space: nowrap;
57
+ }
58
+
59
+ .refresh-icon {
60
+ margin-left: 8px;
61
+ font-size: 14px;
62
+ color: #1890ff;
63
+ vertical-align: middle;
64
+ }
65
+
66
+ /* 日志详情弹窗样式 */
67
+ .log-detail-modal .ant-modal-body {
68
+ padding: 0;
69
+ }
70
+
71
+ .log-detail-tabs {
72
+ height: 400px;
73
+ }
74
+
75
+ .log-detail-content {
76
+ padding: 16px;
77
+ overflow: auto;
78
+ height: 350px;
79
+ }
80
+
81
+ .log-detail-panel {
82
+ background-color: #f5f5f5;
83
+ padding: 16px;
84
+ border-radius: 8px;
85
+ font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
86
+ white-space: pre-wrap;
87
+ word-break: break-all;
88
+ font-size: 13px;
89
+ line-height: 1.5;
90
+ }
91
+
92
+ .log-property {
93
+ display: flex;
94
+ border-bottom: 1px solid #f0f0f0;
95
+ padding: 8px 0;
96
+ }
97
+
98
+ .log-property:last-child {
99
+ border-bottom: none;
100
+ }
101
+
102
+ .log-property-label {
103
+ width: 100px;
104
+ font-weight: 500;
105
+ color: rgba(0, 0, 0, 0.65);
106
+ }
107
+
108
+ .log-property-value {
109
+ flex: 1;
110
+ word-break: break-all;
111
+ }
112
+
113
+ /* 响应式调整 */
114
+ @media (max-width: 768px) {
115
+ .filter-container {
116
+ flex-direction: column;
117
+ align-items: flex-start;
118
+ }
119
+
120
+ .logs-summary {
121
+ margin-top: 8px;
122
+ }
123
+ }
124
+
125
+ /* 日志页面样式 */
126
+ .logs-page {
127
+ padding: 20px;
128
+ }
129
+
130
+ /* 表格行悬停效果,增强可点击感知 */
131
+ .log-table-row {
132
+ cursor: pointer;
133
+ transition: all 0.2s;
134
+ }
135
+
136
+ .log-table-row:hover {
137
+ background-color: rgba(24, 144, 255, 0.05);
138
+ }
139
+
140
+ /* 日志详情模态框样式 */
141
+ .log-detail-modal .ant-modal-content {
142
+ border-radius: 8px;
143
+ overflow: hidden;
144
+ }
145
+
146
+ .log-detail-modal .ant-modal-header {
147
+ padding: 16px 24px;
148
+ background: linear-gradient(to right, #1890ff, #40a9ff);
149
+ border-bottom: none;
150
+ }
151
+
152
+ .log-detail-modal .ant-modal-title {
153
+ color: white;
154
+ }
155
+
156
+ .log-detail-modal .ant-modal-close {
157
+ color: rgba(255, 255, 255, 0.8);
158
+ }
159
+
160
+ .log-detail-modal .ant-modal-close:hover {
161
+ color: white;
162
+ }
163
+
164
+ .log-detail-modal .ant-modal-body {
165
+ padding: 24px;
166
+ max-height: 75vh;
167
+ overflow-y: auto;
168
+ }
169
+
170
+ .log-detail-header {
171
+ display: flex;
172
+ justify-content: space-between;
173
+ align-items: center;
174
+ }
175
+
176
+ .log-detail-title {
177
+ display: flex;
178
+ align-items: center;
179
+ gap: 12px;
180
+ color: white;
181
+ font-weight: 600;
182
+ }
183
+
184
+ .log-timestamp {
185
+ font-size: 13px;
186
+ font-weight: normal;
187
+ opacity: 0.8;
188
+ }
189
+
190
+ .log-detail-status {
191
+ background: rgba(255, 255, 255, 0.15);
192
+ padding: 4px 12px;
193
+ border-radius: 20px;
194
+ color: white;
195
+ font-size: 13px;
196
+ }
197
+
198
+ .status-description {
199
+ display: flex;
200
+ align-items: center;
201
+ gap: 6px;
202
+ }
203
+
204
+ .status-description.success {
205
+ color: #52c41a;
206
+ }
207
+
208
+ .status-description.warning {
209
+ color: #faad14;
210
+ }
211
+
212
+ .status-description.error {
213
+ color: #f5222d;
214
+ }
215
+
216
+ .log-overview {
217
+ margin-bottom: 16px;
218
+ }
219
+
220
+ .log-detail-descriptions {
221
+ margin-bottom: 16px;
222
+ }
223
+
224
+ .log-detail-descriptions .ant-descriptions-row > th,
225
+ .log-detail-descriptions .ant-descriptions-row > td {
226
+ padding: 12px 16px;
227
+ }
228
+
229
+ .header-section .ant-descriptions-item-content,
230
+ .body-section .ant-descriptions-item-content {
231
+ background-color: #fafafa;
232
+ }
233
+
234
+ .code-block-wrapper {
235
+ position: relative;
236
+ width: 100%;
237
+ }
238
+
239
+ .code-block {
240
+ background-color: #f6f8fa;
241
+ border-radius: 4px;
242
+ padding: 12px;
243
+ overflow: auto;
244
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
245
+ font-size: 13px;
246
+ line-height: 1.45;
247
+ max-height: 300px;
248
+ margin: 0;
249
+ white-space: pre-wrap;
250
+ word-break: break-all;
251
+ }
252
+
253
+ .copy-btn {
254
+ position: absolute;
255
+ top: 8px;
256
+ right: 8px;
257
+ background-color: rgba(255, 255, 255, 0.8);
258
+ border-radius: 4px;
259
+ padding: 4px 8px;
260
+ opacity: 0;
261
+ transition: opacity 0.2s;
262
+ }
263
+
264
+ .code-block-wrapper:hover .copy-btn {
265
+ opacity: 1;
266
+ }
267
+
268
+ .log-detail-tabs .ant-tabs-nav {
269
+ margin-bottom: 16px;
270
+ }
271
+
272
+ .header-item .ant-descriptions-item-content {
273
+ word-break: break-all;
274
+ }
275
+
276
+ /* 响应式调整 */
277
+ @media (max-width: 768px) {
278
+ .log-detail-modal .ant-modal-body {
279
+ padding: 16px;
280
+ }
281
+
282
+ .log-detail-descriptions .ant-descriptions-row > th,
283
+ .log-detail-descriptions .ant-descriptions-row > td {
284
+ padding: 8px 12px;
285
+ }
286
+ }
287
+
288
+ /* 过滤器区域样式 */
289
+ .filter-card {
290
+ border-radius: 8px;
291
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
292
+ }
293
+
294
+ .filter-container {
295
+ display: flex;
296
+ justify-content: space-between;
297
+ align-items: center;
298
+ flex-wrap: wrap;
299
+ gap: 16px;
300
+ }
301
+
302
+ .filter-item {
303
+ margin-bottom: 0 !important;
304
+ }
305
+
306
+ .logs-summary {
307
+ display: flex;
308
+ align-items: center;
309
+ }
310
+
311
+ .d-flex {
312
+ display: flex;
313
+ }
314
+
315
+ .align-center {
316
+ align-items: center;
317
+ }
318
+
319
+ .mr-1 {
320
+ margin-right: 4px;
321
+ }
322
+
323
+ .ml-1 {
324
+ margin-left: 4px;
325
+ }
326
+
327
+ .mb-3 {
328
+ margin-bottom: 16px;
329
+ }
330
+
331
+ /* 时间列样式 */
332
+ .time-column {
333
+ display: flex;
334
+ flex-direction: column;
335
+ }
336
+
337
+ .time-value {
338
+ font-weight: 500;
339
+ }
340
+
341
+ .date-small {
342
+ font-size: 12px;
343
+ color: #8c8c8c;
344
+ }
345
+
346
+ /* URL列样式 */
347
+ .url-column {
348
+ max-width: 400px;
349
+ }
350
+
351
+ /* 表格容器样式 */
352
+ .table-container {
353
+ margin-top: 16px;
354
+ background-color: white;
355
+ border-radius: 8px;
356
+ overflow: hidden;
357
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
358
+ }
359
+
360
+ /* 自定义表格样式 */
361
+ .custom-table .ant-table-thead > tr > th {
362
+ background-color: #f5f7fa;
363
+ font-weight: 600;
364
+ }
365
+
366
+ .custom-table .ant-pagination {
367
+ padding: 16px 24px;
368
+ margin: 0;
369
+ }
370
+
371
+ /* 状态标签样式 */
372
+ .status-tag {
373
+ min-width: 64px;
374
+ text-align: center;
375
+ }
376
+
377
+ .status-tag-success {
378
+ color: #52c41a;
379
+ background-color: #f6ffed;
380
+ border-color: #b7eb8f;
381
+ }
382
+
383
+ .status-tag-warning {
384
+ color: #faad14;
385
+ background-color: #fffbe6;
386
+ border-color: #ffe58f;
387
+ }
388
+
389
+ .status-tag-error {
390
+ color: #f5222d;
391
+ background-color: #fff1f0;
392
+ border-color: #ffa39e;
393
+ }
394
+
395
+ /* 页头样式 */
396
+ .logs-page-header {
397
+ display: flex;
398
+ justify-content: space-between;
399
+ align-items: center;
400
+ margin-bottom: 24px;
401
+ }
402
+
403
+ .logs-page-title {
404
+ font-size: 24px;
405
+ font-weight: 600;
406
+ margin: 0;
407
+ }
408
+
409
+ .logs-action-buttons {
410
+ display: flex;
411
+ gap: 12px;
412
+ }
413
+
414
+ /* 自动刷新按钮样式 */
415
+ .auto-refresh {
416
+ display: flex;
417
+ align-items: center;
418
+ gap: 8px;
419
+ }
420
+
421
+ .auto-refresh-text {
422
+ font-size: 13px;
423
+ }
424
+
425
+ .tab-content {
426
+ padding: 8px 0;
427
+ }
@@ -0,0 +1,52 @@
1
+ .main-nav {
2
+ width: 100%;
3
+ }
4
+
5
+ .main-header {
6
+ background-color: #1890ff;
7
+ color: #fff;
8
+ padding: 15px 0;
9
+ text-align: center;
10
+ }
11
+
12
+ .main-header h1 {
13
+ margin: 0;
14
+ font-size: 1.8rem;
15
+ font-weight: 500;
16
+ }
17
+
18
+ .nav-tabs {
19
+ display: flex;
20
+ background-color: #fff;
21
+ border-bottom: 1px solid #e8e8e8;
22
+ padding: 0 20px;
23
+ }
24
+
25
+ .nav-tab {
26
+ padding: 12px 20px;
27
+ color: #666;
28
+ text-decoration: none;
29
+ font-size: 14px;
30
+ font-weight: 500;
31
+ position: relative;
32
+ transition: all 0.3s;
33
+ }
34
+
35
+ .nav-tab:hover {
36
+ color: #1890ff;
37
+ }
38
+
39
+ .nav-tab.active {
40
+ color: #1890ff;
41
+ font-weight: 600;
42
+ }
43
+
44
+ .nav-tab.active::after {
45
+ content: '';
46
+ position: absolute;
47
+ bottom: 0;
48
+ left: 0;
49
+ width: 100%;
50
+ height: 2px;
51
+ background-color: #1890ff;
52
+ }