Browse Source

修改在线聊天配置

ai_dev
zhouhaibin 5 months ago
parent
commit
7f2c6c53b8
  1. 238
      src/views/chat/index.vue
  2. 16
      src/views/chat/lib/ChatWindow.vue

238
src/views/chat/index.vue

@ -1,9 +1,12 @@
<template> <template>
<PageWrapper dense>
<ChatWindow <ChatWindow
ref="chat" ref="chat"
height="850px" id="window-id"
class="chat-window"
:accepted-files="acceptedFiles" :accepted-files="acceptedFiles"
show-audio="false" show-audio="false"
:height="divHeight"
:options-actions="JSON.stringify(optionsActions)" :options-actions="JSON.stringify(optionsActions)"
:text-messages="JSON.stringify(textMessages)" :text-messages="JSON.stringify(textMessages)"
:current-user-id="currentUserId" :current-user-id="currentUserId"
@ -20,28 +23,33 @@
:visible-monitor-window="JSON.stringify(visible)" :visible-monitor-window="JSON.stringify(visible)"
@show-monitor-window="showMonitorWindow()" @show-monitor-window="showMonitorWindow()"
@room-action-handler="handleRoomAction($event)" @room-action-handler="handleRoomAction($event)"
@menu-action-handler="handleMenuAction($event)"
@add-room="addRoom($event)" @add-room="addRoom($event)"
@fetch-messages="fetchMessages($event)" @fetch-messages="fetchMessages($event)"
@send-message="sendMessage($event)" @send-message="sendMessage($event)"
/> />
<LayerVue <LayerVue
ref="layervueRef"
v-model:visible="visible" v-model:visible="visible"
:area="[width, height]" :area="[width, height]"
@resizing="resizing" @resizing="resizing"
@resize-end="resizeEnd" @resize-end="resizeEnd"
:resize="resize" :resize="resize"
title="监控窗口(可拖拽可缩放)" title="监控窗口(可拖拽可缩放)"
offset="rb" :offset="offsetArr"
> :move="moveLayer"
<textarea ref="loggerTextarea" style="width: 100%;height: 100%;" disabled> :move-out="moveOut"
{{ loggerInfo }} :maxmin="[true, true]"
</textarea
> >
<div class="layer-demo-content-center" style="width: 100%; height: 100%" v-html="loggerInfo">
</div>
</LayerVue> </LayerVue>
</PageWrapper>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed } from 'vue'; import { PageWrapper } from '@/components/Page';
import { ref, onMounted, computed, onBeforeUnmount, watch } from 'vue';
import ChatWindow from './lib/ChatWindow.vue'; import ChatWindow from './lib/ChatWindow.vue';
import { defHttp } from '@/utils/http/axios'; import { defHttp } from '@/utils/http/axios';
import { ContentTypeEnum } from '@/enums/httpEnum'; import { ContentTypeEnum } from '@/enums/httpEnum';
@ -54,10 +62,33 @@
import { mapState } from 'pinia'; import { mapState } from 'pinia';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { LayerVue } from 'layer-vue'; import { LayerVue } from 'layer-vue';
import { v } from 'vxe-table'; const layervueRef = ref();
const offsetArr = ref<any>("rb");
const moveLayer = ref('.layer-demo-content-center');
const divHeight = ref('200px'); //
const width = ref(500); const width = ref(500);
const height = ref(800); const height = ref(600);
const isResize = ref(false); const isResize = ref(false);
const moveOutList = ref([
{
label: '上',
value: false,
},
{
label: '右',
value: false,
},
{
label: '下',
value: false,
},
{
label: '左',
value: false,
},
]);
const moveOut: any = computed(() => moveOutList.value.map((v) => v.value));
const resizeList = ref([ const resizeList = ref([
{ {
label: '上', label: '上',
@ -100,7 +131,7 @@ import { v } from 'vxe-table';
let visible = ref(false); let visible = ref(false);
// Or if you used CDN import // Or if you used CDN import
// window['vue-advanced-chat'].register() // window['vue-advanced-chat'].register()
const acceptedFiles = '.docx'; const acceptedFiles = '.docx,.doc,.wps';
const optionsActions = [ const optionsActions = [
{ name: 'all', title: '全功能文档分析' }, { name: 'all', title: '全功能文档分析' },
{ name: 'italic', title: '文档纠错' }, { name: 'italic', title: '文档纠错' },
@ -108,7 +139,6 @@ import { v } from 'vxe-table';
{ name: 'bold', title: '文档公司名识别' }, { name: 'bold', title: '文档公司名识别' },
{ name: 'color', title: '文档相似性检查' }, { name: 'color', title: '文档相似性检查' },
{ name: 'comment1', title: '文档结构检查' }, { name: 'comment1', title: '文档结构检查' },
// { name: 'comment', title: '' },
]; ];
// //
@ -191,13 +221,52 @@ import { v } from 'vxe-table';
// //
const roomActions = [{ name: 'deleteRoom', title: '删除会话' }]; const roomActions = [{ name: 'deleteRoom', title: '删除会话' }];
// //
const menuActions = [ const menuActions = [{ name: 'openMonitorWindow', title: '打开关闭监控窗口' }];
{ name: 'inviteUser', title: '邀请用户' },
{ name: 'removeUser', title: '移除用户' },
{ name: 'deleteRoom', title: '清空会话' },
];
const messageSelectionActions = [{ name: 'deleteMessages', title: 'Delete' }]; const messageSelectionActions = [{ name: 'deleteMessages', title: 'Delete' }];
//.vben-layout-content 使
const getDivHeight = () => {
const divElement = document.querySelector('.vben-layout-content.full');
//
if (divElement) {
//
divHeight.value = String(divElement.offsetHeight) + 'px';
console.log('高度为:' + divHeight.value);
} else {
console.log('找不到指定的div元素');
}
};
//
watch(
() => layervueRef.value?.status,
(newStatus, oldStatus) => {
console.log('layervueRef.value.status changed:', newStatus);
if (newStatus && newStatus.top < 145 && newStatus.width != 0 && newStatus.height != 0) {
if (newStatus.left > 55) {
offsetArr.value = [145, newStatus.left];
layervueRef.value.resetOffset();
} else if (newStatus.left <= 55 && newStatus.top > 0) {
offsetArr.value = [145, 55];
layervueRef.value.resetOffset();
}
}
},
{ deep: true },
);
onMounted(() => {
getDivHeight(); //
//
window.addEventListener('resize', getDivHeight);
// let top = document.documentElement.clientHeight - newStatus.height;
// let left = document.documentElement.clientWidth - newStatus.width;
// console.log('top', top, 'left', left);
});
onBeforeUnmount(() => {
//
window.removeEventListener('resize', getDivHeight);
});
function formatDate(date) { function formatDate(date) {
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // getMonth() 0-11+1 const month = String(date.getMonth() + 1).padStart(2, '0'); // getMonth() 0-11+1
@ -273,11 +342,11 @@ import { v } from 'vxe-table';
const loggerInfo = ref(''); const loggerInfo = ref('');
const { apiUrl, clientId } = useGlobSetting(); const { apiUrl, clientId } = useGlobSetting();
const taskUrls = [ const taskUrls = [
`${apiUrl}/productManagement/supplierInformation/sse/checkPlaceName`, `${apiUrl}/productManagement/docAi/sse/checkPlaceName`,
`${apiUrl}/productManagement/supplierInformation/sse/checkCompanyName`, `${apiUrl}/productManagement/docAi/sse/checkCompanyName`,
`${apiUrl}/productManagement/supplierInformation/sse/checkDocumentError`, `${apiUrl}/productManagement/docAi/sse/checkDocumentError`,
`${apiUrl}/productManagement/supplierInformation/sse/checkTitleName`, `${apiUrl}/productManagement/docAi/sse/checkTitleName`,
`${apiUrl}/productManagement/supplierInformation/sse/checkRepeatText`, `${apiUrl}/productManagement/docAi/sse/checkRepeatText`,
]; ];
function getAnalysisUrl(i) { function getAnalysisUrl(i) {
return taskUrls[i]; return taskUrls[i];
@ -325,7 +394,13 @@ import { v } from 'vxe-table';
console.log('visible', visible.value); console.log('visible', visible.value);
} }
} }
function handleMenuAction({ action }) {
console.log('执行了' + action.name + '操作');
if (action.name === 'openMonitorWindow') {
visible.value = !visible.value;
console.log('visible', visible.value);
}
}
// //
function handleSendMessage({ roomId, text, author }) { function handleSendMessage({ roomId, text, author }) {
const newMessage = { const newMessage = {
@ -337,7 +412,7 @@ import { v } from 'vxe-table';
} }
// //
function fetchMessages({ room, options }) { async function fetchMessages({ room, options }) {
messagesLoaded.value = false; messagesLoaded.value = false;
// $emit('show-demo-options', false); // $emit('show-demo-options', false);
if (options.reset) { if (options.reset) {
@ -371,10 +446,26 @@ import { v } from 'vxe-table';
// //
updateRoomMessages(roomId); updateRoomMessages(roomId);
if (files) {
let getcontent = ref('文件上传中.....'); let getcontent = ref('文件上传中.....');
messagesLoaded.value = false; messagesLoaded.value = false;
if (
files[0].extension != 'docx' &&
files[0].extension != 'DOCX' &&
files[0].extension != 'doc' &&
files[0].extension != 'DOC' &&
files[0].extension != 'wps' &&
files[0].extension != 'WPS'
) {
// AI
const initialAIMessage = createAIMessage(
'文档格式错误,请上传docx、doc或WPS格式文件',
timestamp,
);
roomMsgMap[roomId].push(initialAIMessage);
updateRoomMessages(roomId);
return;
}
// AI // AI
const initialAIMessage = createAIMessage(getcontent.value, timestamp); const initialAIMessage = createAIMessage(getcontent.value, timestamp);
roomMsgMap[roomId].push(initialAIMessage); roomMsgMap[roomId].push(initialAIMessage);
@ -384,12 +475,21 @@ import { v } from 'vxe-table';
const formData = createFormData(files, content); const formData = createFormData(files, content);
const url = getUrlBasedOnContent(content, apiUrl); const url = getUrlBasedOnContent(content, apiUrl);
let uuidfile = buildUUID() + '.' + files[0].extension; // let uuid = buildUUID();
formData.append('uuid', uuidfile); const filesstamp = Date.now();
let originalFilename = files[0].name + '_' + filesstamp + '.' + files[0].extension;
if (await uploadFile(formData)) { let fileName = files[0].name + '_' + filesstamp;
formData.append('originalFilename', originalFilename);
// let result = await uploadFile(formData); //
let result = false;
if (url.includes('/sse/documentEvaluate')) {
result = await xyuploadFile(formData);
} else {
result = await uploadFile(formData); //
}
if (result == true) {
const formData1 = createFormData(null, content); const formData1 = createFormData(null, content);
formData1.append('uuid', uuidfile); formData1.append('originalFilename', fileName + '.' + 'docx');
if (url.includes('/sse/checkDocumentAll')) { if (url.includes('/sse/checkDocumentAll')) {
handleDocumentAnalysisBatches( handleDocumentAnalysisBatches(
url, url,
@ -404,11 +504,20 @@ import { v } from 'vxe-table';
handleDocumentAnalysis(url, formData1, roomId, getcontent, timestamp, clientId, ctrl); handleDocumentAnalysis(url, formData1, roomId, getcontent, timestamp, clientId, ctrl);
} }
} else { } else {
handleUploadError(roomId, timestamp); handleUploadError(roomId, timestamp, result);
} }
// // 3
setTimeout(() => {
getLog(ctrl); getLog(ctrl);
visible.value = true }, 1500);
visible.value = true;
} else {
// AI
const initialAIMessage = createAIMessage('请上传文档进行分析', timestamp);
roomMsgMap[roomId].push(initialAIMessage);
updateRoomMessages(roomId);
return;
}
} }
function createMessage(id, content, roomId, replyMessage, files) { function createMessage(id, content, roomId, replyMessage, files) {
@ -432,9 +541,12 @@ import { v } from 'vxe-table';
if (files) { if (files) {
message['files'] = formattedFiles(files); message['files'] = formattedFiles(files);
message['content'] = message['content'] + '--' + files[0].name + '.' + files[0].extension;
fileInfo.value = new File([files[0].blob], files[0].name + '.' + files[0].extension, { fileInfo.value = new File([files[0].blob], files[0].name + '.' + files[0].extension, {
type: files[0].blob.type, type: files[0].blob.type,
}); });
} else {
message['content'] = message['content'];
} }
if (replyMessage) { if (replyMessage) {
@ -483,42 +595,60 @@ import { v } from 'vxe-table';
function getUrlBasedOnContent(content, apiUrl) { function getUrlBasedOnContent(content, apiUrl) {
if (content.indexOf('地名检查') >= 0) { if (content.indexOf('地名检查') >= 0) {
return `${apiUrl}/productManagement/supplierInformation/sse/checkPlaceName`; return `${apiUrl}/productManagement/docAi/sse/checkPlaceName`;
} else if (content.indexOf('文档公司名识别') >= 0) { } else if (content.indexOf('文档公司名识别') >= 0) {
return `${apiUrl}/productManagement/supplierInformation/sse/checkCompanyName`; return `${apiUrl}/productManagement/docAi/sse/checkCompanyName`;
} else if (content.indexOf('文档相似性检查') >= 0) { } else if (content.indexOf('文档相似性检查') >= 0) {
return `${apiUrl}/productManagement/supplierInformation/sse/checkRepeatText`; return `${apiUrl}/productManagement/docAi/sse/checkRepeatText`;
} else if (content.indexOf('文档纠错') >= 0) { } else if (content.indexOf('文档纠错') >= 0) {
return `${apiUrl}/productManagement/supplierInformation/sse/checkDocumentError`; return `${apiUrl}/productManagement/docAi/sse/checkDocumentError`;
} else if (content.indexOf('文档结构检查') >= 0) { } else if (content.indexOf('文档结构检查') >= 0) {
return `${apiUrl}/productManagement/supplierInformation/sse/checkTitleName`; return `${apiUrl}/productManagement/docAi/sse/checkTitleName`;
} else if (content.indexOf('全功能文档分析') >= 0) { } else if (content.indexOf('全功能文档分析') >= 0) {
return `${apiUrl}/sse/checkDocumentAll`; return `${apiUrl}/sse/checkDocumentAll`;
} else if (content.indexOf('文档图文分析') >= 0) { } else if (content.indexOf('文档图文分析') >= 0) {
return `${apiUrl}/sse/checkDocumentGraphic`; return `${apiUrl}/productManagement/docAi/sse/checkDocumentGraphic`;
} }
return `${apiUrl}/productManagement/supplierInformation/sse-invoke`; return `${apiUrl}/productManagement/docAi/sse/invoke`;
} }
async function uploadFile(formData) { async function uploadFile(formData) {
try { try {
await defHttp.post({ let result = await defHttp.post({
url: '/productManagement/supplierInformation/upload', url: '/productManagement/docAi/sse/upload',
data: formData, data: formData,
headers: { headers: {
'Content-Type': ContentTypeEnum.FORM_DATA, 'Content-Type': ContentTypeEnum.FORM_DATA,
}, },
timeout: 10 * 60 * 1000, timeout: 10 * 60 * 1000,
}); });
console.log('上传成功:', result);
return true; // return true; //
} catch (error) { } catch (error) {
console.error('请求失败:', error); console.error('请求失败:', error);
return false; // return error; //
}
}
async function xyuploadFile(formData) {
try {
let result = await defHttp.post({
url: '/productManagement/docAi/xysse/upload',
data: formData,
headers: {
'Content-Type': ContentTypeEnum.FORM_DATA,
},
timeout: 10 * 60 * 1000,
});
console.log('上传成功:', result);
return true; //
} catch (error) {
console.error('请求失败:', error);
return error; //
} }
} }
function handleUploadError(roomId, timestamp) { function handleUploadError(roomId, timestamp, errResult) {
const errorMessage = createAIMessage('**文件上传失败,请联系管理员**', timestamp); const errorMessage = createAIMessage('**' + errResult + '**', timestamp);
roomMsgMap[roomId][roomMsgMap[roomId].length - 1] = errorMessage; roomMsgMap[roomId][roomMsgMap[roomId].length - 1] = errorMessage;
updateRoomMessages(roomId); updateRoomMessages(roomId);
} }
@ -540,7 +670,6 @@ import { v } from 'vxe-table';
} }
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(() => {
let analysisUrl = getAnalysisUrl(i); let analysisUrl = getAnalysisUrl(i);
fetchEventSource(analysisUrl, { fetchEventSource(analysisUrl, {
method: 'POST', method: 'POST',
@ -560,13 +689,13 @@ import { v } from 'vxe-table';
onerror(err) { onerror(err) {
handleError(roomId, timestamp, err, i); handleError(roomId, timestamp, err, i);
ctrl.abort(); ctrl.abort();
throw err;
resolve('ok'); resolve('ok');
}, },
onclose() { onclose() {
resolve('ok'); resolve('ok');
}, },
}); });
}, 1500);
}); });
}); });
@ -597,7 +726,7 @@ import { v } from 'vxe-table';
}); });
} }
function getLog(ctrl) { function getLog(ctrl) {
fetchEventSource(`${apiUrl}/productManagement/supplierInformation/sse/getLog`, { fetchEventSource(`${apiUrl}/productManagement/docAi/sse/getLog`, {
method: 'get', method: 'get',
headers: { headers: {
Authorization: `Bearer ${getToken()}`, Authorization: `Bearer ${getToken()}`,
@ -606,12 +735,10 @@ import { v } from 'vxe-table';
signal: ctrl.signal, signal: ctrl.signal,
openWhenHidden: true, openWhenHidden: true,
async onmessage(msg) { async onmessage(msg) {
let str = msg.data.replaceAll('<br>', '\n'); let str = msg.data;
loggerInfo.value = loggerInfo.value + str + '\n'; loggerInfo.value = loggerInfo.value + str + '<br>';
loggerInfo.value =
loggerInfo.value + '------------------------------------------------' + '\n';
loggerInfo.value = loggerInfo.value =
loggerInfo.value + '------------------------------------------------' + '\n'; loggerInfo.value + '================================================' + '<br>';
}, },
onerror(err) { onerror(err) {
ctrl.abort(); ctrl.abort();
@ -659,10 +786,10 @@ import { v } from 'vxe-table';
function openFile({ file }) { function openFile({ file }) {
window.open(file.file.url, '_blank'); window.open(file.file.url, '_blank');
} }
const showMonitorWindow =()=>{ const showMonitorWindow = () => {
visible.value = !visible.value; visible.value = !visible.value;
console.log('visible', visible.value); console.log('visible', visible.value);
} };
const resize: any = computed(() => { const resize: any = computed(() => {
return resizeList.value.map((item) => item.value); return resizeList.value.map((item) => item.value);
}); });
@ -676,3 +803,4 @@ import { v } from 'vxe-table';
isResize.value = false; isResize.value = false;
}; };
</script> </script>
<style scoped></style>

16
src/views/chat/lib/ChatWindow.vue

@ -1,5 +1,5 @@
<template> <template>
<div class="vac-card-window" :style="[{ height }, cssVars]"> <div class="vac-card-window" :style="[{ height}, cssVars]">
<div class="vac-chat-container"> <div class="vac-chat-container">
<rooms-list <rooms-list
v-if="!singleRoomCasted" v-if="!singleRoomCasted"
@ -13,7 +13,7 @@
:text-messages="t" :text-messages="t"
:show-search="showSearchCasted" :show-search="showSearchCasted"
:show-add-room="showAddRoomCasted" :show-add-room="showAddRoomCasted"
:show-rooms-list="showRoomsList && roomsListOpenedCasted" :show-rooms-list="false"
:text-formatting="textFormattingCasted" :text-formatting="textFormattingCasted"
:link-options="linkOptionsCasted" :link-options="linkOptionsCasted"
:is-mobile="isMobile" :is-mobile="isMobile"
@ -27,6 +27,8 @@
@room-action-handler="roomActionHandler" @room-action-handler="roomActionHandler"
@show-monitor-window="showMonitorWindow" @show-monitor-window="showMonitorWindow"
> >
<!-- :show-rooms-list="showRoomsList && roomsListOpenedCasted" -->
<template v-for="el in slots" #[el.slot]="data"> <template v-for="el in slots" #[el.slot]="data">
<slot :name="el.slot" v-bind="data" /> <slot :name="el.slot" v-bind="data" />
</template> </template>
@ -235,7 +237,7 @@
'search-room', 'search-room',
'room-action-handler', 'room-action-handler',
'message-selection-action-handler', 'message-selection-action-handler',
"show-monitor-window", 'show-monitor-window',
], ],
data() { data() {
@ -391,7 +393,7 @@
return this.castArray(this.optionsActions); return this.castArray(this.optionsActions);
}, },
visibleMonitorWindowCasted() { visibleMonitorWindowCasted() {
console.log(this.visibleMonitorWindow,this.castBoolean(this.visibleMonitorWindow)) console.log(this.visibleMonitorWindow, this.castBoolean(this.visibleMonitorWindow));
return this.castBoolean(this.visibleMonitorWindow); return this.castBoolean(this.visibleMonitorWindow);
}, },
}, },
@ -577,9 +579,9 @@
roomId: this.room.roomId, roomId: this.room.roomId,
}); });
}, },
showMonitorWindow(){ showMonitorWindow() {
this.$emit('show-monitor-window') this.$emit('show-monitor-window');
} },
}, },
}; };
</script> </script>

Loading…
Cancel
Save