si@aidatagov.com 1 week ago
parent
commit
9d3edeb7bb
  1. 3
      vue-fastapi-frontend/src/main.js
  2. 14
      vue-fastapi-frontend/src/views/aichat/MdRenderer.vue
  3. 141
      vue-fastapi-frontend/src/views/aichat/aichat.vue

3
vue-fastapi-frontend/src/main.js

@ -52,8 +52,7 @@ const app = createApp(App)
// 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download
app.config.globalProperties.download = download
app.config.globalProperties.formatDateTime = formatDateTime
app.config.globalProperties.formatDateTime = formatDateTime
app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange

14
vue-fastapi-frontend/src/views/aichat/MdRenderer.vue

@ -15,6 +15,11 @@
<el-icon><FullScreen/></el-icon>
</el-button>
</div>
<div v-if="item.type === 'docs'" style="width: 100%;margin-top: 5px">
<div v-for="doc in item.docs">
<el-link type="primary" @click="downLoadFile(doc)" :underline="false">{{ doc.file_name }}</el-link>
</div>
</div>
<div v-else style="width: 100%;margin-top: 5px">
<markdown :markdown-string="item.content"></markdown>
</div>
@ -29,7 +34,7 @@ import chatTable from './chatTable.vue'
import htmlCharts from './htmlCharts.vue'
import {Download, FullScreen} from "@element-plus/icons-vue";
import { ref, watch} from 'vue'
const { proxy } = getCurrentInstance();
const props = defineProps({
source: Array,
is_large: Boolean,
@ -41,6 +46,13 @@ function fullscreenG6(data){
emit('fullscreenG6',data)
}
function downLoadFile(doc){
let data = {file:doc.file_name,bucket: doc.bucket,sessionId: doc.session_id}
proxy.download("/default-api/aichat/file/download", {
...data,
}, doc.file_name);
}
function downLoadTable(data){
const worksheet = XLSX.utils.json_to_sheet(data);
// 簿簿

141
vue-fastapi-frontend/src/views/aichat/aichat.vue

@ -150,7 +150,7 @@
</div>
</div>
<!-- 文件导入对话框 -->
<el-dialog :z-index="9999" title="文件导入" v-model="upload.open" width="400px" append-to-body>
<el-dialog :z-index="99999" title="文件导入" v-model="upload.open" width="400px" append-to-body>
<el-upload v-if="upload.open"
ref="uploadRef"
:headers="upload.headers"
@ -180,7 +180,6 @@
<script setup>
import { ref, nextTick, computed, watch, reactive, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import antvg6 from './antv-g6.vue'
import OperationButton from './OperationButton.vue'
import MdRenderer from '@/views/aichat/MdRenderer.vue'
import fullscreenG6 from '@/views/aichat/fullscreenG6.vue'
@ -485,79 +484,83 @@ watch(
}
)
const getWrite = (reader) => {
// 1tempResult
let tempResult = '';
/**
* 处理流式数据
* @param {done, value} obj - 包含 done value 属性的对象
*/
const write_stream = ({ done,value }) => {
try {
if (done) {
return
const write_stream = ({ done, value }) => {
if (done) return;
const decoder = new TextDecoder('utf-8');
let str = decoder.decode(value, { stream: true });
console.log(str)
tempResult += str;
// 2使
const split = tempResult.match(/data:.*?}\r\n/g);
if (split) {
// 3
for (let i = 0; i < split.length; i++) {
const chunkStr = split[i];
tempResult = tempResult.replace(chunkStr, '', 1); // 4
try {
const chunk = JSON.parse(chunkStr.replace('data:', '').trim());
processChunk(chunk);
} catch (e) {
console.error('解析错误:', e, chunkStr);
}
}
const decoder = new TextDecoder('utf-8');
let str = decoder.decode(value, { stream: true });
// chunk
tempResult += str;
console.log(tempResult)
const split = tempResult.match(/data:.*}\r\n/g);
if (split) {
str = split.join('');
tempResult = tempResult.replace(str, '');
//
return reader.read().then(write_stream);
} else {
//
return reader.read().then(write_stream);
}
};
const processChunk = (chunk) => {
const lastMsg = chatList.value[chatList.value.length - 1];
// 5
if (chunk.docs?.length) {
lastMsg.content.push({ content: chunk.docs, type: "docs" });
} else if (chunk.G6_ER?.length) {
lastMsg.content.push({ content: chunk.G6_ER, type: "G6_ER" });
} else if (chunk.html_image?.length) {
lastMsg.content.push({ content: chunk.html_image, type: "html_image" });
} else if (chunk.table?.length) {
lastMsg.content.push({ content: chunk.table, type: "table" });
} else if (chunk.choices?.length) {
// 6
// const text = chunk.choices[0].delta.content.replace(/\n/g, "\n\n");
//
const content = chunk.choices[0].delta.content;
const isNewParagraph = content.startsWith('\n\n');
//
const text = isNewParagraph
? content.replace(/\n{2,}/g, '\n\n')
: content.replace(/\n/g, ' ');
const lastContent = lastMsg.content[lastMsg.content.length - 1];
console.log(lastContent)
if (lastContent?.type === "text") {
lastContent.content += text;
} else {
return reader.read().then(write_stream);
}
// str "data:"
if (str && str.startsWith('data:')) {
split.forEach((chunkStr) => {
const chunk = JSON.parse(chunkStr.replace('data:', '').trim());
if (chunk.docs && chunk.docs[0].length > 0){
//
chatList.value[chatList.value.length - 1].content.push({"content":chunk.docs[0],"type":"docs"})
}else if (chunk.G6_ER && chunk.G6_ER.length > 0){
//ER
chatList.value[chatList.value.length - 1].content.push({"content":chunk.G6_ER,"type":"G6_ER"})
}else if (chunk.html_image && chunk.html_image.length > 0){
//htmlecharts
chatList.value[chatList.value.length - 1].content.push({"content":chunk.html_image,"type":"html_image"})
}else if (chunk.table && chunk.table.length > 0){
//
chatList.value[chatList.value.length - 1].content.push({"content":chunk.table,"type":"table"})
}else {
//
let last_answer = chatList.value[chatList.value.length - 1].content
chunk.choices[0].delta.content = chunk.choices[0].delta.content.replace("\n","\n\n")
if (last_answer.length > 0) {
if(last_answer[last_answer.length - 1].type === 'text'){
chatList.value[chatList.value.length - 1].content[last_answer.length - 1].content += chunk.choices[0].delta.content
}else{
chatList.value[chatList.value.length - 1].content.push({"content":chunk.choices[0].delta.content,"type":"text"})
}
}else{
chatList.value[chatList.value.length - 1].content.push({"content":chunk.choices[0].delta.content,"type":"text"})
}
}
nextTick(() => {
//
scrollDiv.value.setScrollTop(getMaxHeight())
})
if (chunk.isEnd || chunk.is_end){
chatList.value[chatList.value.length - 1].isEnd = true
chatList.value[chatList.value.length - 1].time = formatDate(new Date())
nextTick(() => {
//
scrollDiv.value.setScrollTop(getMaxHeight())
})
return Promise.resolve();
}
});
lastMsg.content.push({ content: text, type: "text" });
}
} catch (e) {
return Promise.reject(e);
}
return reader.read().then(write_stream);
// 7
if (chunk.isEnd || chunk.is_end) {
lastMsg.isEnd = true;
console.log(lastMsg)
lastMsg.time = formatDate(new Date());
}
nextTick(() => scrollDiv.value.setScrollTop(getMaxHeight()));
};
return write_stream
return write_stream;
};
const stopChat = (index) => {

Loading…
Cancel
Save