tabby-ai-assistant 1.0.7 → 1.0.9

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 (53) hide show
  1. package/README.md +0 -6
  2. package/dist/components/chat/ai-sidebar.component.d.ts +16 -3
  3. package/dist/components/chat/chat-input.component.d.ts +4 -0
  4. package/dist/components/chat/chat-interface.component.d.ts +22 -1
  5. package/dist/components/chat/chat-settings.component.d.ts +21 -11
  6. package/dist/components/settings/ai-settings-tab.component.d.ts +14 -4
  7. package/dist/components/settings/general-settings.component.d.ts +43 -12
  8. package/dist/components/settings/provider-config.component.d.ts +83 -5
  9. package/dist/components/settings/security-settings.component.d.ts +14 -4
  10. package/dist/i18n/index.d.ts +48 -0
  11. package/dist/i18n/translations/en-US.d.ts +5 -0
  12. package/dist/i18n/translations/ja-JP.d.ts +5 -0
  13. package/dist/i18n/translations/zh-CN.d.ts +5 -0
  14. package/dist/i18n/types.d.ts +198 -0
  15. package/dist/index.js +1 -1
  16. package/dist/services/chat/ai-sidebar.service.d.ts +23 -1
  17. package/dist/services/core/theme.service.d.ts +53 -0
  18. package/package.json +2 -2
  19. package/src/components/chat/ai-sidebar.component.scss +468 -0
  20. package/src/components/chat/ai-sidebar.component.ts +47 -344
  21. package/src/components/chat/chat-input.component.scss +2 -2
  22. package/src/components/chat/chat-input.component.ts +16 -5
  23. package/src/components/chat/chat-interface.component.html +11 -11
  24. package/src/components/chat/chat-interface.component.scss +410 -4
  25. package/src/components/chat/chat-interface.component.ts +105 -14
  26. package/src/components/chat/chat-message.component.scss +3 -3
  27. package/src/components/chat/chat-message.component.ts +3 -2
  28. package/src/components/chat/chat-settings.component.html +95 -61
  29. package/src/components/chat/chat-settings.component.scss +224 -50
  30. package/src/components/chat/chat-settings.component.ts +56 -30
  31. package/src/components/security/risk-confirm-dialog.component.scss +7 -7
  32. package/src/components/settings/ai-settings-tab.component.html +27 -27
  33. package/src/components/settings/ai-settings-tab.component.scss +34 -20
  34. package/src/components/settings/ai-settings-tab.component.ts +59 -20
  35. package/src/components/settings/general-settings.component.html +69 -40
  36. package/src/components/settings/general-settings.component.scss +151 -58
  37. package/src/components/settings/general-settings.component.ts +168 -55
  38. package/src/components/settings/provider-config.component.html +149 -60
  39. package/src/components/settings/provider-config.component.scss +273 -153
  40. package/src/components/settings/provider-config.component.ts +177 -19
  41. package/src/components/settings/security-settings.component.html +70 -39
  42. package/src/components/settings/security-settings.component.scss +104 -8
  43. package/src/components/settings/security-settings.component.ts +48 -10
  44. package/src/i18n/index.ts +129 -0
  45. package/src/i18n/translations/en-US.ts +193 -0
  46. package/src/i18n/translations/ja-JP.ts +193 -0
  47. package/src/i18n/translations/zh-CN.ts +193 -0
  48. package/src/i18n/types.ts +224 -0
  49. package/src/index.ts +6 -0
  50. package/src/services/chat/ai-sidebar.service.ts +157 -5
  51. package/src/services/core/theme.service.ts +480 -0
  52. package/src/styles/ai-assistant.scss +8 -88
  53. package/src/styles/themes.scss +161 -0
@@ -0,0 +1,480 @@
1
+ /**
2
+ * 主题服务 - 统一管理所有 AI 助手主题
3
+ * 通过动态 <style> 注入实现主题切换
4
+ */
5
+ import { Injectable, OnDestroy } from '@angular/core';
6
+ import { Subject, Subscription } from 'rxjs';
7
+ import { debounceTime } from 'rxjs/operators';
8
+ import { ConfigService } from 'tabby-core';
9
+ import { ConfigProviderService } from './config-provider.service';
10
+
11
+ export type ThemeType = 'auto' | 'light' | 'dark' | 'pixel' | 'tech';
12
+
13
+ // 主题变量定义
14
+ const THEME_VARIABLES: Record<Exclude<ThemeType, 'auto'>, Record<string, string>> = {
15
+ light: {
16
+ // 主色调
17
+ 'ai-primary': '#007bff',
18
+ 'ai-primary-hover': '#0056b3',
19
+ 'ai-secondary': '#6c757d',
20
+ 'ai-success': '#28a745',
21
+ 'ai-warning': '#ffc107',
22
+ 'ai-danger': '#dc3545',
23
+ 'ai-info': '#17a2b8',
24
+ // 风险级别颜色
25
+ 'ai-risk-low': '#28a745',
26
+ 'ai-risk-medium': '#ffc107',
27
+ 'ai-risk-high': '#fd7e14',
28
+ 'ai-risk-critical': '#dc3545',
29
+ // 聊天消息颜色
30
+ 'ai-user-message': '#e3f2fd',
31
+ 'ai-assistant-message': '#f5f5f5',
32
+ 'ai-system-message': '#fff3cd',
33
+ // 背景和边框
34
+ 'ai-bg-primary': '#ffffff',
35
+ 'ai-bg-secondary': '#f8f9fa',
36
+ 'ai-bg-tertiary': '#e9ecef',
37
+ 'ai-text-primary': '#212529',
38
+ 'ai-text-secondary': '#6c757d',
39
+ 'ai-border': '#dee2e6',
40
+ 'ai-border-radius': '0.375rem',
41
+ 'ai-box-shadow': '0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)',
42
+ // 字体
43
+ 'ai-font-family': "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
44
+ 'ai-font-size-base': '14px',
45
+ // 其他
46
+ 'ai-dark': '#212529',
47
+ 'ai-light': '#f8f9fa',
48
+ 'ai-transition-duration': '0.3s'
49
+ },
50
+ dark: {
51
+ // 主色调
52
+ 'ai-primary': '#4dabf7',
53
+ 'ai-primary-hover': '#339af0',
54
+ 'ai-secondary': '#adb5bd',
55
+ 'ai-success': '#51cf66',
56
+ 'ai-warning': '#fcc419',
57
+ 'ai-danger': '#ff6b6b',
58
+ 'ai-info': '#22b8cf',
59
+ // 风险级别颜色
60
+ 'ai-risk-low': '#51cf66',
61
+ 'ai-risk-medium': '#fcc419',
62
+ 'ai-risk-high': '#ff922b',
63
+ 'ai-risk-critical': '#ff6b6b',
64
+ // 聊天消息颜色
65
+ 'ai-user-message': '#1e3a5f',
66
+ 'ai-assistant-message': '#2d3748',
67
+ 'ai-system-message': '#3a3a3a',
68
+ // 背景和边框
69
+ 'ai-bg-primary': '#1a1a1a',
70
+ 'ai-bg-secondary': '#2d2d2d',
71
+ 'ai-bg-tertiary': '#3d3d3d',
72
+ 'ai-text-primary': '#f8f9fa',
73
+ 'ai-text-secondary': '#adb5bd',
74
+ 'ai-border': '#4a4a4a',
75
+ 'ai-border-radius': '0.375rem',
76
+ 'ai-box-shadow': '0 0.125rem 0.25rem rgba(0, 0, 0, 0.3)',
77
+ // 字体
78
+ 'ai-font-family': "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
79
+ 'ai-font-size-base': '14px',
80
+ // 其他
81
+ 'ai-dark': '#212529',
82
+ 'ai-light': '#f8f9fa',
83
+ 'ai-transition-duration': '0.3s'
84
+ },
85
+ pixel: {
86
+ // 主色调 - 经典 GameBoy 绿
87
+ 'ai-primary': '#9bbc0f',
88
+ 'ai-primary-hover': '#8bac0f',
89
+ 'ai-secondary': '#306230',
90
+ 'ai-success': '#9bbc0f',
91
+ 'ai-warning': '#ffeb3b',
92
+ 'ai-danger': '#f44336',
93
+ 'ai-info': '#03a9f4',
94
+ // 风险级别颜色
95
+ 'ai-risk-low': '#9bbc0f',
96
+ 'ai-risk-medium': '#ffeb3b',
97
+ 'ai-risk-high': '#ff9800',
98
+ 'ai-risk-critical': '#f44336',
99
+ // 聊天消息颜色
100
+ 'ai-user-message': '#0f380f',
101
+ 'ai-assistant-message': '#306230',
102
+ 'ai-system-message': '#1a1a1a',
103
+ // 背景和边框
104
+ 'ai-bg-primary': '#0f380f',
105
+ 'ai-bg-secondary': '#1a2a1a',
106
+ 'ai-bg-tertiary': '#306230',
107
+ 'ai-text-primary': '#9bbc0f',
108
+ 'ai-text-secondary': '#8bac0f',
109
+ 'ai-border': '#9bbc0f',
110
+ 'ai-border-radius': '0',
111
+ 'ai-box-shadow': '4px 4px 0 rgba(15, 56, 15, 0.8)',
112
+ // 字体 - 像素风格
113
+ 'ai-font-family': "'Courier New', 'Press Start 2P', monospace",
114
+ 'ai-font-size-base': '12px',
115
+ // 其他
116
+ 'ai-dark': '#0f380f',
117
+ 'ai-light': '#306230',
118
+ 'ai-transition-duration': '0s'
119
+ },
120
+ tech: {
121
+ // 主色调 - 霓虹赛博朋克
122
+ 'ai-primary': '#00fff9',
123
+ 'ai-primary-hover': '#00e6e0',
124
+ 'ai-secondary': '#adb5bd',
125
+ 'ai-success': '#00ff88',
126
+ 'ai-warning': '#ff00ff',
127
+ 'ai-danger': '#ff3366',
128
+ 'ai-info': '#00bfff',
129
+ // 风险级别颜色
130
+ 'ai-risk-low': '#00ff88',
131
+ 'ai-risk-medium': '#ff00ff',
132
+ 'ai-risk-high': '#ff6600',
133
+ 'ai-risk-critical': '#ff3366',
134
+ // 聊天消息颜色
135
+ 'ai-user-message': 'rgba(0, 255, 249, 0.1)',
136
+ 'ai-assistant-message': 'rgba(255, 0, 255, 0.1)',
137
+ 'ai-system-message': 'rgba(0, 255, 136, 0.1)',
138
+ // 背景和边框
139
+ 'ai-bg-primary': '#0a0a0f',
140
+ 'ai-bg-secondary': '#12121a',
141
+ 'ai-bg-tertiary': '#1a1a2e',
142
+ 'ai-text-primary': '#00fff9',
143
+ 'ai-text-secondary': 'rgba(0, 255, 249, 0.7)',
144
+ 'ai-border': 'rgba(0, 255, 249, 0.3)',
145
+ 'ai-border-radius': '4px',
146
+ 'ai-box-shadow': '0 0 20px rgba(0, 255, 249, 0.2)',
147
+ // 字体 - 科幻感
148
+ 'ai-font-family': "'Segoe UI', 'Share Tech Mono', monospace",
149
+ 'ai-font-size-base': '14px',
150
+ // 其他
151
+ 'ai-dark': '#0a0a0f',
152
+ 'ai-light': '#12121a',
153
+ 'ai-transition-duration': '0.3s'
154
+ }
155
+ };
156
+
157
+ @Injectable({
158
+ providedIn: 'root'
159
+ })
160
+ export class ThemeService implements OnDestroy {
161
+ private currentTheme$ = new Subject<ThemeType>();
162
+ private tabbySubscription?: Subscription;
163
+ private styleElement: HTMLStyleElement;
164
+ readonly theme$ = this.currentTheme$.asObservable();
165
+
166
+ private readonly allThemeClasses = [
167
+ 'ai-theme-auto', 'ai-theme-light', 'ai-theme-dark',
168
+ 'ai-theme-pixel', 'ai-theme-tech'
169
+ ];
170
+
171
+ // AI 助手容器选择器
172
+ private readonly containerSelectors = [
173
+ '.ai-chat-interface',
174
+ '.ai-settings-tab',
175
+ '.ai-assistant',
176
+ '.ai-sidebar-container',
177
+ '.ai-chat-modal-left'
178
+ ];
179
+
180
+ constructor(
181
+ private config: ConfigProviderService,
182
+ private tabbyConfig: ConfigService
183
+ ) {
184
+ // 创建并注入动态样式元素
185
+ this.styleElement = document.createElement('style');
186
+ this.styleElement.id = 'ai-assistant-dynamic-theme';
187
+ document.head.appendChild(this.styleElement);
188
+
189
+ this.init();
190
+ }
191
+
192
+ private init(): void {
193
+ const savedTheme = this.config.get<string>('theme', 'auto') as ThemeType;
194
+ this.setTheme(savedTheme);
195
+
196
+ // 监听 Tabby 主题变化(带防抖)
197
+ this.tabbySubscription = this.tabbyConfig.changed$.pipe(
198
+ debounceTime(100)
199
+ ).subscribe(() => {
200
+ const currentTheme = this.config.get<string>('theme', 'auto');
201
+ if (currentTheme === 'auto') {
202
+ this.applyTheme('auto');
203
+ }
204
+ });
205
+ }
206
+
207
+ /**
208
+ * 获取当前主题
209
+ */
210
+ getCurrentTheme(): ThemeType {
211
+ return this.config.get<string>('theme', 'auto') as ThemeType;
212
+ }
213
+
214
+ /**
215
+ * 设置并应用主题
216
+ */
217
+ setTheme(theme: ThemeType): void {
218
+ this.config.set('theme', theme);
219
+ this.applyTheme(theme);
220
+ }
221
+
222
+ /**
223
+ * 核心方法:动态注入主题样式
224
+ */
225
+ applyTheme(theme: ThemeType): void {
226
+ this.currentTheme$.next(theme);
227
+
228
+ // 确定实际生效的主题
229
+ let effectiveTheme: ThemeType = theme;
230
+ if (theme === 'auto') {
231
+ effectiveTheme = this.getTabbyEffectiveTheme();
232
+ }
233
+
234
+ // 1. 生成 CSS 变量样式
235
+ const cssVariables = this.buildCssVariables(effectiveTheme);
236
+ // 2. 生成主题特定样式
237
+ const themeStyles = this.buildThemeStyles(effectiveTheme);
238
+ // 3. 注入完整样式到 DOM
239
+ this.styleElement.innerHTML = `
240
+ /* AI Assistant Dynamic Theme - ${theme} (effective: ${effectiveTheme}) */
241
+ :root,
242
+ html,
243
+ body,
244
+ ${this.containerSelectors.join(',\n')} {
245
+ ${cssVariables}
246
+ }
247
+ ${themeStyles}
248
+ `.trim();
249
+
250
+ // 4. 更新类名和 data 属性
251
+ this.updateBodyClasses(theme, effectiveTheme);
252
+
253
+ // 5. 触发自定义事件
254
+ window.dispatchEvent(new CustomEvent('ai-theme-changed', {
255
+ detail: { theme, effectiveTheme }
256
+ }));
257
+
258
+ console.log('[ThemeService] Theme applied dynamically:', { theme, effectiveTheme });
259
+ }
260
+
261
+ /**
262
+ * 生成 CSS 变量字符串
263
+ */
264
+ private buildCssVariables(theme: ThemeType): string {
265
+ const vars = THEME_VARIABLES[theme] || THEME_VARIABLES.dark;
266
+ return Object.entries(vars)
267
+ .map(([key, value]) => ` --${key}: ${value} !important;`)
268
+ .join('\n');
269
+ }
270
+
271
+ /**
272
+ * 生成主题特定样式(像素风格、科技风格等)
273
+ */
274
+ private buildThemeStyles(theme: ThemeType): string {
275
+ if (theme === 'pixel') {
276
+ return `
277
+ /* Pixel theme specific styles */
278
+ ${this.containerSelectors.join(',\n')} {
279
+ /* 按钮像素化 */
280
+ .btn {
281
+ border: 3px solid var(--ai-border) !important;
282
+ border-radius: 0 !important;
283
+ box-shadow: 4px 4px 0 var(--ai-bg-tertiary) !important;
284
+ font-family: var(--ai-font-family) !important;
285
+ transition: none !important;
286
+ }
287
+
288
+ .btn:active {
289
+ box-shadow: none !important;
290
+ transform: translate(4px, 4px) !important;
291
+ }
292
+
293
+ /* 输入框 */
294
+ input,
295
+ textarea,
296
+ .form-control {
297
+ border: 3px solid var(--ai-border) !important;
298
+ border-radius: 0 !important;
299
+ background: var(--ai-bg-primary) !important;
300
+ color: var(--ai-text-primary) !important;
301
+ font-family: var(--ai-font-family) !important;
302
+ }
303
+
304
+ input:focus,
305
+ textarea:focus,
306
+ .form-control:focus {
307
+ outline: none !important;
308
+ border-color: var(--ai-primary) !important;
309
+ box-shadow: 4px 4px 0 var(--ai-bg-tertiary) !important;
310
+ }
311
+
312
+ /* 聊天气泡 */
313
+ .message-bubble {
314
+ border: 3px solid var(--ai-border) !important;
315
+ border-radius: 0 !important;
316
+ }
317
+
318
+ /* 标题 */
319
+ h2, h3, h4 {
320
+ font-family: var(--ai-font-family) !important;
321
+ letter-spacing: 1px !important;
322
+ }
323
+ }
324
+ `.trim();
325
+ }
326
+
327
+ if (theme === 'tech') {
328
+ return `
329
+ /* Tech theme specific styles */
330
+ ${this.containerSelectors.join(',\n')} {
331
+ /* 扫描线背景 */
332
+ background: repeating-linear-gradient(
333
+ 0deg,
334
+ transparent,
335
+ transparent 2px,
336
+ rgba(0, 255, 249, 0.03) 2px,
337
+ rgba(0, 255, 249, 0.03) 4px
338
+ ) !important;
339
+
340
+ /* 发光按钮 */
341
+ .btn {
342
+ background: linear-gradient(135deg, var(--ai-bg-secondary) 0%, var(--ai-bg-tertiary) 100%) !important;
343
+ border: 1px solid var(--ai-primary) !important;
344
+ color: var(--ai-text-primary) !important;
345
+ box-shadow:
346
+ 0 0 10px rgba(0, 255, 249, 0.2),
347
+ inset 0 0 10px rgba(0, 255, 249, 0.05) !important;
348
+ }
349
+
350
+ .btn:hover {
351
+ box-shadow:
352
+ 0 0 20px rgba(0, 255, 249, 0.4),
353
+ inset 0 0 20px rgba(0, 255, 249, 0.1) !important;
354
+ }
355
+
356
+ /* 发光输入框 */
357
+ input,
358
+ textarea,
359
+ .form-control {
360
+ border: 1px solid var(--ai-primary) !important;
361
+ background: var(--ai-bg-primary) !important;
362
+ color: var(--ai-text-primary) !important;
363
+ box-shadow: 0 0 10px rgba(0, 255, 249, 0.1) !important;
364
+ }
365
+
366
+ input:focus,
367
+ textarea:focus,
368
+ .form-control:focus {
369
+ outline: none !important;
370
+ border-color: var(--ai-primary) !important;
371
+ box-shadow:
372
+ 0 0 20px rgba(0, 255, 249, 0.3),
373
+ inset 0 0 10px rgba(0, 255, 249, 0.05) !important;
374
+ }
375
+
376
+ /* 霓虹标题 */
377
+ h2, h3, h4 {
378
+ text-shadow:
379
+ 0 0 10px var(--ai-primary),
380
+ 0 0 20px var(--ai-primary) !important;
381
+ }
382
+
383
+ /* 滚动条 */
384
+ ::-webkit-scrollbar {
385
+ width: 8px !important;
386
+ background: var(--ai-bg-secondary) !important;
387
+ }
388
+
389
+ ::-webkit-scrollbar-thumb {
390
+ background: var(--ai-primary) !important;
391
+ border-radius: 0 !important;
392
+ box-shadow: 0 0 10px var(--ai-primary) !important;
393
+ }
394
+ }
395
+ `.trim();
396
+ }
397
+
398
+ return '';
399
+ }
400
+
401
+ /**
402
+ * 更新 body 和 html 的类名
403
+ */
404
+ private updateBodyClasses(theme: ThemeType, effectiveTheme: ThemeType): void {
405
+ const root = document.documentElement;
406
+ const body = document.body;
407
+
408
+ // 移除所有主题类
409
+ this.allThemeClasses.forEach(cls => {
410
+ root.classList.remove(cls);
411
+ body.classList.remove(cls);
412
+ });
413
+
414
+ // 添加新主题类
415
+ const themeClass = `ai-theme-${theme}`;
416
+ const effectiveClass = `ai-theme-${effectiveTheme}`;
417
+
418
+ root.classList.add(themeClass);
419
+ body.classList.add(themeClass);
420
+ root.setAttribute('data-ai-theme', effectiveTheme);
421
+ body.setAttribute('data-ai-theme', effectiveTheme);
422
+
423
+ if (theme === 'auto') {
424
+ root.classList.add(effectiveClass);
425
+ body.classList.add(effectiveClass);
426
+ }
427
+
428
+ // 更新所有 AI 容器的类
429
+ const containers = document.querySelectorAll(this.containerSelectors.join(','));
430
+ containers.forEach(container => {
431
+ this.allThemeClasses.forEach(cls => container.classList.remove(cls));
432
+ container.classList.add(themeClass);
433
+ container.setAttribute('data-ai-theme', effectiveTheme);
434
+
435
+ if (theme === 'auto') {
436
+ container.classList.add(effectiveClass);
437
+ }
438
+ });
439
+ }
440
+
441
+ /**
442
+ * 获取 Tabby 当前的有效主题
443
+ */
444
+ private getTabbyEffectiveTheme(): 'light' | 'dark' {
445
+ const appearance = this.tabbyConfig.store?.appearance;
446
+
447
+ if (appearance) {
448
+ if (appearance.colorScheme) {
449
+ const scheme = appearance.colorScheme.toLowerCase();
450
+ if (scheme === 'light') return 'light';
451
+ if (scheme === 'dark') return 'dark';
452
+ }
453
+
454
+ const theme = appearance.theme?.toLowerCase() || '';
455
+ const darkThemes = ['hype', 'standard', 'dark', 'dracula', 'monokai', 'one-dark'];
456
+ if (darkThemes.some(t => theme.includes(t))) {
457
+ return 'dark';
458
+ }
459
+ }
460
+
461
+ return 'dark';
462
+ }
463
+
464
+ /**
465
+ * 刷新所有容器的主题类
466
+ */
467
+ refreshContainers(): void {
468
+ const theme = this.config.get<string>('theme', 'auto') as ThemeType;
469
+ this.applyTheme(theme);
470
+ }
471
+
472
+ ngOnDestroy(): void {
473
+ // 清理动态样式
474
+ if (this.styleElement && this.styleElement.parentNode) {
475
+ this.styleElement.parentNode.removeChild(this.styleElement);
476
+ }
477
+ this.tabbySubscription?.unsubscribe();
478
+ this.currentTheme$.complete();
479
+ }
480
+ }
@@ -2,98 +2,18 @@
2
2
  * Tabby AI Assistant 全局样式
3
3
  */
4
4
 
5
- // 主题颜色
6
- :root {
7
- --ai-primary: #007bff;
8
- --ai-secondary: #6c757d;
9
- --ai-success: #28a745;
10
- --ai-warning: #ffc107;
11
- --ai-danger: #dc3545;
12
- --ai-info: #17a2b8;
13
- --ai-light: #f8f9fa;
14
- --ai-dark: #343a40;
15
-
16
- // 风险级别颜色
17
- --ai-risk-low: #28a745;
18
- --ai-risk-medium: #ffc107;
19
- --ai-risk-high: #fd7e14;
20
- --ai-risk-critical: #dc3545;
21
-
22
- // 聊天消息颜色
23
- --ai-user-message: #e3f2fd;
24
- --ai-assistant-message: #f5f5f5;
25
- --ai-system-message: #fff3cd;
26
-
27
- // 背景和边框
28
- --ai-bg-primary: #ffffff;
29
- --ai-bg-secondary: #f8f9fa;
30
- --ai-border: #dee2e6;
31
- --ai-border-radius: 0.375rem;
32
- --ai-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
33
- }
34
-
35
- // 深色主题 - 支持多种类名
36
- .dark-theme,
37
- .ai-theme-dark,
38
- body.ai-theme-dark {
39
- --ai-primary: #4dabf7;
40
- --ai-secondary: #adb5bd;
41
- --ai-success: #51cf66;
42
- --ai-warning: #fcc419;
43
- --ai-danger: #ff6b6b;
44
- --ai-info: #22b8cf;
45
- --ai-light: #343a40;
46
- --ai-dark: #f8f9fa;
47
-
48
- --ai-risk-low: #51cf66;
49
- --ai-risk-medium: #fcc419;
50
- --ai-risk-high: #ff922b;
51
- --ai-risk-critical: #ff6b6b;
52
-
53
- --ai-user-message: #1e3a5f;
54
- --ai-assistant-message: #2d3748;
55
- --ai-system-message: #3a3a3a;
56
-
57
- --ai-bg-primary: #1a1a1a;
58
- --ai-bg-secondary: #2d2d2d;
59
- --ai-border: #4a4a4a;
60
- --ai-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.3);
61
- }
5
+ // 导入主题系统
6
+ @import 'themes';
62
7
 
63
- // 浅色主题
64
- .light-theme,
65
- .ai-theme-light,
66
- body.ai-theme-light {
67
- --ai-primary: #007bff;
68
- --ai-secondary: #6c757d;
69
- --ai-success: #28a745;
70
- --ai-warning: #ffc107;
71
- --ai-danger: #dc3545;
72
- --ai-info: #17a2b8;
73
- --ai-light: #f8f9fa;
74
- --ai-dark: #343a40;
75
-
76
- --ai-risk-low: #28a745;
77
- --ai-risk-medium: #ffc107;
78
- --ai-risk-high: #fd7e14;
79
- --ai-risk-critical: #dc3545;
80
-
81
- --ai-user-message: #e3f2fd;
82
- --ai-assistant-message: #f5f5f5;
83
- --ai-system-message: #fff3cd;
84
-
85
- --ai-bg-primary: #ffffff;
86
- --ai-bg-secondary: #f8f9fa;
87
- --ai-border: #dee2e6;
88
- --ai-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
89
- }
8
+ // 主题颜色变量已移至 themes.scss
9
+ // 这里只保留通用样式和组件样式
90
10
 
91
11
  // 通用样式
92
12
  .ai-assistant {
93
13
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
94
14
  font-size: 14px;
95
15
  line-height: 1.5;
96
- color: var(--ai-dark);
16
+ color: var(--ai-text-primary);
97
17
  background-color: var(--ai-bg-primary);
98
18
 
99
19
  * {
@@ -208,7 +128,7 @@ body.ai-theme-light {
208
128
  font-size: 14px;
209
129
  line-height: 1.5;
210
130
  background-color: var(--ai-bg-primary);
211
- color: var(--ai-dark);
131
+ color: var(--ai-text-primary);
212
132
 
213
133
  &:focus {
214
134
  outline: none;
@@ -363,7 +283,7 @@ body.ai-theme-light {
363
283
  border: 1px solid var(--ai-border);
364
284
  border-radius: var(--ai-border-radius);
365
285
  background-color: var(--ai-bg-primary);
366
- color: var(--ai-dark);
286
+ color: var(--ai-text-primary);
367
287
 
368
288
  &:focus {
369
289
  outline: none;
@@ -451,7 +371,7 @@ body.ai-theme-light {
451
371
  left: 50%;
452
372
  transform: translateX(-50%);
453
373
  padding: 0.5rem;
454
- background-color: var(--ai-dark);
374
+ background-color: var(--ai-text-primary);
455
375
  color: var(--ai-light);
456
376
  border-radius: var(--ai-border-radius);
457
377
  font-size: 0.875rem;