|
@@ -23,13 +23,14 @@
|
|
|
<div v-for="(item, index) in messageList" :key="index">
|
|
<div v-for="(item, index) in messageList" :key="index">
|
|
|
<!-- AI消息 -->
|
|
<!-- AI消息 -->
|
|
|
<div class="ai-message" v-if="item.type !== 'user'">
|
|
<div class="ai-message" v-if="item.type !== 'user'">
|
|
|
- {{ item.content }}
|
|
|
|
|
|
|
+ <MarkdownView class="left-text" :content="item.content" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 用户消息 -->
|
|
<!-- 用户消息 -->
|
|
|
<div class="user-message" v-if="item.type === 'user'">
|
|
<div class="user-message" v-if="item.type === 'user'">
|
|
|
{{ item.content }}
|
|
{{ item.content }}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- 输入框和发送按钮 -->
|
|
<!-- 输入框和发送按钮 -->
|
|
@@ -81,7 +82,7 @@ onMounted(() => {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
// 聊天对话
|
|
// 聊天对话
|
|
|
-const activeConversationModelPath = ref(null) // 选中的对话编号
|
|
|
|
|
|
|
+const activeConversationModelPath= ref(null) // 选中的对话编号
|
|
|
const activeConversationId = ref(null) // 选中的对话编号
|
|
const activeConversationId = ref(null) // 选中的对话编号
|
|
|
const activeConversation = ref(null) // 选中的 Conversation
|
|
const activeConversation = ref(null) // 选中的 Conversation
|
|
|
const conversationInProgress = ref(false) // 对话是否正在进行中。目前只有【发送】消息时,会更新为 true,避免切换对话、删除对话等操作,导致 stream 中断
|
|
const conversationInProgress = ref(false) // 对话是否正在进行中。目前只有【发送】消息时,会更新为 true,避免切换对话、删除对话等操作,导致 stream 中断
|
|
@@ -105,10 +106,11 @@ const enableContext = ref(true) // 是否开启上下文
|
|
|
const receiveMessageFullText = ref('')
|
|
const receiveMessageFullText = ref('')
|
|
|
const receiveMessageDisplayedText = ref('')
|
|
const receiveMessageDisplayedText = ref('')
|
|
|
|
|
|
|
|
|
|
+
|
|
|
// =========== 【聊天对话】相关 ===========
|
|
// =========== 【聊天对话】相关 ===========
|
|
|
|
|
|
|
|
/** 获取对话信息 */
|
|
/** 获取对话信息 */
|
|
|
-const getConversation = async id => {
|
|
|
|
|
|
|
+const getConversation = async (id) => {
|
|
|
if (!id) {
|
|
if (!id) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -122,10 +124,11 @@ const getConversation = async id => {
|
|
|
activeConversationModelPath.value = personImage.value
|
|
activeConversationModelPath.value = personImage.value
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
// =========== 【发送消息】相关 ===========
|
|
// =========== 【发送消息】相关 ===========
|
|
|
|
|
|
|
|
/** 处理来自 keydown 的发送消息 */
|
|
/** 处理来自 keydown 的发送消息 */
|
|
|
-const handleSendByKeydown = async event => {
|
|
|
|
|
|
|
+const handleSendByKeydown = async (event) => {
|
|
|
// 判断用户是否在输入
|
|
// 判断用户是否在输入
|
|
|
if (isComposing.value) {
|
|
if (isComposing.value) {
|
|
|
return
|
|
return
|
|
@@ -154,7 +157,7 @@ const handleSendByButton = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 处理 prompt 输入变化 */
|
|
/** 处理 prompt 输入变化 */
|
|
|
-const handlePromptInput = event => {
|
|
|
|
|
|
|
+const handlePromptInput = (event) => {
|
|
|
// 非输入法 输入设置为 true
|
|
// 非输入法 输入设置为 true
|
|
|
if (!isComposing.value) {
|
|
if (!isComposing.value) {
|
|
|
// 回车 event data 是 null
|
|
// 回车 event data 是 null
|
|
@@ -183,7 +186,7 @@ const onCompositionend = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 真正执行【发送】消息操作 */
|
|
/** 真正执行【发送】消息操作 */
|
|
|
-const doSendMessage = async content => {
|
|
|
|
|
|
|
+const doSendMessage = async (content) => {
|
|
|
// 校验
|
|
// 校验
|
|
|
if (content.length < 1) {
|
|
if (content.length < 1) {
|
|
|
console.error('发送失败,原因:内容为空!')
|
|
console.error('发送失败,原因:内容为空!')
|
|
@@ -204,7 +207,8 @@ const doSendMessage = async content => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 真正执行【发送】消息操作 */
|
|
/** 真正执行【发送】消息操作 */
|
|
|
-const doSendMessageStream = async userMessage => {
|
|
|
|
|
|
|
+const doSendMessageStream = async (userMessage) => {
|
|
|
|
|
+
|
|
|
// 创建 AbortController 实例,以便中止请求
|
|
// 创建 AbortController 实例,以便中止请求
|
|
|
conversationInAbortController.value = new AbortController()
|
|
conversationInAbortController.value = new AbortController()
|
|
|
// 标记对话进行中
|
|
// 标记对话进行中
|
|
@@ -236,42 +240,41 @@ const doSendMessageStream = async userMessage => {
|
|
|
let isFirstChunk = true // 是否是第一个 chunk 消息段
|
|
let isFirstChunk = true // 是否是第一个 chunk 消息段
|
|
|
|
|
|
|
|
await sendChatMessageStream(
|
|
await sendChatMessageStream(
|
|
|
- userMessage.conversationId,
|
|
|
|
|
- userMessage.content,
|
|
|
|
|
- conversationInAbortController.value,
|
|
|
|
|
- enableContext.value,
|
|
|
|
|
- async res => {
|
|
|
|
|
- const { code, data, msg } = JSON.parse(res.data)
|
|
|
|
|
- if (code !== 0) {
|
|
|
|
|
- console.log(`对话异常! ${msg}`)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- // 如果内容为空,就不处理。
|
|
|
|
|
- // if (data.receive.content === '') {
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- receiveMessageFullText.value =
|
|
|
|
|
- receiveMessageFullText.value + data.receive.content
|
|
|
|
|
- // 首次返回需要添加一个 message 到页面,后面的都是更新
|
|
|
|
|
- if (isFirstChunk) {
|
|
|
|
|
- isFirstChunk = false
|
|
|
|
|
- // 弹出两个假数据
|
|
|
|
|
- activeMessageList.value.pop()
|
|
|
|
|
- activeMessageList.value.pop()
|
|
|
|
|
- // 更新返回的数据
|
|
|
|
|
- activeMessageList.value.push(data.send)
|
|
|
|
|
- activeMessageList.value.push(data.receive)
|
|
|
|
|
|
|
+ userMessage.conversationId,
|
|
|
|
|
+ userMessage.content,
|
|
|
|
|
+ conversationInAbortController.value,
|
|
|
|
|
+ enableContext.value,
|
|
|
|
|
+ async (res) => {
|
|
|
|
|
+ const { code, data, msg } = JSON.parse(res.data)
|
|
|
|
|
+ if (code !== 0) {
|
|
|
|
|
+ console.log(`对话异常! ${msg}`)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果内容为空,就不处理。
|
|
|
|
|
+ // if (data.receive.content === '') {
|
|
|
|
|
+ // return
|
|
|
|
|
+ // }
|
|
|
|
|
+ receiveMessageFullText.value = receiveMessageFullText.value + data.receive.content
|
|
|
|
|
+ // 首次返回需要添加一个 message 到页面,后面的都是更新
|
|
|
|
|
+ if (isFirstChunk) {
|
|
|
|
|
+ isFirstChunk = false
|
|
|
|
|
+ // 弹出两个假数据
|
|
|
|
|
+ activeMessageList.value.pop()
|
|
|
|
|
+ activeMessageList.value.pop()
|
|
|
|
|
+ // 更新返回的数据
|
|
|
|
|
+ activeMessageList.value.push(data.send)
|
|
|
|
|
+ activeMessageList.value.push(data.receive)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ (error) => {
|
|
|
|
|
+ console.log(`对话异常! ${error}`)
|
|
|
|
|
+ stopStream()
|
|
|
|
|
+ // 需要抛出异常,禁止重试
|
|
|
|
|
+ throw error
|
|
|
|
|
+ },
|
|
|
|
|
+ () => {
|
|
|
|
|
+ stopStream()
|
|
|
}
|
|
}
|
|
|
- },
|
|
|
|
|
- error => {
|
|
|
|
|
- console.log(`对话异常! ${error}`)
|
|
|
|
|
- stopStream()
|
|
|
|
|
- // 需要抛出异常,禁止重试
|
|
|
|
|
- throw error
|
|
|
|
|
- },
|
|
|
|
|
- () => {
|
|
|
|
|
- stopStream()
|
|
|
|
|
- }
|
|
|
|
|
)
|
|
)
|
|
|
} catch {}
|
|
} catch {}
|
|
|
}
|
|
}
|
|
@@ -312,9 +315,9 @@ const messageList = computed(() => {
|
|
|
// ============== 【消息滚动】相关 =============
|
|
// ============== 【消息滚动】相关 =============
|
|
|
|
|
|
|
|
/** 滚动到 message 底部 */
|
|
/** 滚动到 message 底部 */
|
|
|
-const scrollToBottom = async isIgnore => {
|
|
|
|
|
|
|
+const scrollToBottom = async (isIgnore) => {
|
|
|
// if (messageRef.value) {
|
|
// if (messageRef.value) {
|
|
|
- // messageRef.value.scrollToBottom(isIgnore)
|
|
|
|
|
|
|
+ // messageRef.value.scrollToBottom(isIgnore)
|
|
|
// }
|
|
// }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -332,9 +335,7 @@ const textRoll = async () => {
|
|
|
const task = async () => {
|
|
const task = async () => {
|
|
|
// 调整速度
|
|
// 调整速度
|
|
|
const diff =
|
|
const diff =
|
|
|
- (receiveMessageFullText.value.length -
|
|
|
|
|
- receiveMessageDisplayedText.value.length) /
|
|
|
|
|
- 10
|
|
|
|
|
|
|
+ (receiveMessageFullText.value.length - receiveMessageDisplayedText.value.length) / 10
|
|
|
if (diff > 5) {
|
|
if (diff > 5) {
|
|
|
textSpeed.value = 10
|
|
textSpeed.value = 10
|
|
|
} else if (diff > 2) {
|
|
} else if (diff > 2) {
|
|
@@ -354,8 +355,7 @@ const textRoll = async () => {
|
|
|
index++
|
|
index++
|
|
|
|
|
|
|
|
// 更新 message
|
|
// 更新 message
|
|
|
- const lastMessage =
|
|
|
|
|
- activeMessageList.value[activeMessageList.value.length - 1]
|
|
|
|
|
|
|
+ const lastMessage = activeMessageList.value[activeMessageList.value.length - 1]
|
|
|
lastMessage.content = receiveMessageDisplayedText.value
|
|
lastMessage.content = receiveMessageDisplayedText.value
|
|
|
// 滚动到住下面
|
|
// 滚动到住下面
|
|
|
await scrollToBottom()
|
|
await scrollToBottom()
|
|
@@ -376,22 +376,24 @@ const textRoll = async () => {
|
|
|
} catch {}
|
|
} catch {}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/** 初始化 **/
|
|
/** 初始化 **/
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
- if (personId.value) {
|
|
|
|
|
|
|
+ if(personId.value) {
|
|
|
// 智能问答
|
|
// 智能问答
|
|
|
- CreateDialogue({ roleId: personId.value })
|
|
|
|
|
- .then(res => {
|
|
|
|
|
- console.log('创建会话:', res)
|
|
|
|
|
- activeConversationId.value = res.data
|
|
|
|
|
- })
|
|
|
|
|
- .catch(error => {
|
|
|
|
|
- console.error('请求出错:', error)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ CreateDialogue({roleId: personId.value}).then(res => {
|
|
|
|
|
+ console.log("创建会话:",res);
|
|
|
|
|
+ activeConversationId.value = res.data;
|
|
|
|
|
+ }).catch(error => {
|
|
|
|
|
+ console.error('请求出错:', error);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
await getConversation(personId.value)
|
|
await getConversation(personId.value)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
// 获取列表数据
|
|
// 获取列表数据
|
|
|
// activeMessageListLoading.value = true
|
|
// activeMessageListLoading.value = true
|
|
|
|
|
+
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|