ai-chat-ui-kit 0.1.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 (95) hide show
  1. package/.eslintrc.cjs +74 -0
  2. package/.github/actions/screenshot/action.yml +35 -0
  3. package/.github/workflows/pages.yml +46 -0
  4. package/README.md +285 -0
  5. package/docs/README.md +176 -0
  6. package/docs/api/components.md +344 -0
  7. package/docs/api/core.md +349 -0
  8. package/docs/chat-style-1-minimal.html +78 -0
  9. package/docs/chat-style-2-neon.html +74 -0
  10. package/docs/chat-style-3-glass.html +73 -0
  11. package/docs/chat-style-4-terminal.html +84 -0
  12. package/docs/chat-style-5-gradient.html +69 -0
  13. package/docs/chat-style-6-corporate.html +116 -0
  14. package/docs/examples/basic-chat.md +291 -0
  15. package/docs/examples/custom-plugins.md +431 -0
  16. package/docs/examples/multi-model.md +466 -0
  17. package/docs/guide/api-adapters.md +431 -0
  18. package/docs/guide/getting-started.md +244 -0
  19. package/docs/guide/headless-mode.md +508 -0
  20. package/docs/guide/plugins.md +416 -0
  21. package/docs/guide/themes.md +327 -0
  22. package/docs/index.html +256 -0
  23. package/docs/theme-preview-1-minimal.html +74 -0
  24. package/docs/theme-preview-2-neon.html +73 -0
  25. package/docs/theme-preview-3-glass.html +77 -0
  26. package/docs/theme-preview-4-terminal.html +86 -0
  27. package/docs/theme-preview-5-gradient.html +79 -0
  28. package/docs/theme-preview-6-corporate.html +71 -0
  29. package/examples/index.html +414 -0
  30. package/examples/react-app/App.tsx +131 -0
  31. package/examples/react-app/index.html +12 -0
  32. package/examples/react-app/main.tsx +15 -0
  33. package/examples/react-app/package.json +24 -0
  34. package/examples/vue-app/index.html +12 -0
  35. package/examples/vue-app/package.json +22 -0
  36. package/examples/vue-app/src/App.vue +145 -0
  37. package/examples/vue-app/src/main.ts +9 -0
  38. package/package.json +44 -0
  39. package/packages/components/package.json +25 -0
  40. package/packages/components/src/chat/chat.css +80 -0
  41. package/packages/components/src/chat/chat.ts +236 -0
  42. package/packages/components/src/index.ts +36 -0
  43. package/packages/components/src/input/input.css +52 -0
  44. package/packages/components/src/input/input.ts +116 -0
  45. package/packages/components/src/markdown/markdown.css +118 -0
  46. package/packages/components/src/markdown/markdown.ts +229 -0
  47. package/packages/components/src/message/message.css +56 -0
  48. package/packages/components/src/message/message.ts +72 -0
  49. package/packages/components/src/styles/global.css +43 -0
  50. package/packages/components/src/tool-call/tool-call.css +98 -0
  51. package/packages/components/src/tool-call/tool-call.ts +171 -0
  52. package/packages/components/src/types.ts +55 -0
  53. package/packages/components/src/utils/helpers.ts +128 -0
  54. package/packages/components/tsconfig.json +25 -0
  55. package/packages/components/tsup.config.ts +18 -0
  56. package/packages/core/package.json +47 -0
  57. package/packages/core/pnpm-lock.yaml +2032 -0
  58. package/packages/core/pnpm-workspace.yaml +2 -0
  59. package/packages/core/src/api/adapters.ts +717 -0
  60. package/packages/core/src/api/base.ts +210 -0
  61. package/packages/core/src/api/index.ts +54 -0
  62. package/packages/core/src/index.ts +93 -0
  63. package/packages/core/src/parser/latex.ts +274 -0
  64. package/packages/core/src/parser/markdown.test.ts +58 -0
  65. package/packages/core/src/parser/markdown.ts +206 -0
  66. package/packages/core/src/parser/mermaid.ts +276 -0
  67. package/packages/core/src/plugins/PluginManager.ts +232 -0
  68. package/packages/core/src/plugins/builtin.ts +406 -0
  69. package/packages/core/src/store/ChatStore.ts +163 -0
  70. package/packages/core/src/store/ModelConfigStore.ts +136 -0
  71. package/packages/core/src/store/ToolCallStore.ts +164 -0
  72. package/packages/core/src/store/base.ts +75 -0
  73. package/packages/core/src/types/index.ts +133 -0
  74. package/packages/core/tsup.config.ts +18 -0
  75. package/packages/themes/package.json +33 -0
  76. package/packages/themes/src/corporate/index.ts +52 -0
  77. package/packages/themes/src/corporate/theme.css +228 -0
  78. package/packages/themes/src/glass/index.ts +52 -0
  79. package/packages/themes/src/glass/theme.css +237 -0
  80. package/packages/themes/src/gradient/index.ts +53 -0
  81. package/packages/themes/src/gradient/theme.css +218 -0
  82. package/packages/themes/src/index.ts +13 -0
  83. package/packages/themes/src/minimal/index.ts +52 -0
  84. package/packages/themes/src/minimal/theme.css +198 -0
  85. package/packages/themes/src/neon/index.ts +52 -0
  86. package/packages/themes/src/neon/theme.css +233 -0
  87. package/packages/themes/src/terminal/index.ts +52 -0
  88. package/packages/themes/src/terminal/theme.css +235 -0
  89. package/packages/themes/src/types.ts +10 -0
  90. package/packages/themes/src/vite-env.d.ts +9 -0
  91. package/packages/themes/tsup.config.ts +21 -0
  92. package/pnpm-workspace.yaml +4 -0
  93. package/tsconfig.json +27 -0
  94. package/vite.config.ts +25 -0
  95. package/vitest.config.ts +28 -0
@@ -0,0 +1,431 @@
1
+ # API 适配器
2
+
3
+ API 适配器允许您将 AI Chat UI Kit 连接到不同的后端 API,无论它们使用何种数据格式。
4
+
5
+ ## 为什么需要 API 适配器?
6
+
7
+ 不同的 AI 服务有不同的 API 格式:
8
+
9
+ - **OpenAI API**: `{ messages: [{ role: 'user', content: '...' }] }`
10
+ - **Claude API**: `{ messages: [{ role: 'user', content: '...' }], model: '...' }`
11
+ - **自定义 API**: 可能有完全不同的格式
12
+
13
+ API 适配器的作用是将您的后端 API 格式转换为 AI Chat UI Kit 期望的格式。
14
+
15
+ ## 适配器接口
16
+
17
+ ### 基本结构
18
+
19
+ ```typescript
20
+ interface APIAdapter {
21
+ // 发送消息
22
+ sendMessage(request: ChatRequest): Promise<ChatResponse>;
23
+
24
+ // 流式发送消息(可选)
25
+ sendMessageStream?(request: ChatRequest, onChunk: (chunk: string) => void): Promise<void>;
26
+
27
+ // 获取消息历史(可选)
28
+ getHistory?(): Promise<Message[]>;
29
+
30
+ // 清除历史(可选)
31
+ clearHistory?(): Promise<void>;
32
+ }
33
+
34
+ interface ChatRequest {
35
+ message: string;
36
+ history?: Message[];
37
+ model?: string;
38
+ temperature?: number;
39
+ maxTokens?: number;
40
+ [key: string]: any; // 其他自定义参数
41
+ }
42
+
43
+ interface ChatResponse {
44
+ content: string;
45
+ role: 'assistant';
46
+ usage?: {
47
+ promptTokens: number;
48
+ completionTokens: number;
49
+ totalTokens: number;
50
+ };
51
+ [key: string]: any; // 其他自定义字段
52
+ }
53
+ ```
54
+
55
+ ## 创建适配器
56
+
57
+ ### 示例 1:OpenAI API 适配器
58
+
59
+ ```typescript
60
+ // adapters/openai.ts
61
+ import { APIAdapter, ChatRequest, ChatResponse } from '@ai-chat/core';
62
+
63
+ export class OpenAIAdapter implements APIAdapter {
64
+ private apiKey: string;
65
+ private model: string;
66
+ private baseURL: string;
67
+
68
+ constructor(config: { apiKey: string; model?: string; baseURL?: string }) {
69
+ this.apiKey = config.apiKey;
70
+ this.model = config.model || 'gpt-3.5-turbo';
71
+ this.baseURL = config.baseURL || 'https://api.openai.com/v1';
72
+ }
73
+
74
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
75
+ const response = await fetch(`${this.baseURL}/chat/completions`, {
76
+ method: 'POST',
77
+ headers: {
78
+ 'Content-Type': 'application/json',
79
+ 'Authorization': `Bearer ${this.apiKey}`,
80
+ },
81
+ body: JSON.stringify({
82
+ model: request.model || this.model,
83
+ messages: [
84
+ ...(request.history || []).map(msg => ({
85
+ role: msg.role,
86
+ content: msg.content,
87
+ })),
88
+ { role: 'user', content: request.message },
89
+ ],
90
+ temperature: request.temperature,
91
+ max_tokens: request.maxTokens,
92
+ }),
93
+ });
94
+
95
+ if (!response.ok) {
96
+ throw new Error(`OpenAI API error: ${response.statusText}`);
97
+ }
98
+
99
+ const data = await response.json();
100
+
101
+ return {
102
+ content: data.choices[0].message.content,
103
+ role: 'assistant',
104
+ usage: {
105
+ promptTokens: data.usage.prompt_tokens,
106
+ completionTokens: data.usage.completion_tokens,
107
+ totalTokens: data.usage.total_tokens,
108
+ },
109
+ };
110
+ }
111
+
112
+ async sendMessageStream(
113
+ request: ChatRequest,
114
+ onChunk: (chunk: string) => void
115
+ ): Promise<void> {
116
+ const response = await fetch(`${this.baseURL}/chat/completions`, {
117
+ method: 'POST',
118
+ headers: {
119
+ 'Content-Type': 'application/json',
120
+ 'Authorization': `Bearer ${this.apiKey}`,
121
+ },
122
+ body: JSON.stringify({
123
+ model: request.model || this.model,
124
+ messages: [
125
+ ...(request.history || []).map(msg => ({
126
+ role: msg.role,
127
+ content: msg.content,
128
+ })),
129
+ { role: 'user', content: request.message },
130
+ ],
131
+ stream: true,
132
+ }),
133
+ });
134
+
135
+ if (!response.ok) {
136
+ throw new Error(`OpenAI API error: ${response.statusText}`);
137
+ }
138
+
139
+ const reader = response.body.getReader();
140
+ const decoder = new TextDecoder();
141
+
142
+ while (true) {
143
+ const { done, value } = await reader.read();
144
+ if (done) break;
145
+
146
+ const chunk = decoder.decode(value);
147
+ const lines = chunk.split('\n').filter(line => line.trim() !== '');
148
+
149
+ for (const line of lines) {
150
+ if (line.startsWith('data: ')) {
151
+ const data = JSON.parse(line.slice(6));
152
+ if (data.choices && data.choices[0].delta.content) {
153
+ onChunk(data.choices[0].delta.content);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### 示例 2:Claude API 适配器
163
+
164
+ ```typescript
165
+ // adapters/claude.ts
166
+ import { APIAdapter, ChatRequest, ChatResponse } from '@ai-chat/core';
167
+
168
+ export class ClaudeAdapter implements APIAdapter {
169
+ private apiKey: string;
170
+ private model: string;
171
+ private baseURL: string;
172
+
173
+ constructor(config: { apiKey: string; model?: string; baseURL?: string }) {
174
+ this.apiKey = config.apiKey;
175
+ this.model = config.model || 'claude-3-opus-20240229';
176
+ this.baseURL = config.baseURL || 'https://api.anthropic.com/v1';
177
+ }
178
+
179
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
180
+ const response = await fetch(`${this.baseURL}/messages`, {
181
+ method: 'POST',
182
+ headers: {
183
+ 'Content-Type': 'application/json',
184
+ 'x-api-key': this.apiKey,
185
+ 'anthropic-version': '2023-06-01',
186
+ },
187
+ body: JSON.stringify({
188
+ model: this.model,
189
+ messages: [
190
+ ...(request.history || []).map(msg => ({
191
+ role: msg.role === 'assistant' ? 'assistant' : 'user',
192
+ content: msg.content,
193
+ })),
194
+ { role: 'user', content: request.message },
195
+ ],
196
+ max_tokens: request.maxTokens || 4096,
197
+ }),
198
+ });
199
+
200
+ if (!response.ok) {
201
+ throw new Error(`Claude API error: ${response.statusText}`);
202
+ }
203
+
204
+ const data = await response.json();
205
+
206
+ return {
207
+ content: data.content[0].text,
208
+ role: 'assistant',
209
+ usage: {
210
+ promptTokens: data.usage.input_tokens,
211
+ completionTokens: data.usage.output_tokens,
212
+ totalTokens: data.usage.input_tokens + data.usage.output_tokens,
213
+ },
214
+ };
215
+ }
216
+ }
217
+ ```
218
+
219
+ ### 示例 3:自定义 API 适配器
220
+
221
+ ```typescript
222
+ // adapters/custom.ts
223
+ import { APIAdapter, ChatRequest, ChatResponse } from '@ai-chat/core';
224
+
225
+ export class CustomAPIAdapter implements APIAdapter {
226
+ private baseURL: string;
227
+ private token: string;
228
+
229
+ constructor(config: { baseURL: string; token: string }) {
230
+ this.baseURL = config.baseURL;
231
+ this.token = config.token;
232
+ }
233
+
234
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
235
+ const response = await fetch(`${this.baseURL}/api/chat`, {
236
+ method: 'POST',
237
+ headers: {
238
+ 'Content-Type': 'application/json',
239
+ 'Authorization': `Bearer ${this.token}`,
240
+ },
241
+ body: JSON.stringify({
242
+ prompt: request.message, // 自定义字段名
243
+ // 转换格式
244
+ }),
245
+ });
246
+
247
+ if (!response.ok) {
248
+ throw new Error(`Custom API error: ${response.statusText}`);
249
+ }
250
+
251
+ const data = await response.json();
252
+
253
+ // 转换为标准格式
254
+ return {
255
+ content: data.reply, // 自定义字段名
256
+ role: 'assistant',
257
+ };
258
+ }
259
+ }
260
+ ```
261
+
262
+ ## 使用适配器
263
+
264
+ ### 在 Core 中使用
265
+
266
+ ```typescript
267
+ // store.ts
268
+ import { createChatStore } from '@ai-chat/core';
269
+ import { OpenAIAdapter } from './adapters/openai';
270
+
271
+ // 创建适配器实例
272
+ const adapter = new OpenAIAdapter({
273
+ apiKey: process.env.OPENAI_API_KEY,
274
+ model: 'gpt-4',
275
+ });
276
+
277
+ // 创建 store
278
+ export const chatStore = createChatStore({
279
+ async onMessage(message: string) {
280
+ const response = await adapter.sendMessage({
281
+ message,
282
+ history: chatStore.getMessages(),
283
+ });
284
+ return response.content;
285
+ },
286
+ });
287
+ ```
288
+
289
+ ### 在 Components 中使用
290
+
291
+ ```typescript
292
+ // main.ts
293
+ import '@ai-chat/components';
294
+ import '@ai-chat/themes/default';
295
+ import { OpenAIAdapter } from './adapters/openai';
296
+
297
+ const adapter = new OpenAIAdapter({
298
+ apiKey: process.env.OPENAI_API_KEY,
299
+ });
300
+
301
+ const chat = document.querySelector('ai-chat');
302
+
303
+ chat.setMessageHandler(async (message) => {
304
+ const response = await adapter.sendMessage({
305
+ message,
306
+ history: chat.getMessages(),
307
+ });
308
+ return response.content;
309
+ });
310
+ ```
311
+
312
+ ### 使用流式响应
313
+
314
+ ```typescript
315
+ const chat = document.querySelector('ai-chat');
316
+
317
+ chat.setMessageHandler(async (message) => {
318
+ let fullResponse = '';
319
+
320
+ await adapter.sendMessageStream(
321
+ {
322
+ message,
323
+ history: chat.getMessages(),
324
+ },
325
+ (chunk) => {
326
+ fullResponse += chunk;
327
+ // 实时更新 UI
328
+ chat.updateLastMessage(fullResponse);
329
+ }
330
+ );
331
+
332
+ return fullResponse;
333
+ });
334
+ ```
335
+
336
+ ## 多模型支持
337
+
338
+ ### 动态切换模型
339
+
340
+ ```typescript
341
+ class MultiModelAdapter implements APIAdapter {
342
+ private adapters: Map<string, APIAdapter> = new Map();
343
+
344
+ registerModel(name: string, adapter: APIAdapter) {
345
+ this.adapters.set(name, adapter);
346
+ }
347
+
348
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
349
+ const model = request.model || 'default';
350
+ const adapter = this.adapters.get(model);
351
+
352
+ if (!adapter) {
353
+ throw new Error(`Model ${model} not found`);
354
+ }
355
+
356
+ return adapter.sendMessage(request);
357
+ }
358
+ }
359
+
360
+ // 使用
361
+ const multiAdapter = new MultiModelAdapter();
362
+ multiAdapter.registerModel('gpt-4', new OpenAIAdapter({ model: 'gpt-4', /* ... */ }));
363
+ multiAdapter.registerModel('claude', new ClaudeAdapter({ /* ... */ }));
364
+
365
+ // 切换模型
366
+ chatStore.sendMessage('Hello', { model: 'gpt-4' });
367
+ chatStore.sendMessage('Hello', { model: 'claude' });
368
+ ```
369
+
370
+ ## 错误处理
371
+
372
+ ```typescript
373
+ class ResilientAdapter implements APIAdapter {
374
+ private adapters: APIAdapter[];
375
+ private currentIndex: number = 0;
376
+
377
+ constructor(adapters: APIAdapter[]) {
378
+ this.adapters = adapters;
379
+ }
380
+
381
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
382
+ let lastError: Error | null = null;
383
+
384
+ // 尝试所有适配器
385
+ for (let i = 0; i < this.adapters.length; i++) {
386
+ try {
387
+ const adapter = this.adapters[(this.currentIndex + i) % this.adapters.length];
388
+ const response = await adapter.sendMessage(request);
389
+ return response;
390
+ } catch (error) {
391
+ lastError = error as Error;
392
+ console.warn(`Adapter ${i} failed, trying next...`, error);
393
+ }
394
+ }
395
+
396
+ throw lastError || new Error('All adapters failed');
397
+ }
398
+ }
399
+ ```
400
+
401
+ ## 缓存适配器
402
+
403
+ ```typescript
404
+ class CachedAdapter implements APIAdapter {
405
+ private adapter: APIAdapter;
406
+ private cache: Map<string, ChatResponse> = new Map();
407
+
408
+ constructor(adapter: APIAdapter) {
409
+ this.adapter = adapter;
410
+ }
411
+
412
+ async sendMessage(request: ChatRequest): Promise<ChatResponse> {
413
+ const cacheKey = JSON.stringify(request);
414
+
415
+ if (this.cache.has(cacheKey)) {
416
+ return this.cache.get(cacheKey)!;
417
+ }
418
+
419
+ const response = await this.adapter.sendMessage(request);
420
+ this.cache.set(cacheKey, response);
421
+
422
+ return response;
423
+ }
424
+ }
425
+ ```
426
+
427
+ ## 下一步
428
+
429
+ - [插件开发](./plugins.md) - 学习如何扩展功能
430
+ - [主题定制](./themes.md) - 学习如何自定义主题
431
+ - [API 参考](../../api/) - 查看完整 API 文档
@@ -0,0 +1,244 @@
1
+ # 快速开始
2
+
3
+ 本指南将帮助您在 5 分钟内上手 AI Chat UI Kit。
4
+
5
+ ## 前置要求
6
+
7
+ - Node.js >= 16.0.0
8
+ - 包管理器:PNPM(推荐)、NPM 或 Yarn
9
+
10
+ ## 安装
11
+
12
+ ### 使用 PNPM(推荐)
13
+
14
+ ```bash
15
+ pnpm add @ai-chat/core @ai-chat/components @ai-chat/themes
16
+ ```
17
+
18
+ ### 使用 NPM
19
+
20
+ ```bash
21
+ npm install @ai-chat/core @ai-chat/components @ai-chat/themes
22
+ ```
23
+
24
+ ### 使用 Yarn
25
+
26
+ ```bash
27
+ yarn add @ai-chat/core @ai-chat/components @ai-chat/themes
28
+ ```
29
+
30
+ ## 基本用法
31
+
32
+ ### 原生 HTML 项目
33
+
34
+ 1. 在 HTML 文件中引入组件和主题:
35
+
36
+ ```html
37
+ <!DOCTYPE html>
38
+ <html lang="zh-CN">
39
+ <head>
40
+ <meta charset="UTF-8">
41
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
42
+ <title>AI Chat Demo</title>
43
+ <script type="module">
44
+ import '@ai-chat/components';
45
+ import '@ai-chat/themes/default';
46
+ </script>
47
+ <style>
48
+ html, body {
49
+ margin: 0;
50
+ padding: 0;
51
+ height: 100%;
52
+ }
53
+ #app {
54
+ height: 100vh;
55
+ }
56
+ </style>
57
+ </head>
58
+ <body>
59
+ <div id="app">
60
+ <ai-chat></ai-chat>
61
+ </div>
62
+
63
+ <script>
64
+ // 获取组件实例
65
+ const chat = document.querySelector('ai-chat');
66
+
67
+ // 设置消息处理回调
68
+ chat.setMessageHandler(async (message) => {
69
+ // 这里调用您的 AI API
70
+ const response = await fetch('/api/chat', {
71
+ method: 'POST',
72
+ headers: { 'Content-Type': 'application/json' },
73
+ body: JSON.stringify({ message })
74
+ });
75
+ const data = await response.json();
76
+ return data.reply;
77
+ });
78
+
79
+ // 添加欢迎消息
80
+ chat.addMessage({
81
+ role: 'assistant',
82
+ content: '你好!我是 AI 助手,有什么可以帮助你的吗?'
83
+ });
84
+ </script>
85
+ </body>
86
+ </html>
87
+ ```
88
+
89
+ ### React 项目
90
+
91
+ 1. 安装依赖(同上)
92
+
93
+ 2. 创建聊天组件:
94
+
95
+ ```tsx
96
+ // ChatApp.tsx
97
+ import React, { useEffect, useRef } from 'react';
98
+ import '@ai-chat/components';
99
+ import '@ai-chat/themes/default';
100
+
101
+ const ChatApp: React.FC = () => {
102
+ const chatRef = useRef<HTMLElement>(null);
103
+
104
+ useEffect(() => {
105
+ if (chatRef.current) {
106
+ // 设置消息处理回调
107
+ (chatRef.current as any).setMessageHandler(async (message: string) => {
108
+ // 调用您的 AI API
109
+ const response = await fetch('/api/chat', {
110
+ method: 'POST',
111
+ headers: { 'Content-Type': 'application/json' },
112
+ body: JSON.stringify({ message })
113
+ });
114
+ const data = await response.json();
115
+ return data.reply;
116
+ });
117
+
118
+ // 添加欢迎消息
119
+ (chatRef.current as any).addMessage({
120
+ role: 'assistant',
121
+ content: '你好!我是 AI 助手,有什么可以帮助你的吗?'
122
+ });
123
+ }
124
+ }, []);
125
+
126
+ return (
127
+ <div style={{ height: '100vh' }}>
128
+ <ai-chat ref={chatRef}></ai-chat>
129
+ </div>
130
+ );
131
+ };
132
+
133
+ export default ChatApp;
134
+ ```
135
+
136
+ 3. 在 App.tsx 中使用:
137
+
138
+ ```tsx
139
+ import React from 'react';
140
+ import ChatApp from './ChatApp';
141
+
142
+ function App() {
143
+ return <ChatApp />;
144
+ }
145
+
146
+ export default App;
147
+ ```
148
+
149
+ ### Vue 3 项目
150
+
151
+ 1. 安装依赖(同上)
152
+
153
+ 2. 创建聊天组件:
154
+
155
+ ```vue
156
+ <!-- ChatApp.vue -->
157
+ <template>
158
+ <div style="height: 100vh">
159
+ <ai-chat ref="chatRef"></ai-chat>
160
+ </div>
161
+ </template>
162
+
163
+ <script setup lang="ts">
164
+ import { ref, onMounted } from 'vue';
165
+ import '@ai-chat/components';
166
+ import '@ai-chat/themes/default';
167
+
168
+ const chatRef = ref<HTMLElement>();
169
+
170
+ onMounted(() => {
171
+ if (chatRef.value) {
172
+ // 设置消息处理回调
173
+ (chatRef.value as any).setMessageHandler(async (message: string) => {
174
+ // 调用您的 AI API
175
+ const response = await fetch('/api/chat', {
176
+ method: 'POST',
177
+ headers: { 'Content-Type': 'application/json' },
178
+ body: JSON.stringify({ message })
179
+ });
180
+ const data = await response.json();
181
+ return data.reply;
182
+ });
183
+
184
+ // 添加欢迎消息
185
+ (chatRef.value as any).addMessage({
186
+ role: 'assistant',
187
+ content: '你好!我是 AI 助手,有什么可以帮助你的吗?'
188
+ });
189
+ }
190
+ });
191
+ </script>
192
+ ```
193
+
194
+ 3. 在 App.vue 中使用:
195
+
196
+ ```vue
197
+ <template>
198
+ <ChatApp />
199
+ </template>
200
+
201
+ <script setup lang="ts">
202
+ import ChatApp from './components/ChatApp.vue';
203
+ </script>
204
+ ```
205
+
206
+ ## 下一步
207
+
208
+ - [Headless 模式](./headless-mode.md) - 学习如何只使用逻辑层,自定义 UI
209
+ - [主题定制](./themes.md) - 学习如何自定义主题
210
+ - [插件开发](./plugins.md) - 学习如何扩展功能
211
+ - [API 参考](../../api/) - 查看完整 API 文档
212
+
213
+ ## 常见问题
214
+
215
+ ### Q: 如何切换主题?
216
+
217
+ A: 只需导入不同的主题包:
218
+
219
+ ```typescript
220
+ // 默认主题
221
+ import '@ai-chat/themes/default';
222
+
223
+ // 气泡主题(仿微信/QQ 风格)
224
+ import '@ai-chat/themes/bubble';
225
+
226
+ // 扁平主题
227
+ import '@ai-chat/themes/flat';
228
+ ```
229
+
230
+ ### Q: 如何自定义样式?
231
+
232
+ A: 所有主题都使用 CSS 变量,您可以在自己的 CSS 中覆盖这些变量:
233
+
234
+ ```css
235
+ :root {
236
+ --ai-primary: #your-color;
237
+ --ai-message-user-bg: #your-color;
238
+ /* ... */
239
+ }
240
+ ```
241
+
242
+ ### Q: 如何兼容不同的 AI API?
243
+
244
+ A: 使用 API 适配器,详见 [API 适配器](./api-adapters.md)。