diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue
index 914b8c30..3c74d927 100644
--- a/src/views/ai/chat/index.vue
+++ b/src/views/ai/chat/index.vue
@@ -147,11 +147,13 @@
@@ -162,11 +164,23 @@ import {ChatMessageApi, ChatMessageSendVO, ChatMessageVO} from "@/api/ai/chat/me
import {formatDate} from "@/utils/formatTime";
import {useClipboard} from '@vueuse/core'
+// 初始化 copy 到粘贴板
+const { copy } = useClipboard();
+
const searchName = ref('') // 查询的内容
const conversationId = ref('1781604279872581648') // 对话id
const conversationInProgress = ref() // 对话进行中
+const conversationInAbortController = ref() // 对话进行中 abort 控制器(控制 stream 对话)
+
const prompt = ref() // prompt
-const promptRes = ref() // prompt res
+
+// 判断 消息列表 滚动的位置(用于判断是否需要滚动到消息最下方)
+const messageContainer: any = ref(null);
+const isScrolling = ref(false)//用于判断用户是否在滚动
+
+/** chat message 列表 */
+defineOptions({ name: 'chatMessageList' })
+const list = ref([]) // 列表的数据
const changeConversation = (conversation) => {
console.log(conversation)
@@ -190,82 +204,71 @@ const searchConversation = () => {
/** send */
const onSend = async () => {
+ const content = prompt.value;
+ // 清空输入框
+ prompt.value = ''
const requestParams = {
conversationId: conversationId.value,
- content: prompt.value,
+ content: content,
} as unknown as ChatMessageSendVO
// 添加 message
const userMessage = await ChatMessageApi.add(requestParams) as unknown as ChatMessageVO;
list.value.push(userMessage)
// 滚动到住下面
scrollToBottom();
- //
+ // stream
await doSendStream(userMessage)
+ //
}
const doSendStream = async (userMessage: ChatMessageVO) => {
// 创建AbortController实例,以便中止请求
- const ctrl = new AbortController()
- // 发送 event stream
- let isFirstMessage = true
- ChatMessageApi.sendStream(userMessage.id, ctrl,(message) => {
- console.log('message', message)
- const data = JSON.parse(message.data) as unknown as ChatMessageVO
- // 如果没有内容结束链接
- if (data.content === '') {
- ctrl.abort()
- }
- // 首次返回需要添加一个 message 到页面,后面的都是更新
- if (isFirstMessage) {
- isFirstMessage = false;
- list.value.push(data)
- } else {
- const lastMessage = list.value[list.value.length - 1];
- lastMessage.content = lastMessage.content + data.content
- list.value[list.value - 1] = lastMessage
- }
- // 滚动到最下面
- scrollToBottom();
- }, (error) => {
- console.log('error', error)
- }, () => {
- console.log('close')
- })
+ conversationInAbortController.value = new AbortController()
+ // 标记对话进行中
+ conversationInProgress.value = true
+ try {
+ // 发送 event stream
+ let isFirstMessage = true
+ ChatMessageApi.sendStream(userMessage.id, conversationInAbortController.value,(message) => {
+ console.log('message', message)
+ const data = JSON.parse(message.data) as unknown as ChatMessageVO
+ // 如果没有内容结束链接
+ if (data.content === '') {
+ // 标记对话结束
+ conversationInProgress.value = false;
+ // 结束 stream 对话
+ conversationInAbortController.value.abort()
+ }
+ // 首次返回需要添加一个 message 到页面,后面的都是更新
+ if (isFirstMessage) {
+ isFirstMessage = false;
+ list.value.push(data)
+ } else {
+ const lastMessage = list.value[list.value.length - 1];
+ lastMessage.content = lastMessage.content + data.content
+ list.value[list.value - 1] = lastMessage
+ }
+ // 滚动到最下面
+ scrollToBottom();
+ }, (error) => {
+ console.log('error', error)
+ // 标记对话结束
+ conversationInProgress.value = false;
+ // 结束 stream 对话
+ conversationInAbortController.value.abort()
+ }, () => {
+ console.log('close')
+ // 标记对话结束
+ conversationInProgress.value = false;
+ // 结束 stream 对话
+ conversationInAbortController.value.abort()
+ })
+ } finally {
+
+ }
- // // 创建一个正在进行中的message
- // const chatMessage = {
- // id: null, // 编号
- // conversationId: conversationId.value, // 会话编号
- // type: 'system', // 消息类型
- // userId: null, // 用户编号
- // roleId: null, // 角色编号
- // model: null, // 模型标志
- // modelId: null, // 模型编号
- // content: '加载中...', // 聊天内容
- // tokens: null, // 消耗 Token 数量
- // createTime: new Date(), // 创建时间
- // } as unknown as ChatMessageVO
- // list.value.push(chatMessage)
- // // 滚动到最下面
- // scrollToBottom();
}
-/** Prompt */
-const onPromptInput = async (e) => {
- console.log(e.data)
- // prompt.value = e.data
-}
-
-
-// 初始化 copy 到粘贴板
-const { copy, isSupported } = useClipboard();
-/** chat message 列表 */
-defineOptions({ name: 'chatMessageList' })
-const list = ref([]) // 列表的数据
-
-// 对话id TODO @范 先写死
-const content = '苹果是什么颜色?'
-
/** 查询列表 */
const messageList = async () => {
try {
@@ -277,9 +280,7 @@ const messageList = async () => {
} finally {
}
}
-// ref
-const messageContainer: any = ref(null);
-const isScrolling = ref(false)//用于判断用户是否在滚动
+
function scrollToBottom() {
nextTick(() => {
@@ -321,6 +322,10 @@ const onDelete = async (id) => {
message: '删除成功!',
type: 'success',
})
+ // tip:如果 stream 进行中的 message,就需要调用 controller 结束
+ if (conversationInAbortController.value) {
+ conversationInAbortController.value.abort()
+ }
// 重新获取 message 列表
await messageList();
}
@@ -525,8 +530,8 @@ onMounted(async () => {
display: flex;
flex-direction: column;
overflow-wrap: break-word;
- background-color: #e4e4e4;
- box-shadow: 0 0 0 1px #e4e4e4;
+ background-color: rgba(228, 228, 228, 0.80);
+ box-shadow: 0 0 0 1px rgba(228, 228, 228, 0.80);
border-radius: 10px;
padding: 10px 10px 5px 10px;
@@ -587,10 +592,18 @@ onMounted(async () => {
display: flex;
flex-direction: column;
height: auto;
- border: 1px solid #e3e3e3;
- border-radius: 10px;
- margin: 20px 20px;
- padding: 9px 10px;
+ margin: 0;
+ padding: 0;
+
+ .prompt-from {
+ display: flex;
+ flex-direction: column;
+ height: auto;
+ border: 1px solid #e3e3e3;
+ border-radius: 10px;
+ margin: 20px 20px;
+ padding: 9px 10px;
+ }
.prompt-input {
height: 80px;