houzhongjian
2025-06-12 11697cb7da4e5d78d21bd2f5c107da456a08c594
大模型功能修改
已修改3个文件
249 ■■■■ 文件已修改
src/api/ai/chat/message/index.ts 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/src/DialogHistory.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/dashboard/components/message/HistoryMessageDialog.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/chat/message/index.ts
@@ -2,7 +2,6 @@
import { fetchEventSource } from '@microsoft/fetch-event-source'
import { getAccessToken } from '@/utils/auth'
import { config } from '@/config/axios/config'
import {refreshToken} from "@/api/login";
// 聊天VO
export interface ChatMessageVO {
@@ -36,6 +35,14 @@
  getChatMessageListByConversationId: async (conversationId: number | null) => {
    return await request.get({
      url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`
    })
  },
  // 消息列表
  getChatMessagePageListByConversationId: async (params: number | null) => {
    return await request.get({
      url: `/ai/chat/message/page-list-by-conversation-id`,
      params: params
    })
  },
@@ -76,35 +83,6 @@
      signal: ctrl.signal
    })
  },
  // 发送 Stream 消息 【工业大模型专用】
  // sendEnergyChatMessageStream: async (
  //   conversationId: number,
  //   content: string,
  //   ctrl,
  //   enableContext: boolean,
  //   onMessage,
  //   onError,
  //   onClose
  // ) => {
  //   const token = getAccessToken()
  //   return fetchEventSource(`${config.base_url}/ai/chat/message/send-energy-stream`, {
  //     method: 'post',
  //     headers: {
  //       'Content-Type': 'application/json',
  //       Authorization: `Bearer ${token}`
  //     },
  //     openWhenHidden: true,
  //     body: JSON.stringify({
  //       conversationId,
  //       content,
  //       useContext: enableContext
  //     }),
  //     onmessage: onMessage,
  //     onerror: onError,
  //     onclose: onClose,
  //     signal: ctrl.signal
  //   })
  // },
  // 删除消息
  deleteChatMessage: async (id: string) => {
@@ -115,18 +93,6 @@
  deleteByConversationId: async (conversationId: number) => {
    return await request.delete({
      url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}`
    })
  },
  // // 删除消息【工业大模型专用】
  // deleteEnergyChatMessage: async (id: string) => {
  //   return await request.delete({ url: `/ai/chat/message/delete-energy?id=${id}` })
  // },
  // 删除指定对话的消息【工业大模型专用】
  deleteEnergyByConversationId: async (conversationId: number) => {
    return await request.delete({
      url: `/ai/chat/message/delete-energy-by-conversation-id?conversationId=${conversationId}`
    })
  },
src/components/Dialog/src/DialogHistory.vue
@@ -73,14 +73,6 @@
          class="absolute right-15px top-[50%] h-40px flex translate-y-[-50%] items-center justify-between"
        >
          <Icon
            v-if="fullscreen"
            class="is-hover mr-10px cursor-pointer"
            :icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
            color="#73C4FF"
            hover-color="var(--el-color-primary)"
            @click="toggleFull"
          />
          <Icon
            class="is-hover cursor-pointer"
            icon="ep:close"
            hover-color="var(--el-color-primary)"
@@ -101,9 +93,8 @@
<style lang="scss">
.history-dialog {
  height: 90vh;
  margin-top: 30px;
  color: #73C4FF;
  overflow: hidden; /* 防止内容溢出 */
  margin-top: 30px;
  background: rgba(3,29,76,0.79);
  border-radius: 4px 4px 4px 4px;
  border: 1px solid;
@@ -115,7 +106,6 @@
  .#{$elNamespace}-dialog {
    margin: 0 !important;
    &__header {
      height: 40px;
      padding: 0;
src/views/ai/dashboard/components/message/HistoryMessageDialog.vue
@@ -1,17 +1,41 @@
<template>
  <DialogHistory title="历史建议" v-model="dialogVisible" width="1200">
    <!-- 左侧:对话列表 -->
    <ConversationList
      v-show="false"
      :active-id="activeConversationId"
      ref="conversationListRef"
    />
    <!-- 右侧:对话详情 -->
  <DialogHistory title="历史建议" v-model="dialogVisible" width="1200" custom-class="transparent-dialog">
    <!-- 搜索工作栏 -->
    <el-form
      class="-mb-15px query-area"
      :model="queryParams"
      ref="queryFormRef"
      :inline="true"
      label-width="68px"
    >
      <el-form-item label="对话时间" prop="createTime">
        <el-date-picker
          v-model="queryParams.createTime"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="datetimerange"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          class="!w-360px transparent-date-picker-popper"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery">
          <Icon icon="ep:search" class="mr-5px"/>
          搜索
        </el-button>
        <el-button @click="resetQuery">
          <Icon icon="ep:refresh" class="mr-5px"/>
          重置
        </el-button>
      </el-form-item>
    </el-form>
    <!-- 对话详情 -->
    <el-container class="detail-container">
      <el-header class="header">
        <div class="title">
          {{ activeConversation?.title ? activeConversation?.title : '' }}
          <span v-if="activeMessageList.length">({{ activeMessageList.length }})</span>
          <span v-if="total">({{ total }})</span>
        </div>
        <div class="btns" v-if="activeConversation">
          <el-button size="small" class="btn" @click="handlerMessageClear">
@@ -43,32 +67,55 @@
            ref="messageRef"
            :conversation="activeConversation"
            :list="activeMessageList"
            :gotoManualMethod="gotoManual"
          />
        </div>
      </el-main>
    </el-container>
    <!-- 分页 -->
    <Pagination
      :total="total"
      v-model:page="queryParams.pageNo"
      v-model:limit="queryParams.pageSize"
      @pagination="handleQuery"
    />
  </DialogHistory>
</template>
<script setup lang="ts">
import {ChatMessageApi, ChatMessageVO} from '@/api/ai/chat/message'
import { ChatConversationVO } from '@/api/ai/chat/conversation'
import ConversationList from '../conversation/HistoryConversationList.vue'
import HistoryMessageList from './HistoryMessageList.vue'
import MessageListEmpty from './MessageListEmpty.vue'
import ConversationListEmpty from '../conversation/ConversationListEmpty.vue'
import {formatDate} from "@vueuse/core";
import {ref} from "vue";
/** AI 聊天对话 列表 */
defineOptions({ name: 'HistoryMessageDialog' })
const route = useRoute() // 路由
// 接收父组件传递的方法
const props = defineProps({
  parentMethod: Function,
  gotoManualMethod: Function
});
// 定义发射事件
const emit = defineEmits(['gotoManualMethod'])
const message = useMessage() // 消息弹窗
const total = ref(0) // 历史建议列表
const dialogVisible = ref(false) // 弹窗的是否展示
const queryFormRef = ref() // 搜索的表单
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  createTime: [],
})
// 聊天对话
const conversationListRef = ref()
const activeConversation = ref<ChatConversationVO | null>(null) // 选中的 Conversation
// 消息列表
@@ -77,14 +124,24 @@
/** 打开弹窗 */
const open = async (messages: ChatMessageVO[], conversation: ChatConversationVO) => {
const open = async (messages: ChatMessageVO[], conversation: ChatConversationVO, activeHistoryMessageTotal: number) => {
  dialogVisible.value = true
  total.value = activeHistoryMessageTotal
  await nextTick() // 等待弹窗DOM挂载
  activeMessageList.value = messages
  activeConversation.value = conversation
}
defineExpose({ open }) // 提供方法给 parent 调用
/** 处理查询时间段 */
const dealDate = async () => {
  const currentDate = new Date();
  const previousDate = new Date(currentDate.getTime() -  2 * 60 * 60 * 1000);
  queryParams.createTime[0] = formatDate(previousDate, 'YYYY-MM-DD HH:mm:ss');
  queryParams.createTime[1] = formatDate(currentDate, 'YYYY-MM-DD HH:mm:ss');
  return queryParams;
}
defineExpose({ open, dealDate }) // 提供方法给 parent 调用
/** 回到 message 列表的顶部 */
const handleGoTopMessage = () => {
@@ -111,19 +168,77 @@
  } catch {}
}
const gotoManual = async (item: ChatMessageVO) => {
  emit('gotoManualMethod', item) // 发送数据给父组件
}
/** 搜索按钮操作 */
const handleQuery = async () => {
  if (props.parentMethod) {
    // props.parentMethod({ data: queryParams }); // 可传递参数
    let pageResult = await props.parentMethod(queryParams)
    activeMessageList.value = pageResult.list
    total.value = pageResult.total
  }
}
/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  queryParams.pageNo = 1
  handleQuery()
}
/** 初始化 **/
onMounted(async () => {
  // await dealDate()
})
</script>
<style lang="scss" scoped>
.query-area {
  margin-top: 10px;
  float: right;
  :deep(.el-form-item__label) {
    color: #73C4FF;
  }
  :deep(.el-date-editor .el-icon) {
    color: #DBEEFF;
  }
  :deep(.el-date-editor .el-range-input) {
    color: rgba(219, 238, 255, 0.5);
  }
  /* 移除所有输入框边框 */
  :deep(.el-form-item .el-input__wrapper) {
    border: none !important;
    box-shadow: none !important;
    background: rgba(255,255,255,0.1) !important; /* 保留浅色背景 */
  }
  /* 所有状态通用透明背景 */
  :deep(.el-button) {
    background: transparent !important;
    border-color: currentColor; /* 保持与文字同色 */
    color: #409EFF; /* 蓝色文字 */
  }
  /* 悬停状态 */
  :deep(.el-button:hover) {
    background: rgba(0, 0, 0, 0.5) !important; /* 轻微悬停反馈 */
  }
  /* 点击状态 */
  :deep(.el-button:active) {
    background: rgba(0, 0, 0, 0.8) !important;
  }
}
// 头部
.detail-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 820px;
  height: 75vh;
  background-color: rgba(0, 0, 0, 0); /* 透明背景 */
  z-index: 1;
  .header {
@@ -165,7 +280,6 @@
      :deep(.el-button:active) {
        background: rgba(0, 0, 0, 0.1) !important;
      }
      /* 禁用状态 */
      :deep(.el-button.is-disabled) {
        opacity: 0.6;
@@ -370,6 +484,45 @@
        }
      }
    }
    /* 下拉组件 */
    :deep(.el-select) {
      /* 下拉箭头 */
      .el-select__caret {
        color: #73C4FF !important; /* 匹配图中的浅蓝箭头 */
        font-size: 16px !important;
      }
    }
    /* 深度选择器调整边框细节 */
    :deep(.el-select__wrapper) {
      background-color: transparent !important;
      border-radius: 6px;        /* 圆角大小 */
      border-width: 1.5px;        /* 边框粗细 */
      box-shadow: 0 0 0 1px #1E5A86 !important; /* 聚焦阴影 */
    }
  }
}
.el-pagination {
  //--el-pagination-button-bg-color: transparent;
  opacity: 0.6;
  :deep(.el-pagination__total) {
    color: white;
  }
  :deep(.el-pager) {
    color: rgba(3,27,21);
    font-weight: bold;
  }
  :deep(.el-pagination__jump) {
    color: white;
  }
  :deep(.el-select__popper) {
    background-color: transparent;
  }
  :deep(.el-scrollbar) {
    --el-scrollbar-opacity: 0.8;
    --el-scrollbar-bg-color: transparent;
  }
}
</style>