|
@@ -15,13 +15,24 @@
|
|
|
<div class="main-content">
|
|
|
<div class="chat-container">
|
|
|
<div class="message-list">
|
|
|
-
|
|
|
+ <div v-for="item in chatRecordList" :key="item.id" :class="item.isUser? 'every-message user-message' : 'message bot-message' ">
|
|
|
+ <!-- 会话图标 -->
|
|
|
+ <div :class="item.isUser == 1? 'user-image' : 'system-image' "></div>
|
|
|
+ <span style="display: flex">
|
|
|
+ <el-text v-html="item.content"></el-text>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="content-box">
|
|
|
- <div v-html="streamHtmlData"></div>
|
|
|
- <span class="loading-dots"></span>
|
|
|
- <span class="dot"></span>
|
|
|
- <span class="dot"></span>
|
|
|
+ <div class="message-box">
|
|
|
+ <div class="typing-message">
|
|
|
+ <span>
|
|
|
+ <span v-html="streamHtmlData"></span>
|
|
|
+ <span class="loading-dots">
|
|
|
+ <span class="dot"></span>
|
|
|
+ <span class="dot"></span>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<el-button @click="stopMessage">停止回答</el-button>
|
|
|
</div>
|
|
@@ -54,14 +65,14 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import {getAiChatRecordList} from '@/api/xjc-integratedmachine/common/aiChat.js'
|
|
|
+ import {aiChatRecordList} from '@/api/xjc-integratedmachine/common/aiChat.js'
|
|
|
import { getToken } from '@/utils/auth'
|
|
|
import { marked } from 'marked'
|
|
|
|
|
|
// 聊天记录
|
|
|
let chatRecordList = ref([])
|
|
|
// md流式数据
|
|
|
- const streamData = ref('');
|
|
|
+ const streamMarkdownData = ref('');
|
|
|
// html流式数据
|
|
|
let streamHtmlData = ref('');
|
|
|
// 流式加载状态
|
|
@@ -71,22 +82,26 @@
|
|
|
// AbortController用于中止请求
|
|
|
let controller = null;
|
|
|
// 输入的问题
|
|
|
- const inputMessage = ref('')
|
|
|
-
|
|
|
+ let inputMessage = ref('')
|
|
|
+ // 发送标识
|
|
|
+ let isSending = ref(false)
|
|
|
// 查看所有聊天记录
|
|
|
list();
|
|
|
function list() {
|
|
|
- getAiChatRecordList().then(resp =>{
|
|
|
+ let queryForm = {
|
|
|
+
|
|
|
+ }
|
|
|
+ aiChatRecordList(queryForm).then(resp =>{
|
|
|
console.log(resp)
|
|
|
- chatRecordList.value = resp;
|
|
|
+ chatRecordList.value = resp.rows;
|
|
|
})
|
|
|
}
|
|
|
|
|
|
const sendMessage = () => {
|
|
|
- if (inputMessage.value.trim()) {
|
|
|
+/* if (inputMessage.value.trim()) {
|
|
|
sendRequest(inputMessage.value.trim())
|
|
|
inputMessage.value = ''
|
|
|
- }
|
|
|
+ }*/
|
|
|
}
|
|
|
|
|
|
const sendRequest = async(message) => {
|
|
@@ -100,7 +115,7 @@
|
|
|
// chatRecordList.value.push(userMessage)
|
|
|
try{
|
|
|
isLoading.value = true;
|
|
|
- streamData.value = ''; // 清空之前的数据
|
|
|
+ streamMarkdownData.value = ''; // 清空之前的数据
|
|
|
|
|
|
// 创建AbortController以便可以中止请求
|
|
|
controller = new AbortController();
|
|
@@ -110,7 +125,7 @@
|
|
|
"content": message? message: "你是谁?"
|
|
|
}
|
|
|
// 发送fetch请求
|
|
|
- const response = await fetch('/dev-api/ai/chat/stream', {
|
|
|
+ const response = await fetch('/dev-api/ai/chat/record/stream', {
|
|
|
method: 'POST',
|
|
|
headers: {
|
|
|
'Content-Type': 'application/json',
|
|
@@ -131,17 +146,17 @@
|
|
|
// 解码并追加数据
|
|
|
let chunk = decoder.decode(value, { stream: true });
|
|
|
chunk = chunk.replace(/\n\n/g, '').replace(/data:/g, '')
|
|
|
- streamData.value += chunk;
|
|
|
- streamHtmlData.value = marked(streamData.value)
|
|
|
+ streamMarkdownData.value += chunk;
|
|
|
+ streamHtmlData.value = marked(streamMarkdownData.value)
|
|
|
}
|
|
|
}catch (error) {
|
|
|
// 如果是手动中止,不显示错误
|
|
|
if (error.name !== 'AbortError') {
|
|
|
console.error('流式读取失败:', error);
|
|
|
- streamData.value = 'Error: ' + error.message;
|
|
|
+ streamMarkdownData.value = 'Error: ' + error.message;
|
|
|
}
|
|
|
} finally {
|
|
|
- streamHtmlData.value = marked(streamData.value)
|
|
|
+ streamHtmlData.value = marked(streamMarkdownData.value)
|
|
|
isLoading.value = false;
|
|
|
console.log("==============");
|
|
|
}
|
|
@@ -214,9 +229,6 @@
|
|
|
width: 10vw;
|
|
|
background-color: #f4f4f9;
|
|
|
padding: 20px;
|
|
|
-/* display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;*/
|
|
|
}
|
|
|
|
|
|
.control-button-box {
|
|
@@ -245,6 +257,15 @@
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
+ .every-message {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ padding: 10px;
|
|
|
+ border-radius: 4px;
|
|
|
+ display: flex;
|
|
|
+ width: 40vw;
|
|
|
+ /* align-items: center; */
|
|
|
+ }
|
|
|
+
|
|
|
.user-message {
|
|
|
max-width: 70%;
|
|
|
background-color: #e1f5fe;
|
|
@@ -258,10 +279,23 @@
|
|
|
align-self: flex-start;
|
|
|
}
|
|
|
|
|
|
- /* 内容区 */
|
|
|
- .content-box {
|
|
|
+ .system-image {
|
|
|
+ width: 32px;
|
|
|
+ height:32px;
|
|
|
+ background-image: url('@/assets/images/common/ai/system.png');
|
|
|
+ }
|
|
|
+
|
|
|
+ .user-image {
|
|
|
+ width: 32px;
|
|
|
+ height:32px;
|
|
|
+ background-image: url('@/assets/images/common/ai/user.png');
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 每个消息的区域 */
|
|
|
+ .message-box {
|
|
|
/*max-height: 300px;*/
|
|
|
width: 60vw;
|
|
|
+ /*height: 30vh;*/
|
|
|
overflow-y: auto;
|
|
|
border: 1px solid #eee;
|
|
|
padding: 10px;
|