<!-- eslint-disable vue/no-v-html -->
<template>
  <div class="btn" @click="showAIChat">
    <div style="display: flex; flex-direction: row" class="btn-header">
      <img src="@/assets/images/vent/home/wakeBtn.png" />
    </div>
  </div>
  <div class="container">
    <div v-if="isShowChatBroad" class="mini-chat">
      <!-- 左侧折叠区域 -->
      <div class="left-side" :class="{ collapsed: isFold }" id="leftSide">
        <div
          class="addBtn"
          :style="{
            backgroundColor: isFold ? '' : '#2cb6ff',
            width: isFold ? '20px' : 'auto',
          }"
          @click="addNew"
        >
          <SvgIcon v-if="isFold" name="add" size="20" :color="''" />
          <span v-if="!isFold" class="btn-text">添加新对话</span>
        </div>
        <div v-if="isFold" class="historyBtn" @click="addNew">
          <SvgIcon v-if="isFold" name="history" size="20" :color="''" />
        </div>
        <div v-else class="historyBtn1">
          <span v-if="!isFold" class="btn-text">历史对话</span>
          <a-list style="width: 136px" :split="false" :data-source="sessionHistory" :scroll="190" class="custom-list">
            <template #renderItem="{ item }">
              <a-list-item
                class="session-item"
                :style="{
                  padding: '8px 10px 0 8px',
                  color: '#5e7081',
                  fontSize: '10px',
                  position: 'relative', // 新增定位
                }"
              >
                <!-- 新增flex布局容器 -->
                <div style="width: 100%">
                  <div v-if="editingId !== item.id" class="text-container">
                    <span class="edit-text" @click="sessionsHistory(item.id)">{{ item.name }}</span>
                    <div class="btn-container">
                      <EditOutlined class="edit-icon" @click="startEditing(item)" />
                      <DeleteOutlined class="delete-icon" @click="startDelete(item)" />
                    </div>
                  </div>
                  <!-- 输入框 -->
                  <a-input
                    size="small"
                    v-else
                    v-model:value="editText"
                    v-focus
                    @blur="handleSave(item)"
                    @keyup.enter="handleSave(item)"
                    class="edit-input"
                  />
                </div>
              </a-list-item>
            </template>
          </a-list>
        </div>
        <div class="foldBtn" @click="fold">
          <SvgIcon v-if="isFold" name="Fold1" size="20" :color="''" />
          <SvgIcon v-else name="unfold" size="20" :color="''" />
        </div>
      </div>
      <!-- 右侧对话框 -->
      <div class="right-side">
        <div class="title"> 智能问答 </div>
        <!-- 对话区域 -->
        <div class="dialog-area" ref="dialogAreaRef">
          <div
            v-for="message in messageHistory"
            :key="message.id"
            class="flex items-center w-100%"
            :style="{ alignSelf: message.type === 'user' ? 'flex-end' : 'flex-start' }"
          >
            <template v-if="message.type === 'user'">
              <div class="flex-grow-1"></div>
              <div class="message-wrapper user-message-wrapper">
                <div class="ask-message">{{ message.parsedContent }}</div>
                <div class="copy-icon-container">
                  <CopyOutlined class="copy-icon" @click="copyToClipboard(message.parsedContent)" title="复制消息" />
                  <EditOutlined class="copy-icon" @click="editAsk(message.parsedContent)" title="重新编辑" />
                </div>
              </div>
            </template>
            <template v-else>
              <SvgIcon size="40" class="answerIcon" name="ai-logo" />
              <div class="message-wrapper ai-message-wrapper">
                <div class="answer-message">
                  <div v-if="message.parsedContentR1" class="thinking-section">
                    <div class="thinking-header" @click="isShow(message)">
                      <span class="thinking-title"
                        >思考过程：<RightOutlined v-if="!message.isShowThink" /> <DownOutlined v-if="message.isShowThink"
                      /></span>
                    </div>
                    <div v-show="message.isShowThink" class="color-gray font-size-12px" v-html="message.parsedContentR1"></div>
                  </div>
                  <div v-if="message.parsedContent" v-html="message.parsedContent"> </div>
                </div>
                <div class="copy-icon-container">
                  <CopyOutlined class="copy-icon" @click="copyToClipboard(message.parsedContent)" title="复制消息" />
                  <RedoOutlined class="copy-icon" @click="refresh()" title="重新生成" />
                </div>
              </div>
            </template>
          </div>
          <!-- 建议信息 -->
          <div v-for="(item, index) in suggestList" :key="index" class="suggestion-item" @click="handleSuggestClick(item)">
            <span class="suggestion-text">{{ item }}</span>
            <a-icon type="right" class="suggestion-arrow" />
          </div>
        </div>
        <!-- 底部输入区 -->
        <div class="input-area">
          <a-textarea v-model:value="inputText" placeholder="请输入你的问题" @keyup.enter="handleSend(inputText)" class="ant-input" auto-size />
          <div class="ctrl-btn">
            <div class="input-controls">
              <button class="control-btn" :class="{ active: isThinking }" @click="toggleThinking">深度思考</button>
              <button class="control-btn" @click="stopReq()">停止响应</button>
            </div>
            <div class="action-bar">
              <Space>
                <Button class="control-btn1" size="small" @mouseenter="showModal(true)">
                  <template #icon>
                    <SvgIcon name="send-file" />
                  </template>
                </Button>
                <Button class="control-btn2" size="small" @click="handleSend(inputText)">
                  <template #icon>
                    <SvgIcon name="send" />
                  </template>
                </Button>
              </Space>
            </div>
          </div>
          <!-- 右侧文件上传区 -->
          <div v-if="open" @mouseenter="showModal(true)" @mouseleave="showModal(false)" class="file-upload">
            <!-- 上传按钮 -->
            <a-upload
              class="custom-upload"
              name="file"
              :multiple="false"
              :before-upload="handleBeforeUpload"
              :file-list="fileList"
              :remove="handleRemove"
              accept=".pdf,.docx,.xlsx,.xls"
            >
              <a-button class="upload-btn">
                <UploadOutlined></UploadOutlined>
                从本地上传
              </a-button>
            </a-upload>
          </div>
        </div>
      </div>
    </div>
    <div class="doc" v-if="isShowDoc">
      <div class="close"> <button class="closeBtn" @click="close">关闭</button></div>
      <!-- 已上传文件列表 -->
      <div class="file-list" v-if="uploadedFiles.length">
        <div class="file-item" v-for="file in uploadedFiles" :key="file.id">
          <div class="file-info">
            <div class="file-name" :title="file.name">{{ file.name }}</div>
          </div>
          <div class="file-actions">
            <button class="btn btn-preview" @click="previewFile(file)"> <i class="fas fa-eye"></i> 预览 </button>
            <button class="btn btn-delete" @click="deleteFile(file.id)"> <i class="fas fa-trash"></i> 删除 </button>
          </div>
        </div>
      </div>
      <!-- 预览内容 -->
      <div class="pre-container">
        <!-- PDF预览 -->
        <VueOfficePdf v-if="fileType === 'pdf'" :src="fileUrl" @rendered="handleRendered" @error="handleError" />
        <!-- Word文档预览 -->
        <VueOfficeDocx v-else-if="fileType === 'docx'" :src="fileUrl" @rendered="handleRendered" @error="handleError" />
        <!-- Excel预览 -->
        <VueOfficeExcel
          v-else-if="fileType === 'xlsx' || fileType === 'xls'"
          :options="{ xls: true }"
          :src="fileUrl"
          @rendered="handleRendered"
          @error="handleError"
        />
        <!-- 不支持的文件类型 -->
        <div v-else class="unsupported">
          <p>不支持预览该文件类型: {{ fileType }}</p>
        </div>
        <!-- 加载状态 -->
        <div v-if="loading" class="loading">
          <p>文件加载中...</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import VueOfficePdf from '@vue-office/pdf/lib/v3/vue-office-pdf.mjs';
import VueOfficeDocx from '@vue-office/docx/lib/v3/vue-office-docx.mjs';
import VueOfficeExcel from '@vue-office/excel/lib/v3/vue-office-excel.mjs';
import { ref, onMounted, nextTick } from 'vue';
import { SvgIcon } from '../Icon';
import { Space, Button, Modal, Input, message } from 'ant-design-vue';
// import AIChat from './index.vue';
import { useUserStore } from '/@/store/modules/user';
import {
  EditOutlined,
  DeleteOutlined,
  UploadOutlined,
  CopyOutlined,
  RightOutlined,
  DownOutlined,
  FastForwardFilled,
  RedoOutlined,
} from '@ant-design/icons-vue';
import { createVNode } from 'vue';
import { marked } from 'marked';
import katex from 'katex';
import 'katex/dist/katex.min.css';
const TextArea = Input.TextArea; // 直接导入TextArea组件使用时打包报错
const inputText = ref(''); // 输入框内容
const refreshText = ref(''); //重新生成文本
const sessionHistory = ref([]);
const isShowChatBroad = ref(false);
const editingId = ref<number | null>(null);
const editText = ref('');
const currentSessionID = ref('');
const taskID = ref('');
const messageID = ref('');
const open = ref<boolean>(false);
const isThinking = ref(false); //深度思考是否开启
const Thinking = ref(false);
const isShowDoc = ref(false);
const fileType = ref('');
const fileUrl = ref('');
const APIKEY = ref('Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd');
interface ListItem {
  id: number;
  name?: string;
}
interface Message {
  id: string; // 唯一标识（可用时间戳生成）
  type: 'user' | 'system' | 'response';
  content: String; // 原始 Markdown 字符串（用于拼接）
  parsedContent: String; // 解析后的 HTML（用于渲染）
  contentR1: String; // 原始思考过程 Markdown
  parsedContentR1: String; // 解析后的思考过程 HTML
  timestamp: number; // 排序依据
  isShowThink: boolean; //深度思考展示
}
// 定义消息历史数组类型
const messageHistory = ref<Message[]>([]);
const isFold = ref(true); // 是否折叠
const userid = useUserStore().getUserInfo.id as string;
const filePath = ref(''); // 绑定输入框值
const uploadedFiles = ref([]);
const showConfirmBtn = ref(false); // 控制确认按钮显示状态
const fileList = ref([]);
const suggestList = ref([]); //建议列表
const loading = ref(false);
// 文件预览
const handleRendered = () => {
  loading.value = false;
  console.log('文件渲染完成');
};
const handleError = (error) => {
  loading.value = false;
  console.error('文件预览错误:', error);
};
function previewFile(data) {
  fileType.value = data.name.split('.').pop().toLowerCase();
  fileUrl.value = data.source_url;
}
function deleteFile(fileId) {
  // 确认删除
  if (confirm('确定要删除这个文件吗？')) {
    uploadedFiles.value = uploadedFiles.value.filter((file) => file.id !== fileId);
  }
}
//启用深度思考
const toggleThinking = () => {
  isThinking.value = !isThinking.value;
  if (isThinking.value) {
    APIKEY.value = 'Bearer app-kprgsFKtySM4Wjxs0ZGzaNFN';
  } else {
    APIKEY.value = 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd';
  }
};
// 折叠思考过程
const isShow = (message) => {
  message.isShowThink = !message.isShowThink;
};
const dialogAreaRef = ref(null);
// 滚动到底部的方法
const scrollToBottom = async () => {
  // 等待 DOM 更新（如消息渲染完成）
  await nextTick();
  if (dialogAreaRef.value) {
    const el = dialogAreaRef.value;
    // 关键：scrollTop = scrollHeight（滚动内容总高度）
    el.scrollTop = el.scrollHeight;
  }
};

// 点击建议项时的处理函数
const handleSuggestClick = (text) => {
  // 将选中的建议填充到文本框
  inputText.value = text;
};
function showAIChat() {
  isShowChatBroad.value = !isShowChatBroad.value;
  if (isShowChatBroad) {
    isShowDoc.value = false;
  }
}
//复制消息
function copyToClipboard(text) {
  if (!text || text.trim() === '') {
    message.warn('没有可复制的内容');
    return;
  }
  // 2. 创建临时textarea 元素
  const textarea = document.createElement('textarea');
  textarea.value = text;
  textarea.style.position = 'fixed';
  textarea.style.top = '-999px';
  textarea.style.left = '-999px';
  textarea.style.width = '200px';
  textarea.style.height = '200px';
  document.body.appendChild(textarea);
  try {
    textarea.select();
    textarea.setSelectionRange(0, text.length);
    const isSuccessful = document.execCommand('copy');
    if (isSuccessful) {
      message.success('复制成功！');
    } else {
      throw new Error('复制命令执行失败');
    }
  } catch (err) {
    console.error('复制失败:', err);
    message.error('复制失败，请手动复制');
  } finally {
    document.body.removeChild(textarea);
  }
}
const initMarked = () => {
  marked.setOptions({
    gfm: true, // 启用GitHub风格的Markdown，包含表格
    breaks: false, // 禁用换行符转换
  });
};
// LaTeX 公式渲染（内部使用）
const renderLatexInHtml = (html) => {
  // 匹配块级公式（$$...$$）
  const blockRegex = /\$\$(.*?)\$\$/gs;
  // 匹配行内公式（$...$）
  const inlineRegex = /\$(.*?)\$/g;
  // // 替换块级公式（居中显示）
  html = html.replace(blockRegex, (match, formula) => {
    matchCount++;
    console.log(`块级公式匹配第 ${matchCount} 次：`, formula); // 查看匹配次数和内容
    return katex.renderToString(formula.trim(), {
      displayMode: true,
      throwOnError: false,
      strict: false,
      trust: true,
    });
  });
  // 替换行内公式（行内显示）
  html = html.replace(inlineRegex, (match, formula) => {
    return katex.renderToString(formula.trim(), {
      displayMode: false,
      throwOnError: false,
      strict: false,
    });
  });
  return html;
};
// Markdown + LaTeX 解析
const parseMarkdownWithLatex = (mdStr) => {
  if (!mdStr) return '';
  try {
    let html = marked(mdStr); // Markdown → HTML
    html = renderLatexInHtml(html); // 替换公式
    return html;
  } catch (error) {
    console.error('解析失败：', error);
    return mdStr; // 降级显示原始字符串
  }
};
//重新生成
const refresh = () => {
  handleSend(refreshText.value);
};
//重新编辑
const editAsk = (data) => {
  inputText.value = data;
};
//获取消息列表
async function handleSend(data) {
  refreshText.value = data;
  inputText.value = '';
  if (isThinking) {
    messageHistory.value.push({
      id: `user_${Date.now()}`,
      type: 'user',
      content: '',
      parsedContent: data,
      contentR1: '',
      parsedContentR1: '',
      timestamp: Date.now(),
      isShowThink: true,
    });
  } else {
    messageHistory.value.push({
      id: `user_${Date.now()}`,
      type: 'user',
      content: '',
      parsedContent: data,
      contentR1: '',
      parsedContentR1: '',
      timestamp: Date.now(),
      isShowThink: false,
    });
  }
  try {
    const response = await fetch('http://39.97.59.228:8000/v1/chat-messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: APIKEY.value,
      },
      body: JSON.stringify({
        conversation_id: currentSessionID.value ? currentSessionID.value : '',
        query: data,
        response_mode: 'streaming',
        user: userid,
        inputs: {},
      }),
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const decoder = new TextDecoder('utf-8');
    const reader = response.body.getReader();
    let textBuffer = ''; // 使用字符串缓冲区来累积数据
    // 在组件中定义
    const currentProcessingMessage = ref(null);
    if (isThinking) {
      const newMessage = {
        id: `response_${Date.now()}`,
        type: 'response',
        content: '',
        parsedContent: '',
        contentR1: '',
        parsedContentR1: '',
        timestamp: Date.now(),
        isShowThink: true,
      };
      messageHistory.value.push(newMessage);
      currentProcessingMessage.value = newMessage; // 保存引用
    } else {
      const newMessage = {
        id: `response_${Date.now()}`,
        type: 'response',
        content: '',
        parsedContent: '',
        contentR1: '',
        parsedContentR1: '',
        timestamp: Date.now(),
        isShowThink: false,
      };
      messageHistory.value.push(newMessage);
      currentProcessingMessage.value = newMessage; // 保存引用
    }
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        if (textBuffer) {
          processLine(textBuffer);
        }
        break;
      }
      textBuffer += decoder.decode(value, { stream: true });
      // 处理每一行数据
      let lineIndex;
      while ((lineIndex = textBuffer.indexOf('\n')) !== -1) {
        const line = textBuffer.substring(0, lineIndex).trim();
        textBuffer = textBuffer.substring(lineIndex + 1);

        if (line) {
          processLine(line);
        }
      }
    }
    function processLine(line) {
      if (line.startsWith('data: ')) {
        try {
          const jsonStr = line.substring('data: '.length);
          const data = JSON.parse(jsonStr);
          switch (data.event) {
            case 'message':
              if (data.answer) {
                const targetMessage = messageHistory.value.find((msg) => msg.id === currentProcessingMessage.value.id);

                if (!targetMessage) break;
                let currentChunk = data.answer;

                // 检查是否包含起始标签
                const startIndex = currentChunk.indexOf('<think>');
                if (startIndex !== -1) {
                  // 找到起始标签：将标签前的内容作为正文
                  if (startIndex > 0) {
                    targetMessage.content += currentChunk.substring(0, startIndex);
                    targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
                  }
                  // 进入思考模式，将标签后的内容追加到contentR1
                  Thinking.value = true;
                  const remainingContent = currentChunk.substring(startIndex + '<think>'.length);
                  if (remainingContent) {
                    targetMessage.contentR1 += remainingContent;
                    targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
                  }
                } else if (Thinking.value) {
                  // 结束标签
                  const endIndex = currentChunk.indexOf('</think>');
                  if (endIndex !== -1) {
                    // 找到结束标签：标签前的内容追加到contentR1
                    if (endIndex > 0) {
                      targetMessage.contentR1 += currentChunk.substring(0, endIndex);
                      targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
                    }
                    // 将标签后的内容作为正文
                    const remainingContent = currentChunk.substring(endIndex + '</think>'.length);
                    if (remainingContent) {
                      targetMessage.content += remainingContent;
                      targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
                    }
                    targetMessage.content += currentChunk;
                    Thinking.value = false;
                    targetMessage.isShowThink = false;
                  } else {
                    // 没有结束标签，继续追加到contentR1
                    targetMessage.contentR1 += currentChunk;
                    targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
                  }
                } else {
                  targetMessage.content += currentChunk;
                  targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
                }
                scrollToBottom(); // 每次接收消息都滚动
              }
              if (data.task_id && !taskID.value) taskID.value = data.task_id;
              if (data.conversation_id && !currentSessionID.value) currentSessionID.value = data.conversation_id;
              if (data.message_id && !messageID.value) {
                messageID.value = data.message_id;
              }
              break;
          }
        } catch (error) {
          console.warn('Error parsing stream chunk:', error, 'Chunk:', line);
        }
      }
    }
    getNextSuggest();
  } catch (error) {
    console.error('Error in handleSend:', error);
    // 在 UI 上显示错误信息
    messageHistory.value.push({
      id: `system_${Date.now()}`,
      type: 'system',
      content: '',
      parsedContent: '请求错误',
      contentR1: '',
      parsedContentR1: '',
      timestamp: Date.now(),
      isShowThink: false,
    });
  }
}
//创建新对话
async function addNew() {
  messageHistory.value = [];
  currentSessionID.value = '';
  taskID.value = '';
  messageID.value = '';
}
// 上传文件
const showModal = (data) => {
  open.value = data;
};
const close = () => {
  isShowDoc.value = false;
};
// 上传文件
const handleBeforeUpload = async (file) => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('user', userid);

  try {
    const response = await fetch(`http://39.97.59.228:8000/v1/files/upload`, {
      method: 'POST',
      headers: {
        Authorization: APIKEY.value,
      },
      body: formData,
    });

    const result = await response.json();
    if (response.ok) {
      const linkText = `[${result.name}](${result.source_url})`;
      // inputText.value += `\n${linkText}`;
      uploadedFiles.value.push(result);
      isShowDoc.value = true;
      previewFile(result);
    } else {
      message.error(`上传失败: ${result.message || '网络错误'}`);
    }
  } catch (error) {
    console.error('保存失败:', error);
    message.error('上传失败，请重试');
  }
  return false;
};

const handleRemove = (file) => {
  const index = fileList.value.findIndex((item) => item.uid === file.uid);
  if (index !== -1) {
    fileList.value.splice(index, 1);
  }
};
//停止响应
async function stopReq() {
  try {
    let response = await fetch(`http://39.97.59.228:8000/v1/chat-messages/${taskID.value}/stop`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: APIKEY.value,
      },
      body: JSON.stringify({
        user: userid,
      }),
    });
    if (!response) {
      throw new Error('Network response was not ok');
    }
  } catch (error) {
    console.error('保存失败:', error);
  }
}
//获取具体会话记录
async function sessionsHistory(id: string, retryCount = 0) {
  const API_KEYS = ['Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd', 'Bearer app-kprgsFKtySM4Wjxs0ZGzaNFN'];
  // 最大重试次数
  const maxRetries = API_KEYS.length - 1;
  try {
    let response = await fetch(`http://39.97.59.228:8000/v1/messages?conversation_id=${id}&user=${userid}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Authorization: API_KEYS[retryCount],
      },
    });
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    const data = await response.json();
    if (data.data.length > 0) {
      messageHistory.value = [];
      data.data.forEach((item: any) => {
        currentSessionID.value = item.conversation_id;
        messageHistory.value.push({
          id: `user_${Date.now()}`,
          type: 'user',
          content: '',
          parsedContent: item.query,
          contentR1: '',
          parsedContentR1: '',
          timestamp: Date.now(),
          isShowThink: false,
        });
        const answer = item.answer;
        // 查找<think>
        const startIndex = answer.indexOf('<think>');
        const endIndex = answer.indexOf('</think>');
        let content = '';
        let contentR1 = '';
        // 根据标签判断
        if (startIndex !== -1 && endIndex !== -1) {
          content = answer.substring(0, startIndex) + answer.substring(endIndex + '</think>'.length);
          contentR1 = answer.substring(startIndex + '<think>'.length, endIndex);
        } else if (startIndex !== -1) {
          // 只有起始标签
          content = answer.substring(0, startIndex);
          contentR1 = answer.substring(startIndex + '<think>'.length);
        } else if (endIndex !== -1) {
          // 只有结束标签
          content = answer.substring(endIndex + '</think>'.length);
          contentR1 = answer.substring(0, endIndex);
        } else {
          // 没有标签
          content = answer;
        }
        // 添加到消息历史
        messageHistory.value.push({
          id: `system_${Date.now()}`,
          type: 'system',
          content: '',
          parsedContent: parseMarkdownWithLatex(content.trim()),
          contentR1: '',
          parsedContentR1: parseMarkdownWithLatex(contentR1.trim()),
          timestamp: Date.now(),
          isShowThink: contentR1.length > 0, // 如果有思考内容则显示
        });
      });
    }
  } catch (error) {
    // 判断是否达到最大重试次数
    if (retryCount < maxRetries) {
      console.warn(`请求失败，正在尝试第 ${retryCount + 2} 个 API Key...`);
      return sessionsHistory(id, retryCount + 1);
    } else {
      console.error('所有 API Key 均尝试失败:', error);
      throw error;
    }
  }
  editingId.value = null;
}
//获取下一轮建议问题列表
//停止响应
async function getNextSuggest() {
  console.log(messageID.value, '123');
  try {
    let response = await fetch(`http://39.97.59.228:8000/v1/messages/${messageID.value}/suggested?user=${userid}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Authorization: APIKEY.value,
      },
    });
    const data = await response.json();
    suggestList.value = data.data;
    if (!response) {
      throw new Error('Network response was not ok');
    }
  } catch (error) {
    console.error('保存失败:', error);
  }
}
//编辑标题
const startEditing = (item: ListItem) => {
  editingId.value = item.id;
  editText.value = item.name || '';
};
// 保存修改
const handleSave = async (item: ListItem) => {
  try {
    let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}/name`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: APIKEY.value,
      },
      body: JSON.stringify({
        name: editText.value,
        user: userid,
      }),
    });
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    item.name = editText.value;
  } catch (error) {
    console.error('保存失败:', error);
  }
  editingId.value = null;
};
// 删除会话
const startDelete = async (item: ListItem) => {
  Modal.confirm({
    title: '确认删除',
    content: `确定要删除会话 "${item.name || '新会话'}" 吗？此操作不可撤销。`,
    okText: '确认',
    cancelText: '取消',
    onOk: async () => {
      // 原有删除逻辑不变
      try {
        let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}`, {
          method: 'DELETE',
          headers: {
            'Content-Type': 'application/json',
            Authorization: APIKEY.value,
          },
          body: JSON.stringify({
            user: userid,
          }),
        });
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        getHistoryList();
      } catch (error) {
        console.error('删除失败:', error);
        Modal.error({
          title: '删除失败',
          content: '删除会话时出现错误，请稍后重试。',
        });
      }
    },
  });
};
const fold = () => {
  isFold.value = !isFold.value;
  if (!isFold.value) {
    getHistoryList();
  }
};
// 获取历史会话列表
async function getHistoryList() {
  sessionHistory.value = [];
  try {
    // 并行请求两个接口，提升效率
    const [response1, response2] = await Promise.all([
      // 第一个请求
      fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
        method: 'get',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd',
        },
      }),
      // 第二个请求
      fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
        method: 'get',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer app-kprgsFKtySM4Wjxs0ZGzaNFN',
        },
      }),
    ]);

    // 检查响应是否成功
    if (!response1.ok || !response2.ok) {
      throw new Error('接口请求失败');
    }

    // 解析两个响应的JSON数据
    const [data1, data2] = await Promise.all([response1.json(), response2.json()]);

    // 合并两个数组（核心修改：用扩展运算符合并）
    // 确保 data1.data 和 data2.data 都是数组（防止接口返回异常）
    const list1 = Array.isArray(data1.data) ? data1.data : [];
    const list2 = Array.isArray(data2.data) ? data2.data : [];

    // 合并数组并赋值给 sessionHistory
    sessionHistory.value = [...list1, ...list2];
    sessionHistory.value.forEach((item) => {
      currentSessionID.value = item.id;
    });
    console.log(sessionHistory.value, '历史数据');
  } catch (error) {
    console.error('获取历史数据失败：', error);
    // 错误处理（比如提示用户）
  }
}
//格式化消息
const formatMessage = (text) => {
  if (!text) return '';
  let formatted = text
    // 处理换行
    .replace(/\n\n/g, '<br>')
    .replace(/\n###/g, '<br>')
    .replace(/###/g, '')
    .replace(/---/g, '')
    .replace(/^- /gm, '<br> - ')
    // 处理粗体
    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
    // 处理斜体
    .replace(/\*(.*?)\*/g, '<em>$1</em>')
    // 处理行内代码
    .replace(/`([^`]+)`/g, '<code>$1</code>');
  return formatted;
};
// 初始化按钮定位
onMounted(() => {
  getHistoryList();
  // 初始化（仅执行一次）
  initMarked();
});
</script>

<style lang="less" scoped>
.btn-header {
  width: 40px;
  height: 40px;
  margin-right: 5px;
  margin-bottom: 5px;
}
.container {
  display: flex;
  flex-direction: row;
}
.mini-chat {
  display: flex;
  min-width: none;
  width: 950px;
  height: 85%;
  border-radius: 4px;
  position: fixed;
  top: 50px;
  right: 20px;
  padding: 10px;
  background-color: #0a1a2f;
  background-image: linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f),
    linear-gradient(to top, #0b69b6, #0a1a2f), linear-gradient(to right, #0b69b6, #0a1a2f);
  background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
  background-position: top left, top right, bottom right, bottom left;
  background-repeat: no-repeat;
  z-index: 9999999;
  color: #fff;
}
.doc {
  display: flex;
  flex-direction: column;
  min-width: 600px;
  height: 85%;
  border-radius: 4px;
  position: fixed;
  top: 50px;
  right: 51%;
  padding: 10px;
  background-color: #0a1a2f;
  background-image: linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f),
    linear-gradient(to top, #0b69b6, #0a1a2f), linear-gradient(to right, #0b69b6, #0a1a2f);
  background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
  background-position: top left, top right, bottom right, bottom left;
  background-repeat: no-repeat;
  z-index: 9999999;
  color: #fff;
}

.close {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  width: 100%;
  padding: 1px;
  border-radius: 8px;
}

.closeBtn {
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.closeBtn:hover {
  background-color: #0056b3;
}
.left-side {
  background: #0c2842;
  transition: width 0.5s ease; /* 平滑过渡动画 */
  width: 140px; /* 展开时宽度 */
  position: relative; /* 用于按钮定位 */
}
.left-side.collapsed {
  width: 40px; /* 折叠时宽度 */
}

.addBtn {
  height: 30px;
  position: absolute;
  background-size: 100% 100%;
  background-position: center;
  padding: 2px;
  right: 10px;
  bottom: 40px;
  left: 10px;
  align-items: center;
  border-radius: 3px;
  cursor: pointer;
}
.custom-list {
  height: 650px;
  overflow-y: auto;
}
.text-container {
  display: flex;
  justify-content: space-between;
  width: 100%;
  overflow: hidden;
}
.btn-container {
  display: flex;
}
.jeecg-layout-header-action span[role='img'] {
  padding: 0;
}
.text-ellipsis {
  flex: 1;
}
.edit-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 90px;
  color: #fff;
  font-size: 12px;
  cursor: pointer;
}
.edit-icon {
  flex-shrink: 0;
  margin-left: auto;
  line-height: 23px;
}
.delete-icon {
  flex-shrink: 0;
  margin-left: auto;
  line-height: 23px;
}
.edit-icon:hover {
  color: #1890ff !important;
  cursor: pointer;
}
.delete-icon:hover {
  color: #1890ff !important;
  cursor: pointer;
}
.edit-input {
  font-size: 10px;
}
.btn-text-bg {
  width: 14px;
  height: 14px;
  position: absolute;
  background-size: 100% 100%;
  right: 10px;
  top: 10px;
  left: 10px;
  bottom: 10px;
}
.btn-text {
  margin-left: 3px;
  font-size: 12px;
  color: #fff;
  white-space: nowrap;
  margin-left: 30px;
  line-height: 29px;
}
.historyBtn {
  width: 20px;
  height: 20px;
  position: absolute;
  background-size: 100% 100%;
  background-position: center;
  padding: 2px;
  right: 10px;
  top: 10px;
}
.historyBtn1 {
  width: 20px;
  height: 20px;
  position: absolute;
  background-size: 100% 100%;
  background-position: center;
  left: 3px;
}
.divider0 {
  border-bottom: 1px solid #1074c1;
  width: auto;
  margin: 0 10px;
  height: 13%;
  display: block;
  background: transparent;
}
.foldBtn {
  width: 20px;
  height: 20px;
  position: absolute;
  background-size: 100% 100%;
  background-position: center;
  padding: 2px;
  right: 10px;
  bottom: 10px;
  cursor: pointer;
}

.right-side {
  flex: 1;
  display: flex;
  flex-direction: column;
  width: calc(100% - 134px) !important;
  .title {
    text-align: center;
    font-size: 14px;
    padding: 5px;
  }
  .dialog-area {
    flex: 1;
    gap: 30px;
    overflow-y: auto;
    padding: 5px;
    display: flex;
    flex-direction: column;
    color: #fff;

    .ask-message {
      padding: 10px;
      border-radius: 5px;
      background: #0c2842;
      max-width: 300px;
      min-width: 50px;
      white-space: pre-wrap;
      word-wrap: break-word;
      overflow-wrap: break-word;
      overflow: auto;
      line-height: 1.5;
    }
    .answer-message {
      padding: 10px;
      border-radius: 5px;
      background: #0c2842;
      max-width: 90%;
    }
  }

  .input-area {
    margin: 10px 10px 20px 10px;
    padding: 10px;
    background-color: #043256;
    border: 1px solid #2cb6ff;
    border-radius: 5px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 5px;
    height: 25%;
  }
  /* 文件列表容器 */
  .uploaded-files {
    padding: 8px;
    background-color: #f5f5f5;
    border-radius: 4px;
    min-height: 40px;
  }

  /* 单个文件项 */
  .file-item {
    display: inline-flex;
    align-items: center;
    padding: 4px 8px;
    margin-right: 8px;
    margin-bottom: 8px;
    background-color: #fff;
    border: 1px solid #e9e9e9;
    border-radius: 4px;
  }

  /* 文件名 */
  .file-name {
    margin-left: 8px;
    margin-right: 8px;
    max-width: 150px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .ant-input {
    border: none;
    background-color: rgba(255, 255, 255, 0) !important;
    color: #fff;
  }
  .ant-input:focus {
    border: none; /* 聚焦时无边框 */
    outline: none; /* 聚焦时无轮廓 */
    box-shadow: none; /* 移除可能存在的阴影效果 */
  }
  .ctrl-btn {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
  }
  .question-input {
    background-color: #1e293b !important;
    border-color: #334155 !important;
    color: #e2e8f0 !important;
    border-radius: 8px !important;
    padding: 12px 16px !important;
    font-size: 14px !important;
  }

  .question-input::placeholder {
    color: #64748b !important;
  }

  .control-btn {
    height: 25px;
    background-color: #043256;
    border: 1px solid #2cb6ff;
    color: #fff;
    font-size: 10px;
    margin-right: 10px;
    cursor: pointer;
    transition: background-color 0.2s ease; /* 平滑过渡效果 */
  }
  /* 激活状态样式（点击后） */
  .control-btn.active {
    background-color: #2cb6ff; /* 蓝色背景（Ant Design 主色） */
    color: white; /* 白色文字 */
  }
  .control-btn1 {
    height: 20px;
    background-color: #234a6b;
    border: 1px solid #234a6b;
    color: #fff;
    font-size: 10px;
    margin-right: 10px;
    cursor: pointer;
    transition: all 0.2s;
  }
  .control-btn2 {
    height: 20px;
    background-color: #2cb6ff;
    border: 1px solid #2cb6ff;
    color: #fff;
    font-size: 10px;
    margin-right: 10px;
    cursor: pointer;
    transition: all 0.2s;
  }
  /* 文件上传区 */
  .file-upload {
    position: absolute;
    right: 20px;
    bottom: 70px;
    width: 180px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    border: 1px solid #2cb6ff;
    background-color: #234a6b;
    border-radius: 6px;
    padding: 10px;
  }

  .input-container {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
  }

  .file-input {
    flex: 1;
    background-color: #234a6b;
    border-color: #2cb6ff !important;
    color: #e2e8f0 !important;
    border-radius: 6px !important;
    font-size: 10px !important;
    padding-right: 70px !important;
    height: 36px !important;
    width: 100% !important;
  }

  .confirm-btn {
    position: absolute;
    right: 5px;
    background-color: #2cb6ff;
    border: none;
    color: #fff;
    border-radius: 4px;
    font-size: 12px;
    padding: 4px 10px;
    cursor: pointer;
    transition: all 0.2s;
    height: 28px;
  }

  .confirm-btn:hover {
    background-color: #2cb6ff;
  }

  .custom-upload {
    width: 100%;
    padding: 0 !important;
  }

  .upload-btn {
    background-color: #234a6b !important;
    border: 1px solid #2188c3 !important;
    color: #dbeafe !important;
    border-radius: 6px !important;
    font-size: 12px !important;
    cursor: pointer;
    transition: all 0.2s;
    padding: 8px 0 !important;
    width: 190% !important;
    height: 36px !important;
    box-sizing: border-box !important;
  }
  .upload-btn:hover {
    background-color: #1f84bd !important;
    color: #fff !important;
  }
  .custom-upload .ant-upload-select:hover .ant-btn {
    border-color: #1f84bd !important;
  }
  .message-wrapper.ai-message-wrapper {
    display: flex;
    align-items: flex-start;
  }
  .answerIcon {
    flex: 0 0 45px;
  }

  .suggestion-item {
    height: 30px;
    margin-left: 45px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    border: 1px solid #1890ff;
    color: white;
    border-radius: 4px;
    cursor: pointer;
    width: 33%;
    font-size: 12px;
  }
  .thinking-section {
    border-left: 3px solid #e5e7eb;
    padding-left: 12px;
    margin-bottom: 16px;
  }

  .thinking-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 0;
    cursor: pointer;
    user-select: none;
  }

  .thinking-title {
    font-size: 14px;
    font-weight: 500;
    color: #6b7280;
  }
}
</style>
<style scoped>
.zxm-popover-inner-content {
  padding: 1px;
}
.message-wrapper {
  display: flex;
  align-items: flex-start;
  position: relative;
}
.user-message-wrapper {
  flex-direction: row-reverse;
}
.ai-message-wrapper {
  flex-direction: row;
}
/* 鼠标滑过 .message-wrapper 时，显示图标 */
.ai-message-wrapper:hover .copy-icon-container {
  opacity: 1;
  visibility: visible;
}
.user-message-wrapper:hover .copy-icon-container {
  opacity: 1;
  visibility: visible;
}
.copy-icon {
  font-size: 16px;
  color: #666;
  cursor: pointer;
}
/* 默认隐藏，hover 时显示 */
.copy-icon-container {
  position: absolute;
  display: flex;
  flex-direction: row;
  bottom: -20px;
  right: 15%;
  opacity: 0;
  visibility: hidden;
  transition: all 0.3s ease;
  z-index: 10;
}
/* 复制图标样式 */
.copy-icon {
  font-size: 16px;
  cursor: pointer;
  margin-right: 20%;
  float: right;
  color: #fff;
}
.message-wrapper:hover .copy-icon {
  opacity: 1;
}
.copy-icon:hover {
  color: #1890ff;
}
::v-deep table {
  border-collapse: collapse;
  width: 100%;
  margin: 10px 0;
  border: 1px solid #333;
}
::v-deep th {
  border: 1px solid #333;
  background-color: #234a6b;
  padding: 5px;
  text-align: center;
}
::v-deep td {
  border: 1px solid #ddd;
  padding: 8px 12px;
  text-align: center;
}
</style>
<style scoped>
/* 已上传文件列表 */
.file-list {
  margin-top: 20px;
}
.pre-container {
  flex: 1;
  width: 100%;
  height: 100%;
  overflow: auto;
}
.vue-office-excel {
  background: #fff !important;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 12px 15px;
  background-color: #ddd;
  border-radius: 6px;
  margin-bottom: 10px;
  transition: background-color 0.2s ease;
}

.file-item:hover {
  background-color: #f0f2f5;
}

.file-info {
  flex: 1;
  overflow: hidden;
}

.file-name {
  font-size: 15px;
  color: #1d2129;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 3px;
}

.file-actions {
  display: flex;
  gap: 10px;
}

.btn {
  padding: 0px 15px;
  margin-left: 10px;
  border-radius: 4px;
  border: none;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn-preview {
  background-color: #165dff;
  color: white;
}

.btn-preview:hover {
  background-color: #0d47a1;
}

.btn-delete {
  background-color: #f2f3f5;
  color: #4e5969;
}

.btn-delete:hover {
  background-color: #e5e6eb;
  color: #1d2129;
}
</style>