@linker-design-plus/chat-next 1.0.1 → 1.0.3
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 +237 -0
- package/dist/eventSource.js +1 -0
- package/dist/eventSource.mjs +65 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +59 -1
- package/dist/index.mjs +52803 -57
- package/dist/src/component/ChatActionbar/chat-actionbar.vue.d.ts +15 -0
- package/dist/src/component/ChatAttachments/chat-attachments.vue.d.ts +29 -0
- package/dist/src/component/ChatItem/chat-item.vue.d.ts +30 -0
- package/dist/src/component/ChatLoading/chat-loading.vue.d.ts +9 -0
- package/dist/src/component/ChatMarkdown/chat-markdown.vue.d.ts +9 -0
- package/dist/src/component/ChatSender/chat-sender-editor.vue.d.ts +15 -0
- package/dist/src/component/ChatSender/chat-sender-select.vue.d.ts +16 -0
- package/dist/src/component/ChatSender/chat-sender.vue.d.ts +51 -0
- package/dist/src/component/ChatThinking/chat-thinking.vue.d.ts +21 -0
- package/dist/src/hooks/useCopy.d.ts +5 -0
- package/dist/src/hooks/useEventSource.d.ts +53 -0
- package/dist/src/typing/chat-next/i-chat-actionbar.d.ts +1 -0
- package/dist/src/typing/chat-next/i-chat-attachment.d.ts +12 -0
- package/dist/src/typing/chat-next/i-chat-item.d.ts +11 -0
- package/dist/src/typing/chat-next/i-chat-loading.d.ts +1 -0
- package/dist/src/typing/chat-next/i-chat-sender.d.ts +15 -0
- package/dist/src/typing/chat-next/i-chat-thinking.d.ts +15 -0
- package/dist/src/typing/index.d.ts +6 -0
- package/dist/src/utils/file.d.ts +7 -0
- package/dist/style.css +1 -1
- package/package.json +15 -1
- package/dist/src/component/chat-item.vue.d.ts +0 -20
- package/dist/src/component/chat-sender.vue.d.ts +0 -8
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# ChatNext 组件库
|
|
2
|
+
|
|
3
|
+
提供了一套用于构建聊天界面的 Vue 3 组件集合。
|
|
4
|
+
|
|
5
|
+
## 组件列表
|
|
6
|
+
|
|
7
|
+
- [ChatSender 发送框](#chatsender-发送框)
|
|
8
|
+
- [ChatAttachments 附件列表](#chatattachments-附件列表)
|
|
9
|
+
- [ChatActionbar 消息操作栏](#chatactionbar-消息操作栏)
|
|
10
|
+
- [ChatThinking 思考过程](#chatthinking-思考过程)
|
|
11
|
+
- [ChatLoading 加载状态](#chatloading-加载状态)
|
|
12
|
+
- [ChatItem 聊天消息项](#chatitem-聊天消息项)
|
|
13
|
+
- [ChatMarkdown Markdown 渲染](#chatmarkdown-markdown渲染)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ChatSender 发送框
|
|
18
|
+
|
|
19
|
+
用于输入和发送聊天消息的组件。支持普通文本输入和富文本模板输入。
|
|
20
|
+
|
|
21
|
+
### 属性 (Props)
|
|
22
|
+
|
|
23
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
24
|
+
| ------------------- | ----------------------------------- | -------------------------------- | ------------------------------------------------------- |
|
|
25
|
+
| `value` / `v-model` | `string` | `-` | 输入框的值。支持语法糖 `v-model` 或 `v-model:value` |
|
|
26
|
+
| `defaultValue` | `string` | `''` | 输入框的值。非受控属性 |
|
|
27
|
+
| `loading` | `boolean` | `true` | 发送按钮是否处于加载状态。为 `false` 时显示停止分析按钮 |
|
|
28
|
+
| `allowEmpty` | `boolean` | `false` | 是否允许发送空内容 |
|
|
29
|
+
| `textareaProps` | `TextareaProps` | `{ placeholder: '输入消息...' }` | 输入框的属性,如 `placeholder` |
|
|
30
|
+
| `templates` | `ITemplateNode[]` | `[]` | 模板节点列表,提供后将开启富文本模板模式 |
|
|
31
|
+
| `validate` | `() => boolean \| Promise<boolean>` | `-` | 发送前的校验函数 |
|
|
32
|
+
|
|
33
|
+
### 事件 (Emits)
|
|
34
|
+
|
|
35
|
+
| 事件名 | 参数 | 说明 |
|
|
36
|
+
| ------------------- | ---------------- | ---------------------------- |
|
|
37
|
+
| `send` | `(text: string)` | 发送消息时触发 |
|
|
38
|
+
| `stop` | `-` | 点击停止按钮时触发 |
|
|
39
|
+
| `update:value` | `(val: string)` | 输入内容变化时触发 |
|
|
40
|
+
| `update:modelValue` | `(val: string)` | 输入内容变化时触发 (v-model) |
|
|
41
|
+
|
|
42
|
+
### 插槽 (Slots)
|
|
43
|
+
|
|
44
|
+
| 插槽名 | 说明 |
|
|
45
|
+
| --------------- | -------------------- |
|
|
46
|
+
| `header` | 输入框外标题区域扩展 |
|
|
47
|
+
| `inner-header` | 输入框内标题区域扩展 |
|
|
48
|
+
| `input-prefix` | 输入框前方区域 |
|
|
49
|
+
| `footer-prefix` | 输入框左下角区域扩展 |
|
|
50
|
+
| `footer-suffix` | 输入框右下角区域扩展 |
|
|
51
|
+
|
|
52
|
+
### 接口类型
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
export type TextareaProps = {
|
|
56
|
+
placeholder?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export interface ITemplateNode {
|
|
60
|
+
type: 'text' | 'select' | 'input';
|
|
61
|
+
id: string; // unique id for template nodes
|
|
62
|
+
content?: string; // only for text
|
|
63
|
+
options?: { label: string; value: string }[] | string[]; // only for select
|
|
64
|
+
multiple?: boolean; // only for select
|
|
65
|
+
value?: string | string[]; // for select and input (string[] for multiple select)
|
|
66
|
+
placeholder?: string; // for input and select
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ChatAttachments 附件列表
|
|
73
|
+
|
|
74
|
+
用于展示上传的附件或文件列表。
|
|
75
|
+
|
|
76
|
+
### 属性 (Props)
|
|
77
|
+
|
|
78
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
79
|
+
| ------------ | ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| `items` | `IChatAttachment[]` | `[]` | 附件列表数据 |
|
|
81
|
+
| `overflow` | `'wrap' \| 'scrollX' \| 'scrollY'` | `'wrap'` | 文件列表超出时样式 |
|
|
82
|
+
| `removable` | `boolean` | `true` | 是否显示删除按钮 |
|
|
83
|
+
| `fieldNames` | `object` | `-` | 自定义数据字段映射,包含 `name`, `suffix`, `size`, `status`, `statusText`, `icon`, `url`, `type`, `uid` |
|
|
84
|
+
|
|
85
|
+
### 事件 (Emits)
|
|
86
|
+
|
|
87
|
+
| 事件名 | 参数 | 说明 |
|
|
88
|
+
| -------- | ---------------------------------------- | ------------------ |
|
|
89
|
+
| `remove` | `(item: IChatAttachment, index: number)` | 点击删除按钮时触发 |
|
|
90
|
+
|
|
91
|
+
### 接口类型
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
export interface IChatAttachment {
|
|
95
|
+
uid?: string | number;
|
|
96
|
+
icon?: string;
|
|
97
|
+
suffix?: string;
|
|
98
|
+
name: string;
|
|
99
|
+
url?: string;
|
|
100
|
+
type?: string;
|
|
101
|
+
size?: number;
|
|
102
|
+
status?: 'success' | 'error' | 'pending';
|
|
103
|
+
statusText?: string;
|
|
104
|
+
[key: string]: any;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## ChatActionbar 消息操作栏
|
|
111
|
+
|
|
112
|
+
展示在聊天消息底部的操作按钮列表(如复制、重试、点赞、点踩)。
|
|
113
|
+
|
|
114
|
+
### 属性 (Props)
|
|
115
|
+
|
|
116
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
117
|
+
| --------- | ---------------- | ----------------------------------- | ---------------------- |
|
|
118
|
+
| `actions` | `IChatActions[]` | `['copy', 'replay', 'good', 'bad']` | 需要显示的操作项列表 |
|
|
119
|
+
| `content` | `string` | `''` | 用于复制操作的文本内容 |
|
|
120
|
+
|
|
121
|
+
> `good`和`bad`点赞点踩暂未实现
|
|
122
|
+
|
|
123
|
+
### 事件 (Emits)
|
|
124
|
+
|
|
125
|
+
| 事件名 | 参数 | 说明 |
|
|
126
|
+
| -------- | ------------------------ | ------------------ |
|
|
127
|
+
| `action` | `(action: IChatActions)` | 点击操作按钮时触发 |
|
|
128
|
+
|
|
129
|
+
### 接口类型
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
export type IChatActions = 'copy' | 'replay' | 'good' | 'bad';
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## ChatThinking 思考过程
|
|
138
|
+
|
|
139
|
+
展示 AI 思考过程的组件,支持展开/收起和不同的动画状态。
|
|
140
|
+
|
|
141
|
+
### 属性 (Props)
|
|
142
|
+
|
|
143
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
144
|
+
| ----------- | ---------------------------------------------- | --------------------------------- | ---------------------------------- |
|
|
145
|
+
| `content` | `IChatThinkingContent` | `{ text: '', title: '思考过程' }` | 思考内容及标题 |
|
|
146
|
+
| `layout` | `'block' \| 'border'` | `'block'` | 布局方式,块级或带虚线边框 |
|
|
147
|
+
| `status` | `'pending' \| 'complete' \| 'stop' \| 'error'` | `'pending'` | 思考状态 |
|
|
148
|
+
| `maxHeight` | `number` | `-` | 展开内容的最大高度 |
|
|
149
|
+
| `animation` | `'circle' \| 'moving' \| 'gradient'` | `'circle'` | 思考中的动画类型 |
|
|
150
|
+
| `collapsed` | `boolean` | `false` | 是否折叠(支持 v-model:collapsed) |
|
|
151
|
+
|
|
152
|
+
### 事件 (Emits)
|
|
153
|
+
|
|
154
|
+
| 事件名 | 参数 | 说明 |
|
|
155
|
+
| ------------------ | ---------------- | ------------------ |
|
|
156
|
+
| `update:collapsed` | `(val: boolean)` | 折叠状态变化时触发 |
|
|
157
|
+
|
|
158
|
+
### 接口类型
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
export interface IChatThinkingContent {
|
|
162
|
+
title?: string;
|
|
163
|
+
text?: string;
|
|
164
|
+
}
|
|
165
|
+
export type IChatThinkingLayout = 'block' | 'border';
|
|
166
|
+
export type IChatThinkingStatus = 'pending' | 'complete' | 'stop' | 'error';
|
|
167
|
+
export type IChatThinkingAnimation = 'circle' | 'moving' | 'gradient';
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## ChatLoading 加载状态
|
|
173
|
+
|
|
174
|
+
消息加载中的动画组件。
|
|
175
|
+
|
|
176
|
+
### 属性 (Props)
|
|
177
|
+
|
|
178
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
179
|
+
| ----------- | ----------------- | ------- | ------------------------------------ |
|
|
180
|
+
| `animation` | `'spin' \| 'dot'` | `'dot'` | 加载动画类型,支持旋转圆环或跳动小点 |
|
|
181
|
+
|
|
182
|
+
### 接口类型
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
export type IChatLoadingAnimation = 'spin' | 'dot';
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## ChatItem 聊天消息项
|
|
191
|
+
|
|
192
|
+
完整的单条聊天消息组件,整合了头像、内容、加载状态、操作栏等。
|
|
193
|
+
|
|
194
|
+
### 属性 (Props)
|
|
195
|
+
|
|
196
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
197
|
+
| ---------- | ----------- | ------- | ------------ |
|
|
198
|
+
| `chatItem` | `IChatItem` | `-` | 消息项数据 |
|
|
199
|
+
| `avatar` | `boolean` | `false` | 是否显示头像 |
|
|
200
|
+
|
|
201
|
+
### 插槽 (Slots)
|
|
202
|
+
|
|
203
|
+
| 插槽名 | 说明 |
|
|
204
|
+
| ------------ | ---------------------------------------- |
|
|
205
|
+
| `user-files` | 用户角色时的文件展示区域 |
|
|
206
|
+
| `loading` | AI 角色 `status='pending'` 时的加载区域 |
|
|
207
|
+
| `thinking` | AI 角色 `status='thinking'` 时的思考区域 |
|
|
208
|
+
| `actions` | AI 角色时的操作栏区域 |
|
|
209
|
+
| `suggest` | AI 角色时的建议区域 |
|
|
210
|
+
| `user-extra` | 用户角色底部的扩展区域 |
|
|
211
|
+
|
|
212
|
+
### 接口类型
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
export interface IChatItem {
|
|
216
|
+
id: string | number;
|
|
217
|
+
role: 'user' | 'assistant' | 'system';
|
|
218
|
+
content: string;
|
|
219
|
+
avatar?: string;
|
|
220
|
+
status?: 'pending' | 'thinking' | 'success' | 'error';
|
|
221
|
+
[key: string]: any;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## ChatMarkdown Markdown 渲染
|
|
228
|
+
|
|
229
|
+
用于安全地渲染包含代码块和高亮的 Markdown 文本。
|
|
230
|
+
|
|
231
|
+
### 属性 (Props)
|
|
232
|
+
|
|
233
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
234
|
+
| --------- | -------- | ------ | ------------------------ |
|
|
235
|
+
| `content` | `string` | `''` | 要渲染的 Markdown 字符串 |
|
|
236
|
+
|
|
237
|
+
_注意:此组件内置了 Highlight.js 语法高亮和 GitHub Markdown CSS 样式,并自带代码块一键复制功能。_
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("@microsoft/fetch-event-source"),u=require("vue"),o=r=>{try{const t=JSON.parse(r);return typeof t=="object"&&t!==null&&(Array.isArray(t)||t.constructor===Object)}catch{return!1}},v=()=>{const r=u.ref(null),t=u.ref(!1);return{startEventSource:async e=>{t.value=!0,r.value=new AbortController;try{await s.fetchEventSource(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json",accept:"*/*",...e.headers},body:e.body?JSON.stringify(e.body):void 0,openWhenHidden:!0,signal:r.value.signal,async onmessage(a){var c;try{if(!o(a.data))return;const l=JSON.parse(a.data);(c=e.onMessage)==null||c.call(e,{event:a.event,data:l})}catch(n){console.error("解析消息失败:",n)}},onclose(){var a;(a=e.onClose)==null||a.call(e)},onerror(a){var c,n;throw(c=e.onError)==null||c.call(e,a),(n=r.value)==null||n.abort(),a}})}finally{t.value=!1}},stopEventSource:()=>{r.value&&(r.value.abort(),r.value=null)},isConnecting:t,controller:r}};exports.useEventSource=v;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { fetchEventSource as o } from "@microsoft/fetch-event-source";
|
|
2
|
+
import { ref as l } from "vue";
|
|
3
|
+
const s = (r) => {
|
|
4
|
+
try {
|
|
5
|
+
const a = JSON.parse(r);
|
|
6
|
+
return typeof a == "object" && a !== null && (Array.isArray(a) || a.constructor === Object);
|
|
7
|
+
} catch {
|
|
8
|
+
return !1;
|
|
9
|
+
}
|
|
10
|
+
}, S = () => {
|
|
11
|
+
const r = l(null), a = l(!1);
|
|
12
|
+
return {
|
|
13
|
+
startEventSource: async (e) => {
|
|
14
|
+
a.value = !0, r.value = new AbortController();
|
|
15
|
+
try {
|
|
16
|
+
await o(e.url, {
|
|
17
|
+
method: e.method || "POST",
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
// 'Accept-Language': localStorage.getItem('language') === 'en' ? 'en' : 'zh-CN',
|
|
21
|
+
// token: JSON.parse(localStorage.getItem('loginState') || '{}')?.token || '',
|
|
22
|
+
// tenant: localStorage.getItem('currentTanantID') || '',
|
|
23
|
+
accept: "*/*",
|
|
24
|
+
...e.headers
|
|
25
|
+
},
|
|
26
|
+
body: e.body ? JSON.stringify(e.body) : void 0,
|
|
27
|
+
openWhenHidden: !0,
|
|
28
|
+
signal: r.value.signal,
|
|
29
|
+
async onmessage(t) {
|
|
30
|
+
var n;
|
|
31
|
+
try {
|
|
32
|
+
if (!s(t.data))
|
|
33
|
+
return;
|
|
34
|
+
const u = JSON.parse(t.data);
|
|
35
|
+
(n = e.onMessage) == null || n.call(e, {
|
|
36
|
+
event: t.event,
|
|
37
|
+
data: u
|
|
38
|
+
});
|
|
39
|
+
} catch (c) {
|
|
40
|
+
console.error("解析消息失败:", c);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
onclose() {
|
|
44
|
+
var t;
|
|
45
|
+
(t = e.onClose) == null || t.call(e);
|
|
46
|
+
},
|
|
47
|
+
onerror(t) {
|
|
48
|
+
var n, c;
|
|
49
|
+
throw (n = e.onError) == null || n.call(e, t), (c = r.value) == null || c.abort(), t;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
} finally {
|
|
53
|
+
a.value = !1;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
stopEventSource: () => {
|
|
57
|
+
r.value && (r.value.abort(), r.value = null);
|
|
58
|
+
},
|
|
59
|
+
isConnecting: a,
|
|
60
|
+
controller: r
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export {
|
|
64
|
+
S as useEventSource
|
|
65
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export { default as HChatItem } from './src/component/chat-item.vue';
|
|
2
|
-
export { default as HChatSender } from './src/component/chat-sender.vue';
|
|
1
|
+
export { default as HChatItem } from './src/component/ChatItem/chat-item.vue';
|
|
2
|
+
export { default as HChatSender } from './src/component/ChatSender/chat-sender.vue';
|
|
3
|
+
export { default as HChatMarkdown } from './src/component/ChatMarkdown/chat-markdown.vue';
|
|
4
|
+
export { default as HChatActionbar } from './src/component/ChatActionbar/chat-actionbar.vue';
|
|
5
|
+
export { default as HChatLoading } from './src/component/ChatLoading/chat-loading.vue';
|
|
6
|
+
export { default as HChatThinking } from './src/component/ChatThinking/chat-thinking.vue';
|
|
7
|
+
export { default as HChatAttachments } from './src/component/ChatAttachments/chat-attachments.vue';
|
|
8
|
+
export { default as HChatSenderSelect } from './src/component/ChatSender/chat-sender-select.vue';
|