Browse Source

修改在线聊天配置

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

396
src/views/chat/index.vue

@ -1,47 +1,55 @@
<template> <template>
<ChatWindow <PageWrapper dense>
ref="chat" <ChatWindow
height="850px" ref="chat"
:accepted-files="acceptedFiles" id="window-id"
show-audio="false" class="chat-window"
:options-actions="JSON.stringify(optionsActions)" :accepted-files="acceptedFiles"
:text-messages="JSON.stringify(textMessages)" show-audio="false"
:current-user-id="currentUserId" :height="divHeight"
:rooms="JSON.stringify(rooms)" :options-actions="JSON.stringify(optionsActions)"
:messages="roomMessages" :text-messages="JSON.stringify(textMessages)"
:menu-actions="JSON.stringify(menuActions)" :current-user-id="currentUserId"
:message-selection-actions="JSON.stringify(messageSelectionActions)" :rooms="JSON.stringify(rooms)"
:loading-rooms="loadingRooms" :messages="roomMessages"
:rooms-loaded="messagesLoaded" :menu-actions="JSON.stringify(menuActions)"
:room-id="roomId" :message-selection-actions="JSON.stringify(messageSelectionActions)"
:room-message="roomMessage" :loading-rooms="loadingRooms"
:messages-loaded="true" :rooms-loaded="messagesLoaded"
:room-actions="JSON.stringify(roomActions)" :room-id="roomId"
:visible-monitor-window="JSON.stringify(visible)" :room-message="roomMessage"
@show-monitor-window="showMonitorWindow()" :messages-loaded="true"
@room-action-handler="handleRoomAction($event)" :room-actions="JSON.stringify(roomActions)"
@add-room="addRoom($event)" :visible-monitor-window="JSON.stringify(visible)"
@fetch-messages="fetchMessages($event)" @show-monitor-window="showMonitorWindow()"
@send-message="sendMessage($event)" @room-action-handler="handleRoomAction($event)"
/> @menu-action-handler="handleMenuAction($event)"
<LayerVue @add-room="addRoom($event)"
v-model:visible="visible" @fetch-messages="fetchMessages($event)"
:area="[width, height]" @send-message="sendMessage($event)"
@resizing="resizing" />
@resize-end="resizeEnd" <LayerVue
:resize="resize" ref="layervueRef"
title="监控窗口(可拖拽可缩放)" v-model:visible="visible"
offset="rb" :area="[width, height]"
> @resizing="resizing"
<textarea ref="loggerTextarea" style="width: 100%;height: 100%;" disabled> @resize-end="resizeEnd"
{{ loggerInfo }} :resize="resize"
</textarea title="监控窗口(可拖拽可缩放)"
:offset="offsetArr"
:move="moveLayer"
:move-out="moveOut"
:maxmin="[true, true]"
> >
</LayerVue> <div class="layer-demo-content-center" style="width: 100%; height: 100%" v-html="loggerInfo">
</div>
</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,44 +446,78 @@ import { v } from 'vxe-table';
// //
updateRoomMessages(roomId); updateRoomMessages(roomId);
if (files) {
let getcontent = ref('文件上传中.....'); let getcontent = ref('文件上传中.....');
messagesLoaded.value = false; messagesLoaded.value = false;
if (
// AI files[0].extension != 'docx' &&
const initialAIMessage = createAIMessage(getcontent.value, timestamp); files[0].extension != 'DOCX' &&
roomMsgMap[roomId].push(initialAIMessage); files[0].extension != 'doc' &&
updateRoomMessages(roomId); files[0].extension != 'DOC' &&
files[0].extension != 'wps' &&
const ctrl = new AbortController(); files[0].extension != 'WPS'
const formData = createFormData(files, content); ) {
// AI
const url = getUrlBasedOnContent(content, apiUrl); const initialAIMessage = createAIMessage(
let uuidfile = buildUUID() + '.' + files[0].extension; '文档格式错误,请上传docx、doc或WPS格式文件',
formData.append('uuid', uuidfile);
if (await uploadFile(formData)) {
const formData1 = createFormData(null, content);
formData1.append('uuid', uuidfile);
if (url.includes('/sse/checkDocumentAll')) {
handleDocumentAnalysisBatches(
url,
formData1,
roomId,
getcontent,
timestamp, timestamp,
clientId,
ctrl,
); );
roomMsgMap[roomId].push(initialAIMessage);
updateRoomMessages(roomId);
return;
}
// AI
const initialAIMessage = createAIMessage(getcontent.value, timestamp);
roomMsgMap[roomId].push(initialAIMessage);
updateRoomMessages(roomId);
const ctrl = new AbortController();
const formData = createFormData(files, content);
const url = getUrlBasedOnContent(content, apiUrl);
// let uuid = buildUUID();
const filesstamp = Date.now();
let originalFilename = files[0].name + '_' + filesstamp + '.' + files[0].extension;
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);
formData1.append('originalFilename', fileName + '.' + 'docx');
if (url.includes('/sse/checkDocumentAll')) {
handleDocumentAnalysisBatches(
url,
formData1,
roomId,
getcontent,
timestamp,
clientId,
ctrl,
);
} else {
handleDocumentAnalysis(url, formData1, roomId, getcontent, timestamp, clientId, ctrl);
}
} else { } else {
handleDocumentAnalysis(url, formData1, roomId, getcontent, timestamp, clientId, ctrl); handleUploadError(roomId, timestamp, result);
} }
// 3
setTimeout(() => {
getLog(ctrl);
}, 1500);
visible.value = true;
} else { } else {
handleUploadError(roomId, timestamp); // AI
const initialAIMessage = createAIMessage('请上传文档进行分析', timestamp);
roomMsgMap[roomId].push(initialAIMessage);
updateRoomMessages(roomId);
return;
} }
//
getLog(ctrl);
visible.value = true
} }
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,33 +670,32 @@ 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', headers: {
headers: { Authorization: `Bearer ${getToken()}`,
Authorization: `Bearer ${getToken()}`, clientId: clientId,
clientId: clientId, },
}, signal: ctrl.signal,
signal: ctrl.signal, openWhenHidden: true,
openWhenHidden: true, body: formData,
body: formData, async onmessage(msg) {
async onmessage(msg) { getcontent.value = msg.data.replaceAll('<br>', '\n');
getcontent.value = msg.data.replaceAll('<br>', '\n'); const message1 = createAIMessage(getcontent.value, timestamp);
const message1 = createAIMessage(getcontent.value, timestamp); roomMsgMap[roomId][roomMsgMap[roomId].length - (taskUrls.length - i)] = message1;
roomMsgMap[roomId][roomMsgMap[roomId].length - (taskUrls.length - i)] = message1; updateRoomMessages(roomId);
updateRoomMessages(roomId); },
}, 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 =
loggerInfo.value + '------------------------------------------------' + '\n'; loggerInfo.value + '================================================' + '<br>';
loggerInfo.value =
loggerInfo.value + '------------------------------------------------' + '\n';
}, },
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