|
|
@ -1,10 +1,10 @@ |
|
|
|
<script setup lang="ts"> |
|
|
|
<script setup lang="ts"> |
|
|
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue' |
|
|
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue' |
|
|
|
import { onBeforeRouteLeave } from 'vue-router' |
|
|
|
import { onBeforeRouteLeave } from 'vue-router' |
|
|
|
import { Button, Spin, UploadDragger, message } from 'ant-design-vue' |
|
|
|
import { Button, Image, Spin, UploadDragger, message } from 'ant-design-vue' |
|
|
|
import type { UploadChangeParam } from 'ant-design-vue' |
|
|
|
import type { UploadChangeParam, UploadProps } from 'ant-design-vue' |
|
|
|
import DefaultImage from '@/assets/images/conversation/default_img3.png' |
|
|
|
|
|
|
|
import { SvgIcon } from '@/components/SvgIcon' |
|
|
|
import { SvgIcon } from '@/components/SvgIcon' |
|
|
|
|
|
|
|
import { AppTextarea } from '@/components/AppTextarea' |
|
|
|
import { AppContainerBox } from '@/components/AppContainerBox' |
|
|
|
import { AppContainerBox } from '@/components/AppContainerBox' |
|
|
|
import { AppSubMenuTitle } from '@/components/AppSubMenuTitle' |
|
|
|
import { AppSubMenuTitle } from '@/components/AppSubMenuTitle' |
|
|
|
import { AppSubMenuList } from '@/components/AppSubMenuList' |
|
|
|
import { AppSubMenuList } from '@/components/AppSubMenuList' |
|
|
@ -12,13 +12,17 @@ import { AppConversationDefault } from '@/components/AppConversationDefault' |
|
|
|
import { AppUserInfo } from '@/components/AppUserInfo' |
|
|
|
import { AppUserInfo } from '@/components/AppUserInfo' |
|
|
|
import { SubMenuActionEnum } from '@/components/AppSubMenuList/index.d' |
|
|
|
import { SubMenuActionEnum } from '@/components/AppSubMenuList/index.d' |
|
|
|
import type { SubMenuItem } from '@/components/AppSubMenuList/index.d' |
|
|
|
import type { SubMenuItem } from '@/components/AppSubMenuList/index.d' |
|
|
|
|
|
|
|
import type { PictureType } from '@/components/AppPicture/index.d' |
|
|
|
|
|
|
|
|
|
|
|
import { AppMessage } from '@/components/AppMessage' |
|
|
|
import { AppMessage } from '@/components/AppMessage' |
|
|
|
import type { MessageItem } from '@/components/AppMessage/index.d' |
|
|
|
import type { MessageItem } from '@/components/AppMessage/index.d' |
|
|
|
|
|
|
|
import type { TopPickItem } from '@/components/AppTopPicks/index.d' |
|
|
|
|
|
|
|
import { AppModelSelect } from '@/components/AppModelSelect' |
|
|
|
|
|
|
|
import type { ModelSelect } from '@/components/AppModelSelect/index.d' |
|
|
|
import { useMessageStore } from '@/store/moules/messageStore/index' |
|
|
|
import { useMessageStore } from '@/store/moules/messageStore/index' |
|
|
|
import { MenuTypeEnum } from '@/enums/menuEnum' |
|
|
|
import { MenuTypeEnum } from '@/enums/menuEnum' |
|
|
|
import { MessageStatusEnum, MessageTypeEnum } from '@/enums/messageEnum' |
|
|
|
import { MessageStatusEnum, MessageTypeEnum, ModelTypeEnum } from '@/enums/messageEnum' |
|
|
|
import { addMessage, conversationList, historyMessage, removeMessage, sendRepository, updateMessage } from '@/api/base/message' |
|
|
|
import { addMessage, conversationList, conversationToTop, historyMessage, removeMessage, sendVisualAnalysis, stopMessage, updateMessage } from '@/api/base/message' |
|
|
|
import { uploadApi } from '@/api/base/file' |
|
|
|
import { uploadApi } from '@/api/base/file' |
|
|
|
import { useMqtt } from '@/hooks/useMqtt' |
|
|
|
import { useMqtt } from '@/hooks/useMqtt' |
|
|
|
import { useMessage } from '@/hooks/useMessage' |
|
|
|
import { useMessage } from '@/hooks/useMessage' |
|
|
@ -28,11 +32,22 @@ const { createConfirm } = useMessage() |
|
|
|
const messageStore = useMessageStore() |
|
|
|
const messageStore = useMessageStore() |
|
|
|
|
|
|
|
|
|
|
|
const sendBtnLoading = ref(false) |
|
|
|
const sendBtnLoading = ref(false) |
|
|
|
const subMenuActiveIndex = ref(0) // 当前会话索引 |
|
|
|
const subMenuActiveIndex = ref(-1) // 当前会话索引 |
|
|
|
const subMenuActionIndex = ref(-1) // 会话操作索引 |
|
|
|
const subMenuActionIndex = ref(-1) // 会话操作索引 |
|
|
|
const subMenuList = ref<SubMenuItem[]>([]) |
|
|
|
const subMenuList = ref<SubMenuItem[]>([]) |
|
|
|
const subMenuInputValue = ref<string>('') |
|
|
|
const subMenuInputValue = ref<string>('') |
|
|
|
const appMessageRef = ref() |
|
|
|
const appMessageRef = ref() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const modelOptions: ModelSelect[] = [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
label: 'DALL-E 3', |
|
|
|
|
|
|
|
value: ModelTypeEnum.DALL_E3, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
const modelIndex = ref(0) |
|
|
|
|
|
|
|
const fileList = ref<string[]>([]) |
|
|
|
|
|
|
|
const roleList = ref<PictureType[]>([]) |
|
|
|
|
|
|
|
const applyList = ref<PictureType[]>([]) |
|
|
|
const messageList = computed(() => messageStore.getMessageList) |
|
|
|
const messageList = computed(() => messageStore.getMessageList) |
|
|
|
const messageStatus = computed(() => messageStore.getMessageStatus) |
|
|
|
const messageStatus = computed(() => messageStore.getMessageStatus) |
|
|
|
const conversationData = computed(() => messageStore.getConversationData) |
|
|
|
const conversationData = computed(() => messageStore.getConversationData) |
|
|
@ -42,21 +57,11 @@ const historyMessageParams = ref({ |
|
|
|
size: 10, |
|
|
|
size: 10, |
|
|
|
total: 0, |
|
|
|
total: 0, |
|
|
|
}) |
|
|
|
}) |
|
|
|
const leadData = ref({ |
|
|
|
|
|
|
|
title: '你好,我是青鸟语言大模型-同聪~', |
|
|
|
|
|
|
|
subTitles: [ |
|
|
|
|
|
|
|
'我可以自由的跟你对话~陪你聊天~帮你想方案~答疑解惑。', |
|
|
|
|
|
|
|
'上传图像至下方,我可以帮你分析哦', |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
image: DefaultImage, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const conversationDefaultShow = ref(false) |
|
|
|
const conversationDefaultShow = ref(false) |
|
|
|
const appMessageShow = ref(true) |
|
|
|
const appMessageShow = ref(true) |
|
|
|
const spinning = ref(true) |
|
|
|
const spinning = ref(true) |
|
|
|
|
|
|
|
|
|
|
|
const fileList = ref([]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch( |
|
|
|
watch( |
|
|
|
() => messageStatus.value, |
|
|
|
() => messageStatus.value, |
|
|
|
(val) => { |
|
|
|
(val) => { |
|
|
@ -71,6 +76,7 @@ watch( |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
function handlesubMenuActionIndex(type: SubMenuActionEnum, item: SubMenuItem, index: number) { |
|
|
|
function handlesubMenuActionIndex(type: SubMenuActionEnum, item: SubMenuItem, index: number) { |
|
|
|
subMenuActionIndex.value = index |
|
|
|
subMenuActionIndex.value = index |
|
|
|
|
|
|
|
const subMenuActionData = subMenuList.value[index] |
|
|
|
if (type === SubMenuActionEnum.EDIT) { |
|
|
|
if (type === SubMenuActionEnum.EDIT) { |
|
|
|
subMenuList.value.forEach((item) => { |
|
|
|
subMenuList.value.forEach((item) => { |
|
|
|
item.actionType = SubMenuActionEnum.NOT |
|
|
|
item.actionType = SubMenuActionEnum.NOT |
|
|
@ -85,37 +91,56 @@ function handlesubMenuActionIndex(type: SubMenuActionEnum, item: SubMenuItem, in |
|
|
|
content: `确定要删除${item.title}会话吗?`, |
|
|
|
content: `确定要删除${item.title}会话吗?`, |
|
|
|
iconType: 'warning', |
|
|
|
iconType: 'warning', |
|
|
|
onOk: () => { |
|
|
|
onOk: () => { |
|
|
|
removeMessage(item.id).then(() => { |
|
|
|
removeMessage(item.id).then(async () => { |
|
|
|
message.success('删除成功') |
|
|
|
message.success('删除成功') |
|
|
|
getConversationList() |
|
|
|
subMenuActiveIndex.value = -1 |
|
|
|
|
|
|
|
conversationDefaultShow.value = true |
|
|
|
|
|
|
|
await getConversationList() |
|
|
|
}) |
|
|
|
}) |
|
|
|
}, |
|
|
|
}, |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (type === SubMenuActionEnum.TO_TOP) { |
|
|
|
|
|
|
|
conversationToTop(item.id).then(async () => { |
|
|
|
|
|
|
|
message.success('置顶成功') |
|
|
|
|
|
|
|
await getConversationList() |
|
|
|
|
|
|
|
const index = subMenuList.value.findIndex(item => item.id === subMenuActionData.id) |
|
|
|
|
|
|
|
await handleSubMenuChange(index) |
|
|
|
|
|
|
|
getHistoryMessage() |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* @description: 切换会话 |
|
|
|
* @description: 切换会话 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
async function handleSubMenuChange(index: number) { |
|
|
|
async function handleSubMenuChange(index: number, item?: SubMenuItem) { |
|
|
|
if (messageStatus.value !== MessageStatusEnum.END) { |
|
|
|
if (messageStatus.value !== MessageStatusEnum.END) { |
|
|
|
message.warn('请先结束对话') |
|
|
|
message.warn('请先结束对话') |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!subMenuList.value.length) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
subMenuActiveIndex.value = index |
|
|
|
subMenuActiveIndex.value = index |
|
|
|
historyMessageParams.value.current = 1 |
|
|
|
historyMessageParams.value.current = 1 |
|
|
|
historyMessageParams.value.total = 0 |
|
|
|
historyMessageParams.value.total = 0 |
|
|
|
messageStore.setConversationData(subMenuList.value[subMenuActiveIndex.value]) |
|
|
|
messageStore.setConversationData(subMenuList.value[subMenuActiveIndex.value]) |
|
|
|
messageStore.setMessageClear() |
|
|
|
messageStore.setMessageClear() |
|
|
|
|
|
|
|
const modelIdx = modelOptions.findIndex(v => v.value === Number(subMenuList.value[subMenuActiveIndex.value].modelType)) |
|
|
|
|
|
|
|
if (modelIdx === -1) { |
|
|
|
|
|
|
|
message.warn('未找到该对话下的模型信息') |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
modelIndex.value = modelIdx |
|
|
|
useMqtt().end() |
|
|
|
useMqtt().end() |
|
|
|
useMqtt().connect() |
|
|
|
useMqtt().connect() |
|
|
|
getHistoryMessage() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 因为会话切换时滚动底部有问题,所以重新加载下 |
|
|
|
// item有的话说明是点击切换,需要重新获取历史消息,否则是不是点击切换调用,不需要获取历史记录 |
|
|
|
appMessageShow.value = false |
|
|
|
if (item) { |
|
|
|
setTimeout(() => { |
|
|
|
getHistoryMessage() |
|
|
|
appMessageShow.value = true |
|
|
|
} |
|
|
|
}, 0) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -124,22 +149,31 @@ async function handleSubMenuChange(index: number) { |
|
|
|
async function handleSend(value: string) { |
|
|
|
async function handleSend(value: string) { |
|
|
|
sendBtnLoading.value = true |
|
|
|
sendBtnLoading.value = true |
|
|
|
conversationDefaultShow.value = false |
|
|
|
conversationDefaultShow.value = false |
|
|
|
if (!conversationData.value) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (subMenuActiveIndex.value === -1) { |
|
|
|
if (subMenuActiveIndex.value === -1) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
await addMessage({ type: MenuTypeEnum.VISUAL_ANALYSIS, title: '新的对话' }) |
|
|
|
spinning.value = true |
|
|
|
|
|
|
|
messageStore.setMessageClear() |
|
|
|
|
|
|
|
await addMessage({ type: MenuTypeEnum.VISUAL_ANALYSIS, title: '新的对话', sort: subMenuList.value.length + 1, modelType: modelOptions[modelIndex.value].value }) |
|
|
|
await getConversationList() |
|
|
|
await getConversationList() |
|
|
|
await nextTick() |
|
|
|
await nextTick() |
|
|
|
|
|
|
|
subMenuActiveIndex.value = subMenuList.value.length - 1 |
|
|
|
|
|
|
|
await handleSubMenuChange(subMenuActiveIndex.value) |
|
|
|
|
|
|
|
if (!conversationData.value) { |
|
|
|
|
|
|
|
message.error('对话发送,请稍后重试!') |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
sendMessage(conversationData.value.id, value) |
|
|
|
sendMessage(conversationData.value.id, value) |
|
|
|
|
|
|
|
spinning.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
catch (error) { |
|
|
|
catch (error) { |
|
|
|
message.error('新建对话失败,请稍后重试!') |
|
|
|
message.error('新建对话失败,请稍后重试!') |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
|
|
|
|
if (!conversationData.value) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
sendMessage(conversationData.value.id, value) |
|
|
|
sendMessage(conversationData.value.id, value) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -153,10 +187,6 @@ async function getConversationList() { |
|
|
|
item.actionType = SubMenuActionEnum.NOT |
|
|
|
item.actionType = SubMenuActionEnum.NOT |
|
|
|
}) |
|
|
|
}) |
|
|
|
subMenuList.value = res |
|
|
|
subMenuList.value = res |
|
|
|
subMenuActiveIndex.value = 0 |
|
|
|
|
|
|
|
if (subMenuList.value.length) { |
|
|
|
|
|
|
|
await handleSubMenuChange(0) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -164,18 +194,20 @@ async function getConversationList() { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
async function getHistoryMessage() { |
|
|
|
async function getHistoryMessage() { |
|
|
|
if (!conversationData.value) { |
|
|
|
if (!conversationData.value) { |
|
|
|
|
|
|
|
spinning.value = false |
|
|
|
|
|
|
|
conversationDefaultShow.value = true |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
spinning.value = true |
|
|
|
spinning.value = true |
|
|
|
historyMessageParams.value.conversationId = conversationData.value.id |
|
|
|
historyMessageParams.value.conversationId = conversationData.value.id |
|
|
|
const res = await historyMessage(historyMessageParams.value) |
|
|
|
const res = await historyMessage(historyMessageParams.value) |
|
|
|
|
|
|
|
messageStore.setMessageClear() |
|
|
|
spinning.value = false |
|
|
|
spinning.value = false |
|
|
|
|
|
|
|
|
|
|
|
if (!res || !res.records || !res.records.length) { |
|
|
|
if (!res || !res.records || !res.records.length) { |
|
|
|
conversationDefaultShow.value = true |
|
|
|
conversationDefaultShow.value = true |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
console.log(res) |
|
|
|
console.log(res.records) |
|
|
|
|
|
|
|
|
|
|
|
res.records.forEach((item: any) => { |
|
|
|
res.records.forEach((item: any) => { |
|
|
|
const itemData: MessageItem = { |
|
|
|
const itemData: MessageItem = { |
|
|
@ -190,6 +222,12 @@ async function getHistoryMessage() { |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
conversationDefaultShow.value = false |
|
|
|
conversationDefaultShow.value = false |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 因为会话切换时滚动底部有问题,所以重新加载下 |
|
|
|
|
|
|
|
// appMessageShow.value = false |
|
|
|
|
|
|
|
// setTimeout(() => { |
|
|
|
|
|
|
|
// appMessageShow.value = true |
|
|
|
|
|
|
|
// }, 0) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -217,6 +255,10 @@ async function onScrollTop(scrollTop: number) { |
|
|
|
* @description: 发送消息hook |
|
|
|
* @description: 发送消息hook |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
async function sendMessage(conversationId: string, question: string): Promise<void> { |
|
|
|
async function sendMessage(conversationId: string, question: string): Promise<void> { |
|
|
|
|
|
|
|
if (!messageStore.getConversationData) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
conversationDefaultShow.value = false |
|
|
|
conversationDefaultShow.value = false |
|
|
|
messageStore.setMessageStatus(MessageStatusEnum.LOADING) |
|
|
|
messageStore.setMessageStatus(MessageStatusEnum.LOADING) |
|
|
|
messageStore.setMessagePushItem({ |
|
|
|
messageStore.setMessagePushItem({ |
|
|
@ -232,13 +274,11 @@ async function sendMessage(conversationId: string, question: string): Promise<vo |
|
|
|
avatar: '', |
|
|
|
avatar: '', |
|
|
|
messageStatus: MessageStatusEnum.LOADING, |
|
|
|
messageStatus: MessageStatusEnum.LOADING, |
|
|
|
}) |
|
|
|
}) |
|
|
|
if (!messageStore.getConversationData) { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sendRepository({ |
|
|
|
sendVisualAnalysis({ |
|
|
|
conversationId, |
|
|
|
conversationId, |
|
|
|
question, |
|
|
|
question, |
|
|
|
|
|
|
|
fileUrl: fileList.value[0], |
|
|
|
}).catch(() => { |
|
|
|
}).catch(() => { |
|
|
|
messageStore.getMessageList.splice(-2) |
|
|
|
messageStore.getMessageList.splice(-2) |
|
|
|
messageStore.setMessageStatus(MessageStatusEnum.END) |
|
|
|
messageStore.setMessageStatus(MessageStatusEnum.END) |
|
|
@ -268,6 +308,20 @@ function handleAddMessage() { |
|
|
|
subMenuActiveIndex.value = -1 |
|
|
|
subMenuActiveIndex.value = -1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @description: 点击默认看板的精选话题 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function handlePick(_index: number, item: TopPickItem) { |
|
|
|
|
|
|
|
handleSend(item.label) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @description: gpt模型切换 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function handleModel(index: number) { |
|
|
|
|
|
|
|
modelIndex.value = index |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function handleUploadChange(info: UploadChangeParam) { |
|
|
|
function handleUploadChange(info: UploadChangeParam) { |
|
|
|
const status = info.file.status |
|
|
|
const status = info.file.status |
|
|
|
if (status !== 'uploading') { |
|
|
|
if (status !== 'uploading') { |
|
|
@ -287,11 +341,13 @@ function handleUploadDrop(e: DragEvent) { |
|
|
|
|
|
|
|
|
|
|
|
async function handleCustomRequest(option: any) { |
|
|
|
async function handleCustomRequest(option: any) { |
|
|
|
console.log(option) |
|
|
|
console.log(option) |
|
|
|
const { file } = option |
|
|
|
|
|
|
|
// uploadApi(file, handleUploadDrop()=>{ |
|
|
|
|
|
|
|
// console.log(111); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }) |
|
|
|
const formData = new FormData() |
|
|
|
|
|
|
|
formData.append('file', option.file) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uploadApi(formData).then((res) => { |
|
|
|
|
|
|
|
fileList.value.push(res.link) |
|
|
|
|
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 下面是子菜单操作项 |
|
|
|
// 下面是子菜单操作项 |
|
|
@ -310,11 +366,18 @@ function handleSubMenuInputBlur(index: number, item: SubMenuItem, inputValue: st |
|
|
|
handleSubMenuInputAffirm(index, item, inputValue) |
|
|
|
handleSubMenuInputAffirm(index, item, inputValue) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
onMounted(async () => { |
|
|
|
getConversationList() |
|
|
|
await getConversationList() |
|
|
|
|
|
|
|
if (subMenuList.value.length) { |
|
|
|
|
|
|
|
subMenuActiveIndex.value = 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
await handleSubMenuChange(subMenuActiveIndex.value) |
|
|
|
|
|
|
|
getHistoryMessage() |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => { |
|
|
|
onUnmounted(() => { |
|
|
|
|
|
|
|
messageStore.setMessageClear() |
|
|
|
|
|
|
|
messageStore.setConversationData(undefined) |
|
|
|
useMqtt().end() |
|
|
|
useMqtt().end() |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
@ -331,7 +394,7 @@ onBeforeRouteLeave(() => { |
|
|
|
<AppContainerBox> |
|
|
|
<AppContainerBox> |
|
|
|
<template #subMenu> |
|
|
|
<template #subMenu> |
|
|
|
<!-- 标题 --> |
|
|
|
<!-- 标题 --> |
|
|
|
<AppSubMenuTitle title="图像分析"></AppSubMenuTitle> |
|
|
|
<AppSubMenuTitle></AppSubMenuTitle> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 按钮 --> |
|
|
|
<!-- 按钮 --> |
|
|
|
<div class="px-5 mb-5"> |
|
|
|
<div class="px-5 mb-5"> |
|
|
@ -357,11 +420,22 @@ onBeforeRouteLeave(() => { |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<template #content> |
|
|
|
<template #content> |
|
|
|
<Spin :spinning="spinning" wrapper-class-name="app-content-spin"> |
|
|
|
<Spin :spinning="spinning" wrapper-class-name="app-content-spin"> |
|
|
|
|
|
|
|
<AppModelSelect |
|
|
|
|
|
|
|
v-if="conversationDefaultShow" |
|
|
|
|
|
|
|
:active-index="modelIndex" |
|
|
|
|
|
|
|
:options="modelOptions" |
|
|
|
|
|
|
|
@change="handleModel" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
</AppModelSelect> |
|
|
|
<!-- 默认导语 --> |
|
|
|
<!-- 默认导语 --> |
|
|
|
<AppConversationDefault |
|
|
|
<AppConversationDefault |
|
|
|
v-if="conversationDefaultShow" |
|
|
|
v-if="conversationDefaultShow" |
|
|
|
|
|
|
|
:is-pick="true" |
|
|
|
|
|
|
|
:is-hot="false" |
|
|
|
|
|
|
|
:role-list="roleList" |
|
|
|
|
|
|
|
:apply-list="applyList" |
|
|
|
height="calc(100% - 160px)" |
|
|
|
height="calc(100% - 160px)" |
|
|
|
:lead-data="leadData" |
|
|
|
@handle-pick="handlePick" |
|
|
|
> |
|
|
|
> |
|
|
|
</AppConversationDefault> |
|
|
|
</AppConversationDefault> |
|
|
|
|
|
|
|
|
|
|
@ -370,6 +444,7 @@ onBeforeRouteLeave(() => { |
|
|
|
v-if="!conversationDefaultShow && appMessageShow" |
|
|
|
v-if="!conversationDefaultShow && appMessageShow" |
|
|
|
ref="appMessageRef" |
|
|
|
ref="appMessageRef" |
|
|
|
class="pl-27 pr-5" |
|
|
|
class="pl-27 pr-5" |
|
|
|
|
|
|
|
height="calc(100% - 160px)" |
|
|
|
:list="messageList" |
|
|
|
:list="messageList" |
|
|
|
@on-scroll-top="onScrollTop" |
|
|
|
@on-scroll-top="onScrollTop" |
|
|
|
@reload-message="reloadMessage" |
|
|
|
@reload-message="reloadMessage" |
|
|
@ -378,12 +453,12 @@ onBeforeRouteLeave(() => { |
|
|
|
</Spin> |
|
|
|
</Spin> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 发送框 --> |
|
|
|
<!-- 发送框 --> |
|
|
|
<div class="upload-box absolute right-0 bottom-5 pl-52 pr-32 mt-10s w-full"> |
|
|
|
<div v-if="!fileList.length" class="upload-box absolute right-0 bottom-5 pl-52 pr-32 mt-10s w-full"> |
|
|
|
<UploadDragger |
|
|
|
<UploadDragger |
|
|
|
v-model:fileList="fileList" |
|
|
|
|
|
|
|
name="file" |
|
|
|
name="file" |
|
|
|
:multiple="true" |
|
|
|
:multiple="false" |
|
|
|
:max-count="1" |
|
|
|
:max-count="1" |
|
|
|
|
|
|
|
:show-upload-list="false" |
|
|
|
:custom-request="handleCustomRequest" |
|
|
|
:custom-request="handleCustomRequest" |
|
|
|
@change="handleUploadChange" |
|
|
|
@change="handleUploadChange" |
|
|
|
@drop="handleUploadDrop" |
|
|
|
@drop="handleUploadDrop" |
|
|
@ -397,6 +472,26 @@ onBeforeRouteLeave(() => { |
|
|
|
</p> |
|
|
|
</p> |
|
|
|
</UploadDragger> |
|
|
|
</UploadDragger> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
v-else |
|
|
|
|
|
|
|
class="w-full" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<div class="absolute left-0 bottom-35 pl-52 pr-32 mt-10 "> |
|
|
|
|
|
|
|
已上传图片: |
|
|
|
|
|
|
|
<Image |
|
|
|
|
|
|
|
class="rounded" |
|
|
|
|
|
|
|
:width="60" |
|
|
|
|
|
|
|
:height="60" |
|
|
|
|
|
|
|
:src="fileList[0]" |
|
|
|
|
|
|
|
fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg==" |
|
|
|
|
|
|
|
></Image> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<AppTextarea |
|
|
|
|
|
|
|
class="pl-52 pr-32 mt-10 " |
|
|
|
|
|
|
|
:btn-loading="sendBtnLoading" |
|
|
|
|
|
|
|
@send="handleSend" |
|
|
|
|
|
|
|
></AppTextarea> |
|
|
|
|
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
</AppContainerBox> |
|
|
|
</AppContainerBox> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|