@becrafter/prompt-manager 0.1.2 → 0.1.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.
Files changed (110) hide show
  1. package/README.md +304 -121
  2. package/app/cli/commands/start.js +28 -4
  3. package/app/cli/support/argv.js +6 -0
  4. package/env.example +32 -0
  5. package/package.json +36 -6
  6. package/packages/server/api/admin.routes.js +409 -1
  7. package/packages/server/api/open.routes.js +7 -2
  8. package/packages/server/api/tool.routes.js +479 -0
  9. package/packages/server/app.js +97 -25
  10. package/packages/server/configs/models/built-in/bigmodel.yaml +6 -0
  11. package/packages/server/configs/models/providers.yaml +50 -0
  12. package/packages/server/configs/templates/built-in/general-iteration.yaml +60 -0
  13. package/packages/server/configs/templates/built-in/general-optimize.yaml +63 -0
  14. package/packages/server/configs/templates/built-in/output-format-optimize.yaml +95 -0
  15. package/packages/server/mcp/heartbeat-patch.js +73 -0
  16. package/packages/server/mcp/mcp.server.js +63 -314
  17. package/packages/server/mcp/prompt.handler.js +26 -0
  18. package/packages/server/mcp/thinking-toolkit.handler.js +380 -0
  19. package/packages/server/package.json +35 -3
  20. package/packages/server/server.js +114 -12
  21. package/packages/server/services/TerminalService.js +498 -0
  22. package/packages/server/services/WebSocketService.js +484 -0
  23. package/packages/server/services/manager.js +38 -7
  24. package/packages/server/services/model.service.js +473 -0
  25. package/packages/server/services/optimization.service.js +457 -0
  26. package/packages/server/services/template.service.js +333 -0
  27. package/packages/server/toolm/tool-description-generator-optimized.service.js +5 -2
  28. package/packages/server/toolm/tool-sync.service.js +47 -3
  29. package/packages/server/utils/config.js +8 -1
  30. package/packages/server/utils/port-checker.js +63 -0
  31. package/packages/server/utils/util.js +27 -0
  32. package/IFLOW.md +0 -175
  33. package/app/desktop/assets/app.1.png +0 -0
  34. package/app/desktop/assets/app.png +0 -0
  35. package/app/desktop/assets/icons/icon.icns +0 -0
  36. package/app/desktop/assets/icons/icon.ico +0 -0
  37. package/app/desktop/assets/icons/icon.png +0 -0
  38. package/app/desktop/assets/icons/tray.png +0 -0
  39. package/app/desktop/assets/templates/about.html +0 -147
  40. package/app/desktop/assets/tray.1.png +0 -0
  41. package/app/desktop/assets/tray.png +0 -0
  42. package/app/desktop/main.js +0 -241
  43. package/app/desktop/package-lock.json +0 -5026
  44. package/app/desktop/package.json +0 -100
  45. package/app/desktop/preload.js +0 -7
  46. package/app/desktop/src/core/error-handler.js +0 -108
  47. package/app/desktop/src/core/event-emitter.js +0 -84
  48. package/app/desktop/src/core/logger.js +0 -108
  49. package/app/desktop/src/core/state-manager.js +0 -125
  50. package/app/desktop/src/services/module-loader.js +0 -214
  51. package/app/desktop/src/services/runtime-manager.js +0 -301
  52. package/app/desktop/src/services/service-manager.js +0 -169
  53. package/app/desktop/src/services/update-manager.js +0 -267
  54. package/app/desktop/src/ui/about-dialog-manager.js +0 -208
  55. package/app/desktop/src/ui/admin-window-manager.js +0 -757
  56. package/app/desktop/src/ui/splash-manager.js +0 -253
  57. package/app/desktop/src/ui/tray-manager.js +0 -186
  58. package/app/desktop/src/utils/icon-manager.js +0 -133
  59. package/app/desktop/src/utils/path-utils.js +0 -58
  60. package/app/desktop/src/utils/resource-paths.js +0 -49
  61. package/app/desktop/src/utils/resource-sync.js +0 -260
  62. package/app/desktop/src/utils/runtime-sync.js +0 -241
  63. package/app/desktop/src/utils/template-renderer.js +0 -284
  64. package/app/desktop/src/utils/version-utils.js +0 -59
  65. package/examples/prompts/developer/code-review.yaml +0 -32
  66. package/examples/prompts/developer/code_refactoring.yaml +0 -31
  67. package/examples/prompts/developer/doc-generator.yaml +0 -36
  68. package/examples/prompts/developer/error-code-fixer.yaml +0 -35
  69. package/examples/prompts/engineer/engineer-professional.yaml +0 -92
  70. package/examples/prompts/engineer/laowang-engineer.yaml +0 -132
  71. package/examples/prompts/engineer/nekomata-engineer.yaml +0 -123
  72. package/examples/prompts/engineer/ojousama-engineer.yaml +0 -124
  73. package/examples/prompts/generator/gen_3d_edu_webpage_html.yaml +0 -117
  74. package/examples/prompts/generator/gen_3d_webpage_html.yaml +0 -75
  75. package/examples/prompts/generator/gen_bento_grid_html.yaml +0 -112
  76. package/examples/prompts/generator/gen_html_web_page.yaml +0 -88
  77. package/examples/prompts/generator/gen_knowledge_card_html.yaml +0 -83
  78. package/examples/prompts/generator/gen_magazine_card_html.yaml +0 -82
  79. package/examples/prompts/generator/gen_mimeng_headline_title.yaml +0 -71
  80. package/examples/prompts/generator/gen_podcast_script.yaml +0 -69
  81. package/examples/prompts/generator/gen_prd_prototype_html.yaml +0 -175
  82. package/examples/prompts/generator/gen_summarize.yaml +0 -157
  83. package/examples/prompts/generator/gen_title.yaml +0 -119
  84. package/examples/prompts/generator/others/api_documentation.yaml +0 -32
  85. package/examples/prompts/generator/others/build_mcp_server.yaml +0 -26
  86. package/examples/prompts/generator/others/project_architecture.yaml +0 -31
  87. package/examples/prompts/generator/others/test_case_generator.yaml +0 -30
  88. package/examples/prompts/generator/others/writing_assistant.yaml +0 -72
  89. package/examples/prompts/recommend/human_3-0_growth_diagnostic_coach_prompt.yaml +0 -105
  90. package/examples/prompts/workflow/sixstep-workflow.yaml +0 -192
  91. package/packages/admin-ui/.babelrc +0 -3
  92. package/packages/admin-ui/admin.html +0 -412
  93. package/packages/admin-ui/css/codemirror-theme_xq-light.css +0 -43
  94. package/packages/admin-ui/css/codemirror.css +0 -344
  95. package/packages/admin-ui/css/main.css +0 -2592
  96. package/packages/admin-ui/css/recommended-prompts.css +0 -610
  97. package/packages/admin-ui/package-lock.json +0 -6973
  98. package/packages/admin-ui/package.json +0 -36
  99. package/packages/admin-ui/src/codemirror.js +0 -53
  100. package/packages/admin-ui/src/index.js +0 -3188
  101. package/packages/admin-ui/webpack.config.js +0 -76
  102. package/packages/server/toolm/test-tools.js +0 -264
  103. package/scripts/build-icons.js +0 -135
  104. package/scripts/build.sh +0 -57
  105. package/scripts/postinstall.js +0 -34
  106. package/scripts/surge/CNAME +0 -1
  107. package/scripts/surge/README.md +0 -47
  108. package/scripts/surge/package-lock.json +0 -34
  109. package/scripts/surge/package.json +0 -20
  110. package/scripts/surge/sync-to-surge.js +0 -151
@@ -1,757 +0,0 @@
1
- const { BrowserWindow, nativeImage } = require('electron');
2
- const path = require('path');
3
-
4
- /**
5
- * 管理后台窗口管理器
6
- * 负责创建和管理管理后台窗口,提供加载效果
7
- */
8
- class AdminWindowManager {
9
- constructor(logger, iconManager) {
10
- this.logger = logger;
11
- this.iconManager = iconManager;
12
- this.adminWindow = null;
13
- }
14
-
15
- /**
16
- * 打开管理后台窗口
17
- * @param {string} adminUrl - 管理后台URL
18
- */
19
- openAdminWindow(adminUrl) {
20
- if (this.adminWindow && !this.adminWindow.isDestroyed()) {
21
- this.adminWindow.focus();
22
- return;
23
- }
24
-
25
- try {
26
- this.logger.info('Opening admin window', { url: adminUrl });
27
-
28
- // 创建窗口
29
- this.adminWindow = this.createAdminWindow();
30
-
31
- // 先显示加载页面(随机选择一种动画效果)
32
- const animationTypes = ['spinner', 'dots', 'wave', 'pulse', 'bars', 'gradient', 'orbit', 'ripple'];
33
- const randomAnimation = animationTypes[Math.floor(Math.random() * animationTypes.length)];
34
- this.showLoadingPage(randomAnimation);
35
-
36
- // 设置窗口事件
37
- this.setupWindowEvents(adminUrl);
38
-
39
- this.logger.info('Admin window created successfully');
40
- } catch (error) {
41
- this.logger.error('Failed to open admin window', error);
42
- }
43
- }
44
-
45
- /**
46
- * 创建管理后台窗口
47
- */
48
- createAdminWindow() {
49
- const window = new BrowserWindow({
50
- width: 1200,
51
- height: 800,
52
- minWidth: 800,
53
- minHeight: 600,
54
- title: 'Prompt Server 管理后台',
55
- show: false, // 先不显示,等加载完成后再显示
56
- backgroundColor: '#ffffff',
57
- webPreferences: {
58
- contextIsolation: true,
59
- nodeIntegration: false,
60
- sandbox: true
61
- }
62
- });
63
-
64
- // 设置窗口图标(如果可用)
65
- try {
66
- const icon = this.iconManager.getAppIcon();
67
- if (icon && !icon.isEmpty()) {
68
- window.setIcon(icon);
69
- }
70
- } catch (error) {
71
- this.logger.warn('Failed to set window icon', error);
72
- }
73
-
74
- return window;
75
- }
76
-
77
- /**
78
- * 显示加载页面
79
- * @param {string} animationType - 动画类型
80
- */
81
- showLoadingPage(animationType = 'spinner') {
82
- if (!this.adminWindow || this.adminWindow.isDestroyed()) {
83
- return;
84
- }
85
-
86
- const htmlContent = this.generateLoadingHTML(animationType);
87
- this.adminWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(htmlContent)}`);
88
-
89
- // 加载页面后显示窗口
90
- this.adminWindow.once('ready-to-show', () => {
91
- if (this.adminWindow && !this.adminWindow.isDestroyed()) {
92
- this.adminWindow.show();
93
- this.logger.info('Admin window loading page shown', { animationType });
94
- }
95
- });
96
- }
97
-
98
- /**
99
- * 生成加载页面HTML
100
- * @param {string} animationType - 动画类型: 'spinner' | 'dots' | 'wave' | 'pulse' | 'skeleton' | 'bars' | 'gradient' | 'orbit' | 'ripple'
101
- */
102
- generateLoadingHTML(animationType = 'spinner') {
103
- const baseStyles = this.getBaseStyles();
104
- const animationStyles = this.getAnimationStyles(animationType);
105
- const animationHTML = this.getAnimationHTML(animationType);
106
-
107
- return `<!DOCTYPE html>
108
- <html>
109
- <head>
110
- <meta charset="UTF-8">
111
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
112
- <title>正在加载管理后台...</title>
113
- <style>
114
- ${baseStyles}
115
- ${animationStyles}
116
- </style>
117
- </head>
118
- <body>
119
- <div class="loading-container">
120
- <div class="loading-text">正在加载管理后台...</div>
121
- ${animationHTML}
122
- </div>
123
-
124
- <script>
125
- // 模拟进度更新(如果动画类型支持)
126
- const progressBar = document.querySelector('.progress-bar');
127
- if (progressBar) {
128
- let progress = 0;
129
- const progressFill = document.querySelector('.progress-fill');
130
- const interval = setInterval(() => {
131
- progress += Math.random() * 10;
132
- if (progress > 90) {
133
- progress = 90;
134
- }
135
- if (progressFill) {
136
- progressFill.style.width = progress + '%';
137
- }
138
- }, 200);
139
- window.addEventListener('beforeunload', () => {
140
- clearInterval(interval);
141
- });
142
- }
143
- </script>
144
- </body>
145
- </html>`;
146
- }
147
-
148
- /**
149
- * 获取基础样式
150
- */
151
- getBaseStyles() {
152
- return `
153
- * {
154
- margin: 0;
155
- padding: 0;
156
- box-sizing: border-box;
157
- }
158
-
159
- body {
160
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
161
- background: #ffffff;
162
- display: flex;
163
- align-items: center;
164
- justify-content: center;
165
- height: 100vh;
166
- overflow: hidden;
167
- color: rgb(134, 134, 134);
168
- }
169
-
170
- .loading-container {
171
- text-align: center;
172
- padding: 60px 40px;
173
- background: #ffffff;
174
- border-radius: 16px;
175
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
176
- border: 1px solid rgb(200, 200, 200);
177
- max-width: 500px;
178
- width: 90%;
179
- }
180
-
181
- .loading-text {
182
- font-size: 14px;
183
- margin-bottom: 48px;
184
- color: rgb(134, 134, 134);
185
- font-weight: 400;
186
- letter-spacing: 0.5px;
187
- }
188
-
189
- .animation-wrapper {
190
- margin: 40px 0;
191
- display: flex;
192
- justify-content: center;
193
- align-items: center;
194
- }`;
195
- }
196
-
197
- /**
198
- * 获取动画样式
199
- */
200
- getAnimationStyles(animationType) {
201
- const styles = {
202
- spinner: `
203
- .spinner {
204
- width: 80px;
205
- height: 80px;
206
- margin: 0 auto;
207
- position: relative;
208
- }
209
-
210
- .spinner-ring {
211
- width: 100%;
212
- height: 100%;
213
- border: 5px solid rgba(200, 200, 200, 0.2);
214
- border-top-color: rgb(134, 134, 134);
215
- border-radius: 50%;
216
- animation: spin 1s linear infinite;
217
- }
218
-
219
- @keyframes spin {
220
- to { transform: rotate(360deg); }
221
- }`,
222
-
223
- dots: `
224
- .dots {
225
- display: flex;
226
- justify-content: center;
227
- gap: 12px;
228
- margin: 40px 0;
229
- }
230
-
231
- .dot {
232
- width: 16px;
233
- height: 16px;
234
- background: rgb(134, 134, 134);
235
- border-radius: 50%;
236
- animation: dotPulse 1.4s infinite ease-in-out;
237
- }
238
-
239
- .dot:nth-child(1) { animation-delay: -0.32s; }
240
- .dot:nth-child(2) { animation-delay: -0.16s; }
241
-
242
- @keyframes dotPulse {
243
- 0%, 80%, 100% {
244
- transform: scale(0.8);
245
- opacity: 0.5;
246
- }
247
- 40% {
248
- transform: scale(1.2);
249
- opacity: 1;
250
- }
251
- }`,
252
-
253
- wave: `
254
- .wave {
255
- display: flex;
256
- justify-content: center;
257
- align-items: center;
258
- gap: 6px;
259
- margin: 40px 0;
260
- height: 80px;
261
- }
262
-
263
- .wave-bar {
264
- width: 6px;
265
- height: 60px;
266
- background: rgb(134, 134, 134);
267
- border-radius: 3px;
268
- animation: wave 1.2s infinite ease-in-out;
269
- }
270
-
271
- .wave-bar:nth-child(1) { animation-delay: -0.4s; }
272
- .wave-bar:nth-child(2) { animation-delay: -0.3s; }
273
- .wave-bar:nth-child(3) { animation-delay: -0.2s; }
274
- .wave-bar:nth-child(4) { animation-delay: -0.1s; }
275
- .wave-bar:nth-child(5) { animation-delay: 0s; }
276
-
277
- @keyframes wave {
278
- 0%, 40%, 100% {
279
- transform: scaleY(0.4);
280
- opacity: 0.5;
281
- }
282
- 20% {
283
- transform: scaleY(1);
284
- opacity: 1;
285
- }
286
- }`,
287
-
288
- pulse: `
289
- .pulse {
290
- width: 100px;
291
- height: 100px;
292
- margin: 0 auto;
293
- position: relative;
294
- }
295
-
296
- .pulse-circle {
297
- width: 100%;
298
- height: 100%;
299
- border: 4px solid rgb(134, 134, 134);
300
- border-radius: 50%;
301
- position: absolute;
302
- animation: pulseRing 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
303
- }
304
-
305
- .pulse-circle:nth-child(2) {
306
- animation-delay: 0.5s;
307
- }
308
-
309
- .pulse-circle:nth-child(3) {
310
- animation-delay: 1s;
311
- }
312
-
313
- @keyframes pulseRing {
314
- 0% {
315
- transform: scale(0.8);
316
- opacity: 1;
317
- }
318
- 100% {
319
- transform: scale(1.8);
320
- opacity: 0;
321
- }
322
- }`,
323
-
324
- bars: `
325
- .bars {
326
- display: flex;
327
- justify-content: center;
328
- align-items: flex-end;
329
- gap: 5px;
330
- margin: 40px 0;
331
- height: 80px;
332
- }
333
-
334
- .bar {
335
- width: 8px;
336
- background: rgb(134, 134, 134);
337
- border-radius: 4px;
338
- animation: barBounce 1.4s infinite ease-in-out;
339
- }
340
-
341
- .bar:nth-child(1) { height: 30px; animation-delay: -0.32s; }
342
- .bar:nth-child(2) { height: 55px; animation-delay: -0.16s; }
343
- .bar:nth-child(3) { height: 80px; animation-delay: 0s; }
344
- .bar:nth-child(4) { height: 55px; animation-delay: 0.16s; }
345
- .bar:nth-child(5) { height: 30px; animation-delay: 0.32s; }
346
-
347
- @keyframes barBounce {
348
- 0%, 80%, 100% {
349
- transform: scaleY(0.5);
350
- opacity: 0.7;
351
- }
352
- 40% {
353
- transform: scaleY(1);
354
- opacity: 1;
355
- }
356
- }`,
357
-
358
- gradient: `
359
- .gradient-loader {
360
- width: 100px;
361
- height: 100px;
362
- margin: 0 auto;
363
- border-radius: 50%;
364
- background: linear-gradient(45deg,
365
- rgb(134, 134, 134) 0%,
366
- rgba(134, 134, 134, 0.3) 50%,
367
- rgb(134, 134, 134) 100%);
368
- background-size: 200% 200%;
369
- animation: gradientMove 2s ease infinite;
370
- }
371
-
372
- @keyframes gradientMove {
373
- 0% {
374
- background-position: 0% 50%;
375
- }
376
- 50% {
377
- background-position: 100% 50%;
378
- }
379
- 100% {
380
- background-position: 0% 50%;
381
- }
382
- }`,
383
-
384
- orbit: `
385
- .orbit {
386
- width: 100px;
387
- height: 100px;
388
- margin: 0 auto;
389
- position: relative;
390
- }
391
-
392
- .orbit-dot {
393
- width: 16px;
394
- height: 16px;
395
- background: rgb(134, 134, 134);
396
- border-radius: 50%;
397
- position: absolute;
398
- top: 0;
399
- left: 50%;
400
- transform: translateX(-50%);
401
- animation: orbitRotate 1.5s linear infinite;
402
- }
403
-
404
- .orbit-dot:nth-child(2) {
405
- animation-delay: 0.5s;
406
- }
407
-
408
- .orbit-dot:nth-child(3) {
409
- animation-delay: 1s;
410
- }
411
-
412
- @keyframes orbitRotate {
413
- 0% {
414
- transform: translateX(-50%) rotate(0deg) translateY(0);
415
- }
416
- 100% {
417
- transform: translateX(-50%) rotate(360deg) translateY(0);
418
- }
419
- }`,
420
-
421
- ripple: `
422
- .ripple {
423
- width: 100px;
424
- height: 100px;
425
- margin: 0 auto;
426
- position: relative;
427
- }
428
-
429
- .ripple-circle {
430
- width: 100%;
431
- height: 100%;
432
- border: 3px solid rgb(134, 134, 134);
433
- border-radius: 50%;
434
- position: absolute;
435
- animation: rippleExpand 1.5s cubic-bezier(0, 0, 0.2, 1) infinite;
436
- }
437
-
438
- .ripple-circle:nth-child(2) {
439
- animation-delay: 0.5s;
440
- }
441
-
442
- .ripple-circle:nth-child(3) {
443
- animation-delay: 1s;
444
- }
445
-
446
- @keyframes rippleExpand {
447
- 0% {
448
- transform: scale(0.8);
449
- opacity: 1;
450
- }
451
- 100% {
452
- transform: scale(1.8);
453
- opacity: 0;
454
- }
455
- }`
456
- };
457
-
458
- // 添加进度条样式(所有动画共用)
459
- const progressBarStyle = `
460
- .progress-bar {
461
- width: 100%;
462
- height: 3px;
463
- background: rgba(200, 200, 200, 0.3);
464
- border-radius: 2px;
465
- margin-top: 48px;
466
- overflow: hidden;
467
- }
468
-
469
- .progress-fill {
470
- height: 100%;
471
- background: rgb(134, 134, 134);
472
- border-radius: 2px;
473
- animation: progress 2s ease-in-out infinite;
474
- width: 60%;
475
- }
476
-
477
- @keyframes progress {
478
- 0% { transform: translateX(-100%); }
479
- 50% { transform: translateX(0%); }
480
- 100% { transform: translateX(100%); }
481
- }`;
482
-
483
- return (styles[animationType] || styles.spinner) + progressBarStyle;
484
- }
485
-
486
- /**
487
- * 获取动画HTML
488
- */
489
- getAnimationHTML(animationType) {
490
- const htmls = {
491
- spinner: `
492
- <div class="animation-wrapper">
493
- <div class="spinner">
494
- <div class="spinner-ring"></div>
495
- </div>
496
- </div>
497
- <div class="progress-bar">
498
- <div class="progress-fill"></div>
499
- </div>`,
500
-
501
- dots: `
502
- <div class="dots">
503
- <div class="dot"></div>
504
- <div class="dot"></div>
505
- <div class="dot"></div>
506
- </div>
507
- <div class="progress-bar">
508
- <div class="progress-fill"></div>
509
- </div>`,
510
-
511
- wave: `
512
- <div class="wave">
513
- <div class="wave-bar"></div>
514
- <div class="wave-bar"></div>
515
- <div class="wave-bar"></div>
516
- <div class="wave-bar"></div>
517
- <div class="wave-bar"></div>
518
- </div>
519
- <div class="progress-bar">
520
- <div class="progress-fill"></div>
521
- </div>`,
522
-
523
- pulse: `
524
- <div class="animation-wrapper">
525
- <div class="pulse">
526
- <div class="pulse-circle"></div>
527
- <div class="pulse-circle"></div>
528
- <div class="pulse-circle"></div>
529
- </div>
530
- </div>
531
- <div class="progress-bar">
532
- <div class="progress-fill"></div>
533
- </div>`,
534
-
535
- bars: `
536
- <div class="bars">
537
- <div class="bar"></div>
538
- <div class="bar"></div>
539
- <div class="bar"></div>
540
- <div class="bar"></div>
541
- <div class="bar"></div>
542
- </div>
543
- <div class="progress-bar">
544
- <div class="progress-fill"></div>
545
- </div>`,
546
-
547
- gradient: `
548
- <div class="animation-wrapper">
549
- <div class="gradient-loader"></div>
550
- </div>
551
- <div class="progress-bar">
552
- <div class="progress-fill"></div>
553
- </div>`,
554
-
555
- orbit: `
556
- <div class="animation-wrapper">
557
- <div class="orbit">
558
- <div class="orbit-dot"></div>
559
- <div class="orbit-dot"></div>
560
- <div class="orbit-dot"></div>
561
- </div>
562
- </div>
563
- <div class="progress-bar">
564
- <div class="progress-fill"></div>
565
- </div>`,
566
-
567
- ripple: `
568
- <div class="animation-wrapper">
569
- <div class="ripple">
570
- <div class="ripple-circle"></div>
571
- <div class="ripple-circle"></div>
572
- <div class="ripple-circle"></div>
573
- </div>
574
- </div>
575
- <div class="progress-bar">
576
- <div class="progress-fill"></div>
577
- </div>`
578
- };
579
-
580
- return htmls[animationType] || htmls.spinner;
581
- }
582
-
583
- /**
584
- * 设置窗口事件
585
- * @param {string} adminUrl - 管理后台URL
586
- */
587
- setupWindowEvents(adminUrl) {
588
- if (!this.adminWindow) return;
589
-
590
- // 监听页面开始加载
591
- this.adminWindow.webContents.on('did-start-loading', () => {
592
- this.logger.debug('Admin page started loading');
593
- });
594
-
595
- // 监听页面加载完成
596
- this.adminWindow.webContents.on('did-finish-load', () => {
597
- this.logger.info('Admin page finished loading');
598
- // 页面加载完成后,窗口会自动显示实际内容
599
- });
600
-
601
- // 监听页面加载失败
602
- this.adminWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL) => {
603
- this.logger.error('Admin page failed to load', {
604
- errorCode,
605
- errorDescription,
606
- url: validatedURL
607
- });
608
-
609
- // 显示错误页面
610
- this.showErrorPage(errorDescription, validatedURL);
611
- });
612
-
613
- // 监听窗口关闭
614
- this.adminWindow.on('closed', () => {
615
- this.adminWindow = null;
616
- this.logger.info('Admin window closed');
617
- });
618
-
619
- // 延迟加载实际URL,给加载页面一些显示时间
620
- setTimeout(() => {
621
- if (this.adminWindow && !this.adminWindow.isDestroyed()) {
622
- this.logger.info('Loading admin URL', { url: adminUrl });
623
- this.adminWindow.loadURL(adminUrl);
624
- }
625
- }, 500); // 500ms延迟,让用户看到加载动画
626
- }
627
-
628
- /**
629
- * 显示错误页面
630
- * @param {string} errorDescription - 错误描述
631
- * @param {string} url - 失败的URL
632
- */
633
- showErrorPage(errorDescription, url) {
634
- if (!this.adminWindow || this.adminWindow.isDestroyed()) {
635
- return;
636
- }
637
-
638
- const htmlContent = `<!DOCTYPE html>
639
- <html>
640
- <head>
641
- <meta charset="UTF-8">
642
- <title>加载失败</title>
643
- <style>
644
- * {
645
- margin: 0;
646
- padding: 0;
647
- box-sizing: border-box;
648
- }
649
-
650
- body {
651
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
652
- background: #f5f5f5;
653
- display: flex;
654
- align-items: center;
655
- justify-content: center;
656
- height: 100vh;
657
- color: #333;
658
- }
659
-
660
- .error-container {
661
- text-align: center;
662
- padding: 40px;
663
- background: white;
664
- border-radius: 12px;
665
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
666
- max-width: 500px;
667
- width: 90%;
668
- }
669
-
670
- .error-icon {
671
- font-size: 64px;
672
- margin-bottom: 24px;
673
- }
674
-
675
- .error-title {
676
- font-size: 24px;
677
- font-weight: 600;
678
- margin-bottom: 16px;
679
- color: #e74c3c;
680
- }
681
-
682
- .error-message {
683
- font-size: 14px;
684
- color: #666;
685
- margin-bottom: 8px;
686
- line-height: 1.6;
687
- }
688
-
689
- .error-url {
690
- font-size: 12px;
691
- color: #999;
692
- word-break: break-all;
693
- margin-top: 16px;
694
- padding: 12px;
695
- background: #f9f9f9;
696
- border-radius: 6px;
697
- }
698
-
699
- .retry-button {
700
- margin-top: 24px;
701
- padding: 12px 24px;
702
- background: #667eea;
703
- color: white;
704
- border: none;
705
- border-radius: 6px;
706
- font-size: 14px;
707
- cursor: pointer;
708
- transition: background 0.2s;
709
- }
710
-
711
- .retry-button:hover {
712
- background: #5568d3;
713
- }
714
- </style>
715
- </head>
716
- <body>
717
- <div class="error-container">
718
- <div class="error-icon">⚠️</div>
719
- <div class="error-title">无法加载管理后台</div>
720
- <div class="error-message">${errorDescription || '页面加载失败'}</div>
721
- <div class="error-url">${url || ''}</div>
722
- <button class="retry-button" onclick="window.location.reload()">重试</button>
723
- </div>
724
- </body>
725
- </html>`;
726
-
727
- this.adminWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(htmlContent)}`);
728
- }
729
-
730
- /**
731
- * 关闭管理后台窗口
732
- */
733
- closeAdminWindow() {
734
- if (this.adminWindow && !this.adminWindow.isDestroyed()) {
735
- this.adminWindow.close();
736
- this.adminWindow = null;
737
- this.logger.info('Admin window closed');
738
- }
739
- }
740
-
741
- /**
742
- * 检查窗口是否存在
743
- */
744
- hasWindow() {
745
- return this.adminWindow && !this.adminWindow.isDestroyed();
746
- }
747
-
748
- /**
749
- * 获取窗口实例
750
- */
751
- getWindow() {
752
- return this.adminWindow;
753
- }
754
- }
755
-
756
- module.exports = AdminWindowManager;
757
-