@kernelift/ai-chat 1.0.11 → 2.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.
package/README.md CHANGED
@@ -1,94 +1,128 @@
1
- # Kernelift AI 聊天框组件使用手册
1
+ # @kernelift/ai-chat
2
2
 
3
- `kernelift/核心跃升` 基于 `vue3` 编写的 AI 聊天框组件,依赖 `pnpm` 管理依赖。
3
+ [![npm version](https://badge.fury.io/js/%40kernelift%2Fai-chat.svg)](https://badge.fury.io/js/%40kernelift%2Fai-chat)
4
+ [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](https://opensource.org/licenses/GPL-3.0)
4
5
 
5
- 配合的请求SSE库:[Sse-Client](./SSE-Client.md)
6
+ 基于 Vue 3 + TypeScript 的现代化 AI 聊天框组件,提供企业级的对话界面解决方案。
6
7
 
7
- ## 目录
8
+ ## ✨ 特性
8
9
 
9
- - [概述](#概述)
10
- - [安装与导入](#安装与导入)
11
- - [组件构成](#组件构成)
12
- - [主容器组件](#主容器组件)
13
- - [子组件详解](#子组件详解)
14
- - [事件处理](#事件处理)
15
- - [样式定制](#样式定制)
16
- - [使用示例](#使用示例)
17
- - [API 参考](#api-参考)
10
+ - 🚀 **现代化架构** - 基于 Vue 3 Composition API + TypeScript
11
+ - 💬 **流式对话** - 支持 SSE 实时通信和流式消息显示
12
+ - 🎨 **主题系统** - 内置亮色/暗色主题,支持自定义主题色
13
+ - 📱 **响应式设计** - 完美适配桌面端和移动端
14
+ - 📚 **历史管理** - 智能的对话历史记录管理
15
+ - 🛠️ **高度可定制** - 丰富的插槽和配置选项
16
+ - 🌐 **国际化** - 内置中英文支持
17
+ - 🧠 **AI 能力** - 支持深度思考、联网搜索等 AI 功能
18
18
 
19
- ## 概述
19
+ ## 📦 安装
20
20
 
21
- Vue3 AI 聊天框组件是一个功能完整的聊天界面解决方案,支持流式对话、消息气泡、侧边栏历史记录、主题切换等特性。
21
+ ```bash
22
+ # 使用 pnpm
23
+ pnpm add @kernelift/ai-chat
22
24
 
23
- ### 主要特性
25
+ # 使用 npm
26
+ npm install @kernelift/ai-chat
24
27
 
25
- - 💬 **实时对话** - 支持流式消息显示
26
- - 📱 **响应式设计** - 适配桌面端和移动端
27
- - 🎨 **主题系统** - 支持亮色/暗色主题切换
28
- - 📚 **历史记录** - 侧边栏对话历史管理
29
- - 🛠️ **工具集成** - 支持深度思考、联网搜索等功能
30
- - 🎯 **可定制** - 丰富的插槽和配置选项
28
+ # 使用 yarn
29
+ yarn add @kernelift/ai-chat
30
+ ```
31
31
 
32
- ## 安装与导入
32
+ ### 依赖要求
33
33
 
34
- ### 安装依赖
34
+ - Vue 3.3+
35
+ - TypeScript 5.0+
36
+ - @kernelift/markdown (workspace:\*)
35
37
 
36
- ```bash
37
- # 安装核心依赖
38
- pnpm install @kernelift/markdown @kernelift/ai-chat
39
- ```
38
+ ## 🚀 快速开始
40
39
 
41
- #### 其他推荐依赖 (选用)
40
+ ### 基础用法
42
41
 
43
- ```bash
44
- pnpm install @vueuse/core @kernelift/utils
45
- ```
42
+ ```vue
43
+ <template>
44
+ <ChatContainer
45
+ v-model:messages="messages"
46
+ v-model:inputText="inputText"
47
+ v-model:loading="loading"
48
+ :records="records"
49
+ @send="handleSend"
50
+ @bubble-event="handleBubbleEvent"
51
+ />
52
+ </template>
46
53
 
47
- ### 组件导入
54
+ <script setup>
55
+ import { ref } from 'vue'
56
+ import { ChatContainer } from '@kernelift/ai-chat'
57
+ import '@kernelift/ai-chat/style.css'
58
+ import type { ChatMessage, ChatRecord, BubbleEvent } from '@kernelift/ai-chat'
48
59
 
49
- ```typescript
50
- // 全局注册
51
- import { createApp } from 'vue';
52
- import { ChatContainer } from '@kernelift/ai-chat';
53
- import '@kernelift/ai-chat/style.css';
60
+ const messages = ref<ChatMessage[]>([])
61
+ const inputText = ref('')
62
+ const loading = ref(false)
63
+ const records = ref<ChatRecord[]>([])
54
64
 
55
- const app = createApp(App);
56
- app.component('ChatContainer', ChatContainer);
57
- ```
65
+ const handleSend = (text: string) => {
66
+ console.log('发送消息:', text)
67
+ }
58
68
 
59
- ```vue
60
- <!-- 局部导入 -->
61
- <script setup>
62
- import {
63
- ChatContainer,
64
- ChatBubble,
65
- ChatSender,
66
- ChatSidebar,
67
- ChatHeader,
68
- ThinkingProcess
69
- } from '@kernelift/ai-chat';
70
- import '@kernelift/ai-chat/style.css';
71
- import type { ChatMessage, ChatRecord, BubbleEvent } from '@kernelift/ai-chat';
69
+ const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
70
+ console.log('气泡事件:', eventName, data)
71
+ }
72
72
  </script>
73
73
  ```
74
74
 
75
- ## 组件构成
75
+ ## 📚 目录
76
+
77
+ - [组件架构](#组件架构)
78
+ - [组件详解](#组件详解)
79
+ - [事件处理](#事件处理)
80
+ - [样式定制](#样式定制)
81
+ - [完整示例](#完整示例)
82
+ - [API 文档](#api-文档)
83
+ - [常见问题](#常见问题)
84
+
85
+ ## 🏗️ 组件架构
76
86
 
77
- ### 组件结构
87
+ ### 组件层次结构
78
88
 
79
89
  ```
80
90
  ChatContainer (主容器)
81
91
  ├── ChatSidebar (侧边栏)
92
+ │ ├── Logo 区域
93
+ │ ├── 新建聊天按钮
94
+ │ ├── 聊天记录列表
95
+ │ └── 记录操作菜单
82
96
  ├── ChatHeader (头部)
83
- ├── ChatBubble (消息气泡)
84
- ├── ThinkingProcess (思考过程)
85
- ├── ChatSender (发送器)
86
- └── 工作区 (可选)
97
+ ├── Logo 显示
98
+ │ └── 主题切换按钮
99
+ ├── 消息区域
100
+ │ ├── ChatBubble (消息气泡)
101
+ │ │ ├── 用户消息
102
+ │ │ └── AI 助手消息
103
+ │ │ ├── 思考过程 (ThinkingProcess)
104
+ │ │ ├── 消息内容
105
+ │ │ └── 操作按钮
106
+ │ └── 空状态提示
107
+ └── ChatSender (发送器)
108
+ ├── 工具按钮区域
109
+ ├── 输入框
110
+ └── 发送按钮
87
111
  ```
88
112
 
89
- ## 主容器组件
113
+ ### 数据流
114
+
115
+ ```
116
+ 用户输入 → ChatSender → send事件 → 父组件处理 → 更新messages → ChatBubble渲染
117
+
118
+ AI响应处理 → 流式更新 → 实时显示
119
+ ```
90
120
 
91
- ### 基本用法
121
+ ## 🧩 组件详解
122
+
123
+ ### ChatContainer - 主容器
124
+
125
+ 主容器组件,负责整体布局和状态管理。
92
126
 
93
127
  ```vue
94
128
  <template>
@@ -96,38 +130,30 @@ ChatContainer (主容器)
96
130
  v-model:messages="messages"
97
131
  v-model:inputText="inputText"
98
132
  v-model:loading="loading"
99
- :records="chatRecords"
133
+ v-model:record-id="activeRecordId"
134
+ v-model:enable-think="enableThink"
135
+ v-model:enable-net="enableNet"
136
+ :records="records"
137
+ :theme-mode="themeMode"
138
+ :primary-color="#615ced"
139
+ :has-header="true"
140
+ :has-theme-mode="true"
141
+ :show-workspace="true"
142
+ :input-height="140"
100
143
  @send="handleSend"
101
144
  @bubble-event="handleBubbleEvent"
102
- />
145
+ @create-record="handleCreateRecord"
146
+ @change-record="handleChangeRecord"
147
+ @change-theme="handleThemeChange"
148
+ >
149
+ <!-- 插槽内容 -->
150
+ </ChatContainer>
103
151
  </template>
104
-
105
- <script setup lang="ts">
106
- import { ref } from 'vue';
107
- import type { ChatMessage, ChatRecord, BubbleEvent } from '@kernelift/ai-chat';
108
-
109
- const messages = ref<ChatMessage[]>([]);
110
- const inputText = ref('');
111
- const loading = ref(false);
112
- const chatRecords = ref<ChatRecord[]>([]);
113
-
114
- const handleSend = (text: string) => {
115
- // 处理发送消息
116
- console.log('发送消息:', text);
117
- };
118
-
119
- const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
120
- // 处理气泡事件
121
- console.log('气泡事件:', eventName, data);
122
- };
123
- </script>
124
152
  ```
125
153
 
126
- ## 子组件详解
127
-
128
154
  ### ChatBubble - 消息气泡
129
155
 
130
- 消息气泡组件支持多种消息类型和交互操作。
156
+ 负责显示单条消息,支持多种消息类型和交互操作。
131
157
 
132
158
  ```vue
133
159
  <template>
@@ -157,9 +183,22 @@ const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
157
183
  </template>
158
184
  ```
159
185
 
186
+ #### 消息类型支持
187
+
188
+ - **用户消息** (`role: 'user'`) - 右对齐,蓝色背景
189
+ - **AI 助手消息** (`role: 'assistant'`) - 左对齐,白色背景
190
+ - **系统消息** (`role: 'system'`) - 居中显示,特殊样式
191
+
192
+ #### 消息状态
193
+
194
+ - `loading` - 正在生成中,显示加载动画
195
+ - `isThinking` - 正在思考,显示思考过程
196
+ - `isError` - 错误状态,显示错误信息
197
+ - `isTerminated` - 已终止生成
198
+
160
199
  ### ChatSender - 消息发送器
161
200
 
162
- 发送器组件提供消息输入和工具按钮。
201
+ 提供消息输入、工具按钮和发送功能。
163
202
 
164
203
  ```vue
165
204
  <template>
@@ -178,13 +217,27 @@ const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
178
217
  </el-button>
179
218
  </el-tooltip>
180
219
  </template>
220
+
221
+ <!-- 自定义发送按钮 -->
222
+ <template #send-button="{ state, execute }">
223
+ <button :disabled="!state.inputValue || state.loading" @click="execute">
224
+ {{ state.loading ? '停止' : '发送' }}
225
+ </button>
226
+ </template>
181
227
  </ChatSender>
182
228
  </template>
183
229
  ```
184
230
 
231
+ #### 功能特性
232
+
233
+ - **自动调整高度** - 根据内容自动调整输入框高度
234
+ - **快捷键支持** - Enter 发送,Shift+Enter 换行
235
+ - **工具按钮** - 支持深度思考、联网搜索等功能
236
+ - **粘贴处理** - 智能处理粘贴的文本和图片
237
+
185
238
  ### ChatSidebar - 侧边栏
186
239
 
187
- 侧边栏组件管理对话历史记录。
240
+ 管理对话历史记录和导航。
188
241
 
189
242
  ```vue
190
243
  <template>
@@ -205,13 +258,25 @@ const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
205
258
  <span>AI对话平台</span>
206
259
  </div>
207
260
  </template>
261
+
262
+ <!-- 自定义新建按钮 -->
263
+ <template #new-chat-button>
264
+ <button class="new-chat-btn">+ 新建对话</button>
265
+ </template>
208
266
  </ChatSidebar>
209
267
  </template>
210
268
  ```
211
269
 
270
+ #### 功能特性
271
+
272
+ - **历史记录管理** - 创建、切换、删除对话记录
273
+ - **搜索功能** - 快速搜索历史对话
274
+ - **折叠展开** - 支持侧边栏折叠以节省空间
275
+ - **拖拽调整** - 可拖拽调整侧边栏宽度
276
+
212
277
  ### ThinkingProcess - 思考过程
213
278
 
214
- 展示AI的思考推理过程。
279
+ 展示 AI 的思考推理过程。
215
280
 
216
281
  ```vue
217
282
  <template>
@@ -232,53 +297,71 @@ const handleBubbleEvent = (eventName: BubbleEvent, data: ChatMessage) => {
232
297
  </template>
233
298
  ```
234
299
 
235
- ## 事件处理
300
+ #### 功能特性
301
+
302
+ - **折叠展开** - 支持思考过程的折叠和展开
303
+ - **Markdown 渲染** - 思考过程支持 Markdown 格式
304
+ - **实时更新** - 思考过程中实时显示内容
236
305
 
237
- ### 消息事件
306
+ ## 🎯 事件处理
307
+
308
+ ### 消息发送事件
238
309
 
239
310
  ```typescript
240
- // 消息发送
241
- const handleSend = (text: string) => {
242
- // 添加用户消息
311
+ // 发送消息
312
+ const handleSend = (text: string, isEnableThink?: boolean, isEnableNet?: boolean) => {
313
+ // 1. 添加用户消息
243
314
  messages.value.push({
244
315
  id: generateId(),
245
316
  role: 'user',
246
317
  content: text,
247
- timestamp: Date.now()
318
+ timestamp: Date.now(),
319
+ isThinking: isEnableThink,
320
+ extraData: {
321
+ question: text
322
+ }
248
323
  });
249
324
 
250
- // 调用AI接口
251
- callAI(text).then((response) => {
325
+ // 2. 调用AI接口
326
+ callAI(text, isEnableThink, isEnableNet).then((response) => {
252
327
  // 处理AI响应
253
328
  });
254
329
  };
330
+ ```
331
+
332
+ ### 气泡交互事件
255
333
 
256
- // 气泡交互事件
334
+ ```typescript
257
335
  const handleBubbleEvent = (eventName: BubbleEvent, message: ChatMessage) => {
258
336
  switch (eventName) {
259
337
  case 'like':
260
338
  // 点赞处理
261
- message.isLiked = true;
339
+ message.isLiked = !message.isLiked;
262
340
  message.isDisliked = false;
263
341
  break;
342
+
264
343
  case 'dislike':
265
344
  // 点踩处理
345
+ message.isDisliked = !message.isDisliked;
266
346
  message.isLiked = false;
267
- message.isDisliked = true;
268
347
  break;
348
+
269
349
  case 'copy':
270
350
  // 复制消息
271
351
  navigator.clipboard.writeText(message.content);
272
352
  ElMessage.success('已复制到剪贴板');
273
353
  break;
354
+
274
355
  case 'reload':
275
356
  // 重新生成
276
357
  handleRegenerate(message);
277
358
  break;
359
+
278
360
  case 'terminate':
279
361
  // 终止生成
280
362
  handleTerminate(message);
281
363
  break;
364
+
282
365
  case 'bookmark':
283
366
  // 收藏消息
284
367
  message.isBookmarked = !message.isBookmarked;
@@ -287,12 +370,52 @@ const handleBubbleEvent = (eventName: BubbleEvent, message: ChatMessage) => {
287
370
  };
288
371
  ```
289
372
 
373
+ ### 记录管理事件
374
+
375
+ ```typescript
376
+ // 创建新记录
377
+ const handleCreateRecord = (messages: ChatMessage[]) => {
378
+ const newRecord: ChatRecord = {
379
+ id: generateId(),
380
+ name: messages[0]?.content.slice(0, 20) + '...' || '新对话',
381
+ content: messages[0]?.content || '',
382
+ type: 'text',
383
+ createTime: new Date().toLocaleDateString(),
384
+ userId: 'current-user',
385
+ extraData: { messages }
386
+ };
387
+
388
+ records.value.unshift(newRecord);
389
+ activeRecordId.value = newRecord.id;
390
+ };
391
+
392
+ // 切换记录
393
+ const handleChangeRecord = (record?: ChatRecord) => {
394
+ if (record) {
395
+ messages.value = record.extraData?.messages || [];
396
+ activeRecordId.value = record.id;
397
+ }
398
+ };
399
+
400
+ // 删除记录
401
+ const handleDeleteRecord = (record: ChatRecord) => {
402
+ const index = records.value.findIndex((r) => r.id === record.id);
403
+ if (index > -1) {
404
+ records.value.splice(index, 1);
405
+ if (activeRecordId.value === record.id) {
406
+ activeRecordId.value = null;
407
+ messages.value = [];
408
+ }
409
+ }
410
+ };
411
+ ```
412
+
290
413
  ### 流式消息处理
291
414
 
292
415
  ```typescript
293
- import { SSEClient } from './sse-client';
416
+ import { SSEClient } from '@kernelift/ai-chat';
294
417
 
295
- const handleStreamResponse = async (question: string) => {
418
+ const handleStreamResponse = async (question: string, enableThink?: boolean) => {
296
419
  const client = new SSEClient('your-token', 'https://api.example.com');
297
420
 
298
421
  let currentMessage: ChatMessage = {
@@ -300,7 +423,8 @@ const handleStreamResponse = async (question: string) => {
300
423
  role: 'assistant',
301
424
  content: '',
302
425
  timestamp: Date.now(),
303
- loading: true
426
+ loading: true,
427
+ isThinking: enableThink
304
428
  };
305
429
 
306
430
  messages.value.push(currentMessage);
@@ -310,6 +434,13 @@ const handleStreamResponse = async (question: string) => {
310
434
  currentMessage.content += content;
311
435
  },
312
436
 
437
+ onThinkingDelta: (content: string) => {
438
+ if (!currentMessage.thoughtProcess) {
439
+ currentMessage.thoughtProcess = '';
440
+ }
441
+ currentMessage.thoughtProcess += content;
442
+ },
443
+
313
444
  onToolCallDelta: (data: any) => {
314
445
  // 处理工具调用
315
446
  if (!currentMessage.toolCalls) {
@@ -333,12 +464,426 @@ const handleStreamResponse = async (question: string) => {
333
464
  };
334
465
 
335
466
  await client.connect('/api/chat/stream', handlers, {
336
- body: { question }
467
+ body: { question, enable_thinking: enableThink }
337
468
  });
338
469
  };
339
470
  ```
340
471
 
341
- ## 样式定制
472
+ ## 🎨 样式定制
473
+
474
+ ### CSS 变量定制
475
+
476
+ ```css
477
+ /* 全局样式变量 */
478
+ :root {
479
+ /* 主题色 */
480
+ --kl-chat-primary-color: #615ced;
481
+ --kl-chat-primary-rgb: 97, 92, 237;
482
+
483
+ /* 文本颜色 */
484
+ --kl-text-color: #1b1b1b;
485
+ --kl-note-color: #9ca3af;
486
+ --kl-process-text-color: #61666b;
487
+
488
+ /* 背景色 */
489
+ --kl-background-color: #fff;
490
+ --kl-main-background-color: #f7f8fc;
491
+ --kl-sender-background-color: #fff;
492
+
493
+ /* 输入框 */
494
+ --kl-sender-text-color: #4a4a4a;
495
+ --kl-tool-button-default-color: #7d7d7d;
496
+
497
+ /* 边框 */
498
+ --kl-border-color: #d1d5db;
499
+
500
+ /* 主题色衍生 */
501
+ --kl-color-primary: var(--kl-chat-primary-color);
502
+ --kl-color-primary-light-3: #8a86f1;
503
+ --kl-color-primary-light-5: #a9a6f5;
504
+ --kl-color-primary-light-7: #c8c6f8;
505
+ --kl-color-primary-light-8: #dddafc;
506
+ --kl-color-primary-light-9: #f2f1fe;
507
+ }
508
+
509
+ /* 暗色主题 */
510
+ .dark {
511
+ --kl-chat-primary-color: #8a86f1;
512
+ --kl-text-color: #e5e7eb;
513
+ --kl-note-color: #9ca3af;
514
+ --kl-background-color: #1a1a1a;
515
+ --kl-main-background-color: #262626;
516
+ --kl-sender-background-color: #2d2d2d;
517
+ --kl-sender-text-color: #e5e7eb;
518
+ --kl-border-color: #374151;
519
+ --kl-process-text-color: #9ca3af;
520
+ }
521
+ ```
522
+
523
+ ### SCSS 样式定制
524
+
525
+ ```scss
526
+ // 自定义主题
527
+ .kernelift-chat-container {
528
+ // 主容器样式
529
+ border-radius: 16px;
530
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
531
+ overflow: hidden;
532
+
533
+ &__aside {
534
+ // 侧边栏样式
535
+ background: linear-gradient(180deg, #ffffff 0%, #f8f9fa 100%);
536
+ border-right: 1px solid var(--kl-border-color);
537
+ }
538
+
539
+ &__messages-section {
540
+ // 消息区域样式
541
+ background-color: var(--kl-main-background-color);
542
+ }
543
+
544
+ &__sender {
545
+ // 发送器样式
546
+ background-color: var(--kl-sender-background-color);
547
+ border-top: 1px solid var(--kl-border-color);
548
+ }
549
+ }
550
+
551
+ // 自定义消息气泡
552
+ .custom-chat-bubble {
553
+ .kernelift-chat-bubble__assistant {
554
+ background: linear-gradient(135deg, #ffffff 0%, #f0f4ff 100%);
555
+ border: 1px solid #e1e8ff;
556
+ border-radius: 12px;
557
+
558
+ &:hover {
559
+ box-shadow: 0 4px 12px rgba(97, 92, 237, 0.1);
560
+ }
561
+ }
562
+
563
+ .kernelift-chat-bubble__user {
564
+ &-content {
565
+ background: linear-gradient(135deg, var(--kl-chat-primary-color) 0%, #8a86f1 100%);
566
+ color: white;
567
+ border-radius: 12px;
568
+
569
+ &:hover {
570
+ opacity: 0.9;
571
+ }
572
+ }
573
+ }
574
+ }
575
+
576
+ // 自定义发送器
577
+ .custom-chat-sender {
578
+ .kernelift-chat-sender__textarea {
579
+ border-radius: 8px;
580
+ border: 2px solid var(--kl-border-color);
581
+
582
+ &:focus {
583
+ border-color: var(--kl-chat-primary-color);
584
+ box-shadow: 0 0 0 3px rgba(97, 92, 237, 0.1);
585
+ }
586
+ }
587
+
588
+ .kernelift-chat-sender__send-button {
589
+ background: linear-gradient(135deg, var(--kl-chat-primary-color) 0%, #8a86f1 100%);
590
+ border-radius: 8px;
591
+
592
+ &:hover:not(:disabled) {
593
+ transform: translateY(-1px);
594
+ box-shadow: 0 4px 12px rgba(97, 92, 237, 0.3);
595
+ }
596
+ }
597
+ }
598
+ ```
599
+
600
+ ### 响应式样式
601
+
602
+ ```scss
603
+ // 移动端适配
604
+ @media (max-width: 768px) {
605
+ .kernelift-chat-container {
606
+ height: 100vh;
607
+ border-radius: 0;
608
+
609
+ &__aside {
610
+ position: fixed;
611
+ left: -100%;
612
+ top: 0;
613
+ height: 100vh;
614
+ width: 80vw;
615
+ z-index: 1000;
616
+ transition: left 0.3s ease;
617
+
618
+ &.mobile-open {
619
+ left: 0;
620
+ }
621
+ }
622
+
623
+ &__main {
624
+ margin-left: 0;
625
+ }
626
+
627
+ &__sender {
628
+ height: 160px;
629
+ }
630
+ }
631
+
632
+ .kernelift-chat-bubble {
633
+ margin: 8px 12px;
634
+
635
+ &__actions {
636
+ opacity: 1; // 移动端始终显示操作按钮
637
+ }
638
+ }
639
+ }
640
+ ```
641
+
642
+ ## 💻 完整示例
643
+
644
+ ### 基础聊天应用
645
+
646
+ ```vue
647
+ <template>
648
+ <div class="chat-app">
649
+ <ChatContainer
650
+ v-model="inputText"
651
+ v-model:loading="senderLoading"
652
+ v-model:messages="messages"
653
+ v-model:record-id="activeRecordId"
654
+ :records="records"
655
+ :theme-mode="themeMode"
656
+ :is-generate-loading="generateLoading"
657
+ :record-actions="recordActions"
658
+ has-theme-mode
659
+ has-thinking
660
+ :markdown-class-name="themeMode === 'dark' ? 'prose-invert' : 'prose'"
661
+ @send="handleSend"
662
+ @cancel="handleCancel"
663
+ @create-record="handleCreateRecord"
664
+ @change-record="handleChangeRecord"
665
+ @bubble-event="handleBubbleEvent"
666
+ @change-theme="(mode) => (themeMode = mode)"
667
+ >
668
+ <!-- 自定义空状态 -->
669
+ <template #empty>
670
+ <div class="empty-state">
671
+ <div class="welcome-title">AI 助手</div>
672
+ <div class="welcome-desc">你好!有什么可以帮助你的吗?</div>
673
+ </div>
674
+ </template>
675
+
676
+ <!-- 自定义 Logo -->
677
+ <template #logo>
678
+ <div class="brand-logo">
679
+ <IconRender icon="material-symbols:chat" />
680
+ <span>AI 对话</span>
681
+ </div>
682
+ </template>
683
+ </ChatContainer>
684
+ </div>
685
+ </template>
686
+
687
+ <script setup lang="ts">
688
+ import { ref, onUnmounted } from 'vue';
689
+ import {
690
+ ChatContainer,
691
+ type BubbleEvent,
692
+ type ChatMessage,
693
+ type ChatRecord,
694
+ type ChatRecordAction
695
+ } from '@kernelift/ai-chat';
696
+ import '@kernelift/ai-chat/style.css';
697
+ import { useStorage } from '@vueuse/core';
698
+
699
+ // 状态管理
700
+ const inputText = ref('');
701
+ const messages = ref<ChatMessage[]>([]);
702
+ const records = useStorage<ChatRecord[]>('chat-records', []);
703
+ const activeRecordId = ref<string | null>(null);
704
+ const senderLoading = ref(false);
705
+ const generateLoading = ref(false);
706
+ const themeMode = ref<'light' | 'dark'>('light');
707
+
708
+ // 记录操作
709
+ const recordActions: ChatRecordAction[] = [
710
+ {
711
+ id: 'edit',
712
+ name: '编辑',
713
+ icon: 'edit',
714
+ action: (record) => {
715
+ console.log('编辑记录:', record);
716
+ }
717
+ },
718
+ {
719
+ id: 'delete',
720
+ name: '删除',
721
+ icon: 'delete',
722
+ action: (record) => {
723
+ records.value = records.value.filter((r) => r.id !== record.id);
724
+ }
725
+ }
726
+ ];
727
+
728
+ // 发送消息
729
+ const handleSend = async (text: string, enableThink?: boolean) => {
730
+ inputText.value = '';
731
+
732
+ // 添加用户消息
733
+ messages.value.push({
734
+ id: Date.now().toString(),
735
+ role: 'user',
736
+ content: text,
737
+ timestamp: Date.now(),
738
+ isThinking: enableThink
739
+ });
740
+
741
+ senderLoading.value = true;
742
+ generateLoading.value = true;
743
+
744
+ try {
745
+ // 模拟 AI 响应
746
+ await simulateAIResponse(text, enableThink);
747
+ } catch (error) {
748
+ console.error('发送失败:', error);
749
+ } finally {
750
+ senderLoading.value = false;
751
+ generateLoading.value = false;
752
+ }
753
+ };
754
+
755
+ // 模拟 AI 响应
756
+ const simulateAIResponse = async (text: string, enableThink?: boolean) => {
757
+ const responseId = Date.now().toString();
758
+
759
+ messages.value.push({
760
+ id: responseId,
761
+ role: 'assistant',
762
+ content: '',
763
+ timestamp: Date.now(),
764
+ loading: true,
765
+ isThinking: enableThink
766
+ });
767
+
768
+ const targetMessage = messages.value.find((m) => m.id === responseId)!;
769
+
770
+ // 模拟思考过程
771
+ if (enableThink) {
772
+ targetMessage.thoughtProcess = '正在分析用户问题...\n';
773
+ await new Promise((resolve) => setTimeout(resolve, 1000));
774
+ targetMessage.thoughtProcess += '整理相关信息...\n';
775
+ await new Promise((resolve) => setTimeout(resolve, 1000));
776
+ targetMessage.thoughtProcess += '生成回答...\n';
777
+ await new Promise((resolve) => setTimeout(resolve, 500));
778
+ targetMessage.isThinking = false;
779
+ }
780
+
781
+ // 模拟流式响应
782
+ const response = `这是对"${text}"的回答。`;
783
+ for (let i = 0; i < response.length; i++) {
784
+ targetMessage.content += response[i];
785
+ await new Promise((resolve) => setTimeout(resolve, 50));
786
+ }
787
+
788
+ targetMessage.loading = false;
789
+ };
790
+
791
+ // 取消生成
792
+ const handleCancel = () => {
793
+ generateLoading.value = false;
794
+ senderLoading.value = false;
795
+
796
+ const lastMessage = messages.value[messages.value.length - 1];
797
+ if (lastMessage?.loading) {
798
+ lastMessage.loading = false;
799
+ lastMessage.isTerminated = true;
800
+ }
801
+ };
802
+
803
+ // 处理气泡事件
804
+ const handleBubbleEvent = (event: BubbleEvent, data: ChatMessage) => {
805
+ switch (event) {
806
+ case 'like':
807
+ data.isLiked = !data.isLiked;
808
+ data.isDisliked = false;
809
+ break;
810
+ case 'dislike':
811
+ data.isDisliked = !data.isDisliked;
812
+ data.isLiked = false;
813
+ break;
814
+ case 'copy':
815
+ navigator.clipboard.writeText(data.content);
816
+ break;
817
+ case 'bookmark':
818
+ data.isBookmarked = !data.isBookmarked;
819
+ break;
820
+ }
821
+ };
822
+
823
+ // 创建记录
824
+ const handleCreateRecord = (msgs: ChatMessage[]) => {
825
+ const newRecord: ChatRecord = {
826
+ id: Date.now().toString(),
827
+ name: msgs[0]?.content.slice(0, 20) + '...' || '新对话',
828
+ content: msgs[0]?.content || '',
829
+ type: 'text',
830
+ createTime: new Date().toLocaleDateString(),
831
+ userId: 'current-user',
832
+ extraData: { messages: msgs }
833
+ };
834
+
835
+ records.value.unshift(newRecord);
836
+ activeRecordId.value = newRecord.id;
837
+ };
838
+
839
+ // 切换记录
840
+ const handleChangeRecord = (record?: ChatRecord) => {
841
+ if (record) {
842
+ messages.value = record.extraData?.messages || [];
843
+ activeRecordId.value = record.id;
844
+ } else {
845
+ messages.value = [];
846
+ activeRecordId.value = null;
847
+ }
848
+ };
849
+ </script>
850
+
851
+ <style scoped>
852
+ .chat-app {
853
+ height: 100vh;
854
+ padding: 20px;
855
+ background: #f5f5f5;
856
+ }
857
+
858
+ .empty-state {
859
+ text-align: center;
860
+ padding: 60px 20px;
861
+ }
862
+
863
+ .welcome-title {
864
+ font-size: 32px;
865
+ font-weight: bold;
866
+ margin-bottom: 16px;
867
+ color: var(--kl-chat-primary-color);
868
+ }
869
+
870
+ .welcome-desc {
871
+ font-size: 16px;
872
+ color: var(--kl-note-color);
873
+ line-height: 1.6;
874
+ }
875
+
876
+ .brand-logo {
877
+ display: flex;
878
+ align-items: center;
879
+ gap: 8px;
880
+ font-size: 18px;
881
+ font-weight: bold;
882
+ }
883
+ </style>
884
+ ```
885
+
886
+ ## 📖 API 文档
342
887
 
343
888
  ### CSS 变量定制
344
889
 
@@ -679,7 +1224,6 @@ function handleScrollBottom() {
679
1224
  :enable-think="true"
680
1225
  :enable-net="false"
681
1226
  :theme-mode="themeMode"
682
- :messager="{}"
683
1227
  :input-height="80"
684
1228
  @send="handleSend"
685
1229
  @cancel="handleCancel"
@@ -810,154 +1354,288 @@ function handleScrollBottom() {
810
1354
  </style>
811
1355
  ```
812
1356
 
813
- ### 移动端适配示例
1357
+ ### Props 属性
1358
+
1359
+ | 属性名 | 类型 | 默认值 | 说明 |
1360
+ | ------------------- | ------------------------ | ----------- | ------------------ |
1361
+ | `records` | `ChatRecord[]` | `[]` | 聊天记录列表 |
1362
+ | `recordActions` | `ChatRecordAction[]` | `[]` | 记录操作按钮配置 |
1363
+ | `hasHeader` | `boolean` | `true` | 是否显示头部 |
1364
+ | `hasThemeMode` | `boolean` | `false` | 是否支持主题切换 |
1365
+ | `hasThinking` | `boolean` | `true` | 是否支持深度思考 |
1366
+ | `hasNetSearch` | `boolean` | `false` | 是否支持联网搜索 |
1367
+ | `hasSenderTools` | `boolean` | `false` | 是否显示发送工具区 |
1368
+ | `showWorkspace` | `boolean` | `true` | 是否显示工作区 |
1369
+ | `showSender` | `boolean` | `true` | 是否显示发送框 |
1370
+ | `isGenerateLoading` | `boolean` | `undefined` | 是否正在生成 |
1371
+ | `defaultRecordId` | `string` | `undefined` | 默认记录ID |
1372
+ | `defaultCollapse` | `boolean` | `false` | 侧边栏默认折叠 |
1373
+ | `defaultAsideWidth` | `number` | `250` | 侧边栏默认宽度 |
1374
+ | `markdownClassName` | `string` | `undefined` | Markdown 样式类名 |
1375
+ | `primaryColor` | `string` | `'#615ced'` | 主题色 |
1376
+ | `themeMode` | `'light' \| 'dark'` | `'light'` | 主题模式 |
1377
+ | `enableNet` | `boolean` | `undefined` | 联网搜索启用状态 |
1378
+ | `enableThink` | `boolean` | `undefined` | 深度思考启用状态 |
1379
+ | `inputHeight` | `number` | `140` | 输入框高度 |
1380
+ | `onCopy` | `(code: string) => void` | `undefined` | 复制代码回调 |
1381
+ | `i18n` | `Record<string, any>` | `zhCN` | 国际化配置 |
1382
+
1383
+ ### v-model 双向绑定
1384
+
1385
+ | 属性名 | 类型 | 说明 |
1386
+ | --------------------- | ---------------- | ---------------- |
1387
+ | `v-model` | `string` | 输入框文本 |
1388
+ | `v-model:messages` | `ChatMessage[]` | 消息列表 |
1389
+ | `v-model:loading` | `boolean` | 发送加载状态 |
1390
+ | `v-model:recordId` | `string \| null` | 当前记录ID |
1391
+ | `v-model:enableThink` | `boolean` | 深度思考启用状态 |
1392
+ | `v-model:enableNet` | `boolean` | 联网搜索启用状态 |
1393
+
1394
+ ### Events 事件
1395
+
1396
+ | 事件名 | 参数 | 说明 |
1397
+ | -------------------- | ------------------------------------------------------------ | -------------- |
1398
+ | `send` | `(text: string, enableThink?: boolean, enableNet?: boolean)` | 发送消息 |
1399
+ | `cancel` | - | 取消生成 |
1400
+ | `clear` | - | 清空聊天 |
1401
+ | `create-record` | `(messages: ChatMessage[])` | 创建记录 |
1402
+ | `change-record` | `(record?: ChatRecord)` | 切换记录 |
1403
+ | `change-collapse` | `(collapse: boolean)` | 折叠状态改变 |
1404
+ | `change-theme` | `(theme: 'light' \| 'dark')` | 主题切换 |
1405
+ | `change-aside-width` | `(width: number)` | 侧边栏宽度改变 |
1406
+ | `click-logo` | - | 点击Logo |
1407
+ | `bubble-event` | `(event: BubbleEvent, message: ChatMessage)` | 气泡交互事件 |
1408
+ | `close-workspace` | - | 关闭工作区 |
1409
+ | `scroll-bottom` | - | 滚动到底部 |
1410
+
1411
+ ### Slots 插槽
1412
+
1413
+ | 插槽名 | 参数 | 说明 |
1414
+ | ------------------------ | ----------------------------------------------------------------------- | -------------- |
1415
+ | `left-aside` | `{ mobile: boolean }` | 左侧边栏 |
1416
+ | `aside` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 主侧边栏 |
1417
+ | `logo` | `{ mobile: boolean }` | Logo区域 |
1418
+ | `new-chat-button` | `{ mobile: boolean }` | 新建聊天按钮 |
1419
+ | `record-dropdown` | `{ mobile: boolean }` | 记录下拉菜单 |
1420
+ | `header` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 头部区域 |
1421
+ | `header-logo` | `{ mobile: boolean }` | 头部Logo |
1422
+ | `bubble-header` | `{ data: ChatMessage, mobile: boolean }` | 气泡头部 |
1423
+ | `bubble-footer` | `{ data: ChatMessage, mobile: boolean }` | 气泡底部 |
1424
+ | `bubble-event` | `{ data: ChatMessage, mobile: boolean }` | 气泡操作区 |
1425
+ | `bubble-content-header` | `{ data: ChatMessage, mobile: boolean }` | 气泡内容头部 |
1426
+ | `bubble-content-footer` | `{ data: ChatMessage, mobile: boolean }` | 气泡内容底部 |
1427
+ | `bubble-thinking-header` | `{ data: ChatMessage, mobile: boolean }` | 思考过程头部 |
1428
+ | `bubble-loading-content` | `{ mobile: boolean }` | 加载内容 |
1429
+ | `empty` | `{ mobile: boolean }` | 空状态 |
1430
+ | `sender-tools` | `{ mobile: boolean }` | 发送工具区 |
1431
+ | `sender-footer-tools` | `{ value: string, loading: boolean, mobile: boolean }` | 发送器底部工具 |
1432
+ | `footer` | `{ mobile: boolean }` | 底部区域 |
1433
+ | `workspace` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 工作区 |
1434
+ | `send-button` | `{ state: object, execute: Function, mobile: boolean }` | 发送按钮 |
1435
+ | `think-button` | `{ state: object, execute: Function, mobile: boolean }` | 思考按钮 |
1436
+ | `net-button` | `{ state: object, execute: Function, mobile: boolean }` | 联网按钮 |
1437
+ | `sender-textarea` | `{ state: object, execute: Function, mobile: boolean, height: number }` | 输入框 |
1438
+
1439
+ ### 类型定义
1440
+
1441
+ #### ChatMessage
1442
+
1443
+ ```typescript
1444
+ interface ChatMessage {
1445
+ id: string;
1446
+ role: 'user' | 'assistant' | 'system';
1447
+ content: string;
1448
+ loading?: boolean;
1449
+ isThinking?: boolean;
1450
+ thoughtCollapse?: boolean;
1451
+ thoughtProcess?: string;
1452
+ timestamp: number;
1453
+ isTerminated?: boolean;
1454
+ isLiked?: boolean;
1455
+ isDisliked?: boolean;
1456
+ isError?: boolean;
1457
+ error?: string;
1458
+ isBookmarked?: boolean;
1459
+ nextTips?: string[];
1460
+ toolCalls?: any[];
1461
+ hideFooterTools?: boolean;
1462
+ extraData?: Record<string, any>;
1463
+ }
1464
+ ```
1465
+
1466
+ #### ChatRecord
1467
+
1468
+ ```typescript
1469
+ interface ChatRecord {
1470
+ id: string;
1471
+ name: string;
1472
+ content: string;
1473
+ type: string;
1474
+ createTime: string;
1475
+ userId: string;
1476
+ updateTime?: string;
1477
+ extraData?: Record<string, any>;
1478
+ }
1479
+ ```
1480
+
1481
+ #### BubbleEvent
1482
+
1483
+ ```typescript
1484
+ type BubbleEvent = 'like' | 'dislike' | 'bookmark' | 'terminate' | 'reload' | 'copy';
1485
+ ```
1486
+
1487
+ #### ChatRecordAction
1488
+
1489
+ ```typescript
1490
+ interface ChatRecordAction {
1491
+ id: string;
1492
+ name: string;
1493
+ icon?: string | Component;
1494
+ divided?: boolean;
1495
+ disabled?: boolean;
1496
+ action: (record: ChatRecord) => void;
1497
+ }
1498
+ ```
1499
+
1500
+ ## ❓ 常见问题
1501
+
1502
+ ### Q: 如何自定义主题色?
1503
+
1504
+ A: 通过 `primary-color` 属性和 CSS 变量可以自定义主题色:
814
1505
 
815
1506
  ```vue
816
- <template>
817
- <ChatContainer
818
- v-model:messages="messages"
819
- v-model:inputText="inputText"
820
- :records="records"
821
- :has-header="true"
822
- :has-sender-tools="false"
823
- :show-workspace="false"
824
- @send="handleSend"
825
- >
826
- <!-- 移动端优化的发送器 -->
827
- <template #sender-footer-tools="{ value, loading, mobile }">
828
- <div class="mobile-tools">
829
- <el-button :disabled="!value || loading" size="small" @click="handleQuickAction">
830
- 快捷操作
831
- </el-button>
832
- </div>
833
- </template>
834
- </ChatContainer>
835
- </template>
1507
+ <ChatContainer primary-color="#ff6b6b" />
1508
+ ```
836
1509
 
837
- <style scoped>
838
- /* 移动端样式优化 */
839
- @media (max-width: 768px) {
840
- :deep(.kernelift-chat-container) {
841
- padding: 4px;
842
- }
1510
+ ```css
1511
+ :root {
1512
+ --kl-chat-primary-color: #ff6b6b;
1513
+ }
1514
+ ```
843
1515
 
844
- :deep(.kernelift-chat-sender) {
845
- height: 160px;
846
- }
1516
+ ### Q: 如何集成 AI 服务?
1517
+
1518
+ A: 在 `send` 事件中调用你的 AI 服务接口:
1519
+
1520
+ ```typescript
1521
+ const handleSend = async (text: string) => {
1522
+ // 添加用户消息
1523
+ messages.value.push({
1524
+ id: generateId(),
1525
+ role: 'user',
1526
+ content: text,
1527
+ timestamp: Date.now()
1528
+ });
847
1529
 
848
- :deep(.kernelift-chat-bubble__actions) {
849
- opacity: 1; /* 移动端始终显示操作按钮 */
1530
+ try {
1531
+ // 调用 AI 服务
1532
+ const response = await yourAIService.chat(text);
1533
+
1534
+ // 添加 AI 响应
1535
+ messages.value.push({
1536
+ id: generateId(),
1537
+ role: 'assistant',
1538
+ content: response.content,
1539
+ timestamp: Date.now()
1540
+ });
1541
+ } catch (error) {
1542
+ console.error('AI 服务错误:', error);
850
1543
  }
851
- }
852
- </style>
1544
+ };
1545
+ ```
1546
+
1547
+ ### Q: 如何实现流式响应?
1548
+
1549
+ A: 使用内置的 SSEClient 或其他流式处理方案:
1550
+
1551
+ ```typescript
1552
+ import { SSEClient } from '@kernelift/ai-chat';
1553
+
1554
+ const handleStreamResponse = async (question: string) => {
1555
+ const client = new SSEClient('token', 'https://api.example.com');
1556
+
1557
+ const currentMessage = {
1558
+ id: generateId(),
1559
+ role: 'assistant',
1560
+ content: '',
1561
+ timestamp: Date.now(),
1562
+ loading: true
1563
+ };
1564
+
1565
+ messages.value.push(currentMessage);
1566
+
1567
+ await client.connect('/chat/stream', {
1568
+ onContent: (content) => {
1569
+ currentMessage.content += content;
1570
+ },
1571
+ onComplete: () => {
1572
+ currentMessage.loading = false;
1573
+ },
1574
+ onError: (error) => {
1575
+ currentMessage.loading = false;
1576
+ currentMessage.isError = true;
1577
+ }
1578
+ });
1579
+ };
1580
+ ```
1581
+
1582
+ ### Q: 如何在移动端使用?
1583
+
1584
+ A: 组件内置了响应式支持,移动端会自动适配。可以通过 `mobile` 插槽参数进行移动端特定定制:
1585
+
1586
+ ```vue
1587
+ <template #sender-footer-tools="{ mobile }">
1588
+ <div v-if="mobile" class="mobile-tools">
1589
+ <!-- 移动端特定工具 -->
1590
+ </div>
1591
+ </template>
1592
+ ```
1593
+
1594
+ ### Q: 如何持久化聊天记录?
1595
+
1596
+ A: 使用 `useStorage` 或其他持久化方案:
1597
+
1598
+ ```typescript
1599
+ import { useStorage } from '@vueuse/core';
1600
+
1601
+ const records = useStorage<ChatRecord[]>('chat-records', []);
1602
+ const messages = useStorage<ChatMessage[]>('current-messages', []);
1603
+ ```
1604
+
1605
+ ### Q: 如何处理长对话?
1606
+
1607
+ A: 建议实现分页加载或记录分割:
1608
+
1609
+ ```typescript
1610
+ const handleLoadMore = async () => {
1611
+ const olderMessages = await loadOlderMessages(currentPage);
1612
+ messages.value.unshift(...olderMessages);
1613
+ };
1614
+ ```
1615
+
1616
+ ### Q: 如何添加自定义工具按钮?
1617
+
1618
+ A: 通过 `sender-tools` 插槽添加:
1619
+
1620
+ ```vue
1621
+ <template #sender-tools>
1622
+ <el-tooltip content="自定义工具">
1623
+ <el-button @click="handleCustomTool">
1624
+ <IconRender icon="custom-icon" />
1625
+ </el-button>
1626
+ </el-tooltip>
1627
+ </template>
853
1628
  ```
854
1629
 
855
- ## API 参考
856
-
857
- ### ChatProps 接口属性说明
858
-
859
- 根据提供的 `withDefaults` 配置,以下表格展示了 `ChatProps` 接口中各个属性的默认值:
860
-
861
- | 参数 | 类型 | 默认值 | 说明 |
862
- | ------------------- | -------------------- | ------------------ | ---------------------------------- |
863
- | `records` | `ChatRecord[]` | `[]` | 聊天记录列表,默认为空数组 |
864
- | `recordActions` | `ChatRecordAction[]` | `[]` | 聊天记录操作按钮配置,默认为空数组 |
865
- | `hasHeader` | `boolean` | `true` | 是否显示聊天区域头部,默认显示 |
866
- | `hasThemeMode` | `boolean` | `false` | 是否支持主题切换,默认不支持 |
867
- | `hasThinking` | `boolean` | `true` | 是否支持深度思考功能,默认支持 |
868
- | `hasNetSearch` | `boolean` | `false` | 是否支持联网搜索功能,默认不支持 |
869
- | `hasSenderTools` | `boolean` | `false` | 是否显示发送工具区域,默认不显示 |
870
- | `showWorkspace` | `boolean` | `true` | 是否显示工作区,默认显示 |
871
- | `showSender` | `boolean` | `true` | 是否显示发送框,默认显示 |
872
- | `isGenerateLoading` | `boolean` | `undefined` | 是否处于生成加载状态,无默认值 |
873
- | `defaultRecordId` | `string` | `undefined` | 默认选中聊天记录ID,无默认值 |
874
- | `defaultCollapse` | `boolean` | `false` | 侧边栏默认折叠状态,默认展开 |
875
- | `defaultAsideWidth` | `number` | `250` | 侧边栏默认宽度,250像素 |
876
- | `markdownClassName` | `string` | `undefined` | Markdown内容自定义类名,无默认值 |
877
- | `primaryColor` | `string` | `'#615ced'` | 主题主色调,默认紫色 `#615ced` |
878
- | `themeMode` | `'light' \| 'dark'` | `'light'` | 主题模式,默认亮色模式 |
879
- | `enableNet` | `boolean` | `undefined` | 联网搜索启用状态,无默认值 |
880
- | `enableThink` | `boolean` | `undefined` | 深度思考启用状态,无默认值 |
881
- | `messager` | `any` | **必需,无默认值** | 消息处理器,必需属性,无默认值 |
882
- | `inputHeight` | `number` | `140` | 发送框高度 |
883
-
884
- #### 注意事项
885
-
886
- 1. **必需属性**:`messager` 是唯一必需属性,没有默认值,必须由父组件传入
887
- 2. **无默认值属性**:以下属性没有默认值,使用时需要检查是否为 `undefined`:
888
- - `isGenerateLoading`
889
- - `defaultRecordId`
890
- - `markdownClassName`
891
- - `enableNet`
892
- - `enableThink`
893
- 3. **默认显示**:以下属性默认值为 `true`,表示默认会显示或启用:
894
- - `hasHeader` - 显示头部
895
- - `showWorkspace` - 显示工作区
896
- - `hasThinking` - 支持深度思考
897
- 4. **默认不显示/不支持**:以下属性默认值为 `false`,表示默认不显示或不支持:
898
- - `hasThemeMode` - 主题切换功能
899
- - `hasNetSearch` - 联网搜索功能
900
- - `hasSenderTools` - 发送工具区域
901
- 5. **尺寸相关**:`defaultAsideWidth` 默认值为 `250`,表示侧边栏默认宽度为250像素
902
- 6. **颜色主题**:
903
- - `primaryColor` 默认紫色 (`#615ced`)
904
- - `themeMode` 默认亮色模式 (`light`)
905
-
906
- ### ChatEvents 接口事件说明
907
-
908
- | 事件名 | 参数 | 返回值类型 | 说明 |
909
- | -------------------- | ------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------- |
910
- | `send` | `value: string`, `isEnableThink?: boolean`, `isEnableNet?: boolean` | `void` | 发送消息时触发,携带消息内容、是否启用思考和是否启用联网搜索参数 |
911
- | `cancel` | 无参数 | `void` | 取消消息生成/发送时触发 |
912
- | `clear` | 无参数 | `void` | 清空当前聊天记录时触发 |
913
- | `create-record` | `data: ChatMessage[]` | `void` | 创建新聊天记录时触发,携带消息数据数组 |
914
- | `change-record` | `value?: ChatRecord` | `void` | 切换聊天记录时触发,携带选中的聊天记录(可选) |
915
- | `change-collapse` | `collapse: boolean` | `void` | 侧边栏折叠状态改变时触发,携带当前折叠状态 |
916
- | `change-theme` | `themeMode: 'light' \| 'dark'` | `void` | 主题切换时触发,携带当前主题模式 |
917
- | `change-aside-width` | `width: number` | `void` | 侧边栏宽度改变时触发,携带当前宽度值(像素) |
918
- | `click-logo` | 无参数 | `void` | 点击Logo时触发 |
919
- | `bubble-event` | `eventName: BubbleEvent`, `data: ChatMessage` | `void` | 消息气泡交互事件触发,携带事件名称和对应的消息数据 |
920
- | `close-workspace` | 无参数 | `void` | 关闭工作区(右侧面板)时触发 |
921
- | `scroll-bottom` | 无参数 | `void` | 聊天记录(左侧面板)滚动至底部时触发 |
922
-
923
- ### 补充说明
924
-
925
- 1. **必需属性**:`messager` 是唯一标记为必需的属性,其他属性均为可选
926
- 2. **受控属性**:`enableNet` 和 `enableThink` 是受控属性,需要通过 `v-model:enable-net` 和 `v-model:enable-think` 进行双向绑定
927
- 3. **事件参数**:所有事件均通过 `emit` 方法触发,父组件可以通过 `@事件名` 监听
928
- 4. **类型定义**:表格中的 `ChatRecord`、`ChatRecordAction`、`ChatMessage`、`BubbleEvent` 等类型需要根据实际项目中的定义进行替换
929
- 5. **默认值**:所有属性的默认值均为 `undefined`,表示组件内部会有相应的默认处理逻辑
930
-
931
- ### 插槽列表
932
-
933
- | Slot 名称 | 作用域参数 | 说明 |
934
- | ------------------------ | --------------------------------------------------------------------------------------------------------- | ------------------------------ |
935
- | `left-aside` | `{ mobile: boolean }` | 左侧侧边栏区域 |
936
- | `aside` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 主侧边栏区域,包含聊天记录列表 |
937
- | `logo` | `{ mobile: boolean }` | 侧边栏 Logo 区域 |
938
- | `new-chat-button` | `{ mobile: boolean }` | 新建聊天按钮区域 |
939
- | `record-dropdown` | `{ mobile: boolean }` | 聊天记录下拉菜单区域 |
940
- | `header` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 聊天头部区域 |
941
- | `header-logo` | `{ mobile: boolean }` | 折叠状态下的头部 Logo |
942
- | `bubble-header` | `{ data: ChatMessage, mobile: boolean }` | 消息气泡头部 |
943
- | `bubble-footer` | `{ data: ChatMessage, mobile: boolean }` | 消息气泡底部 |
944
- | `bubble-event` | `{ data: ChatMessage, mobile: boolean }` | 消息气泡事件处理区域 |
945
- | `bubble-content-header` | `{ data: ChatMessage, mobile: boolean }` | 消息气泡内容顶部 |
946
- | `bubble-content-footer` | `{ data: ChatMessage, mobile: boolean }` | 消息气泡内容底部 |
947
- | `bubble-thinking-header` | `{ data: ChatMessage, mobile: boolean }` | 思考过程头部 |
948
- | `bubble-loading-content` | `{ mobile: boolean }` | 加载中的消息内容 |
949
- | `empty` | `{ mobile: boolean }` | 空状态显示内容 |
950
- | `sender-tools` | `{ mobile: boolean }` | 发送工具区域 |
951
- | `sender-footer-tools` | `{ value: string, loading: boolean, mobile: boolean }` | 发送器底部工具区域 |
952
- | `footer` | `{ mobile: boolean }` | 页面底部区域 |
953
- | `workspace` | `{ record: ChatRecord \| undefined, mobile: boolean }` | 工作区内容 |
954
- | `send-button` | `{ state: { inputValue: string, loading: boolean }, execute: Function, mobile: boolean }` | 发送按钮 |
955
- | `think-button` | `{ state: { enableThink: boolean, hasThinking: boolean }, execute: Function, mobile: boolean }` | 思考按钮 |
956
- | `net-button` | `{ state: { enableNet: boolean, hasNetSearch: boolean }, execute: Function, mobile: boolean }` | 联网按钮 |
957
- | `sender-textarea` | `{ state: { inputValue: string, loading: boolean }, execute: Function, mobile: boolean, height: number }` | 发送输入文本框 |
1630
+ ## 📄 许可证
1631
+
1632
+ GPL-3.0 License
1633
+
1634
+ ## 🤝 贡献
1635
+
1636
+ 欢迎提交 Issue Pull Request!
958
1637
 
959
1638
  ---
960
1639
 
961
- **版本**: 1.0.0
962
- **兼容性**: Vue 3.3+
963
- **License**: 商业使用需联系授权
1640
+ **版本**: 2.0.0
1641
+ **更新时间**: 2024-12-25