潘志宝
2025-06-13 124f894f4e08fd63eae8c7a85babbc19f2cc1829
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>