af-mobile-client-vue3 1.4.55 → 1.4.57
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/package.json +1 -1
- package/src/App.vue +1 -0
- package/src/components/common/MateChat/components/MateChatContent.vue +3 -11
- package/src/components/common/MateChat/components/MateChatHeader.vue +51 -12
- package/src/components/common/MateChat/composables/useMateChat.ts +50 -70
- package/src/components/common/MateChat/index.vue +20 -5
- package/src/components/common/MateChat/types.ts +241 -236
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -6,7 +6,6 @@ import MateChatHeader from '@af-mobile-client-vue3/components/common/MateChat/co
|
|
|
6
6
|
import { PromptList } from '@af-mobile-client-vue3/components/common/MateChat/components/PromptList'
|
|
7
7
|
import { useMateChat } from '@af-mobile-client-vue3/components/common/MateChat/composables/useMateChat'
|
|
8
8
|
import { useDebounceFn } from '@vueuse/core'
|
|
9
|
-
import { Button as VanButton } from 'vant'
|
|
10
9
|
import { computed, nextTick, ref, watch } from 'vue'
|
|
11
10
|
import 'vant/es/image-preview/style'
|
|
12
11
|
|
|
@@ -110,6 +109,7 @@ function handleSelectSession(session: { chatId: string, title: string, lastTime:
|
|
|
110
109
|
:app-id="props.config.appId"
|
|
111
110
|
:app-key="props.config.appKey"
|
|
112
111
|
@select-session="handleSelectSession"
|
|
112
|
+
@new-conversation="newConversation"
|
|
113
113
|
/>
|
|
114
114
|
<McLayoutContent
|
|
115
115
|
v-if="startPage"
|
|
@@ -161,20 +161,13 @@ function handleSelectSession(session: { chatId: string, title: string, lastTime:
|
|
|
161
161
|
style="flex: 1"
|
|
162
162
|
@item-click="onSubmit($event.label)"
|
|
163
163
|
/>
|
|
164
|
-
<VanButton
|
|
165
|
-
style="margin-left: auto"
|
|
166
|
-
icon="add"
|
|
167
|
-
title="新建对话"
|
|
168
|
-
size="small"
|
|
169
|
-
round
|
|
170
|
-
@click="newConversation"
|
|
171
|
-
/>
|
|
172
164
|
</div>
|
|
173
165
|
<McLayoutSender>
|
|
174
166
|
<McInput
|
|
175
167
|
:value="inputValue"
|
|
176
168
|
placeholder="请输入您的问题,我会为您解答"
|
|
177
169
|
:max-length="2000"
|
|
170
|
+
:autosize="true"
|
|
178
171
|
@change="(e) => (inputValue = e)"
|
|
179
172
|
@submit="onSubmit"
|
|
180
173
|
/>
|
|
@@ -186,7 +179,7 @@ function handleSelectSession(session: { chatId: string, title: string, lastTime:
|
|
|
186
179
|
.chat-card {
|
|
187
180
|
width: 100%;
|
|
188
181
|
max-width: 1200px;
|
|
189
|
-
height:
|
|
182
|
+
height: 100%;
|
|
190
183
|
background: #ffffff;
|
|
191
184
|
border-radius: 24px;
|
|
192
185
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
|
|
@@ -205,7 +198,6 @@ function handleSelectSession(session: { chatId: string, title: string, lastTime:
|
|
|
205
198
|
/* 移动端适配 */
|
|
206
199
|
@media (max-width: 768px) {
|
|
207
200
|
.chat-card {
|
|
208
|
-
height: calc(100vh - 16px);
|
|
209
201
|
border-radius: 16px;
|
|
210
202
|
padding: 8px;
|
|
211
203
|
}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import type { ChatHistoryItem } from '@af-mobile-client-vue3/components/common/MateChat/types'
|
|
3
3
|
import { getHistories } from '@af-mobile-client-vue3/components/common/MateChat/apiService'
|
|
4
4
|
import { useChatHistoryCache } from '@af-mobile-client-vue3/components/common/MateChat/composables/useChatHistoryCache'
|
|
5
|
-
import { Empty, Icon, Loading, Popup } from 'vant'
|
|
5
|
+
import { Empty, Icon, Loading, Popup, Popover as VanPopover } from 'vant'
|
|
6
6
|
import { ref } from 'vue'
|
|
7
7
|
import 'vant/es/popup/style'
|
|
8
8
|
import 'vant/es/empty/style'
|
|
9
9
|
import 'vant/es/loading/style'
|
|
10
10
|
import 'vant/es/icon/style'
|
|
11
|
+
import 'vant/es/popover/style'
|
|
11
12
|
|
|
12
13
|
interface Props {
|
|
13
14
|
/**
|
|
@@ -47,6 +48,10 @@ interface Emits {
|
|
|
47
48
|
* 选择某条历史会话
|
|
48
49
|
*/
|
|
49
50
|
(e: 'selectSession', session: SessionItem): void
|
|
51
|
+
/**
|
|
52
|
+
* 新建对话
|
|
53
|
+
*/
|
|
54
|
+
(e: 'newConversation'): void
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -58,6 +63,12 @@ const emit = defineEmits<Emits>()
|
|
|
58
63
|
const showHistory = ref(false)
|
|
59
64
|
const isLoading = ref(false)
|
|
60
65
|
const sessionList = ref<SessionItem[]>([])
|
|
66
|
+
const showMenu = ref(false)
|
|
67
|
+
|
|
68
|
+
const menuActions: { text: string, key: 'new' | 'history', icon: string }[] = [
|
|
69
|
+
{ text: '新对话', key: 'new', icon: 'add-o' },
|
|
70
|
+
{ text: '历史对话', key: 'history', icon: 'clock-o' },
|
|
71
|
+
]
|
|
61
72
|
|
|
62
73
|
// 使用历史会话缓存
|
|
63
74
|
const { getCachedHistory, setCachedHistory } = useChatHistoryCache()
|
|
@@ -72,6 +83,20 @@ function handleSelectSession(session: SessionItem) {
|
|
|
72
83
|
showHistory.value = false
|
|
73
84
|
}
|
|
74
85
|
|
|
86
|
+
/**
|
|
87
|
+
* 处理下拉菜单点击
|
|
88
|
+
*/
|
|
89
|
+
function handleMenuSelect(action: { text: string, key: 'new' | 'history', icon?: string }) {
|
|
90
|
+
showMenu.value = false
|
|
91
|
+
if (action.key === 'new') {
|
|
92
|
+
emit('newConversation')
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
if (action.key === 'history') {
|
|
96
|
+
handleOpenHistory()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
75
100
|
/**
|
|
76
101
|
* 格式化时间字符串为日期时间字符串
|
|
77
102
|
*/
|
|
@@ -139,11 +164,24 @@ async function fetchSessions() {
|
|
|
139
164
|
|
|
140
165
|
<template>
|
|
141
166
|
<div class="matechat-header-wrapper">
|
|
142
|
-
<McHeader
|
|
167
|
+
<McHeader
|
|
168
|
+
:logo-img="showTitle ? props.logoImage : ''"
|
|
169
|
+
:title="showTitle ? props.title : ''"
|
|
170
|
+
:logo-clickable="false"
|
|
171
|
+
>
|
|
143
172
|
<template #operationArea>
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
173
|
+
<VanPopover
|
|
174
|
+
v-model:show="showMenu"
|
|
175
|
+
placement="bottom-end"
|
|
176
|
+
:actions="menuActions"
|
|
177
|
+
@select="handleMenuSelect"
|
|
178
|
+
>
|
|
179
|
+
<template #reference>
|
|
180
|
+
<div class="matechat-header-history-btn">
|
|
181
|
+
<Icon name="ellipsis" size="16" />
|
|
182
|
+
</div>
|
|
183
|
+
</template>
|
|
184
|
+
</VanPopover>
|
|
147
185
|
</template>
|
|
148
186
|
</McHeader>
|
|
149
187
|
|
|
@@ -204,15 +242,17 @@ async function fetchSessions() {
|
|
|
204
242
|
justify-content: center;
|
|
205
243
|
width: 32px;
|
|
206
244
|
height: 32px;
|
|
207
|
-
border-radius:
|
|
208
|
-
background-color: rgba(255, 255, 255, 0.
|
|
245
|
+
border-radius: 8px;
|
|
246
|
+
background-color: rgba(255, 255, 255, 0.9);
|
|
247
|
+
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
248
|
+
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.12);
|
|
209
249
|
cursor: pointer;
|
|
210
250
|
transition: all 0.2s ease;
|
|
211
251
|
|
|
212
252
|
&:hover {
|
|
213
|
-
background-color:
|
|
214
|
-
transform: translateY(-
|
|
215
|
-
box-shadow: 0 2px
|
|
253
|
+
background-color: #ffffff;
|
|
254
|
+
transform: translateY(-0.5px);
|
|
255
|
+
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.16);
|
|
216
256
|
}
|
|
217
257
|
}
|
|
218
258
|
|
|
@@ -221,7 +261,6 @@ async function fetchSessions() {
|
|
|
221
261
|
width: 320px;
|
|
222
262
|
max-width: 80vw;
|
|
223
263
|
background-color: #ffffff;
|
|
224
|
-
border-radius: 16px;
|
|
225
264
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
|
|
226
265
|
padding: 16px 16px 12px;
|
|
227
266
|
box-sizing: border-box;
|
|
@@ -260,7 +299,7 @@ async function fetchSessions() {
|
|
|
260
299
|
|
|
261
300
|
&__item {
|
|
262
301
|
padding: 10px 8px;
|
|
263
|
-
border-radius:
|
|
302
|
+
border-radius: 0;
|
|
264
303
|
cursor: pointer;
|
|
265
304
|
transition: all 0.2s ease;
|
|
266
305
|
|
|
@@ -138,97 +138,77 @@ export function useMateChat(config: MateChatConfig) {
|
|
|
138
138
|
return
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
// 流式:使用 FastGPT SSE
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
// 流式:使用 FastGPT SSE,增量更新最后一条模型消息内容
|
|
142
|
+
// 规则:
|
|
143
|
+
// 1)每次收到 chunk 都立即累加到 msg.content,保证实时流式效果
|
|
144
|
+
// 2)在累加后的内容上做一次“是否为转人工 JSON 消息”的前缀粗判:以 {"msgType 开头
|
|
145
|
+
// 3)如果判断为转人工,则保持 loading 状态,等待 onComplete 再统一处理整条消息
|
|
146
|
+
// 4)如果判断不是转人工,则当作普通文本流式展示,onComplete 时仅结束 loading
|
|
147
|
+
const transferPrefix = '{"msgType'
|
|
148
|
+
let checkedTransfer = false // 是否已经做过类型判定
|
|
149
|
+
let isTransferMessage = false // 是否判定为转人工消息
|
|
146
150
|
|
|
147
151
|
const callbacks: ChatStreamCallbacks = {
|
|
148
152
|
onMessage(chunk) {
|
|
149
|
-
|
|
153
|
+
const msg = messages.value[loadingMessageIndex]
|
|
154
|
+
if (!msg) {
|
|
150
155
|
return
|
|
151
156
|
}
|
|
157
|
+
// 1. 实时累加内容,保证流式体验
|
|
158
|
+
msg.content += chunk
|
|
152
159
|
|
|
153
|
-
//
|
|
160
|
+
// 2. 如果还没有做过类型判定,基于当前累积内容做一次前缀粗判
|
|
154
161
|
if (!checkedTransfer) {
|
|
155
|
-
const trimmed =
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
const trimmed = msg.content.trimStart()
|
|
163
|
+
// 内容太短,无法判断,继续等待更多 chunk
|
|
164
|
+
if (!trimmed || trimmed.length < transferPrefix.length) {
|
|
158
165
|
return
|
|
159
166
|
}
|
|
160
167
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const msg = messages.value[loadingMessageIndex]
|
|
165
|
-
if (!msg) {
|
|
166
|
-
return
|
|
167
|
-
}
|
|
168
|
-
msg.content += chunk
|
|
169
|
-
msg.loading = true
|
|
170
|
-
return
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 有可能是 JSON,累积前缀做精准匹配
|
|
174
|
-
prefixBuffer += trimmed
|
|
175
|
-
|
|
176
|
-
// 如果当前前缀还是 transferPrefix 的前缀,继续等后续 chunk
|
|
177
|
-
if (transferPrefix.startsWith(prefixBuffer)) {
|
|
178
|
-
// 还没完整匹配上整个标识,继续等待
|
|
179
|
-
if (prefixBuffer.length < transferPrefix.length) {
|
|
180
|
-
return
|
|
181
|
-
}
|
|
168
|
+
if (trimmed.startsWith(transferPrefix)) {
|
|
169
|
+
// 以 {"msgType 开头,标记为“可能是转人工消息”
|
|
170
|
+
isTransferMessage = true
|
|
182
171
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
messages.value.push({
|
|
188
|
-
from: 'service',
|
|
189
|
-
content: '您好,客服xxx工号xxx为你服务。功能开发中,敬请期待。',
|
|
190
|
-
})
|
|
191
|
-
transferHandled = true
|
|
192
|
-
checkedTransfer = true
|
|
193
|
-
// 更新缓存:追加用户消息和客服消息(在 onComplete 中统一处理)
|
|
194
|
-
return
|
|
172
|
+
else {
|
|
173
|
+
// 不以 {"msgType 开头,当作普通文本处理
|
|
174
|
+
isTransferMessage = false
|
|
175
|
+
msg.loading = false
|
|
195
176
|
}
|
|
196
|
-
|
|
197
|
-
// 前缀与约定不匹配,当作普通内容处理,并不再尝试转人工识别
|
|
198
177
|
checkedTransfer = true
|
|
199
|
-
const msg = messages.value[loadingMessageIndex]
|
|
200
|
-
if (!msg) {
|
|
201
|
-
return
|
|
202
|
-
}
|
|
203
|
-
msg.content += prefixBuffer
|
|
204
|
-
msg.loading = true
|
|
205
|
-
prefixBuffer = ''
|
|
206
|
-
return
|
|
207
178
|
}
|
|
208
|
-
|
|
209
|
-
// 已经判断过不会转人工,正常流式追加内容
|
|
210
|
-
const msg = messages.value[loadingMessageIndex]
|
|
211
|
-
if (!msg) {
|
|
212
|
-
return
|
|
213
|
-
}
|
|
214
|
-
msg.content += chunk
|
|
215
|
-
msg.loading = true
|
|
216
179
|
},
|
|
217
180
|
onComplete() {
|
|
218
|
-
if (transferHandled) {
|
|
219
|
-
// 转人工情况:更新缓存
|
|
220
|
-
appendMessages(chatId.value, [
|
|
221
|
-
{ from: 'user', content: evt },
|
|
222
|
-
{ from: 'service', content: '您好,客服xxx工号xxx为你服务。功能开发中,敬请期待。' },
|
|
223
|
-
])
|
|
224
|
-
return
|
|
225
|
-
}
|
|
226
181
|
const msg = messages.value[loadingMessageIndex]
|
|
227
182
|
if (!msg) {
|
|
228
183
|
return
|
|
229
184
|
}
|
|
185
|
+
// 根据前面判定结果决定如何处理整条消息
|
|
186
|
+
if (isTransferMessage) {
|
|
187
|
+
// 尝试按 JSON 解析,判断是否真的是转人工指令
|
|
188
|
+
try {
|
|
189
|
+
const parsed = JSON.parse(msg.content.trim())
|
|
190
|
+
if (parsed && parsed.msgType === 'transfer') {
|
|
191
|
+
// 确认为转人工:移除模型气泡,插入客服气泡
|
|
192
|
+
messages.value.splice(loadingMessageIndex, 1)
|
|
193
|
+
messages.value.push({
|
|
194
|
+
from: 'service',
|
|
195
|
+
content: '您好,客服xxx工号xxx为你服务。功能开发中,敬请期待。',
|
|
196
|
+
})
|
|
197
|
+
// 转人工情况:更新缓存
|
|
198
|
+
appendMessages(chatId.value, [
|
|
199
|
+
{ from: 'user', content: evt },
|
|
200
|
+
{ from: 'service', content: '您好,客服xxx工号xxx为你服务。功能开发中,敬请期待。' },
|
|
201
|
+
])
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// 解析失败则回退为普通文本处理
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 普通消息:结束 loading,按完整文本渲染并写入缓存
|
|
230
211
|
msg.loading = false
|
|
231
|
-
// 流式完成后更新缓存:追加用户消息和完整的模型回复
|
|
232
212
|
appendMessages(chatId.value, [
|
|
233
213
|
{ from: 'user', content: evt },
|
|
234
214
|
{ from: 'model', content: msg.content, loading: false },
|
|
@@ -41,6 +41,21 @@ const finalLoading = computed(() => forceLoading.value || isLoading.value || !!c
|
|
|
41
41
|
// 当前使用的配置
|
|
42
42
|
const currentConfig = ref<MateChatConfig | null>(null)
|
|
43
43
|
|
|
44
|
+
const defaultBackgroundGradient = 'background: linear-gradient(to bottom, #d0c9ff 0%, #e6d6f0 8%, #f1dbea 12%, #c8dcfb 40%, #abc6f6 60%, #87aefe 90%)'
|
|
45
|
+
// 琉璃配色
|
|
46
|
+
// background: linear-gradient(to bottom, #a8f0ed 0%, #a8e6cf 8%, #c5b3ff 12%, #e0b3ff 40%, #fff4b8 60%, #ffb8d1 90%);
|
|
47
|
+
// 紫罗兰配色
|
|
48
|
+
// background: linear-gradient(to bottom, #d0c9ff 0%, #e6d6f0 8%, #f1dbea 12%, #c8dcfb 40%, #abc6f6 60%, #87aefe 90%);
|
|
49
|
+
// 蓝白配色
|
|
50
|
+
// 'linear-gradient(to bottom, #1c57e0 0%, #3b82f6 20%, #60a5fa 40%, #93c5fd 60%, #dbeafe 80%, #ffffff 100%)'
|
|
51
|
+
// 计算背景渐变样式
|
|
52
|
+
const backgroundStyle = computed(() => {
|
|
53
|
+
const gradient = currentConfig.value?.backgroundGradient || defaultBackgroundGradient
|
|
54
|
+
return {
|
|
55
|
+
background: gradient,
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
44
59
|
// 存储原始配置数据
|
|
45
60
|
const rawConfigs = ref<MateChatConfigs | MateChatConfig | null>(null)
|
|
46
61
|
|
|
@@ -305,7 +320,7 @@ onMounted(() => {
|
|
|
305
320
|
</script>
|
|
306
321
|
|
|
307
322
|
<template>
|
|
308
|
-
<div id="mate-chat-view">
|
|
323
|
+
<div id="mate-chat-view" :style="backgroundStyle">
|
|
309
324
|
<!-- 密码输入对话框 -->
|
|
310
325
|
<PasswordDialog
|
|
311
326
|
ref="passwordDialogRef"
|
|
@@ -351,9 +366,9 @@ onMounted(() => {
|
|
|
351
366
|
#mate-chat-view {
|
|
352
367
|
/* 外层渐变背景容器 */
|
|
353
368
|
width: 100%;
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
/*
|
|
369
|
+
height: 100%;
|
|
370
|
+
min-height: 100%;
|
|
371
|
+
/* 背景色通过 :style 绑定从配置中获取 */
|
|
357
372
|
padding: 20px;
|
|
358
373
|
display: flex;
|
|
359
374
|
justify-content: center;
|
|
@@ -381,7 +396,7 @@ onMounted(() => {
|
|
|
381
396
|
|
|
382
397
|
/* 移动端适配 */
|
|
383
398
|
@media (max-width: 768px) {
|
|
384
|
-
height: calc(
|
|
399
|
+
height: calc(100% - 18px);
|
|
385
400
|
border-radius: 16px;
|
|
386
401
|
padding: 8px;
|
|
387
402
|
}
|
|
@@ -1,236 +1,241 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MateChat 提示项接口
|
|
3
|
-
*/
|
|
4
|
-
export interface MateChatPromptItem {
|
|
5
|
-
value: string
|
|
6
|
-
label: string
|
|
7
|
-
iconConfig?: {
|
|
8
|
-
name: string
|
|
9
|
-
color?: string
|
|
10
|
-
}
|
|
11
|
-
desc?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* MateChat 配置接口
|
|
16
|
-
*/
|
|
17
|
-
export interface MateChatConfig {
|
|
18
|
-
/**
|
|
19
|
-
* 可选密码,如果存在则需要密码验证
|
|
20
|
-
*/
|
|
21
|
-
password?: string
|
|
22
|
-
/**
|
|
23
|
-
* FastGPT 应用 ID
|
|
24
|
-
*/
|
|
25
|
-
appId: string
|
|
26
|
-
/**
|
|
27
|
-
* FastGPT API Key
|
|
28
|
-
*/
|
|
29
|
-
appKey: string
|
|
30
|
-
/**
|
|
31
|
-
* 介绍文案
|
|
32
|
-
*/
|
|
33
|
-
description: string[]
|
|
34
|
-
/**
|
|
35
|
-
* 首屏推荐问题列表
|
|
36
|
-
*/
|
|
37
|
-
introPrompt: MateChatPromptItem[]
|
|
38
|
-
/**
|
|
39
|
-
* 底部快捷问题列表
|
|
40
|
-
*/
|
|
41
|
-
simplePrompt: MateChatPromptItem[]
|
|
42
|
-
/**
|
|
43
|
-
* 客服名称
|
|
44
|
-
*/
|
|
45
|
-
serviceName: string
|
|
46
|
-
/**
|
|
47
|
-
* 是否使用流式对话
|
|
48
|
-
*/
|
|
49
|
-
useStream: boolean
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MateChat 提示项接口
|
|
3
|
+
*/
|
|
4
|
+
export interface MateChatPromptItem {
|
|
5
|
+
value: string
|
|
6
|
+
label: string
|
|
7
|
+
iconConfig?: {
|
|
8
|
+
name: string
|
|
9
|
+
color?: string
|
|
10
|
+
}
|
|
11
|
+
desc?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* MateChat 配置接口
|
|
16
|
+
*/
|
|
17
|
+
export interface MateChatConfig {
|
|
18
|
+
/**
|
|
19
|
+
* 可选密码,如果存在则需要密码验证
|
|
20
|
+
*/
|
|
21
|
+
password?: string
|
|
22
|
+
/**
|
|
23
|
+
* FastGPT 应用 ID
|
|
24
|
+
*/
|
|
25
|
+
appId: string
|
|
26
|
+
/**
|
|
27
|
+
* FastGPT API Key
|
|
28
|
+
*/
|
|
29
|
+
appKey: string
|
|
30
|
+
/**
|
|
31
|
+
* 介绍文案
|
|
32
|
+
*/
|
|
33
|
+
description: string[]
|
|
34
|
+
/**
|
|
35
|
+
* 首屏推荐问题列表
|
|
36
|
+
*/
|
|
37
|
+
introPrompt: MateChatPromptItem[]
|
|
38
|
+
/**
|
|
39
|
+
* 底部快捷问题列表
|
|
40
|
+
*/
|
|
41
|
+
simplePrompt: MateChatPromptItem[]
|
|
42
|
+
/**
|
|
43
|
+
* 客服名称
|
|
44
|
+
*/
|
|
45
|
+
serviceName: string
|
|
46
|
+
/**
|
|
47
|
+
* 是否使用流式对话
|
|
48
|
+
*/
|
|
49
|
+
useStream: boolean
|
|
50
|
+
/**
|
|
51
|
+
* 背景渐变颜色(CSS linear-gradient 字符串)
|
|
52
|
+
* 如果不提供,使用默认蓝白渐变
|
|
53
|
+
*/
|
|
54
|
+
backgroundGradient?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 配置中心返回的多个配置对象
|
|
59
|
+
* key 为配置名称,value 为 MateChatConfig
|
|
60
|
+
*/
|
|
61
|
+
export type MateChatConfigs = Record<string, MateChatConfig>
|
|
62
|
+
|
|
63
|
+
// ==================== API 相关类型定义 ====================
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 聊天消息接口
|
|
67
|
+
*/
|
|
68
|
+
export interface ChatMessage {
|
|
69
|
+
role: 'user' | 'assistant' | 'system'
|
|
70
|
+
content: string
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 聊天请求参数接口
|
|
75
|
+
*/
|
|
76
|
+
export interface ChatCompletionsRequest {
|
|
77
|
+
chatId: string
|
|
78
|
+
stream: boolean
|
|
79
|
+
detail: boolean
|
|
80
|
+
messages: ChatMessage[]
|
|
81
|
+
customUid?: string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 聊天响应使用情况接口
|
|
86
|
+
*/
|
|
87
|
+
export interface ChatUsage {
|
|
88
|
+
prompt_tokens: number
|
|
89
|
+
completion_tokens: number
|
|
90
|
+
total_tokens: number
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 聊天响应选择项接口
|
|
95
|
+
*/
|
|
96
|
+
export interface ChatChoice {
|
|
97
|
+
message: {
|
|
98
|
+
role: 'assistant'
|
|
99
|
+
content: string
|
|
100
|
+
}
|
|
101
|
+
finish_reason: string
|
|
102
|
+
index: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 聊天响应接口
|
|
107
|
+
*/
|
|
108
|
+
export interface ChatCompletionsResponse {
|
|
109
|
+
id: string
|
|
110
|
+
model: string
|
|
111
|
+
usage: ChatUsage
|
|
112
|
+
choices: ChatChoice[]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 业务层聊天结果
|
|
117
|
+
*/
|
|
118
|
+
export interface ChatBizResult {
|
|
119
|
+
/**
|
|
120
|
+
* normal: 普通回复
|
|
121
|
+
* transfer: 转人工
|
|
122
|
+
*/
|
|
123
|
+
type: 'normal' | 'transfer'
|
|
124
|
+
/**
|
|
125
|
+
* 大模型原始返回内容
|
|
126
|
+
*/
|
|
127
|
+
content: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 流式对话回调
|
|
132
|
+
*/
|
|
133
|
+
export interface ChatStreamCallbacks {
|
|
134
|
+
/**
|
|
135
|
+
* 每次收到 FastGPT SSE 的增量内容时触发
|
|
136
|
+
*/
|
|
137
|
+
onMessage?: (chunk: string) => void
|
|
138
|
+
/**
|
|
139
|
+
* 流结束时触发(包括收到 [DONE] 或正常读取结束)
|
|
140
|
+
*/
|
|
141
|
+
onComplete?: () => void
|
|
142
|
+
/**
|
|
143
|
+
* 请求或解析发生异常时触发
|
|
144
|
+
*/
|
|
145
|
+
onError?: (error: unknown) => void
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 历史会话项接口
|
|
150
|
+
*/
|
|
151
|
+
export interface ChatHistoryItem {
|
|
152
|
+
chatId: string
|
|
153
|
+
updateTime: string
|
|
154
|
+
appId: string
|
|
155
|
+
customTitle: string
|
|
156
|
+
title: string
|
|
157
|
+
top: boolean
|
|
158
|
+
[key: string]: any
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 历史会话查询请求参数接口
|
|
163
|
+
*/
|
|
164
|
+
export interface GetHistoriesRequest {
|
|
165
|
+
appId: string
|
|
166
|
+
outLinkUid: string
|
|
167
|
+
offset: number
|
|
168
|
+
pageSize: number
|
|
169
|
+
source: string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 历史会话查询响应接口
|
|
174
|
+
*/
|
|
175
|
+
export interface GetHistoriesResponse {
|
|
176
|
+
code: number
|
|
177
|
+
statusText: string
|
|
178
|
+
message: string
|
|
179
|
+
data: {
|
|
180
|
+
list: ChatHistoryItem[]
|
|
181
|
+
total: number
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 历史会话记录项接口
|
|
187
|
+
*/
|
|
188
|
+
export interface ChatRecordItem {
|
|
189
|
+
_id: string
|
|
190
|
+
dataId: string
|
|
191
|
+
hideInUI: boolean
|
|
192
|
+
obj: 'Human' | 'AI'
|
|
193
|
+
value: Array<{
|
|
194
|
+
type: string
|
|
195
|
+
text: {
|
|
196
|
+
content: string
|
|
197
|
+
}
|
|
198
|
+
}>
|
|
199
|
+
customFeedbacks: any[]
|
|
200
|
+
time: string
|
|
201
|
+
durationSeconds?: number
|
|
202
|
+
llmModuleAccount?: number
|
|
203
|
+
totalQuoteList?: any[]
|
|
204
|
+
historyPreviewLength?: number
|
|
205
|
+
[key: string]: any
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 获取历史会话记录请求参数接口
|
|
210
|
+
*/
|
|
211
|
+
export interface GetPaginationRecordsRequest {
|
|
212
|
+
appId: string
|
|
213
|
+
chatId: string
|
|
214
|
+
offset: number
|
|
215
|
+
pageSize: number
|
|
216
|
+
loadCustomFeedbacks: boolean
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 获取历史会话记录响应接口
|
|
221
|
+
*/
|
|
222
|
+
export interface GetPaginationRecordsResponse {
|
|
223
|
+
code: number
|
|
224
|
+
statusText: string
|
|
225
|
+
message: string
|
|
226
|
+
data: {
|
|
227
|
+
list: ChatRecordItem[]
|
|
228
|
+
total: number
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ==================== MateChat 组件内部类型 ====================
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* MateChat 组件内部使用的消息结构
|
|
236
|
+
*/
|
|
237
|
+
export interface MateChatMessage {
|
|
238
|
+
from: 'user' | 'model' | 'service'
|
|
239
|
+
content: string
|
|
240
|
+
loading?: boolean
|
|
241
|
+
}
|