From 682b0d3b961fb4584ab528cf58e7099a977168ab Mon Sep 17 00:00:00 2001
From: houzhongjian <houzhongyi@126.com>
Date: 星期四, 12 六月 2025 13:22:55 +0800
Subject: [PATCH] 大模型功能修改

---
 src/views/ai/dashboard/components/message/HistoryMessageList.vue          |   33 ++++-
 src/views/ai/model/template/index.vue                                     |    4 
 src/views/ai/dashboard/components/conversation/CommonConversationList.vue |  116 +++++++++++++------
 src/views/ai/dashboard/components/message/MessageList.vue                 |   16 ++
 src/views/ai/dashboard/zhuanlu/index.vue                                  |   58 +++++++--
 src/views/ai/dashboard/components/conversation/CommonConversation.vue     |  130 +++++++++++++--------
 6 files changed, 244 insertions(+), 113 deletions(-)

diff --git a/src/views/ai/dashboard/components/conversation/CommonConversation.vue b/src/views/ai/dashboard/components/conversation/CommonConversation.vue
index 2de4e77..04137e7 100644
--- a/src/views/ai/dashboard/components/conversation/CommonConversation.vue
+++ b/src/views/ai/dashboard/components/conversation/CommonConversation.vue
@@ -18,6 +18,9 @@
       ref="sidebarRef">
       <ConversationList
         :active-id="activeConversationId"
+        :quick-access="quickAccessFlag"
+        :model-name="modelName"
+        :default-message="defaultMessage"
         ref="conversationListRef"
         @on-conversation-create="handleConversationCreateSuccess"
         @on-conversation-click="handleConversationClick"
@@ -55,9 +58,8 @@
           <!-- 情况一:消息加载中 -->
           <MessageLoading v-if="activeMessageListLoading" />
           <!-- 情况二:无聊天对话时 -->
-          <MessageNewConversation
+          <MessageListEmpty
             v-if="!activeConversation"
-            @on-new-conversation="handleConversationCreate"
           />
           <!-- 情况三:消息列表为空 -->
           <MessageListEmpty
@@ -89,7 +91,7 @@
               @input="handlePromptInput"
               @compositionstart="onCompositionstart"
               @compositionend="onCompositionend"
-              placeholder="问我任何问题...(Shift+Enter 换行,按下 Enter 发送)"
+              placeholder="请问我问题...(Shift+Enter 换行,按下 Enter 发送)"
             ></textarea>
             <div class="prompt-btns">
               <div class="content">
@@ -141,13 +143,21 @@
 import MessageList from '../message/MessageList.vue'
 import MessageListEmpty from '../message/MessageListEmpty.vue'
 import MessageLoading from '../message/MessageLoading.vue'
-import MessageNewConversation from '../message/MessageNewConversation.vue'
 import { onClickOutside } from '@vueuse/core'
 import * as authUtil from "@/utils/auth";
 import {refreshToken} from "@/api/login";
+import {formatToDateTime} from "@/utils/dateUtil";
+import {ElLoading} from "element-plus";
 
 /** AI 聊天对话 列表 */
 defineOptions({ name: 'NormalConversation' })
+
+const props = defineProps({
+  data: {
+    type: Object,
+    default: () => null
+  }
+})
 
 const route = useRoute() // 路由
 const message = useMessage() // 消息弹窗
@@ -175,8 +185,12 @@
   isCollapsed.value = !isCollapsed.value
 }
 
+const modelName = ref<string>('common') // 对话搜索
+
 // 聊天对话
 const conversationListRef = ref()
+const quickAccessFlag = ref(false)
+const defaultMessage = ref<ChatMessageVO>()
 const activeConversationId = ref<number | null>(null) // 选中的对话编号
 const activeConversation = ref<ChatConversationVO | null>(null) // 选中的 Conversation
 const conversationInProgress = ref(false) // 对话是否正在进行中。目前只有【发送】消息时,会更新为 true,避免切换对话、删除对话等操作
@@ -199,7 +213,6 @@
 // 接收 Stream 消息
 const receiveMessageFullText = ref('')
 const receiveMessageDisplayedText = ref('')
-
 
 // =========== 【聊天对话】相关 ===========
 
@@ -298,7 +311,6 @@
     activeMessageList.value = await ChatMessageApi.getChatMessageListByConversationId(
       activeConversationId.value
     )
-
     // 滚动到最下面
     await nextTick()
     await scrollToBottom()
@@ -335,19 +347,37 @@
   return []
 })
 
-//处理调度推理结论
-const dealResult = (conversations: any) => {
-  const regex = /<think>(\n*)([\s\S]*?)(\n*)<\/think>(\n*)([\s\S]*)/;
-  conversations.forEach((conversation) => {
-    if(conversation.content.includes('<\/think>')) {
-      conversation.thinkingFlag = false
-    } else {
-      conversation.thinkingFlag = true
-    }
-    const match = conversation.content.match(regex);
-    if(match) {
-      conversation.thinking = match[2];
-      conversation.conclusion = match[5]
+// //处理调度推理结论(deepSeek)
+// const dealResult = (conversations: any) => {
+//   const regex = /<think>(\n*)([\s\S]*?)(\n*)<\/think>(\n*)([\s\S]*)/;
+//   conversations.forEach((conversation) => {
+//     if(conversation.content.includes('<\/think>')) {
+//       conversation.thinkingFlag = false
+//     } else {
+//       conversation.thinkingFlag = true
+//     }
+//     const match = conversation.content.match(regex);
+//     if(match) {
+//       conversation.thinking = match[2];
+//       conversation.conclusion = match[5]
+//     }
+//   })
+// }
+
+//处理调度推理结论(微调大模型)
+const dealResult = (messages: any) => {
+  messages.forEach((message) => {
+    if(message.type === 'assistant') {
+      const spliceText = message.content.includes("总结:") ? "总结:" : "结论:";
+      // 创建同时捕获前后内容的正则表达式
+      const regex = new RegExp(`^([\\s\\S]*?)${spliceText}([\\s\\S]*)$`);
+      const match = message.content.match(regex);
+      if(match) {
+        message.thinking = match[1];
+        message.conclusion = match[2]
+      } else {
+        message.thinking = message.content
+      }
     }
   })
 }
@@ -455,19 +485,20 @@
     message.error('发送失败,原因:内容为空!')
     return
   }
+  // 发送请求时如果accessToken过期,无法中断请求,暂时增加请求前刷新token
+  authUtil.setToken(await refreshToken())
   if (activeConversationId.value == null) {
-    message.error('还没创建对话,不能发送!')
-    return
+    await conversationListRef.value.createConversation(props.data?formatToDateTime(new Date(props.data.createTime)):null)
   }
   // 清空输入框
   prompt.value = ''
-  // 发送请求时如果accessToken过期,无法中断请求,暂时增加请求前刷新token
-  authUtil.setToken(await refreshToken())
-  // 执行发送
-  await doSendMessageStream({
-    conversationId: activeConversationId.value,
-    content: content
-  } as ChatMessageVO)
+  setTimeout(() => {
+    // 执行发送
+    doSendMessageStream({
+      conversationId: activeConversationId.value,
+      content: content
+    } as ChatMessageVO)
+  }, 400)
 }
 
 /** 真正执行【发送】消息操作 */
@@ -478,7 +509,6 @@
   conversationInProgress.value = true
   // 设置为空
   receiveMessageFullText.value = ''
-
   try {
     // 1.1 先添加两个假数据,等 stream 返回再替换
     activeMessageList.value.push({
@@ -499,8 +529,7 @@
     await nextTick()
     await scrollToBottom() // 底部
     // 1.3 开始滚动
-    textRoll()
-
+    await textRoll()
     // 2. 发送 event stream
     let isFirstChunk = true // 是否是第一个 chunk 消息段
     await ChatMessageApi.sendChatMessageStream(
@@ -542,7 +571,9 @@
         stopStream()
       }
     )
-  } catch {}
+  } catch {
+    console.log('sendStream Exception')
+  }
 }
 
 /** 停止 stream 流式调用 */
@@ -632,16 +663,19 @@
 
 /** 初始化 **/
 onMounted(async () => {
-  // 如果有 conversationId 参数,则默认选中
-  if (route.query.conversationId) {
-    const id = route.query.conversationId as unknown as number
-    activeConversationId.value = id
-    await getConversation(id)
+  defaultMessage.value = props.data
+  if(defaultMessage.value) {
+    prompt.value = defaultMessage.value.content
+    quickAccessFlag.value = true
+  } else {
+    // 获取列表数据
+    activeMessageListLoading.value = true
+    await getMessageList()
   }
+})
 
-  // 获取列表数据
-  activeMessageListLoading.value = true
-  await getMessageList()
+onUnmounted(() => {
+  stopStream()
 })
 </script>
 
@@ -655,7 +689,7 @@
 
 .sidebar-toggle {
   position: absolute;
-  left: 300px;  // 初始展开位置
+  left: 320px;  // 初始展开位置
   top: 40%;
   z-index: 1000;
   width: 20px;
@@ -682,12 +716,12 @@
   left: 0;
   top: 0;
   bottom: 0;
-  width: 300px;
+  width: 320px;
   background: rgba(13,28,58,0.9);
   box-shadow: 2px 0 8px rgba(0,0,0,0.1);
   transition: transform 0.3s ease, opacity 0.2s ease;
   z-index: 999;
-  overflow: hidden;
+  overflow-x: hidden;
 
   &.collapsed {
     transform: translateX(-100%);
@@ -699,7 +733,7 @@
 // 头部
 .detail-container {
   width: 100%;
-  height: 885px;
+  height: 910px;
   margin-left: 5px;
   background-color: rgba(0, 0, 0, 0); /* 透明背景 */
   transition: margin 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -796,7 +830,7 @@
 .footer-container {
   display: flex;
   flex-direction: column;
-  height: 114px;
+  height: 205px;
   margin-left: 10px;
   padding: 0;
 
@@ -831,7 +865,7 @@
       flex-direction: column;
       padding: 9px 10px;
       width: 876px;
-      height: 114px;
+      height: 205px;
       background: rgba(115,196,255,0.05);
       border-radius: 4px 4px 4px 4px;
       border: 1px solid #73C4FF;
@@ -842,8 +876,8 @@
     }
 
     .prompt-input {
-      width: 876px;
-      height: 113.55px;
+      width: 860px;
+      height: 203px;
       font-weight: 400;
       font-size: 14px;
       background-color: rgba(219,238,255,0);
diff --git a/src/views/ai/dashboard/components/conversation/CommonConversationList.vue b/src/views/ai/dashboard/components/conversation/CommonConversationList.vue
index df1c641..590e88c 100644
--- a/src/views/ai/dashboard/components/conversation/CommonConversationList.vue
+++ b/src/views/ai/dashboard/components/conversation/CommonConversationList.vue
@@ -1,8 +1,8 @@
 <!--  AI 对话  -->
 <template>
-  <el-aside width="260px" class="conversation-container h-100%">
+  <el-aside width="280px" class="conversation-container h-100%">
     <!-- 左顶部:对话 -->
-    <div class="h-100%">
+    <div class="h-80%">
       <div class="conversation-title">
         <img
           src="@/assets/ai/zhuanlu/conversation_big.png"
@@ -12,7 +12,7 @@
         对话列表
       </div>
 <!--      <hr class="line"/>-->
-      <el-button class="w-1/1 btn-new-conversation" type="primary" @click="createConversation">
+      <el-button class="w-1/1 btn-new-conversation" type="primary" @click="createNewConversation">
         <img
           src="@/assets/ai/zhuanlu/conversation_big.png"
           class="mr-8px w-[1.5em] h-[1.5em]"
@@ -82,8 +82,6 @@
             </div>
           </div>
         </div>
-        <!-- 底部占位  -->
-        <div class="h-160px w-100%"></div>
       </div>
     </div>
 
@@ -102,12 +100,13 @@
 import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation'
 import { Bottom, Top } from '@element-plus/icons-vue'
 import roleAvatarDefaultImg from '@/assets/ai/zhuanlu/assistant.png'
+import {ChatMessageVO} from "@/api/ai/chat/message";
+import {formatToDate, formatToDateTime} from "@/utils/dateUtil";
 
 const message = useMessage() // 消息弹窗
 
 // 定义属性
 const searchName = ref<string>('') // 对话搜索
-const modelName = ref<string>('common') // 对话搜索
 const activeConversationId = ref<number | null>(null) // 选中的对话,默认为 null
 const hoverConversationId = ref<number | null>(null) // 悬浮上去的对话
 const conversationList = ref([] as ChatConversationVO[]) // 对话列表
@@ -120,7 +119,16 @@
   activeId: {
     type: String || null,
     required: true
-  }
+  },
+  modelName: {
+    type: String || null,
+    required: true
+  },
+  quickAccess: {
+    type: Boolean || null,
+    required: true
+  },
+  defaultMessage: {}
 })
 
 // 定义钩子
@@ -169,10 +177,7 @@
     }, 50)
 
     // 1.1 获取 对话数据
-    conversationList.value = await ChatConversationApi.getChatConversationEnergyList(modelName.value)
-    if(conversationList.value.length == 0) {
-      await createConversation()
-    }
+    conversationList.value = await ChatConversationApi.getChatConversationEnergyList(props.modelName)
     // 1.2 排序
     conversationList.value.sort((a, b) => {
       return b.createTime - a.createTime
@@ -184,7 +189,7 @@
       return
     }
 
-    // 2. 对话根据时间分组(置顶、今天、一天前、三天前、七天前、30 天前)
+    // 2. 对话根据时间分组(置顶、今天、昨天、三天前、七天前、30 天前)
     conversationMap.value = await getConversationGroupByCreateTime(conversationList.value)
   } finally {
     // 清理定时器
@@ -203,7 +208,7 @@
   const groupMap = {
     置顶: [],
     今天: [],
-    一天前: [],
+    昨天: [],
     三天前: [],
     七天前: [],
     三十天前: []
@@ -212,9 +217,11 @@
   const now = Date.now()
   // 定义时间间隔常量(单位:毫秒)
   const oneDay = 24 * 60 * 60 * 1000
-  const threeDays = 3 * oneDay
   const sevenDays = 7 * oneDay
   const thirtyDays = 30 * oneDay
+  //今天
+  const today = formatToDate(new Date())
+  const yesterday = formatToDate(new Date().setDate(new Date().getDate() - 1))
   for (const conversation of list) {
     // 置顶
     if (conversation.pinned) {
@@ -223,11 +230,13 @@
     }
     // 计算时间差(单位:毫秒)
     const diff = now - conversation.createTime
+    let conversationDate = formatToDate(conversation.createTime)
+    let titleDate = conversation.title.split(' ')[0]
     // 根据时间间隔判断
-    if (diff < oneDay) {
+    if (titleDate == today) {
       groupMap['今天'].push(conversation)
-    } else if (diff < threeDays) {
-      groupMap['一天前'].push(conversation)
+    } else if (titleDate == yesterday) {
+      groupMap['昨天'].push(conversation)
     } else if (diff < sevenDays) {
       groupMap['三天前'].push(conversation)
     } else if (diff < thirtyDays) {
@@ -240,17 +249,22 @@
 }
 
 /** 新建对话 */
-const createConversation = async () => {
+const createNewConversation = async () => {
+  await createConversation(null)
+}
+
+/** 新建对话 */
+const createConversation = async (title: String) => {
   // 1. 新建对话
   const conversationId = await ChatConversationApi.createChatConversationEnergy(
-    {modelName: modelName.value} as unknown as ChatConversationVO
+    {modelName: props.modelName, title: title} as unknown as ChatConversationVO
   )
   // 2. 获取对话内容
   await getChatConversationList()
   // 3. 选中对话
   await handleConversationClick(conversationId)
-  // 4. 回调
-  emits('onConversationCreate')
+  // // 4. 回调
+  // emits('onConversationCreate')
 }
 
 /** 修改对话的标题 */
@@ -344,15 +358,28 @@
 onMounted(async () => {
   // 获取 对话列表
   await getChatConversationList()
-  // 默认选中
-  if (props.activeId) {
-    activeConversationId.value = props.activeId
-  } else {
-    // 首次默认选中第一个
+  if(!props.quickAccess) {
+    // 默认选中
+    if (props.activeId) {
+      activeConversationId.value = props.activeId
+    } else {
+      // 首次默认选中第一个
+      if (conversationList.value.length) {
+        activeConversationId.value = conversationList.value[0].id
+        // 回调 onConversationClick
+        await emits('onConversationClick', conversationList.value[0])
+      }
+    }
+  } else if(props.defaultMessage) {
+    let tempTitle = formatToDateTime(new Date(props.defaultMessage.createTime))
     if (conversationList.value.length) {
-      activeConversationId.value = conversationList.value[0].id
-      // 回调 onConversationClick
-      await emits('onConversationClick', conversationList.value[0])
+      conversationList.value.forEach((item) => {
+        if(item.title === tempTitle) {
+          activeConversationId.value = item.id
+          // 回调 onConversationClick
+          emits('onConversationClick', item)
+        }
+      })
     }
   }
 })
@@ -395,16 +422,30 @@
   }
 
   .conversation-list {
-    overflow: auto;
+    overflow-y: auto;
     height: 100%;
+    margin-top: 10px;
+    /* Firefox */
+    scrollbar-width: thin;
+    scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
 
+    /* WebKit */
+    &::-webkit-scrollbar {
+      width: 6px;
+      background: transparent;
+    }
+    &::-webkit-scrollbar-thumb {
+      border-radius: 4px;
+      background: rgba(0, 0, 0, 0.15);
+      transition: background 0.3s;
+      &:hover { background: rgba(0, 0, 0, 0.25); }
+    }
     .classify-title {
       padding-top: 10px;
       b {
         color: white;
       }
     }
-
     .conversation-item {
       margin-top: 5px;
     }
@@ -443,10 +484,9 @@
       }
 
       .title {
-        padding: 2px 10px;
+        padding: 2px 5px;
         max-width: 220px;
-        font-size: 14px;
-        font-weight: 400;
+        font-size: 13px;
         color: rgba(0, 0, 0, 0.77);
         overflow: hidden;
         white-space: nowrap;
@@ -478,17 +518,19 @@
     }
   }
 
-  // 角色仓库、清空未设置对话
+  // 清空未设置对话
   .tool-box {
-    bottom: 0;
+    display: flex;
     padding: 0 20px;
+    width: 90%;
+    margin-left: 5%;
     background-color: rgba(69,133,255,0.2);
     box-shadow: 0 0 1px 1px rgba(69,133,255,0.4);
     line-height: 35px;
     justify-content: space-between;
     align-items: center;
     color: var(--el-text-color);
-
+    border-radius: 2px;
     div {
       display: flex;
       margin-left: 20%;
diff --git a/src/views/ai/dashboard/components/message/HistoryMessageList.vue b/src/views/ai/dashboard/components/message/HistoryMessageList.vue
index 91371e1..b4ebf44 100644
--- a/src/views/ai/dashboard/components/message/HistoryMessageList.vue
+++ b/src/views/ai/dashboard/components/message/HistoryMessageList.vue
@@ -43,7 +43,7 @@
           <div>
             <el-text class="time">{{ formatDate(item.createTime) }}</el-text>
           </div>
-          <div class="right-text-container">
+          <div class="right-text-container question" @click="gotoManual(item)">
             <div class="right-text">{{ item.content }}</div>
           </div>
           <div class="right-btns">
@@ -71,15 +71,12 @@
 import { ArrowDownBold } from '@element-plus/icons-vue'
 import { ChatMessageApi, ChatMessageVO } from '@/api/ai/chat/message'
 import { ChatConversationVO } from '@/api/ai/chat/conversation'
-import { useUserStore } from '@/store/modules/user'
 import userAvatarDefaultImg from '@/assets/ai/zhuanlu/user.png'
 import roleAvatarDefaultImg from '@/assets/ai/zhuanlu/assistant.png'
 
-const dialogVisible = ref(false) // 弹窗的是否展示
 
 const message = useMessage() // 消息弹窗
 const { copy } = useClipboard() // 初始化 copy 到粘贴板
-const userStore = useUserStore()
 
 // 判断“消息列表”滚动的位置(用于判断是否需要滚动到消息最下方)
 const messageContainer: any = ref(null)
@@ -87,6 +84,7 @@
 
 const userAvatar = computed(() => userAvatarDefaultImg)
 const roleAvatar = computed(() => props.conversation.roleAvatar ?? roleAvatarDefaultImg)
+
 
 // 定义 props
 const props = defineProps({
@@ -97,7 +95,9 @@
   list: {
     type: Array as PropType<ChatMessageVO[]>,
     required: true
-  }
+  },
+
+  gotoManualMethod: Function
 })
 
 const { list } = toRefs(props) // 消息列表
@@ -146,6 +146,12 @@
 
 // ============ 处理消息操作 ==============
 
+const gotoManual = async (item: ChatMessageVO) => {
+  if(props.gotoManualMethod) {
+    props.gotoManualMethod(item)
+  }
+}
+
 /** 复制 */
 const copyContent = async (content) => {
   await copy(content)
@@ -192,6 +198,11 @@
     flex-direction: column;
     text-align: left;
     margin: 0 15px;
+
+    .question:hover {
+      cursor: pointer;
+      background: rgba(40, 139, 255, 0.3);
+    }
 
     .time {
       text-align: left;
@@ -282,9 +293,15 @@
   bottom: 0;
   right: 50%;
   .el-button {
-    background: rgba(255,215,0,0.2);
-    border: solid 1px rgba(255,215,0,0.8);
-    color: rgba(255,215,0,0.8);
+    background: rgba(255,255,255,0.1);
+    border: solid 1px rgba(255,215,0,0.6);
+    color: rgba(255,215,0,0.5);
+  }
+  .el-button:hover {
+    cursor: pointer;
+    background-color: rgba(255,255,255,0.4);
+    border: solid 2px rgba(255,215,0);
+    color: rgba(255,215,0);
   }
 }
 </style>
diff --git a/src/views/ai/dashboard/components/message/MessageList.vue b/src/views/ai/dashboard/components/message/MessageList.vue
index 616b9f4..5ecf1bc 100644
--- a/src/views/ai/dashboard/components/message/MessageList.vue
+++ b/src/views/ai/dashboard/components/message/MessageList.vue
@@ -240,7 +240,7 @@
       overflow-wrap: break-word;
       background: rgba(115,196,255,0);
       border-radius: 4px 4px 4px 4px;
-      padding: 20px 10px 5px 0;
+      padding: 0 10px 0 0;
       .left-text {
         color: rgba(219,238,255,0.8);
         font-size: 1rem;
@@ -295,11 +295,23 @@
   }
 }
 
-// 回到底部
 .to-bottom {
   position: absolute;
   z-index: 1000;
   bottom: 0;
   right: 50%;
+
+  .el-button {
+    background: rgba(255, 255, 255, 0.1);
+    border: solid 1px rgba(255, 215, 0, 0.6);
+    color: rgba(255, 215, 0, 0.5);
+  }
+
+  .el-button:hover {
+    cursor: pointer;
+    background-color: rgba(255, 255, 255, 0.4);
+    border: solid 2px rgba(255, 215, 0);
+    color: rgba(255, 215, 0);
+  }
 }
 </style>
diff --git a/src/views/ai/dashboard/zhuanlu/index.vue b/src/views/ai/dashboard/zhuanlu/index.vue
index 0d0be46..9feb5d0 100644
--- a/src/views/ai/dashboard/zhuanlu/index.vue
+++ b/src/views/ai/dashboard/zhuanlu/index.vue
@@ -62,7 +62,7 @@
 
     <div class="gas-scheduling-center">
       <div class="mode-switch">
-        <el-radio-group v-model="tabPosition" class="custom-radio-group">
+        <el-radio-group v-model="tabPosition" @change="handleChange" class="custom-radio-group">
           <el-radio-button label="model">大模型模式</el-radio-button>
           <el-radio-button label="conversation">对话模式</el-radio-button>
         </el-radio-group>
@@ -164,12 +164,15 @@
         <!-- 历史建议 -->
         <HistoryMessageDialog
           ref="historyMessageRef"
-          :conversation="activeConversation"
+          :parentMethod="queryHistoryMessage"
+          @gotoManualMethod="gotoManual"
         />
       </div>
 
       <div v-else>
-        <NormalConversation />
+        <NormalConversation
+          :data="defaultMessage"
+        />
       </div>
     </div>
 
@@ -265,6 +268,7 @@
 import {round} from "lodash-es";
 import {ArrowUpBold} from "@element-plus/icons-vue";
 import * as authUtil from "@/utils/auth";
+import HistoryMessageList from "@/views/ai/dashboard/components/message/HistoryMessageList.vue";
 
 const mqhsList = ref([
   {
@@ -548,6 +552,7 @@
 const messageRef = ref()
 const activeMessageList = ref<ChatMessageVO[]>([]) // 选中对话的消息列表
 const activeHistoryMessageList = ref<ChatMessageVO[]>([]) // 历史建议列表
+const activeHistoryMessageTotal = ref(0) // 历史建议总数
 const activeMessageListLoading = ref<boolean>(false) // activeMessageList 是否正在加载中
 const activeMessageListLoadingTimer = ref<any>() // activeMessageListLoading Timer 定时器。如果加载速度很快,就不进入加载中
 // 消息滚动
@@ -573,8 +578,30 @@
 const historyMessageRef = ref()
 const openHistoryMessage = async () => {
   // 刷新 message 列表
-  await getHistoryMessageList()
-  historyMessageRef.value.open(activeHistoryMessageList.value, activeConversation.value)
+  let resDate = await historyMessageRef.value.dealDate()
+  await getHistoryMessageList(resDate)
+  historyMessageRef.value.open(activeHistoryMessageList.value, activeConversation.value, activeHistoryMessageTotal.value)
+}
+
+const queryHistoryMessage = async (queryParams: ChatMessageVO) => {
+  return await getHistoryMessageList(queryParams)
+}
+
+//切换对话模式判断
+const handleChange = async () => {
+  // 对话进行中,不允许切换
+  if (conversationInProgress.value) {
+    message.alert('对话中,不允许切换!')
+    return false
+  }
+}
+
+// 默认选中消息
+const defaultMessage = ref<ChatMessageVO>()
+
+const gotoManual = async (item: ChatMessageVO) => {
+  defaultMessage.value = item
+  tabPosition.value = 'conversation'
 }
 
 // =========== 【聊天对话】相关 ===========
@@ -671,22 +698,23 @@
 }
 
 /** 获取消息 message 列表 */
-const getHistoryMessageList = async () => {
+const getHistoryMessageList = async (params: any) => {
   if (activeConversationId.value === null) {
     return
   }
+  params.conversationId = activeConversationId.value
   // 获取消息列表
-  activeHistoryMessageList.value = await ChatMessageApi.getChatMessageListByConversationId(
-    activeConversationId.value
-  )
-  if (activeHistoryMessageList.value.length > 0) {
+  let pageResult = await ChatMessageApi.getChatMessagePageListByConversationId(params)
+  activeHistoryMessageList.value = pageResult.list
+  activeHistoryMessageTotal.value = pageResult.total
+  if (activeHistoryMessageList.value != null && activeHistoryMessageList.value.length > 0) {
     activeHistoryMessageList.value.forEach((message: ChatMessageVO) => {
       if(message.type != 'user') {
         dealResult(message)
       }
     })
-    return activeHistoryMessageList.value
   }
+  return pageResult
 }
 //处理调度推理结论
 const dealResult = (message: any) => {
@@ -709,7 +737,6 @@
 const messageList = computed(() => {
   if (activeMessageList.value.length > 0) {
     activeMessageList.value[1].thinking = dealResultAndData(activeMessageList.value[1].content)
-    console.log(activeMessageList.value)
     return activeMessageList.value
   }
   // 没有消息时,如果有 systemMessage 则展示它
@@ -1143,11 +1170,11 @@
   let returnValue = 0;
   if(type == 'max') {
     returnValue = computed(() => {
-      return Math.max(...tank) + 20
+      return Number((Math.max(...tank) + 20).toFixed(0))
     })
   } else if(type == 'min') {
     returnValue = computed(() => {
-      return Math.min(...tank) - 60
+      return Number((Math.min(...tank) - 60).toFixed(0))
     })
   } else if(type == 'average') {
     returnValue = computed(() => {
@@ -1155,7 +1182,7 @@
       tank.forEach((item) => {
         sum += item[0]
       })
-      return (sum / tank.length).toFixed(0);
+      return Number((sum / tank.length).toFixed(0));
     })
   }
   return returnValue.value
@@ -1582,6 +1609,7 @@
 
 // 清理监听
 onUnmounted(() => {
+  console.log('stopStream')
   const events = ['fullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange'];
   events.forEach(event => {
     document.removeEventListener(event, handleFullscreenChange);
diff --git a/src/views/ai/model/template/index.vue b/src/views/ai/model/template/index.vue
index fa84bdb..b6de43b 100644
--- a/src/views/ai/model/template/index.vue
+++ b/src/views/ai/model/template/index.vue
@@ -109,9 +109,7 @@
 
 </template>
 <script lang="ts" setup>
-  import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
-  import {dateFormatter} from '@/utils/formatTime'
-  import download from '@/utils/download'
+  import { DICT_TYPE } from '@/utils/dict'
   import * as AiQuestionTemplateApi from '@/api/ai/questiontemplate'
   import TemplateForm from './templateForm.vue'
   import * as AiModelApi from "@/api/ai/model/model";

--
Gitblit v1.9.3