si@aidatagov.com 2 weeks ago
parent
commit
2b5911c988
  1. 4
      vue-fastapi-frontend/src/api/aichat/aichat.js
  2. 24
      vue-fastapi-frontend/src/layout/components/AppMain.vue
  3. 5
      vue-fastapi-frontend/src/utils/request.js
  4. 66
      vue-fastapi-frontend/src/views/aichat/aichat.vue
  5. 28
      vue-fastapi-frontend/src/views/aichat/index.vue

4
vue-fastapi-frontend/src/api/aichat/aichat.js

@ -22,8 +22,8 @@ export function getChatList(sessionId) {
})
}
export function postChatMessage(data) {
return postStream('/aichat-api/stream-chat',data)
export function postChatMessage(data,signal) {
return postStream('/aichat-api/robot/robot_chat',data,signal)
}
export function DeleteChatSession(sessionId) {

24
vue-fastapi-frontend/src/layout/components/AppMain.vue

@ -11,8 +11,8 @@
<el-link :underline="false" class="ai_chat_link" :style="{display: showDiv?'none':'block'}" @click="showDivClick">
<img src="@/assets/images/aichat.gif"/>
</el-link>
<div class="ai_chat_div" :style="aiChatDivStyle">
<aichat-index :is_large="largeDiv" :chatDataList="chatDataList"></aichat-index>
<div class="ai_chat_div" v-if="showDiv" :style="aiChatDivStyle">
<aichat-index :is_large="largeDiv"></aichat-index>
<div class="ai_chat_div_operate">
<el-link :underline="false" style="font-size: 20px;" :style="{display:largeDiv?'none':'block'}" @click="littleChatDiv"><i class="ri-collapse-diagonal-line"></i></el-link>
<el-link :underline="false" style="font-size: 20px;" :style="{display:largeDiv?'block':'none'}" @click="largeChatDiv"><i class="ri-expand-diagonal-line"></i></el-link>
@ -35,7 +35,6 @@ const route = useRoute()
const tagsViewStore = useTagsViewStore()
const showDiv = ref(false)
const largeDiv = ref(true)
const chatDataList = ref([])
const aiChatDivStyle = ref({display: 'none',width: '450px',height: '600px',bottom: '16px',right: '16px'})
@ -61,25 +60,6 @@ function largeChatDiv(){
function showDivClick(){
showDiv.value = !showDiv.value
aiChatDivStyle.value.display = 'block'
if (Cookies.get("chatSessionId")){
//
getChatList(Cookies.get("chatSessionId")).then(res=>{
let array = res.data
if (array && array.length >0){
for (let i = 0; i < array.length; i++) {
if (array[i].type === 'answer'){
array[i].content = JSON.parse(array[i].content)
}
if (array[i].type === 'question'){
array[i].file = JSON.parse(array[i].file)
}
}
}
chatDataList.value = array
})
}else {
Cookies.set("chatSessionId",uuidv4())
}
}
function littleChatDiv(){

5
vue-fastapi-frontend/src/utils/request.js

@ -157,11 +157,12 @@ export default service
* @param data 请求body
* @returns
*/
export function postStream(url, data) {
export function postStream(url, data,signal) {
const headers = { 'Content-Type': 'application/json' }
return fetch(url, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined,
headers: headers
headers: headers,
signal: signal.signal
})
}

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

@ -44,7 +44,7 @@
v-if="item.isStop && !item.isEnd"
@click="startChat(index)"
link
>继续
>重新生成
</el-button>
<el-button type="primary" v-else-if="!item.isEnd" @click="stopChat(index)" link
>停止回答
@ -150,7 +150,7 @@
</div>
</div>
<!-- 文件导入对话框 -->
<el-dialog title="文件导入" v-model="upload.open" width="400px" append-to-body>
<el-dialog z-index="9999" title="文件导入" v-model="upload.open" width="400px" append-to-body>
<el-upload v-if="upload.open"
ref="uploadRef"
:headers="upload.headers"
@ -229,6 +229,7 @@ const inputValue = ref('')
const chartOpenId = ref('')
const chatList = ref([])
const answerList = ref([])
const controller = ref(null)
const popoverVisible = ref(false)
const currentMachine = ref([])
@ -263,32 +264,22 @@ function setScrollBottom() {
*/
const scrollTop = ref(0)
const scorll = ref(true)
const getMaxHeight = () => {
return dialogScrollbar.value.scrollHeight
}
const handleScrollTop = ($event) => {
scrollTop.value = $event.scrollTop
if (
dialogScrollbar.value.scrollHeight - (scrollTop.value + scrollDiv.value.wrapRef.offsetHeight) <=
30
) {
scorll.value = true
} else {
scorll.value = false
}
emit('scroll', { ...$event, dialogScrollbar: dialogScrollbar.value, scrollDiv: scrollDiv.value })
}
const handleScroll = () => {
if (!props.log && scrollDiv.value) {
if (scrollDiv.value) {
//
if (scrollDiv.value.wrapRef.offsetHeight < dialogScrollbar.value.scrollHeight) {
//
if (scorll.value) {
scrollDiv.value.setScrollTop(getMaxHeight())
}
}
}
}
@ -303,7 +294,8 @@ const handleFileSuccess = (response, file, fileList) => {
currentFiles.value.push({file:response.data.file,bucket:response.data.bucket})
upload.open = false;
upload.isUploading = false;
proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
proxy.$modal.msgSuccess(response.msg);
// proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "", { dangerouslyUseHTMLString: true });
};
/** 提交上传文件 */
@ -425,7 +417,9 @@ async function sendChatHandle(event) {
if (!event.ctrlKey) {
// ctrl
event.preventDefault()
if (inputValue.value.trim() && ((chatList.value.length > 1 && chatList.value[chatList.value.length - 1].isEnd) || chatList.value.length < 2)) {
if (inputValue.value.trim() && (chatList.value.length === 0||
(chatList.value[chatList.value.length - 1].isStop ||
chatList.value[chatList.value.length - 1].isEnd))) {
chatList.value.push({
"type": "question",
"content": inputValue.value.trim(),
@ -434,13 +428,13 @@ async function sendChatHandle(event) {
"sessionName": chatList.value.length > 0 ? chatList.value[0].content.substring(0, 20) : inputValue.value.trim().substring(0, 20),
"file": currentFiles.value
})
let question = JSON.parse(JSON.stringify(chatList.value[chatList.value.length - 1]))
question.file = JSON.stringify(question.file)
await addChat(question)
nextTick(() => {
//
scrollDiv.value.setScrollTop(getMaxHeight())
})
let question = JSON.parse(JSON.stringify(chatList.value[chatList.value.length - 1]))
question.file = JSON.stringify(question.file)
await addChat(question)
inputValue.value = ''
let data = {
"query": inputValue.value.trim(),
@ -459,7 +453,11 @@ async function sendChatHandle(event) {
}
function sendChatMessage(data){
postChatMessage(data).then(res=>{
controller.value = new AbortController()
postChatMessage(data,{signal:controller.value.signal}).then(res=>{
if (res.status !== 200){
chatList.value.push({"type":"answer","content":[{"type":"text","content":"服务异常,错误码:"+res.status}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":'',"thumbDownReason":''})
}else {
currentFiles.value = []
chatList.value.push({"type":"answer","content":[],"isEnd":false,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName, "operate":'',"thumbDownReason":''})
answerList.value.push({"index":chatList.value.length-1, "content":[], "isEnd":false})
@ -470,16 +468,21 @@ function sendChatMessage(data){
answer.content = JSON.stringify(answer.content)
addChat(answer)
})
}
}).catch((e) => {
chatList.value.push({"type":"answer","content":[{"type":"text","content":"服务异常"}],"isEnd":true,"isStop":false})
chatList.value.push({"type":"answer","content":[{"type":"text","content":"服务异常"}],"isEnd":true,"isStop":false,"sessionId":chatList.value[0].sessionId,"sessionName":chatList.value[0].sessionName,"operate":"","thumbDownReason":""})
})
}
watch(
chatList,
() => {
handleScroll()
},
{ deep: true, immediate: true }
nextTick(() => {
//
scrollDiv.value.setScrollTop(getMaxHeight())
})
},{
deep:true, immediate:true
}
)
const getWrite = (reader) => {
let tempResult = '';
@ -533,8 +536,9 @@ const getWrite = (reader) => {
answerList.value[answerList.value.length - 1].content.push({"content":chunk.choices[0].delta.content,"type":"text"})
}
}
if (!chatList.value[answerList.value[answerList.value.length - 1].index].isStop){
chatList.value[chatList.value.length - 1].content =answerList.value[answerList.value.length - 1].content
let isStop = chatList.value[chatList.value.length-1].isStop
if (!isStop){
chatList.value[chatList.value.length - 1].content = answerList.value[answerList.value.length - 1].content
}
nextTick(() => {
//
@ -543,7 +547,7 @@ const getWrite = (reader) => {
if (chunk.isEnd){
answerList.value[answerList.value.length - 1].isEnd = true
answerList.value[answerList.value.length - 1].time = formatDate(new Date())
if (!chatList.value[answerList.value[answerList.value.length - 1].index].isStop){
if (!isStop){
chatList.value[chatList.value.length - 1].isEnd = true
chatList.value[chatList.value.length - 1].time = formatDate(new Date())
}
@ -565,9 +569,15 @@ const getWrite = (reader) => {
const stopChat = (index) => {
chatList.value[index].isStop = true
if (controller.value !== null){
controller.value.abort()
}
let answer = JSON.parse(JSON.stringify(chatList.value[index]))
answer.content = JSON.stringify(answer.content)
addChat(answer)
}
const startChat = (index) => {
chatList.value[index].isStop = false
regenerationChart(index)
}
defineExpose({

28
vue-fastapi-frontend/src/views/aichat/index.vue

@ -109,7 +109,7 @@ function deleteLog(row) {
listChatHistory(sessionId).then(response =>{
chatLogeData.value = response.data
})
proxy.$modal.msgSuccess("复制成功");
proxy.$modal.msgSuccess("删除成功");
})
}
@ -159,7 +159,31 @@ function clickListHandle(item){
})
}
watch(() => props.chatDataList, value => currentRecordList.value = JSON.parse(JSON.stringify(value)))
onMounted(
()=>{
if (Cookies.get("chatSessionId")){
//
getChatList(Cookies.get("chatSessionId")).then(res=>{
let array = res.data
if (array && array.length >0){
for (let i = 0; i < array.length; i++) {
if (array[i].type === 'answer'){
array[i].content = JSON.parse(array[i].content)
}
if (array[i].type === 'question'){
array[i].file = JSON.parse(array[i].file)
}
}
}
currentRecordList.value = array
}).then(()=>{
AiChatRef.value.setScrollBottom()
})
}else {
Cookies.set("chatSessionId",uuidv4())
}
}
)
</script>
<style lang="scss">

Loading…
Cancel
Save