@zhin.js/client 1.0.0 → 1.0.2

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 (43) hide show
  1. package/README.md +334 -67
  2. package/app/index.html +4 -3
  3. package/app/postcss.config.js +5 -0
  4. package/app/src/components/ThemeToggle.tsx +21 -0
  5. package/app/src/hooks/useTheme.ts +17 -0
  6. package/app/src/layouts/dashboard.tsx +259 -0
  7. package/app/src/main.tsx +121 -0
  8. package/app/src/pages/dashboard-bots.tsx +198 -0
  9. package/app/src/pages/dashboard-home.tsx +301 -0
  10. package/app/src/pages/dashboard-logs.tsx +298 -0
  11. package/app/src/pages/dashboard-plugin-detail.tsx +360 -0
  12. package/app/src/pages/dashboard-plugins.tsx +166 -0
  13. package/app/src/style.css +1105 -0
  14. package/app/src/theme/index.ts +92 -0
  15. package/app/tailwind.config.js +70 -0
  16. package/app/tsconfig.json +5 -0
  17. package/dist/index.js +15 -3
  18. package/package.json +20 -7
  19. package/src/index.ts +19 -3
  20. package/src/router/index.tsx +55 -0
  21. package/src/store/index.ts +111 -0
  22. package/src/store/reducers/index.ts +16 -0
  23. package/src/store/reducers/route.ts +122 -0
  24. package/src/store/reducers/script.ts +103 -0
  25. package/src/store/reducers/ui.ts +31 -0
  26. package/src/types.ts +11 -17
  27. package/src/websocket/index.ts +193 -0
  28. package/src/websocket/useWebSocket.ts +42 -0
  29. package/app/components.d.ts +0 -33
  30. package/app/src/App.vue +0 -7
  31. package/app/src/main.ts +0 -127
  32. package/app/src/pages/$.vue +0 -899
  33. package/app/src/pages/404.vue +0 -11
  34. package/app/src/pages/contexts/overview.vue +0 -177
  35. package/app/src/pages/dashboard.vue +0 -323
  36. package/app/src/pages/plugins/installed.vue +0 -734
  37. package/app/src/pages/system/status.vue +0 -241
  38. package/app/src/services/api.ts +0 -155
  39. package/app/src/styles/README.md +0 -202
  40. package/app/src/styles/common.css +0 -0
  41. package/global.d.ts +0 -19
  42. package/src/router.ts +0 -44
  43. package/src/store.ts +0 -53
@@ -0,0 +1,1105 @@
1
+ @import "tailwindcss";
2
+ @config "../tailwind.config.js";
3
+
4
+ /* ============================================
5
+ Radix UI Themes - 主题定制
6
+ 基于官方文档: https://www.radix-ui.com/themes/docs/overview/getting-started
7
+ ============================================ */
8
+
9
+ /* ============================================
10
+ 自定义 CSS Tokens (全局变量)
11
+ Radix UI Themes 使用 CSS 变量系统
12
+ ============================================ */
13
+
14
+ :root,
15
+ .light,
16
+ .light-theme {
17
+ /* 动画和过渡 */
18
+ --transition-duration: 200ms;
19
+ --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
20
+
21
+ /* 自定义阴影增强 */
22
+ --shadow-1: 0 1px 2px 0 rgb(0 0 0 / 0.05);
23
+ --shadow-2: 0 2px 4px -1px rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.04);
24
+ --shadow-3: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.06);
25
+ --shadow-4: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.05);
26
+ --shadow-5: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.04);
27
+
28
+ /* Glassmorphism 效果 */
29
+ --glass-bg: rgba(255, 255, 255, 0.75);
30
+ --glass-border: rgba(255, 255, 255, 0.2);
31
+ --glass-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.1);
32
+
33
+ /* 自定义渐变 */
34
+ --gradient-primary: linear-gradient(135deg, var(--accent-9) 0%, var(--purple-9) 100%);
35
+ --gradient-success: linear-gradient(135deg, var(--green-9) 0%, var(--teal-9) 100%);
36
+ --gradient-warning: linear-gradient(135deg, var(--amber-9) 0%, var(--orange-9) 100%);
37
+ --gradient-danger: linear-gradient(135deg, var(--red-9) 0%, var(--crimson-9) 100%);
38
+ --gradient-info: linear-gradient(135deg, var(--blue-9) 0%, var(--cyan-9) 100%);
39
+ }
40
+
41
+ .dark,
42
+ .dark-theme {
43
+ /* 暗色模式下的 Glassmorphism */
44
+ --glass-bg: rgba(0, 0, 0, 0.5);
45
+ --glass-border: rgba(255, 255, 255, 0.1);
46
+ --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
47
+
48
+ /* 暗色模式阴影增强 */
49
+ --shadow-1: 0 1px 2px 0 rgb(0 0 0 / 0.3);
50
+ --shadow-2: 0 2px 4px -1px rgb(0 0 0 / 0.4), 0 1px 2px -1px rgb(0 0 0 / 0.2);
51
+ --shadow-3: 0 4px 6px -1px rgb(0 0 0 / 0.5), 0 2px 4px -2px rgb(0 0 0 / 0.3);
52
+ --shadow-4: 0 10px 15px -3px rgb(0 0 0 / 0.6), 0 4px 6px -4px rgb(0 0 0 / 0.4);
53
+ --shadow-5: 0 20px 25px -5px rgb(0 0 0 / 0.7), 0 8px 10px -6px rgb(0 0 0 / 0.5);
54
+ }
55
+
56
+ /* ============================================
57
+ 全局样式优化
58
+ ============================================ */
59
+
60
+ * {
61
+ -webkit-font-smoothing: antialiased;
62
+ -moz-osx-font-smoothing: grayscale;
63
+ }
64
+
65
+ html {
66
+ scroll-behavior: smooth;
67
+ }
68
+
69
+ body {
70
+ font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
71
+ }
72
+
73
+ /* ============================================
74
+ 滚动条美化 (适配明暗主题)
75
+ ============================================ */
76
+
77
+ ::-webkit-scrollbar {
78
+ width: 10px;
79
+ height: 10px;
80
+ }
81
+
82
+ ::-webkit-scrollbar-track {
83
+ background: var(--gray-3);
84
+ border-radius: var(--radius-2);
85
+ }
86
+
87
+ ::-webkit-scrollbar-thumb {
88
+ background: var(--gray-8);
89
+ border-radius: var(--radius-2);
90
+ border: 2px solid var(--gray-3);
91
+ transition: background var(--transition-duration) var(--transition-timing);
92
+ }
93
+
94
+ ::-webkit-scrollbar-thumb:hover {
95
+ background: var(--gray-10);
96
+ }
97
+
98
+ /* ============================================
99
+ Radix UI 组件微调
100
+ 使用 data-* 选择器覆盖,保持 Radix 原生样式
101
+ ============================================ */
102
+
103
+ /* Card - 卡片增强 */
104
+ .rt-Card {
105
+ transition: all var(--transition-duration) var(--transition-timing);
106
+ }
107
+
108
+ .rt-Card[data-accent-color]:hover {
109
+ box-shadow: var(--shadow-3);
110
+ transform: translateY(-2px);
111
+ }
112
+
113
+ /* Button - 按钮微动效 */
114
+ .rt-Button {
115
+ transition: all var(--transition-duration) var(--transition-timing);
116
+ font-weight: 500;
117
+ }
118
+
119
+ .rt-Button:not(:disabled):hover {
120
+ transform: translateY(-1px);
121
+ box-shadow: var(--shadow-2);
122
+ }
123
+
124
+ .rt-Button:not(:disabled):active {
125
+ transform: translateY(0);
126
+ box-shadow: var(--shadow-1);
127
+ }
128
+
129
+ .rt-Button:disabled {
130
+ opacity: 0.5;
131
+ cursor: not-allowed;
132
+ }
133
+
134
+ /* TextField - 输入框聚焦增强 */
135
+ .rt-TextFieldInput,
136
+ .rt-TextAreaInput {
137
+ transition: all var(--transition-duration) var(--transition-timing);
138
+ }
139
+
140
+ .rt-TextFieldInput:focus-visible,
141
+ .rt-TextAreaInput:focus-visible {
142
+ box-shadow: 0 0 0 3px var(--accent-a5);
143
+ outline: none;
144
+ }
145
+
146
+ /* Badge - 徽章微动效 */
147
+ .rt-Badge {
148
+ font-weight: 600;
149
+ transition: transform var(--transition-duration) var(--transition-timing);
150
+ }
151
+
152
+ .rt-Badge:hover {
153
+ transform: scale(1.05);
154
+ }
155
+
156
+ /* Select - 选择器增强 */
157
+ .rt-SelectTrigger {
158
+ transition: all var(--transition-duration) var(--transition-timing);
159
+ }
160
+
161
+ .rt-SelectTrigger:hover:not([data-disabled]) {
162
+ background-color: var(--gray-a3);
163
+ }
164
+
165
+ .rt-SelectContent {
166
+ box-shadow: var(--shadow-5);
167
+ animation: slideDownAndFade 200ms cubic-bezier(0.16, 1, 0.3, 1);
168
+ }
169
+
170
+ /* Checkbox - 复选框增强 */
171
+ .rt-CheckboxButton {
172
+ transition: all var(--transition-duration) var(--transition-timing);
173
+ }
174
+
175
+ .rt-CheckboxButton:hover:not([data-disabled]) {
176
+ background-color: var(--accent-a3);
177
+ }
178
+
179
+ /* Switch - 开关增强 */
180
+ .rt-SwitchButton {
181
+ transition: all var(--transition-duration) var(--transition-timing);
182
+ }
183
+
184
+ .rt-SwitchButton:hover:not([data-disabled]) {
185
+ box-shadow: var(--shadow-2);
186
+ }
187
+
188
+ /* Tabs - 标签页增强 */
189
+ .rt-TabsList {
190
+ background-color: var(--gray-a2);
191
+ padding: 4px;
192
+ border-radius: calc(var(--radius-3) + 2px);
193
+ }
194
+
195
+ .rt-TabsTrigger {
196
+ transition: all var(--transition-duration) var(--transition-timing);
197
+ font-weight: 500;
198
+ }
199
+
200
+ .rt-TabsTrigger[data-state="active"] {
201
+ box-shadow: var(--shadow-1);
202
+ }
203
+
204
+ /* Dialog - 对话框动画 */
205
+ .rt-DialogContent {
206
+ animation: contentShow 200ms cubic-bezier(0.16, 1, 0.3, 1);
207
+ }
208
+
209
+ /* DropdownMenu - 下拉菜单动画 */
210
+ .rt-DropdownMenuContent {
211
+ animation: slideDownAndFade 200ms cubic-bezier(0.16, 1, 0.3, 1);
212
+ box-shadow: var(--shadow-5);
213
+ }
214
+
215
+ /* Popover - 弹出框动画 */
216
+ .rt-PopoverContent {
217
+ animation: slideDownAndFade 200ms cubic-bezier(0.16, 1, 0.3, 1);
218
+ box-shadow: var(--shadow-4);
219
+ }
220
+
221
+ /* Tooltip - 工具提示 */
222
+ .rt-TooltipContent {
223
+ animation: slideDownAndFade 150ms cubic-bezier(0.16, 1, 0.3, 1);
224
+ box-shadow: var(--shadow-3);
225
+ }
226
+
227
+ /* Separator - 分隔线增强 */
228
+ .rt-Separator[data-orientation="horizontal"] {
229
+ background: linear-gradient(
230
+ 90deg,
231
+ transparent,
232
+ var(--gray-a6) 20%,
233
+ var(--gray-a6) 80%,
234
+ transparent
235
+ );
236
+ }
237
+
238
+ .rt-Separator[data-orientation="vertical"] {
239
+ background: linear-gradient(
240
+ 180deg,
241
+ transparent,
242
+ var(--gray-a6) 20%,
243
+ var(--gray-a6) 80%,
244
+ transparent
245
+ );
246
+ }
247
+
248
+ /* ============================================
249
+ 自定义动画关键帧
250
+ ============================================ */
251
+
252
+ @keyframes slideDownAndFade {
253
+ from {
254
+ opacity: 0;
255
+ transform: translateY(-4px);
256
+ }
257
+ to {
258
+ opacity: 1;
259
+ transform: translateY(0);
260
+ }
261
+ }
262
+
263
+ @keyframes slideUpAndFade {
264
+ from {
265
+ opacity: 0;
266
+ transform: translateY(4px);
267
+ }
268
+ to {
269
+ opacity: 1;
270
+ transform: translateY(0);
271
+ }
272
+ }
273
+
274
+ @keyframes contentShow {
275
+ from {
276
+ opacity: 0;
277
+ transform: scale(0.96);
278
+ }
279
+ to {
280
+ opacity: 1;
281
+ transform: scale(1);
282
+ }
283
+ }
284
+
285
+ @keyframes fadeIn {
286
+ from {
287
+ opacity: 0;
288
+ }
289
+ to {
290
+ opacity: 1;
291
+ }
292
+ }
293
+
294
+ @keyframes pulse {
295
+ 0%, 100% {
296
+ opacity: 1;
297
+ }
298
+ 50% {
299
+ opacity: 0.5;
300
+ }
301
+ }
302
+
303
+ /* ============================================
304
+ 工具类 (与 Tailwind 配合使用)
305
+ ============================================ */
306
+
307
+ /* Glassmorphism 效果 */
308
+ .glass {
309
+ background: var(--glass-bg) !important;
310
+ backdrop-filter: blur(12px) saturate(180%);
311
+ -webkit-backdrop-filter: blur(12px) saturate(180%);
312
+ border: 1px solid var(--glass-border);
313
+ box-shadow: var(--glass-shadow);
314
+ }
315
+
316
+ /* 渐变背景 */
317
+ .gradient-primary {
318
+ background: var(--gradient-primary);
319
+ color: white;
320
+ }
321
+
322
+ .gradient-success {
323
+ background: var(--gradient-success);
324
+ color: white;
325
+ }
326
+
327
+ .gradient-warning {
328
+ background: var(--gradient-warning);
329
+ color: white;
330
+ }
331
+
332
+ .gradient-danger {
333
+ background: var(--gradient-danger);
334
+ color: white;
335
+ }
336
+
337
+ .gradient-info {
338
+ background: var(--gradient-info);
339
+ color: white;
340
+ }
341
+
342
+ /* 文本渐变 */
343
+ .text-gradient {
344
+ background: var(--gradient-primary);
345
+ -webkit-background-clip: text;
346
+ -webkit-text-fill-color: transparent;
347
+ background-clip: text;
348
+ }
349
+
350
+ /* 悬停提升效果 */
351
+ .hover-lift {
352
+ transition: transform var(--transition-duration) var(--transition-timing),
353
+ box-shadow var(--transition-duration) var(--transition-timing);
354
+ }
355
+
356
+ .hover-lift:hover {
357
+ transform: translateY(-4px);
358
+ box-shadow: var(--shadow-4);
359
+ }
360
+
361
+ /* 悬停发光效果 */
362
+ .hover-glow:hover {
363
+ box-shadow: 0 0 20px var(--accent-a5);
364
+ }
365
+
366
+ /* 平滑过渡 */
367
+ .transition-smooth {
368
+ transition: all var(--transition-duration) var(--transition-timing);
369
+ }
370
+
371
+ /* ============================================
372
+ 响应式优化
373
+ ============================================ */
374
+
375
+ @media (max-width: 768px) {
376
+ /* 移动端禁用悬停效果 */
377
+ .rt-Card[data-accent-color]:hover,
378
+ .rt-Button:not(:disabled):hover,
379
+ .hover-lift:hover {
380
+ transform: none;
381
+ }
382
+
383
+ /* 减小阴影 */
384
+ .rt-Card[data-accent-color]:hover {
385
+ box-shadow: var(--shadow-2);
386
+ }
387
+ }
388
+
389
+ /* ============================================
390
+ 无障碍优化
391
+ ============================================ */
392
+
393
+ /* 聚焦可见性增强 */
394
+ *:focus-visible {
395
+ outline: 2px solid var(--accent-9);
396
+ outline-offset: 2px;
397
+ border-radius: var(--radius-2);
398
+ }
399
+
400
+ /* 减少动画运动(用户偏好) */
401
+ @media (prefers-reduced-motion: reduce) {
402
+ *,
403
+ *::before,
404
+ *::after {
405
+ animation-duration: 0.01ms !important;
406
+ animation-iteration-count: 1 !important;
407
+ transition-duration: 0.01ms !important;
408
+ scroll-behavior: auto !important;
409
+ }
410
+ }
411
+
412
+ /* 高对比度模式 */
413
+ @media (prefers-contrast: high) {
414
+ .rt-Card,
415
+ .rt-Button,
416
+ .rt-Badge {
417
+ border-width: 2px;
418
+ }
419
+ }
420
+
421
+ /* ============================================
422
+ 打印样式
423
+ ============================================ */
424
+
425
+ @media print {
426
+ * {
427
+ animation: none !important;
428
+ transition: none !important;
429
+ box-shadow: none !important;
430
+ }
431
+
432
+ .rt-Card {
433
+ border: 1px solid var(--gray-6);
434
+ }
435
+
436
+ /* 隐藏不必要的元素 */
437
+ .rt-Button,
438
+ .no-print {
439
+ display: none;
440
+ }
441
+ }
442
+
443
+ /* ============================================
444
+ 深色模式特定优化
445
+ ============================================ */
446
+
447
+ .dark .rt-Card {
448
+ /* 暗色模式下卡片背景稍微提亮 */
449
+ background-color: var(--gray-2);
450
+ }
451
+
452
+ .dark .rt-Button[data-variant="solid"] {
453
+ /* 暗色模式下实心按钮对比度增强 */
454
+ box-shadow: var(--shadow-2);
455
+ }
456
+
457
+ /* ============================================
458
+ 性能优化
459
+ ============================================ */
460
+
461
+ /* GPU 加速 */
462
+ .rt-Card[data-accent-color],
463
+ .rt-Button,
464
+ .hover-lift {
465
+ will-change: transform;
466
+ }
467
+
468
+ /* 防止布局抖动 */
469
+ .rt-Button {
470
+ contain: layout style paint;
471
+ }
472
+
473
+ /* ============================================
474
+ Dashboard 统一风格样式
475
+ ============================================ */
476
+
477
+ /* 菜单项 / 频道项通用样式 */
478
+ .menu-item,
479
+ .channel-item {
480
+ display: flex;
481
+ align-items: center;
482
+ gap: 0.75rem;
483
+ padding: 0.75rem;
484
+ border-radius: calc(var(--radius-3) + 4px);
485
+ transition: all var(--transition-duration) var(--transition-timing);
486
+ cursor: pointer;
487
+ position: relative;
488
+ overflow: hidden;
489
+ text-decoration: none;
490
+ }
491
+
492
+ /* 默认状态 */
493
+ .menu-item:not(.active),
494
+ .channel-item:not(.active) {
495
+ color: var(--gray-11);
496
+ }
497
+
498
+ .dark .menu-item:not(.active),
499
+ .dark .channel-item:not(.active) {
500
+ color: var(--gray-11);
501
+ }
502
+
503
+ /* 悬停状态 */
504
+ .menu-item:not(.active):hover,
505
+ .channel-item:not(.active):hover {
506
+ background-color: var(--gray-a3);
507
+ }
508
+
509
+ .dark .menu-item:not(.active):hover,
510
+ .dark .channel-item:not(.active):hover {
511
+ background-color: var(--gray-a4);
512
+ }
513
+
514
+ /* 激活状态 - 渐变背景 */
515
+ .menu-item.active,
516
+ .channel-item.active {
517
+ background: linear-gradient(135deg, var(--blue-9) 0%, var(--purple-9) 100%);
518
+ color: white;
519
+ box-shadow: var(--shadow-3);
520
+ }
521
+
522
+ /* 图标容器 */
523
+ .menu-item .icon,
524
+ .channel-item .icon {
525
+ display: flex;
526
+ align-items: center;
527
+ justify-content: center;
528
+ flex-shrink: 0;
529
+ width: 1.25rem;
530
+ height: 1.25rem;
531
+ transition: transform var(--transition-duration) var(--transition-timing);
532
+ }
533
+
534
+ /* 图标悬停缩放 */
535
+ .menu-item:not(.active):hover .icon,
536
+ .channel-item:not(.active):hover .icon {
537
+ transform: scale(1.1);
538
+ }
539
+
540
+ /* 文本容器 */
541
+ .menu-item .text,
542
+ .channel-item .text {
543
+ flex: 1;
544
+ min-width: 0;
545
+ }
546
+
547
+ .menu-item .text .title,
548
+ .channel-item .text .title {
549
+ font-size: var(--font-size-2);
550
+ font-weight: 500;
551
+ white-space: nowrap;
552
+ overflow: hidden;
553
+ text-overflow: ellipsis;
554
+ }
555
+
556
+ .menu-item .text .subtitle,
557
+ .channel-item .text .subtitle {
558
+ font-size: var(--font-size-1);
559
+ color: var(--gray-a11);
560
+ white-space: nowrap;
561
+ overflow: hidden;
562
+ text-overflow: ellipsis;
563
+ }
564
+
565
+ .menu-item.active .text .subtitle,
566
+ .channel-item.active .text .subtitle {
567
+ color: rgba(255, 255, 255, 0.8);
568
+ }
569
+
570
+ /* 激活指示点 */
571
+ .menu-item.active .indicator,
572
+ .channel-item.active .indicator {
573
+ margin-left: auto;
574
+ flex-shrink: 0;
575
+ }
576
+
577
+ .menu-item.active .indicator::after,
578
+ .channel-item.active .indicator::after {
579
+ content: '';
580
+ display: block;
581
+ width: 0.375rem;
582
+ height: 0.375rem;
583
+ border-radius: 50%;
584
+ background-color: white;
585
+ }
586
+
587
+ /* 徽章位置 */
588
+ .menu-item .badge,
589
+ .channel-item .badge {
590
+ flex-shrink: 0;
591
+ }
592
+
593
+ /* 卡片统一风格 */
594
+ .dashboard-card {
595
+ background-color: white;
596
+ border: 1px solid var(--gray-a4);
597
+ border-radius: var(--radius-4);
598
+ box-shadow: var(--shadow-2);
599
+ transition: all var(--transition-duration) var(--transition-timing);
600
+ }
601
+
602
+ .dark .dashboard-card {
603
+ background-color: var(--gray-2);
604
+ border-color: var(--gray-a6);
605
+ }
606
+
607
+ .dashboard-card:hover {
608
+ box-shadow: var(--shadow-3);
609
+ transform: translateY(-2px);
610
+ }
611
+
612
+ /* 图标容器 - 圆形背景 */
613
+ .icon-container {
614
+ display: flex;
615
+ align-items: center;
616
+ justify-content: center;
617
+ flex-shrink: 0;
618
+ border-radius: var(--radius-3);
619
+ transition: all var(--transition-duration) var(--transition-timing);
620
+ }
621
+
622
+ .icon-container.sm {
623
+ width: 2rem;
624
+ height: 2rem;
625
+ padding: 0.375rem;
626
+ }
627
+
628
+ .icon-container.md {
629
+ width: 2.5rem;
630
+ height: 2.5rem;
631
+ padding: 0.5rem;
632
+ }
633
+
634
+ .icon-container.lg {
635
+ width: 3rem;
636
+ height: 3rem;
637
+ padding: 0.625rem;
638
+ }
639
+
640
+ /* 彩色图标背景 */
641
+ .icon-container.blue {
642
+ background-color: var(--blue-a3);
643
+ color: var(--blue-9);
644
+ }
645
+
646
+ .icon-container.green {
647
+ background-color: var(--green-a3);
648
+ color: var(--green-9);
649
+ }
650
+
651
+ .icon-container.purple {
652
+ background-color: var(--purple-a3);
653
+ color: var(--purple-9);
654
+ }
655
+
656
+ .icon-container.orange {
657
+ background-color: var(--orange-a3);
658
+ color: var(--orange-9);
659
+ }
660
+
661
+ .icon-container.red {
662
+ background-color: var(--red-a3);
663
+ color: var(--red-9);
664
+ }
665
+
666
+ /* 暗色模式下图标容器 */
667
+ .dark .icon-container.blue {
668
+ background-color: var(--blue-a4);
669
+ color: var(--blue-10);
670
+ }
671
+
672
+ .dark .icon-container.green {
673
+ background-color: var(--green-a4);
674
+ color: var(--green-10);
675
+ }
676
+
677
+ .dark .icon-container.purple {
678
+ background-color: var(--purple-a4);
679
+ color: var(--purple-10);
680
+ }
681
+
682
+ .dark .icon-container.orange {
683
+ background-color: var(--orange-a4);
684
+ color: var(--orange-10);
685
+ }
686
+
687
+ .dark .icon-container.red {
688
+ background-color: var(--red-a4);
689
+ color: var(--red-10);
690
+ }
691
+
692
+ /* 统计卡片 */
693
+ .stat-card {
694
+ display: flex;
695
+ flex-direction: column;
696
+ align-items: center;
697
+ justify-content: center;
698
+ gap: 0.5rem;
699
+ padding: 1rem;
700
+ border-radius: var(--radius-3);
701
+ transition: all var(--transition-duration) var(--transition-timing);
702
+ }
703
+
704
+ .stat-card:hover {
705
+ transform: scale(1.02);
706
+ }
707
+
708
+ /* 页面标题区域 */
709
+ .page-header {
710
+ display: flex;
711
+ justify-content: space-between;
712
+ align-items: center;
713
+ margin-bottom: 1.5rem;
714
+ }
715
+
716
+ .page-title {
717
+ font-size: var(--font-size-6);
718
+ font-weight: 600;
719
+ color: var(--gray-12);
720
+ margin: 0;
721
+ }
722
+
723
+ .dark .page-title {
724
+ color: var(--gray-12);
725
+ }
726
+
727
+ /* 空状态 */
728
+ .empty-state {
729
+ display: flex;
730
+ flex-direction: column;
731
+ align-items: center;
732
+ justify-content: center;
733
+ gap: 1rem;
734
+ padding: 3rem 1.5rem;
735
+ text-align: center;
736
+ color: var(--gray-a11);
737
+ }
738
+
739
+ .empty-state .icon {
740
+ width: 4rem;
741
+ height: 4rem;
742
+ display: flex;
743
+ align-items: center;
744
+ justify-content: center;
745
+ border-radius: 50%;
746
+ background-color: var(--gray-a3);
747
+ color: var(--gray-a10);
748
+ }
749
+
750
+ .empty-state .title {
751
+ font-size: var(--font-size-4);
752
+ font-weight: 600;
753
+ color: var(--gray-12);
754
+ margin: 0;
755
+ }
756
+
757
+ .empty-state .description {
758
+ font-size: var(--font-size-2);
759
+ color: var(--gray-a11);
760
+ margin: 0;
761
+ }
762
+
763
+ /* ============================================
764
+ ProcessSandbox 响应式布局
765
+ ============================================ */
766
+
767
+ /* 容器 */
768
+ .sandbox-container {
769
+ display: flex;
770
+ gap: 1rem;
771
+ padding: 1rem;
772
+ height: 100vh;
773
+ width: 100%;
774
+ max-width: 100vw;
775
+ position: relative;
776
+ overflow: hidden;
777
+ }
778
+
779
+ /* 频道侧边栏 */
780
+ .channel-sidebar {
781
+ width: 256px;
782
+ display: flex;
783
+ flex-direction: column;
784
+ flex-shrink: 0;
785
+ transition: transform var(--transition-duration) var(--transition-timing);
786
+ }
787
+
788
+ /* 聊天区域 */
789
+ .chat-area {
790
+ display: flex;
791
+ flex-direction: column;
792
+ gap: 0.75rem;
793
+ flex: 1;
794
+ min-width: 0;
795
+ height: 100%;
796
+ overflow: hidden;
797
+ }
798
+
799
+ /* 聊天区域内的卡片 */
800
+ .chat-area > .rt-Card:nth-child(1) {
801
+ /* 顶部信息栏 - 固定高度 */
802
+ flex-shrink: 0;
803
+ }
804
+
805
+ .chat-area > .rt-Card:nth-child(2) {
806
+ /* 消息列表 - 自动填充剩余空间 */
807
+ flex: 1;
808
+ min-height: 0;
809
+ display: flex;
810
+ flex-direction: column;
811
+ overflow: hidden;
812
+ }
813
+
814
+ .chat-area > .rt-Card:nth-child(3) {
815
+ /* 输入框区域 - 固定高度 */
816
+ flex-shrink: 0;
817
+ }
818
+
819
+ /* 富文本编辑器样式 */
820
+ .rich-text-editor {
821
+ font-family: inherit;
822
+ transition: border-color var(--transition-duration) var(--transition-timing);
823
+ }
824
+
825
+ .rich-text-editor:focus {
826
+ border-color: var(--blue-8) !important;
827
+ box-shadow: 0 0 0 1px var(--blue-8);
828
+ }
829
+
830
+ /* 空编辑器占位符 */
831
+ .rich-text-editor:empty::before {
832
+ content: attr(data-placeholder);
833
+ color: var(--gray-a9);
834
+ pointer-events: none;
835
+ }
836
+
837
+ /* 编辑器内的元素样式 */
838
+ .rich-text-editor .editor-face {
839
+ width: 24px;
840
+ height: 24px;
841
+ vertical-align: middle;
842
+ margin: 0 2px;
843
+ display: inline-block;
844
+ }
845
+
846
+ .rich-text-editor .editor-image {
847
+ max-width: 200px;
848
+ border-radius: 8px;
849
+ margin: 4px 0;
850
+ display: block;
851
+ }
852
+
853
+ .rich-text-editor .editor-at {
854
+ display: inline-flex;
855
+ align-items: center;
856
+ padding: 2px 6px;
857
+ background-color: var(--blue-a3);
858
+ color: var(--blue-11);
859
+ border-radius: 4px;
860
+ font-size: 0.9em;
861
+ margin: 0 2px;
862
+ user-select: none;
863
+ cursor: pointer;
864
+ transition: background-color 0.2s;
865
+ }
866
+
867
+ .rich-text-editor .editor-at:hover {
868
+ background-color: var(--blue-a4);
869
+ }
870
+
871
+ .rich-text-editor .editor-at-symbol {
872
+ font-weight: 600;
873
+ margin-right: 2px;
874
+ color: var(--blue-10);
875
+ }
876
+
877
+ .rich-text-editor .editor-at-name {
878
+ font-weight: 500;
879
+ }
880
+
881
+ /* 暗色模式 */
882
+ .dark .rich-text-editor {
883
+ background-color: var(--gray-2);
884
+ border-color: var(--gray-7);
885
+ color: var(--gray-12);
886
+ }
887
+
888
+ .dark .rich-text-editor:focus {
889
+ border-color: var(--blue-9) !important;
890
+ box-shadow: 0 0 0 1px var(--blue-9);
891
+ }
892
+
893
+ .dark .rich-text-editor:empty::before {
894
+ color: var(--gray-a8);
895
+ }
896
+
897
+ .dark .rich-text-editor .editor-at {
898
+ background-color: var(--blue-a4);
899
+ color: var(--blue-11);
900
+ }
901
+
902
+ .dark .rich-text-editor .editor-at:hover {
903
+ background-color: var(--blue-a5);
904
+ }
905
+
906
+ .dark .rich-text-editor .editor-at-symbol {
907
+ color: var(--blue-11);
908
+ }
909
+
910
+ /* 滚动条样式 */
911
+ .rich-text-editor::-webkit-scrollbar {
912
+ width: 6px;
913
+ }
914
+
915
+ .rich-text-editor::-webkit-scrollbar-thumb {
916
+ background: var(--gray-a6);
917
+ border-radius: var(--radius-2);
918
+ }
919
+
920
+ .rich-text-editor::-webkit-scrollbar-thumb:hover {
921
+ background: var(--gray-a8);
922
+ }
923
+
924
+ /* 移动端频道列表切换按钮 - 默认隐藏 */
925
+ .mobile-channel-toggle {
926
+ display: none;
927
+ }
928
+
929
+ /* 频道列表遮罩层 - 默认隐藏 */
930
+ .channel-overlay {
931
+ display: none;
932
+ }
933
+
934
+ /* ============================================
935
+ 移动端响应式 (< 768px)
936
+ ============================================ */
937
+
938
+ @media (max-width: 768px) {
939
+ /* 容器调整 */
940
+ .sandbox-container {
941
+ padding: 0;
942
+ gap: 0;
943
+ flex-direction: column;
944
+ height: 100vh;
945
+ }
946
+
947
+ /* 移动端频道列表切换按钮 */
948
+ .mobile-channel-toggle {
949
+ display: flex;
950
+ align-items: center;
951
+ justify-content: center;
952
+ gap: 0.5rem;
953
+ padding: 0.75rem 1rem;
954
+ margin: 0.5rem;
955
+ margin-bottom: 0.5rem;
956
+ background: var(--blue-9);
957
+ color: white;
958
+ border: none;
959
+ border-radius: var(--radius-3);
960
+ font-weight: 500;
961
+ font-size: var(--font-size-2);
962
+ cursor: pointer;
963
+ transition: all var(--transition-duration) var(--transition-timing);
964
+ box-shadow: var(--shadow-2);
965
+ }
966
+
967
+ .mobile-channel-toggle:active {
968
+ transform: scale(0.98);
969
+ box-shadow: var(--shadow-1);
970
+ }
971
+
972
+ /* 频道侧边栏 - 移动端默认隐藏,显示时从左侧滑入 */
973
+ .channel-sidebar {
974
+ position: fixed;
975
+ left: 0;
976
+ top: 0;
977
+ bottom: 0;
978
+ width: 280px;
979
+ max-width: 80vw;
980
+ transform: translateX(-100%);
981
+ z-index: 1000;
982
+ box-shadow: var(--shadow-5);
983
+ }
984
+
985
+ .channel-sidebar.show {
986
+ transform: translateX(0);
987
+ }
988
+
989
+ /* 遮罩层 */
990
+ .channel-overlay {
991
+ display: block;
992
+ position: fixed;
993
+ inset: 0;
994
+ background-color: rgba(0, 0, 0, 0.5);
995
+ z-index: 999;
996
+ animation: fadeIn 200ms ease-out;
997
+ }
998
+
999
+ /* 聊天区域调整 */
1000
+ .chat-area {
1001
+ flex: 1;
1002
+ gap: 0.5rem;
1003
+ padding: 0 0.5rem 0.5rem;
1004
+ height: auto;
1005
+ }
1006
+
1007
+ .chat-area > .rt-Card {
1008
+ margin: 0;
1009
+ }
1010
+
1011
+ /* 顶部信息栏 - 移动端简化 */
1012
+ .chat-area .rt-Card:first-child .rt-Flex {
1013
+ flex-direction: column;
1014
+ align-items: flex-start !important;
1015
+ gap: 0.75rem !important;
1016
+ }
1017
+
1018
+ /* 输入框区域 - 移动端调整 */
1019
+ .chat-area .rt-Card:last-child {
1020
+ margin-bottom: env(safe-area-inset-bottom, 0);
1021
+ }
1022
+
1023
+ /* 消息列表 - 减小间距 */
1024
+ .chat-area .rt-Card:nth-child(2) {
1025
+ flex: 1;
1026
+ min-height: 0;
1027
+ }
1028
+
1029
+ /* 工具栏按钮 - 移动端缩小 */
1030
+ .chat-area .rt-IconButton {
1031
+ width: 2rem;
1032
+ height: 2rem;
1033
+ }
1034
+
1035
+ /* 表情选择器 - 移动端全屏 */
1036
+ .chat-area .emoji-picker {
1037
+ position: fixed;
1038
+ inset: 0;
1039
+ max-height: none;
1040
+ border-radius: 0;
1041
+ }
1042
+
1043
+ /* 图片上传 - 移动端全屏 */
1044
+ .chat-area .image-upload {
1045
+ position: fixed;
1046
+ inset: 0;
1047
+ max-height: none;
1048
+ border-radius: 0;
1049
+ }
1050
+ }
1051
+
1052
+ /* ============================================
1053
+ 平板响应式 (768px - 1024px)
1054
+ ============================================ */
1055
+
1056
+ @media (min-width: 768px) and (max-width: 1024px) {
1057
+ .sandbox-container {
1058
+ padding: 0.75rem;
1059
+ gap: 0.75rem;
1060
+ }
1061
+
1062
+ .channel-sidebar {
1063
+ width: 200px;
1064
+ }
1065
+
1066
+ .chat-area {
1067
+ gap: 0.5rem;
1068
+ }
1069
+ }
1070
+
1071
+ /* ============================================
1072
+ 大屏优化 (> 1400px)
1073
+ ============================================ */
1074
+
1075
+ @media (min-width: 1400px) {
1076
+ .sandbox-container {
1077
+ padding: 1.5rem;
1078
+ gap: 1.5rem;
1079
+ }
1080
+
1081
+ .channel-sidebar {
1082
+ width: 280px;
1083
+ }
1084
+ }
1085
+
1086
+ /* ============================================
1087
+ Dashboard Container 内嵌适配
1088
+ 确保在 dashboard 的 Container 内正确显示
1089
+ ============================================ */
1090
+
1091
+ /* Dashboard 的 Container 组件会添加 padding,需要抵消 */
1092
+ .rt-Container .sandbox-container {
1093
+ margin: calc(-1 * var(--container-padding, 1.5rem));
1094
+ width: calc(100% + 2 * var(--container-padding, 1.5rem));
1095
+ max-width: none;
1096
+ height: calc(100vh - 4rem); /* 减去顶部导航栏高度 */
1097
+ }
1098
+
1099
+ @media (max-width: 768px) {
1100
+ .rt-Container .sandbox-container {
1101
+ margin: calc(-1 * var(--container-padding, 1rem));
1102
+ width: calc(100% + 2 * var(--container-padding, 1rem));
1103
+ height: calc(100vh - 3.5rem); /* 移动端导航栏稍矮 */
1104
+ }
1105
+ }