<script setup>
import { ref, onMounted, watch, nextTick, reactive, onUnmounted } from "vue";
import { ElDialog, ElMessage } from "element-plus";
import MessageItem from "@/components/deepNine/MessageItem.vue";
import ThinkingGif from "@/components/deepNine/ThinkingGif.vue";
import {
  dbqbFirstAPI,
  dbqbSecondOneAPI,
  dbqbSecondTwoAPI,
  dbqbSecondThreeAPI,
  dbqbSecondFourAPI,
  dataListAPI,
} from "../api/AIxiaocaishen";
import {
  getNineTurnsAPI,
  deepNineFirstAPI,
  deepNineSecondOneAPI,
  deepNineSecondTwoAPI,
  deepNineSecondThreeAPI,
} from "../api/deepNine";
import { useUserStore } from "../store/userPessionCode";
import { useDeepNineStore } from "../store/deepNine";
import { useDeepNineAudioStore } from "../store/deepNineAudio";
import { useDataStore } from "@/store/dataList.js";
import { marked } from "marked"; // 引入marked库
// 导入思考过程GIF
import thinkingGif from "@/assets/img/gif/思考.gif";
import analyzeGif from "@/assets/img/gif/解析.gif";
import generateGif from "@/assets/img/gif/生成.gif";
import katex from "katex"; // 引入 KaTeX 库
import { htmlToText } from "html-to-text";
import { Howl, Howler } from "howler";
import * as echarts from "echarts";
import _, { add } from "lodash";
import moment from "moment";
import title1 from "@/assets/img/AIchat/核心价值评估.png";
import title2 from "@/assets/img/AIchat/主力作战.png";
import title3 from "@/assets/img/AIchat/攻防三维.png";
import title4 from "@/assets/img/AIchat/综合作战.png";
import logo2 from "@/assets/img/AIchat/开启无限财富.png";
import getCountAll from "../assets/img/homePage/get-count-all.png";
import voice from "../assets/img/homePage/tail/voice.png";
import voiceNoActive from "../assets/img/homePage/tail/voice-no-active.png";

import { useChatStore } from "../store/chat";
const homepageChatStore = useChatStore();

const chatStore = useDeepNineStore();
const audioStore = useDeepNineAudioStore();
const dataStore = useDataStore();

// 将这些变量移到全局作用域
const audioQueue = ref([]);
const isPlayingAudio = ref(false);
let currentPlayIndex = 0;
let isCallingPlayNext = false;

// 音频预加载状态
const audioPreloadStatus = {
  one: { loaded: false, url: null },
  two: { loaded: false, url: null },
  three: { loaded: false, url: null },
  four: { loaded: false, url: null },
  five: { loaded: false, url: null },
};

// 音频队列顺序管理
const audioQueueOrder = {
  "API1-第一个": 1, // 第一个接口的第一个音频 (link1)
  "API1-第二个": 2, // 第一个接口的第二个音频 (link)
  "API2-第一个": 3, // 第二个接口的第一个音频 (link3)
  "API2-第二个": 4, // 第二个接口的第二个音频 (link1)
  "API3-第一个": 5, // 第三个接口的音频 (link)
};

// 播放下一个音频的函数
const playNextAudio = () => {
  if (isCallingPlayNext) {
    console.log("playNextAudio已在执行中，跳过重复调用");
    return;
  }

  if (currentPlayIndex >= audioQueue.value.length) {
    console.log(
      "所有音频播放完成，重置到第一个音频 currentPlayIndex",
      currentPlayIndex
    );
    // 播放完成后重置到第一个音频，但不自动播放
    currentPlayIndex = 0;
    audioStore.isPlaying = false;
    audioStore.isPaused = false;
    audioStore.playbackPosition = 0;
    // 清除音频实例，确保下次点击从头开始
    audioStore.soundInstance = null;
    audioStore.nowSound = null;
    if (audioQueue.value.length > 0) {
      audioStore.setCurrentAudioUrl(audioQueue.value[0]);
    }
    return;
  }

  isCallingPlayNext = true;
  const audioInfo = audioQueue.value[currentPlayIndex];

  if (!audioInfo || !audioInfo.url) {
    console.warn(`音频信息无效，跳过索引 ${currentPlayIndex}`);
    currentPlayIndex++;
    isCallingPlayNext = false;
    playNextAudio();
    return;
  }

  console.log(`开始播放 ${audioInfo.name}，索引: ${currentPlayIndex}`);

  const audio = new Howl({
    src: [audioInfo.url],
    html5: false,
    format: ["mp3", "acc"],
    // rate: 2,
    retryCount: 0,
    onplay: () => {
      audioStore.isPlaying = true;
      isPlayingAudio.value = true;
      isCallingPlayNext = false;
      console.log(`${audioInfo.name}音频开始播放111`);
    },
    onpause: () => {
      audioStore.isPlaying = false;
      audioStore.isPaused = true;
      audioStore.playbackPosition = audio.seek() || 0;
      console.log(`${audioInfo.name}音频已暂停`);
    },
    onresume: () => {
      audioStore.isPlaying = true;
      audioStore.isPaused = false;
      console.log(`${audioInfo.name}音频继续播放`);
    },
    onend: () => {
      console.log(`${audioInfo.name}音频播放完成，准备播放下一个`);
      audioStore.isPlaying = false;
      audioStore.isPaused = false;
      audioStore.playbackPosition = 0;
      isPlayingAudio.value = false;

      currentPlayIndex++;

      console.log(
        "currentPlayIndex",
        currentPlayIndex,
        "audioQueue.value.length",
        audioQueue.value.length
      );
      if (currentPlayIndex < audioQueue.value.length) {
        console.log(
          `队列中还有音频，500ms后播放下一个 (索引:${currentPlayIndex})`
        );
        setTimeout(() => {
          isCallingPlayNext = false;
          playNextAudio();
        }, 200);
      } else {
        console.log("🎉 所有音频播放完成，清除音频实例");
        chatStore.messages[chatStore.currentUserIndex].audioStatus = false;
        audioStore.nowSound = null;
        audioStore.soundInstance = null;
        isCallingPlayNext = false;
      }
    },
    onstop: () => {
      console.log(`${audioInfo.name}音频被停止`);
      audioStore.isPlaying = false;
      audioStore.isPaused = false;
      audioStore.playbackPosition = 0;
    },
    onloaderror: (id, err) => {
      console.error(`${audioInfo.name}音频播放失败:`, err);
      isPlayingAudio.value = false;
      isCallingPlayNext = false;
      setTimeout(() => {
        playNextAudio();
      }, 100);
    },
  });

  audioStore.setCurrentAudioUrl(audioInfo.url);
  audioStore.nowSound = audio;
  audioStore.setAudioInstance(audio);

  console.log(`尝试播放${audioInfo.name}音频`);
  audio.play();
};

// 添加音频到播放队列（确保顺序）
const addToAudioQueue = (url, name) => {
  console.log(`=== 添加音频到队列 ===`);
  console.log("URL:", url);
  console.log("Name:", name);
  console.log("音频启用状态:", audioStore.isVoiceEnabled);

  if (url && audioStore.isVoiceEnabled) {
    const audioItem = {
      url,
      name,
      order: audioQueueOrder[name] || 999,
    };
    audioQueue.value.push(audioItem);

    // 按顺序排序队列
    audioQueue.value.sort((a, b) => a.order - b.order);

    console.log(`音频${name}已添加到播放队列，顺序:${audioItem.order}`);
    console.log(
      "当前队列顺序:",
      audioQueue.value.map((item) => `${item.name}(${item.order})`)
    );
    // 只有在确实没有音频在播放且这是第一个音频时才开始播放
    if (
      !isPlayingAudio.value &&
      !audioStore.isPlaying &&
      audioQueue.value.length === 1
    ) {
      console.log("✅ 条件满足：没有音频在播放且这是第一个音频，立即开始播放", {
        isPlayingAudio: isPlayingAudio.value,
        audioStoreIsPlaying: audioStore.isPlaying,
        queueLength: audioQueue.value.length,
      });
      playNextAudio();
    } else {
      console.log("⏳ 等待条件：", {
        isPlayingAudio: isPlayingAudio.value,
        audioStoreIsPlaying: audioStore.isPlaying,
        queueLength: audioQueue.value.length,
        reason:
          audioQueue.value.length > 1 ? "队列中已有其他音频" : "有音频正在播放",
      });
    }
  } else {
    console.log("❌ 跳过添加音频：", {
      hasUrl: !!url,
      voiceEnabled: audioStore.isVoiceEnabled,
    });
  }
  console.log(`=== 添加音频完成 ===`);
};

// 语音播放控制函数
const toggleVoiceForUser = (index) => {
  console.log(
    "上一个按钮坐标",
    chatStore.currentUserIndex,
    "当前按钮坐标",
    index
  );

  if (
    !chatStore.messages[index].audioArray[0] ||
    !chatStore.messages[index].audioArray[1] ||
    !chatStore.messages[index].audioArray[2] ||
    !chatStore.messages[index].audioArray[3]
  ) {
    return;
  }

  // 先把当前按钮状态修改
  chatStore.messages[index].audioStatus =
    !chatStore.messages[index].audioStatus;
  // 如果当前按钮和之前的按钮不是同一个则再修改之前的按钮的状态
  if (chatStore.currentUserIndex != index) {
    if (chatStore.currentUserIndex != null) {
      if (audioStore.isPlaying) {
        audioStore.togglePlayPause();
      }
      chatStore.messages[chatStore.currentUserIndex].audioStatus = false;
    }

    // 强制停止所有音频实例（移动端兼容）
    if (audioStore.soundInstance) {
      audioStore.soundInstance.stop();
      audioStore.soundInstance = null;
    }

    audioPreloadStatus.one = { loaded: false, url: null };
    audioPreloadStatus.two = { loaded: false, url: null };
    audioPreloadStatus.three = { loaded: false, url: null };
    audioPreloadStatus.four = { loaded: false, url: null };
    audioPreloadStatus.five = { loaded: false, url: null };
    if (chatStore.messages[index].audioArray[0]) {
      audioPreloadStatus.one.loaded = true;
      audioPreloadStatus.one.url = chatStore.messages[index].audioArray[0];
    }
    if (chatStore.messages[index].audioArray[1]) {
      audioPreloadStatus.two.loaded = true;
      audioPreloadStatus.two.url = chatStore.messages[index].audioArray[1];
    }
    if (chatStore.messages[index].audioArray[2]) {
      audioPreloadStatus.three.loaded = true;
      audioPreloadStatus.three.url = chatStore.messages[index].audioArray[2];
    }
    if (chatStore.messages[index].audioArray[3]) {
      audioPreloadStatus.four.loaded = true;
      audioPreloadStatus.four.url = chatStore.messages[index].audioArray[3];
    }
    chatStore.currentUserIndex = index;
    audioQueue.value = [];
    isPlayingAudio.value = false;
    audioStore.soundInstance = null;
    currentPlayIndex = 0;
    isCallingPlayNext = false;
    setTimeout(() => {
      addToAudioQueue(chatStore.messages[index].audioArray[0], "API1-第一个");
      addToAudioQueue(chatStore.messages[index].audioArray[1], "API2-第二个");
      addToAudioQueue(chatStore.messages[index].audioArray[2], "API3-第三个");
      addToAudioQueue(chatStore.messages[index].audioArray[3], "API4-第四个");

      if (!audioStore.isVoiceEnabled) {
        audioStore.toggleVoice();
      } else {
        if (audioStore.currentAudioUrl || audioStore.ttsUrl) {
          // audioStore.togglePlayPause();
        } else {
          audioStore.toggleVoice();
        }
      }
    }, 100); // 100ms延迟足够移动端清理音频实例
  } else {
    if (!audioStore.isVoiceEnabled) {
      console.log("1111");
      audioStore.toggleVoice();
    } else {
      if (currentPlayIndex >= audioQueue.value.length) {
        console.log("重新开始播放音频序列");
        currentPlayIndex = 0;
        isPlayingAudio.value = false;
        isCallingPlayNext = false;
        audioStore.soundInstance = null;
        // 重新开始播放
        if (audioQueue.value.length > 0) {
          playNextAudio();
        }
      } else if (audioStore.currentAudioUrl || audioStore.ttsUrl) {
        console.log("2222");
        audioStore.togglePlayPause();
      } else {
        console.log("3333");
        audioStore.toggleVoice();
      }
    }
  }
};

// 计算属性：判断语音是否启用
const isVoice = computed(() => {
  return audioStore.isVoiceEnabled;
});
// 随机GIF
const currentGif = ref("");

const renderer = new marked.Renderer();
// 重写 del 方法，让删除线不生效
renderer.del = function (text) {
  // 处理各种数据类型
  console.log("text", text);
  return "~" + text.tokens[0].raw + "<br>" + text.tokens[2].raw + "~";
};

// 定义自定义事件
const emit = defineEmits([
  "updateMessage",
  "sendMessage",
  "enableInput",
  "ensureAIchat",
  "scrollToBottom",
  "showCount",
]);

// 音频播放方法
const playAudio = (url) => {
  // 添加空值校验
  if (!url) {
    console.warn("音频URL为空，跳过播放");
    audioStore.isPlaying = false;
    return;
  }

  const handlePlay = () => {
    if (audioStore.isNewInstance) {
      const newSound = new Howl({
        src: [url],
        html5: true, // 强制HTML5 Audio解决iOS兼容问题
        format: ["mp3", "acc"],
        rate: 1.2, // 调整播放速度
        onplay: () => {
          audioStore.isPlaying = true; // 改为更新store状态
          newSound.volume(1); // 添加音量设置
        },
        onend: () => (audioStore.isPlaying = false),
        onstop: () => (audioStore.isPlaying = false),
        onloaderror: (id, err) => {
          console.error("音频加载失败:", err);
          ElMessage.error("音频播放失败，请检查网络连接");
        },
      });
      if (audioStore.nowSound) {
        audioStore.nowSound.stop();
      }
      audioStore.nowSound = newSound;
      audioStore.isNewInstance = false;

      console.log("新音频");
    } else {
      console.log("已经有音频");
    }

    const newSound = audioStore.nowSound;

    // 添加立即播放逻辑
    newSound.play();

    audioStore.setAudioInstance(newSound);
    Howler._howls.push(newSound); // 强制注册到全局管理
  };

  handlePlay();
};
// 新增暂停方法
const pauseAudio = () => {
  if (audioStore.soundInstance) {
    audioStore.soundInstance.pause();

    audioStore.isPlaying = false;
  }
};

// 音频轮流播放方法
const playAudioSequence = (audioUrls) => {
  console.log("playAudioSequence被调用，参数:", audioUrls);
  if (!audioUrls || audioUrls.length === 0) {
    console.warn("音频URL列表为空，跳过播放");
    return;
  }

  let currentIndex = 0;
  let audioSequence = [...audioUrls]; // 保存音频序列

  const playNext = () => {
    if (currentIndex >= audioSequence.length) {
      console.log("所有音频播放完成，重置到第一个音频");
      // 播放完成后重置到第一个音频，但不自动播放
      currentIndex = 0;
      audioStore.isPlaying = false;
      audioStore.isPaused = false;
      audioStore.playbackPosition = 0;
      // 清除音频实例，确保下次点击从头开始
      audioStore.soundInstance = null;
      audioStore.nowSound = null;
      if (audioSequence.length > 0) {
        audioStore.setCurrentAudioUrl(audioSequence[0]);
      }
      return;
    }

    const currentUrl = audioSequence[currentIndex];
    console.log(`正在播放第${currentIndex + 1}个音频:`, currentUrl);
    console.log(
      "音频URL有效性检查:",
      !!currentUrl,
      "长度:",
      currentUrl?.length
    );

    // 增强URL验证
    if (
      !currentUrl ||
      typeof currentUrl !== "string" ||
      currentUrl.trim() === ""
    ) {
      console.error(`音频 ${currentIndex + 1} URL无效，跳过该音频`);
      currentIndex++;
      setTimeout(() => {
        playNext();
      }, 100);
      return;
    }

    // 检查URL格式
    try {
      new URL(currentUrl);
    } catch (e) {
      console.error(`音频 ${currentIndex + 1} URL格式错误:`, currentUrl);
      currentIndex++;
      setTimeout(() => {
        playNext();
      }, 100);
      return;
    }

    // 设置当前音频URL
    audioStore.setCurrentAudioUrl(currentUrl);

    // 停止当前播放的音频
    if (audioStore.nowSound) {
      audioStore.nowSound.stop();
    }

    const sound = new Howl({
      src: [currentUrl],
      html5: true,
      format: ["mp3", "acc"],
      rate: 1.2,
      onplay: () => {
        audioStore.isPlaying = true;
        audioStore.isPaused = false;
        console.log(`开始播放音频 ${currentIndex + 1}`);
        console.log("音频播放状态:", {
          duration: sound.duration(),
          state: sound.state(),
          playing: sound.playing(),
        });
      },
      onpause: () => {
        audioStore.isPlaying = false;
        audioStore.isPaused = true;
        audioStore.playbackPosition = sound.seek() || 0;
        console.log(`音频 ${currentIndex + 1} 已暂停`);
      },
      onend: () => {
        audioStore.isPlaying = false;
        audioStore.isPaused = false;
        audioStore.playbackPosition = 0;
        console.log(`音频 ${currentIndex + 1} 播放完成`);
        currentIndex++;
        // 如果是最后一个音频播放完成，立即清除实例
        if (currentIndex >= audioSequence.length) {
          console.log("最后一个音频播放完成，清除音频实例");
          audioStore.soundInstance = null;
          audioStore.nowSound = null;
          currentIndex = 0; // 立即重置索引
        }
        // 播放下一个音频
        setTimeout(() => {
          playNext();
        }, 500); // 间隔500ms播放下一个
      },
      onstop: () => {
        audioStore.isPlaying = false;
        audioStore.isPaused = false;
        audioStore.playbackPosition = 0;
        console.log(`音频 ${currentIndex + 1} 已停止`);
      },
      onloaderror: (id, err) => {
        console.error(`音频 ${currentIndex + 1} 加载失败:`, err);
        console.error("失败的音频URL:", currentUrl);
        console.error("错误详情:", { id, err });

        // 增加重试机制
        if (!sound.retryCount) {
          sound.retryCount = 0;
        }

        if (sound.retryCount < 2) {
          sound.retryCount++;
          console.log(
            `音频 ${currentIndex + 1} 第${sound.retryCount}次重试加载`
          );
          setTimeout(() => {
            sound.load();
          }, 1000 * sound.retryCount); // 递增延时重试
        } else {
          console.warn(`音频 ${currentIndex + 1} 重试失败，跳过该音频`);
          currentIndex++;
          // 跳过失败的音频，播放下一个
          setTimeout(() => {
            playNext();
          }, 100);
        }
      },
    });

    audioStore.nowSound = sound;
    audioStore.setAudioInstance(sound);

    // 添加播放超时检测
    const playTimeout = setTimeout(() => {
      if (!audioStore.isPlaying && sound.state() === "loading") {
        console.warn(`音频 ${currentIndex + 1} 播放超时，可能网络问题`);
        sound.stop();
        currentIndex++;
        playNext();
      }
    }, 10000); // 10秒超时

    // 播放成功后清除超时
    sound.once("play", () => {
      clearTimeout(playTimeout);
    });

    console.log(`尝试播放音频 ${currentIndex + 1}，URL: ${currentUrl}`);
    sound.play();
  };

  // 重写togglePlayPause方法以支持音频序列控制
  audioStore.togglePlayPause = () => {
    console.log("音频控制按钮被点击 11111111111");
    console.log("当前播放状态:", audioStore.isPlaying);
    console.log("当前暂停状态:", audioStore.isPaused);
    console.log("当前音频实例:", audioStore.soundInstance);
    console.log(
      "当前索引:",
      currentIndex,
      "音频序列长度:",
      audioSequence.length
    );

    if (audioStore.soundInstance) {
      if (audioStore.isPlaying) {
        // 暂停当前音频
        console.log("暂停当前音频");
        audioStore.pause();
      } else if (audioStore.isPaused) {
        // 从暂停位置继续播放
        console.log("从暂停位置继续播放");
        audioStore.play();
      } else {
        // 重新开始播放当前音频或从头开始播放序列
        console.log("重新开始播放，当前索引:", currentIndex);
        if (currentIndex >= audioSequence.length) {
          console.log("所有音频已播放完成，从头开始");
          currentIndex = 0; // 重置到第一个音频
        }
        playNext();
      }
    } else {
      // 没有音频实例时，从头开始播放
      console.log("没有音频实例，从头开始播放");
      currentIndex = 0;
      playNext();
    }
  };

  // 开始播放第一个音频
  playNext();
};

// 获取消息
const chatMsg = computed(() => chatStore.messages);
const props = defineProps({
  messages: Array,
  chartData: {
    type: Object,
    default: null,
  },
  index: {
    type: Number,
    required: true,
  },
});

// 打字机效果
const typewriterContent = ref("");
const isTyping = ref(false);

const typeWriter = (text, callback) => {
  let index = 0;
  isTyping.value = true;
  typewriterContent.value = "";

  const typingInterval = setInterval(() => {
    if (index < text.length) {
      typewriterContent.value += text.charAt(index);
      index++;
      // 自动滚动到底部
      nextTick(() => {
        const container = document.querySelector(".message-area");
        if (container) container.scrollTop = container.scrollHeight;
      });
    } else {
      clearInterval(typingInterval);
      isTyping.value = false;
      if (callback) callback();
    }
  }, 50); // 调整速度(毫秒)
};

const typingQueue = ref([]);
const isTypingInProgress = ref(false);

// 创建打字机效果的Promise函数
const createTypingEffect = (message, content, speed) => {
  return new Promise((resolve) => {
    chatStore.messages.push(message);
    if (Array.isArray(content) && content.length > 0) {
      message.content = "";
      message.isTyping = true;

      let currentIndex = 0;

      const processNextElement = () => {
        if (currentIndex >= content.length) {
          if (message.isEnd) {
            if (message.isEnd == "1") {
              apiStatus.one.isEnd = true;
            } else if (message.isEnd == "2") {
              apiStatus.two.isEnd = true;
            } else if (message.isEnd == "3") {
              apiStatus.three.isEnd = true;
            }
          }
          if (message.error) {
            chatStore.messages.push({
              class: "ing",
              type: "ing",
              flag: false,
              content: "系统正在为您努力加载中，请稍后再试",
            });
            chatStore.isLoading = false;
            chatStore.chatInput = false;
            emit("enableInput");
            if (message.error == "2") {
              apiStatus.two.isError = true;
            } else if (message.error == "3") {
              apiStatus.three.isError = true;
            }
          }
          if (message.end) {
            homepageChatStore.getUserCount();
            chatStore.isLoading = false;
            console.log("打印完毕，接触输入框禁用状态");
            chatStore.chatInput = false;
            emit("enableInput");
          }
          message.isTyping = false;
          nextTick(() => {
            resolve(); // 完成后resolve
          });
          return;
        }

        if (currentIndex % 2 === 0) {
          // 偶数下标：直接加入
          message.content += content[currentIndex];
          currentIndex++;
          processNextElement(); // 立即处理下一个元素
        } else {
          // 奇数下标：打字机效果
          const text = content[currentIndex];
          let charIndex = 0;

          const typingInterval = setInterval(() => {
            if (charIndex < text.length) {
              message.content += text.charAt(charIndex);
              charIndex++;
            } else {
              clearInterval(typingInterval);
              currentIndex++;
              processNextElement(); // 处理下一个元素
            }
          }, speed);
        }
      };

      processNextElement(); // 开始处理
    } else {
      if (message.kline) {
        if (message.klineType == 2) {
          console.log("K线消息已添加到聊天列表");

          // 在渲染完成后初始化图表
          nextTick(() => {
            console.log("nextTick开始 - 准备渲染图表");
            console.log("消息列表:", chatStore.messages);

            // 寻找最新添加的K线消息索引
            let klineIndex = -1;
            for (let i = 0; i < chatStore.messages.length; i++) {
              if (chatStore.messages[i].messageId === message.messageId) {
                klineIndex = i;
                break;
              }
            }

            console.log("找到的K线消息索引:", klineIndex);

            if (klineIndex !== -1) {
              const containerId = `kline-container-${klineIndex}`;
              console.log("图表容器ID:", containerId);

              // 确保DOM已经渲染完成
              setTimeout(() => {
                console.log("延时执行，确保DOM已渲染");
                KlineCanvsEcharts(containerId);
              }, 100); // 短暂延时确保DOM已渲染
            } else {
              console.warn("未找到K线消息");
            }
          });
        }
        if (message.isEnd) {
          if (message.isEnd == "1") {
            apiStatus.one.isEnd = true;
          } else if (message.isEnd == "2") {
            apiStatus.two.isEnd = true;
          } else if (message.isEnd == "3") {
            apiStatus.three.isEnd = true;
          }
        }
        if (message.error) {
          chatStore.messages.push({
            class: "ing",
            type: "ing",
            flag: false,
            content: "系统正在为您努力加载中，请稍后再试",
          });
          chatStore.isLoading = false;
          chatStore.chatInput = false;
          emit("enableInput");
          if (message.error == "2") {
            apiStatus.two.isError = true;
          } else if (message.error == "3") {
            apiStatus.three.isError = true;
          }
        }
        // 延时1秒后resolve
        setTimeout(() => {
          resolve();
        }, 1000);
      } else {
        if (message.isEnd) {
          if (message.isEnd == "1") {
            apiStatus.one.isEnd = true;
          } else if (message.isEnd == "2") {
            apiStatus.two.isEnd = true;
          } else if (message.isEnd == "3") {
            apiStatus.three.isEnd = true;
          }
        }
        if (message.error) {
          chatStore.messages.push({
            class: "ing",
            type: "ing",
            flag: false,
            content: "系统正在为您努力加载中，请稍后再试",
          });
          chatStore.isLoading = false;
          chatStore.chatInput = false;
          emit("enableInput");
          if (message.error == "2") {
            apiStatus.two.isError = true;
          } else if (message.error == "3") {
            apiStatus.three.isError = true;
          }
        }
        // 延时1秒后resolve
        setTimeout(() => {
          resolve();
        }, 1000);
      }
    }
  });
};

let apiStatus = {};

// 队列处理函数
const processTypingQueue = async () => {
  if (isTypingInProgress.value || typingQueue.value.length === 0) {
    return;
  }

  isTypingInProgress.value = true;

  while (typingQueue.value.length > 0) {
    const task = typingQueue.value.shift();
    await createTypingEffect(task.message, task.content, task.speed);
  }

  isTypingInProgress.value = false;
};

// 添加打字机任务到队列
const addTypingTask = (message, content, speed) => {
  typingQueue.value.push({ message, content, speed });
  processTypingQueue();
};

// 显示思考过程
async function showThinkingProcess(stockName = null) {
  // 第一步：正在思考
  const thinkingMessage1 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    flag: true,
    content: "深度九大模型正在思考",
    gif: thinkingGif,
    nowrap: true,
  });
  chatStore.messages.push(thinkingMessage1);
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();

  // 第二步：正在解析关键数据（持续显示直到获取到股票名称）
  const thinkingMessage2 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    flag: true,
    content: "正在解析关键数据",
    gif: analyzeGif,
    nowrap: true,
  });
  chatStore.messages.push(thinkingMessage2);

  // 如果没有股票名称，保持第二步显示
  if (!stockName) {
    return thinkingMessage2; // 返回消息引用，以便后续更新
  }

  // 有股票名称后，继续后续步骤
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();

  // 第三步：生成具体股票的深度共振分析图谱
  const thinkingMessage3 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    flag: true,
    content: `正在生成${stockName}深度共振分析图谱`,
    gif: generateGif,
    nowrap: true,
  });
  chatStore.messages.push(thinkingMessage3);
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();

  // 第四步：报告已生成
  const thinkingMessage4 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    content: "报告已生成！",
    nowrap: true,
  });
  chatStore.messages.push(thinkingMessage4);
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();

  return null;
}

// 继续思考过程（当获取到股票名称后调用）
async function continueThinkingProcess(thinkingMessageRef, stockName) {
  if (!thinkingMessageRef || !stockName) return;

  // 等待一段时间后继续
  await new Promise((resolve) => setTimeout(resolve, 1500));

  // 移除第二步消息
  const index = chatStore.messages.indexOf(thinkingMessageRef);
  if (index > -1) {
    chatStore.messages.splice(index, 1);
  }

  // 第三步：生成具体股票的深度共振分析图谱
  const thinkingMessage3 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    flag: true,
    content: `正在生成${stockName}深度共振分析图谱`,
    gif: generateGif,
  });
  chatStore.messages.push(thinkingMessage3);
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();

  // 第四步：报告已生成
  const thinkingMessage4 = reactive({
    sender: "ai",
    class: "ing",
    type: "ing",
    content: "报告已生成！",
  });
  chatStore.messages.push(thinkingMessage4);
  await new Promise((resolve) => setTimeout(resolve, 1500));
  chatStore.messages.pop();
}

const hasValidData = ref(false);

// 创建一个非响应式的对象来存储图表实例
const chartInstancesMap = {};

// 存储上一次的消息的length
const previousMessagesLength = ref(0);

watch(
  () => props.messages,
  async (newVal, oldVal) => {
    // // 添加空值判断
    if (!newVal?.length || newVal === previousMessagesLength.value) return;

    chatStore.firstAPICall = true;
    console.log("第一阶段,意图识别,获取回复，历史记录禁止点击");

    previousMessagesLength.value = newVal.length;
    if (newVal.length > 0) {
      // 清理语音下标
      console.log("chatStore.currentUserIndex", chatStore.currentUserIndex);
      if (chatStore.currentUserIndex != null) {
        chatStore.messages[chatStore.currentUserIndex].audioStatus = false;
      }
      chatStore.currentUserIndex = null;
      audioStore.stop(); // 暂停语音

      // 🔧 新增：重置音频队列状态，确保新音频能够自动播放
      audioQueue.value = [];
      isPlayingAudio.value = false;
      currentPlayIndex = 0;
      isCallingPlayNext = false;

      // 重置音频预加载状态
      audioPreloadStatus.one = { loaded: false, url: null };
      audioPreloadStatus.two = { loaded: false, url: null };
      audioPreloadStatus.three = { loaded: false, url: null };
      audioPreloadStatus.four = { loaded: false, url: null };

      // 清除音频实例
      audioStore.soundInstance = null;
      audioStore.nowSound = null;
      audioStore.isPlaying = false;
      audioStore.isPaused = false;
      audioStore.playbackPosition = 0;

      console.log("消息列表已更新，最新消息:", newVal[newVal.length - 1]);
      chatStore.messages.push(newVal[newVal.length - 1]);
      chatStore.currentUserIndex = chatStore.messages.length - 1;
      chatStore.inputUserIndex = chatStore.messages.length - 1;
      console.log(
        "消息列表已更新，最新消息:",
        chatStore.messages[chatStore.messages.length - 1],
        "最新用户坐标",
        chatStore.currentUserIndex
      );

      // 获取权限
      const userStore = useUserStore();

      const params1 = {
        language: "cn",
        marketList: "usa,sg,my,hk,cn,can,vi,th,in",
        content: newVal[newVal.length - 1].content,

        token: localStorage.getItem("localToken"),
        model: 1,
        // language: "cn",
        // marketList: "hk,cn,usa,my,sg,vi,in,gb"
        // token: "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w",
      };
      // 标志
      let flag = true;
      const codeData = ref();
      // 开始思考过程（不带股票名称）
      const thinkingMessageRef = await showThinkingProcess();

      // 第一阶段,意图识别
      try {
        // 调用工作流获取回复
        const result = await deepNineFirstAPI(params1);
        codeData.value = result.data;
        console.log(codeData.value, "codeData");
        // 根据意图识别结果判断
        if (result.code == 200) {
          // 意图识别成功后，更新历史记录状态
          chatStore.searchRecord = true;
          // 获取到股票名称后，继续思考过程
          if (thinkingMessageRef && codeData.value.name) {
            await continueThinkingProcess(
              thinkingMessageRef,
              codeData.value.name
            );
          }
          // for (let i = chatStore.messages.length - 1; i >= 0; --i) {
          //   if (chatStore.messages[i].sender == "user") {
          //     chatStore.messages[i].audioStatus = true;
          //     break;
          //   }
          // }
          chatStore.messages.push({
            // class: "ing",
            // type: "ing",
            // flag: flag,
            // content: result.data.kaishi,
          });
        } else {
          // 意图识别失败，先清理思考过程消息
          if (thinkingMessageRef) {
            const index = chatStore.messages.indexOf(thinkingMessageRef);
            if (index > -1) {
              chatStore.messages.splice(index, 1);
            }
          }

          flag = false;
          console.log("执行回绝话术");
          const AIcontent = ref(result.msg);
          // 修改后的消息处理逻辑

          const processedContent = marked(AIcontent.value);
          const katexRegex = /\$\$(.*?)\$\$/g;
          let aiContent = processedContent.replace(
            katexRegex,
            (match, formula) => {
              try {
                return katex.renderToString(formula, { throwOnError: false });
              } catch (error) {
                console.error("KaTeX 渲染错误:", error);
                return match;
              }
            }
          );
          console.log(AIcontent, "AIcontent");

          if (result.code == 406) {
            AIcontent.value = `<p>尊敬的用户您好，您当前的“深度九大模型专属Token”数量为0，无法进行股票查询，可联系客服团队进行充值，感谢您的理解与支持</p>`;
          }

          const aiMsg = {
            class: "ing",
            type: "ing",
            flag: flag,
            content: AIcontent,
          };

          chatStore.messages.push(aiMsg);

          chatStore.isLoading = false;
          chatStore.chatInput = false;
          chatStore.firstAPICall = false;

          console.log("历史记录可以点击");
          emit("enableInput");
        }
      } catch (e) {
        // 意图识别异常，先清理思考过程消息
        if (thinkingMessageRef) {
          const index = chatStore.messages.indexOf(thinkingMessageRef);
          if (index > -1) {
            chatStore.messages.splice(index, 1);
          }
        }

        console.log(e, "意图识别失败");
        chatStore.messages.push({
          class: "ing",
          type: "ing",
          flag: false,
          content: "系统正在为您努力加载中，请稍后再试",
        });
        chatStore.isLoading = false;
        chatStore.chatInput = false;
        chatStore.firstAPICall = false;
        console.log("历史记录可以点击");
        emit("enableInput");
      }

      if (flag) {
        const params2 = {
          language: "cn",
          token: localStorage.getItem("localToken"),
          parentId: codeData.value.parentId,
          stockId: codeData.value.stockId,
          recordId: codeData.value.recordId,

          // content: newVal[newVal.length - 1].content,
          // marketList: "usa,sg,my,hk,cn,can,vi,th,in",
          // name: codeData.value.name,
          // code: codeData.value.code,
          // market: codeData.value.market,

          // language: "cn",
          // marketList: "hk,cn,usa,my,sg,vi,in,gb"
          // token: "+SsksARQgUHIbIG3rRnnbZi0+fEeMx8pywnIlrmTxo5EOPR/wjWDV7w7+ZUseiBtf9kFa/atmNx6QfSpv5w",
        };

        try {
          const env = import.meta.env.VITE_ENV;

          const result20 = await getNineTurnsAPI(
            {
              token:
                env == "development" || env == "test"
                  ? "8Csj5VVX1UbIb4C3oxrnbZi0+fEeMx8pywnIlrmTm45Cb/EllzWACLto9J9+fCFsfdgBOvKvyY94FvqlvM0"
                  : "8nkj4QBV1RPIb4CzoRTnbZi0+fEeMx8pywnIlrmTxdwROKkuwWqAWu9orpkpeXVqL98DPfeonNYpHv+mucA",
            },
            {
              market: codeData.value.market,
              language: "cn",
              code: codeData.value.code,
            }
          );

          // 添加空值检查防止访问null对象的属性
          const nineTurns = result20.data ? result20.data : null;

          const isNineTurns =
            nineTurns &&
            nineTurns.DXT &&
            nineTurns.JZJG &&
            nineTurns.KLine20 &&
            nineTurns.StockInformation &&
            nineTurns.ZJQS
              ? true
              : false;

          const katexRegex = /\$\$(.*?)\$\$/g;

          let result21;
          let result22;
          let result23;
          let result24;
          // 用于跟踪API完成状态和结果
          apiStatus = {
            one: {
              completed: false,
              result: null,
              error: null,
              isError: false,
              isEnd: false,
            },
            two: {
              completed: false,
              result: null,
              error: null,
              isError: false,
              isEnd: false,
            },
            three: {
              completed: false,
              result: null,
              error: null,
              isError: false,
              isEnd: false,
            },
            four: {
              completed: false,
              result: null,
              error: null,
              isError: false,
              isEnd: false,
            },
          };

          // 预加载音频函数
          const preloadAudio = (url, apiKey) => {
            if (!url || !audioStore.isVoiceEnabled) {
              audioPreloadStatus[apiKey].loaded = true;
              return Promise.resolve();
            }

            // 立即设置URL，确保即使预加载失败也能使用
            audioPreloadStatus[apiKey].url = url;
            console.log(`设置音频${apiKey}的URL:`, url);

            return new Promise((resolve) => {
              const audio = new Howl({
                src: [url],
                html5: true,
                format: ["mp3", "acc"],
                rate: 1.2,
                preload: true,
                onload: () => {
                  console.log(`音频${apiKey}预加载完成:`, url);
                  audioPreloadStatus[apiKey].loaded = true;
                  resolve();
                },
                onloaderror: (id, err) => {
                  console.error(`音频${apiKey}预加载失败:`, err);
                  audioPreloadStatus[apiKey].loaded = true; // 标记为已处理，避免阻塞
                  // URL已经在上面设置了，即使预加载失败也保留URL
                  resolve();
                },
              });
            });
          };

          // 检查第一个接口是否可以开始输出（文本和音频都准备好）
          const canStartFirstOutput = () => {
            return apiStatus.one.completed && audioPreloadStatus.one.loaded;
          };

          // 检查并按顺序执行代码的函数
          const checkAndExecuteInOrder = () => {
            // 检查OneAPI - 只有当文本和音频都准备好时才开始输出
            if (canStartFirstOutput() && !apiStatus.one.executed) {
              if (apiStatus.one.result) {
                apiStatus.one.executed = true;
                console.log(
                  "执行OneAPI代码（文本和音频同步开始）:",
                  apiStatus.one.result
                );

                // 将第一个音频添加到播放队列（确保顺序：API1）
                if (audioPreloadStatus.one.url) {
                  chatStore.messages[chatStore.inputUserIndex].audioArray.push(
                    audioPreloadStatus.one.url
                  );
                  if (chatStore.currentUserIndex == chatStore.inputUserIndex) {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = true;
                    addToAudioQueue(audioPreloadStatus.one.url, "API1-第一个");
                  } else {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = false;
                  }
                  console.log(
                    "音频队列：添加API1-1音频(link1)，当前队列长度:",
                    audioQueue.value.length
                  );
                }

                // 添加第二个音频(link)到队列
                if (audioPreloadStatus.two.url) {
                  chatStore.messages[chatStore.inputUserIndex].audioArray.push(
                    audioPreloadStatus.two.url
                  );
                  if (chatStore.currentUserIndex == chatStore.inputUserIndex) {
                    addToAudioQueue(audioPreloadStatus.two.url, "API1-第二个");
                  } else {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = false;
                  }
                  console.log(
                    "音频队列：添加API1-2音频(link)，当前队列长度:",
                    audioQueue.value.length
                  );
                }

                // 在这里添加OneAPI成功后需要执行的代码
                // 删除正在为您生成信息
                chatStore.messages.pop();
                // 添加报告头和时间
                addTypingTask(
                  {
                    sender: "ai",
                    class: "title1",
                    type: "title1",
                    content: codeData.value.name + "深度共振分析图谱",
                    date: result21.data.date,
                  },
                  "",
                  50
                );

                chatStore.firstAPICall = false;
                console.log("历史记录可以点击");

                const pc1 = marked(
                  result21.data.name +
                    "\n" +
                    result21.data.price +
                    "\n" +
                    result21.data.date
                );
                const ac1 = pc1.replace(katexRegex, (match, formula) => {
                  try {
                    return katex.renderToString(formula, {
                      throwOnError: false,
                    });
                  } catch (error) {
                    console.error("KaTeX 渲染错误:", error);
                    return match;
                  }
                });

                // 先推送初始消息
                const aiMessage1 = reactive({
                  sender: "ai",
                  class: "content1",
                  type: "content1",
                  content: "",
                  isTyping: true,
                });

                addTypingTask(aiMessage1, ["", ac1], 130);

                // 九转结构K线图
                if (
                  nineTurns &&
                  nineTurns.DXT &&
                  nineTurns.JZJG &&
                  nineTurns.KLine20 &&
                  nineTurns.StockInformation &&
                  nineTurns.ZJQS
                ) {
                  const nineTurnsData = JSON.parse(
                    JSON.stringify(toRaw(nineTurns))
                  );
                  console.log("处理 K 线数据 - 开始");
                  console.log("nineTurnsData", nineTurnsData);

                  const Kline20 = {
                    name: nineTurnsData.StockInformation.Name,
                    Kline: nineTurnsData,
                  };

                  // 打印K线数据结构
                  console.log("K线数据结构:", Kline20);
                  console.log("K线数据名称:", Kline20.name);
                  console.log("K线数据:", Kline20.Kline ? Kline20.Kline : null);

                  // 设置数据有效标志
                  hasValidData.value = true;
                  console.log("hasValidData设置为:", hasValidData.value);

                  // 先推送K线图消息
                  const klineMessageId2 = `kline-${Date.now() + 1}`;
                  console.log("生成K线消息ID:", klineMessageId2);

                  // 添加九转结构图表
                  addTypingTask(
                    {
                      sender: "ai",
                      class: "content2",
                      type: "content2",
                      kline: true,
                      chartData: Kline20,
                      messageId: klineMessageId2,
                      hasValidData: true, // 添加hasValidData标志
                      klineType: 2,
                    },
                    "",
                    50
                  );

                  // 添加标题-数据分析时代下的认知变现
                  addTypingTask(
                    {
                      sender: "ai",
                      class: "title2",
                      type: "title2",
                      content: "",
                    },
                    "",
                    50
                  );

                  // 添加图片-数据分析时代下的认知变现
                  addTypingTask(
                    {
                      sender: "ai",
                      class: "content3",
                      type: "img1",
                      content:
                        "https://d31zlh4on95l9h.cloudfront.net/images/5baa0a449cf74fb6a1afb1c909a21194.png",
                    },
                    "",
                    50
                  );

                  // 添加标题-结构框架分析
                  addTypingTask(
                    {
                      sender: "ai",
                      class: "title3",
                      type: "title3",
                      content:
                        "https://d31zlh4on95l9h.cloudfront.net/images/9ab9d76b6906eb914fa1842dbcd56841.png",
                    },
                    "",
                    50
                  );

                  // 添加内容框1
                  const ac2 = `<p>${result21.data.jgkjfx}</p>`;

                  // 先推送初始消息
                  const aiMessage2 = reactive({
                    sender: "ai",
                    class: "content3",
                    type: "content3",
                    content: "",
                    isTyping: true,
                    error: apiStatus.two.error ? "2" : "",
                    isEnd: "1",
                  });

                  addTypingTask(aiMessage2, ["", ac2], 130);
                }
              } else {
                chatStore.messages.push({
                  class: "ing",
                  type: "ing",
                  flag: false,
                  content: "系统正在为您努力加载中，请稍后再试",
                });
                chatStore.isLoading = false;
                chatStore.chatInput = false;
                emit("enableInput");
              }
            }

            // 检查TwoAPI（需要OneAPI已执行）
            if (
              apiStatus.one.executed &&
              apiStatus.two.completed &&
              !apiStatus.two.executed
            ) {
              if (apiStatus.two.result) {
                apiStatus.two.executed = true;
                console.log("执行TwoAPI代码:", apiStatus.two.result);

                // 将第二个接口的音频添加到播放队列（确保顺序：API2）
                if (audioPreloadStatus.three.url) {
                  chatStore.messages[chatStore.inputUserIndex].audioArray.push(
                    audioPreloadStatus.three.url
                  );
                  if (chatStore.currentUserIndex == chatStore.inputUserIndex) {
                    addToAudioQueue(
                      audioPreloadStatus.three.url,
                      "API2-第一个"
                    );
                  } else {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = false;
                  }
                  console.log(
                    "音频队列：添加API2-1音频(link3)，当前队列长度:",
                    audioQueue.value.length
                  );
                }

                if (audioPreloadStatus.four.url) {
                  chatStore.messages[chatStore.inputUserIndex].audioArray.push(
                    audioPreloadStatus.four.url
                  );
                  if (chatStore.currentUserIndex == chatStore.inputUserIndex) {
                    addToAudioQueue(audioPreloadStatus.four.url, "API2-第二个");
                  } else {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = false;
                  }
                  console.log(
                    "音频队列：添加API2-2音频(link1)，当前队列长度:",
                    audioQueue.value.length
                  );
                }

                // 在这里添加TwoAPI成功后需要执行的代码
                // 添加标题-资金动向监控
                addTypingTask(
                  {
                    sender: "ai",
                    class: "title3",
                    type: "title3",
                    content:
                      "	https://d31zlh4on95l9h.cloudfront.net/images/f95c44f83b3e3c52e88964631c199060.png",
                  },
                  "",
                  50
                );
                const ac31 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【资金异动信号】</p><p>`;
                const ac32 = result22.data.dxtsc;

                // const ac33 = result22.data.zjqssc1;

                const ac34 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【资金趋势导航】</p><p>`;
                const ac35 = result22.data.zjqssc1;

                // const ac3 = `<p>${result23.data.DXTSC}</p><p>${result23.data.DXTSC2}</p><p>${result23.data.ZJQSSC1}</p>`;
                const ac3Arr = [];
                ac3Arr.push(ac31);
                if (ac32 != "") {
                  ac3Arr.push(`<p>${ac32}</p>`);
                }
                // if (ac33 != "") {
                //   ac3Arr.push("");
                //   ac3Arr.push(`<p>${ac33}</p>`);
                // }
                ac3Arr.push(ac34);
                if (ac35 != "") {
                  ac3Arr.push(`<p>${ac35}</p>`);
                }
                // 先推送初始消息
                const aiMessage3 = reactive({
                  sender: "ai",
                  class: "content3",
                  type: "content3",
                  content: "",
                  isTyping: true,
                  error: apiStatus.three.error ? "3" : "",
                  isEnd: "2",
                });
                addTypingTask(aiMessage3, ac3Arr, 200);
              } else {
                if (
                  apiStatus.one.isEnd &&
                  apiStatus.two.error &&
                  !apiStatus.two.isError
                ) {
                  apiStatus.two.isError = true;
                  chatStore.messages.push({
                    class: "ing",
                    type: "ing",
                    flag: false,
                    content: "系统正在为您努力加载中，请稍后再试",
                  });
                  chatStore.isLoading = false;
                  chatStore.chatInput = false;
                  emit("enableInput");
                }
              }
            }

            // 检查ThreeAPI（需要TwoAPI已执行）
            if (
              apiStatus.two.executed &&
              apiStatus.three.completed &&
              !apiStatus.three.executed
            ) {
              if (apiStatus.three.result) {
                apiStatus.three.executed = true;
                console.log("执行ThreeAPI代码:", apiStatus.three.result);

                // 将第三个接口的音频添加到播放队列（确保顺序：API3）
                if (audioPreloadStatus.five.url) {
                  chatStore.messages[chatStore.inputUserIndex].audioArray.push(
                    audioPreloadStatus.five.url
                  );
                  if (chatStore.currentUserIndex == chatStore.inputUserIndex) {
                    addToAudioQueue(audioPreloadStatus.five.url, "API3-第一个");
                  } else {
                    chatStore.messages[
                      chatStore.inputUserIndex
                    ].audioStatus = false;
                  }
                  console.log(
                    "音频队列：添加API3音频(link)，当前队列长度:",
                    audioQueue.value.length
                  );
                }

                // 在这里添加ThreeAPI成功后需要执行的代码
                // 添加标题-策略共振决策模型
                addTypingTask(
                  {
                    sender: "ai",
                    class: "title3",
                    type: "title3",
                    content:
                      "https://d31zlh4on95l9h.cloudfront.net/images/d1fa1f4cbd6452796a4c5368d9f57c4d.png",
                  },
                  "",
                  50
                );

                // 添加内容框4
                const ac5 = `<p>${result23.data.zjqssc2}</p>`;

                // 先推送初始消息
                const aiMessage5 = reactive({
                  sender: "ai",
                  class: "content3",
                  type: "content3",
                  content: "",
                  isTyping: true,
                });
                addTypingTask(aiMessage5, ["", ac5], 240);

                const ac6 = "该内容由AI生成,请注意甄别";
                // 先推送初始消息
                const aiMessage6 = reactive({
                  sender: "ai",
                  class: "mianze",
                  type: "mianze",
                  content: "",
                  isTyping: true,
                  end: true,
                });
                addTypingTask(aiMessage6, ["", ac6], 210);
              } else {
                if (
                  apiStatus.two.isEnd &&
                  apiStatus.three.error &&
                  !apiStatus.three.isError
                ) {
                  apiStatus.three.isError = true;
                  chatStore.messages.push({
                    class: "ing",
                    type: "ing",
                    flag: false,
                    content: "系统正在为您努力加载中，请稍后再试",
                  });
                  chatStore.isLoading = false;
                  chatStore.chatInput = false;
                  emit("enableInput");
                }
              }
            }

            // 检查是否所有API都已完成并执行
            if (
              apiStatus.one.completed &&
              apiStatus.two.completed &&
              apiStatus.three.completed
            ) {
              console.log("所有API已完成，开始收集预加载的音频URL");
              // 收集所有预加载的音频URL
              const audioUrls = [];
              console.log("预加载音频状态检查:");
              console.log("audioPreloadStatus:", audioPreloadStatus);

              if (audioPreloadStatus.one.url) {
                console.log(
                  "添加预加载音频URL one:",
                  audioPreloadStatus.one.url
                );
                audioUrls.push(audioPreloadStatus.one.url);
              }
              if (audioPreloadStatus.two.url) {
                console.log(
                  "添加预加载音频URL two:",
                  audioPreloadStatus.two.url
                );
                audioUrls.push(audioPreloadStatus.two.url);
              }
              if (audioPreloadStatus.three.url) {
                console.log(
                  "添加预加载音频URL three:",
                  audioPreloadStatus.three.url
                );
                audioUrls.push(audioPreloadStatus.three.url);
              }
              if (audioPreloadStatus.four.url) {
                console.log(
                  "添加预加载音频URL four:",
                  audioPreloadStatus.four.url
                );
                audioUrls.push(audioPreloadStatus.four.url);
              }

              console.log("收集到的预加载音频URLs:", audioUrls);
              console.log("语音是否启用:", audioStore.isVoiceEnabled);

              // 音频播放逻辑已移至各个接口的执行代码中
              console.log("所有接口执行完成，音频已在各接口中单独播放");
            }
          };

          const handleOneAPI = async () => {
            try {
              result21 = await deepNineSecondOneAPI(params2);
              if (result21.code == 400) {
                throw new Error("API返回错误码400，请求失败");
              }
              console.log("OneAPI成功返回:", result21);

              apiStatus.one.completed = true;
              apiStatus.one.result = result21;

              // 预加载第一个接口的音频 - link1和link
              if (result21?.data?.link1) {
                await preloadAudio(result21.data.link1.trim(), "one");
              } else {
                audioPreloadStatus.one.loaded = true;
              }

              if (result21?.data?.link) {
                await preloadAudio(result21.data.link.trim(), "two");
              } else {
                audioPreloadStatus.two.loaded = true;
              }

              // 检查是否可以执行
              checkAndExecuteInOrder();
            } catch (error) {
              console.error("OneAPI失败:", error);
              apiStatus.one.completed = true;
              apiStatus.one.error = error;
              audioPreloadStatus.one.loaded = true; // 失败时也标记为已处理
              audioPreloadStatus.two.loaded = true; // 失败时也标记为已处理
              // 即使失败也要检查后续执行
              checkAndExecuteInOrder();
            }
          };

          const handleTwoAPI = async () => {
            try {
              result22 = await deepNineSecondTwoAPI(params2);
              if (result22.code == 400) {
                throw new Error("API返回错误码400，请求失败");
              }
              console.log("TwoAPI成功返回:", result22);

              apiStatus.two.completed = true;
              apiStatus.two.result = result22;

              // 预加载第二个接口的音频 - link3和link1
              if (result22?.data?.link3) {
                await preloadAudio(result22.data.link3.trim(), "three");
              } else {
                audioPreloadStatus.three.loaded = true;
              }

              if (result22?.data?.link1) {
                await preloadAudio(result22.data.link1.trim(), "four");
              } else {
                audioPreloadStatus.four.loaded = true;
              }

              // 检查是否可以执行
              checkAndExecuteInOrder();
            } catch (error) {
              console.error("TwoAPI失败:", error);
              apiStatus.two.completed = true;
              apiStatus.two.error = error;
              audioPreloadStatus.three.loaded = true;
              audioPreloadStatus.four.loaded = true;
              checkAndExecuteInOrder();
            }
          };

          const handleThreeAPI = async () => {
            try {
              result23 = await deepNineSecondThreeAPI(params2);
              if (result23.code == 400) {
                throw new Error("API返回错误码400，请求失败");
              }
              // result23 = await dbqbSecondThreeAPI();

              console.log("ThreeAPI成功返回:", result23);

              apiStatus.three.completed = true;
              apiStatus.three.result = result23;

              // 预加载第三个接口的音频 - 只有link字段
              if (result23?.data?.link) {
                await preloadAudio(result23.data.link.trim(), "five");
              } else {
                audioPreloadStatus.three.loaded = true;
              }

              // 检查是否可以执行
              checkAndExecuteInOrder();
            } catch (error) {
              console.error("ThreeAPI失败:", error);
              apiStatus.three.completed = true;
              apiStatus.three.error = error;
              audioPreloadStatus.three.loaded = true;
              checkAndExecuteInOrder();
            }
          };

          if (isNineTurns) {
            handleOneAPI();
            handleTwoAPI();
            handleThreeAPI();
          } else {
            chatStore.messages.pop();
            chatStore.messages.push({
              class: "ing",
              type: "ing",
              flag: false,
              content: "数据缺失，请稍后重试",
            });
            chatStore.isLoading = false;
            chatStore.chatInput = false;
            chatStore.firstAPICall = false;
            emit("enableInput");
          }
        } catch (e) {
          console.error("请求失败:", e);
          chatStore.firstAPICall = false;
          hasValidData.value = false; // 请求失败时设置数据无效
        } finally {
          // chatStore.setLoading(false);
          await homepageChatStore.getUserCount();
        }
      }
    }
  },
  { deep: false }
);

// 点击历史记录
watch(
  () => chatStore.dbqbClickRecord,
  (newValue, oldValue) => {
    console.log("new", newValue);
    if (!newValue || Object.keys(newValue).length === 0) {
      return;
    }

    const clickRecord = ref(newValue);
    console.log("dbqbClickRecord 发生变化:", clickRecord.value);

    // 🔧 新增：完整的任务停止逻辑
    try {
      // 1. 停止所有音频相关任务
      chatStore.currentUserIndex = null;
      audioStore.stop(); // 暂停语音

      // 🔧 新增：重置音频队列状态，确保新音频能够自动播放
      audioQueue.value = [];
      isPlayingAudio.value = false;
      currentPlayIndex = 0;
      isCallingPlayNext = false;

      // 🔧 新增：重置音频预加载状态
      audioPreloadStatus.one = { loaded: false, url: null };
      audioPreloadStatus.two = { loaded: false, url: null };
      audioPreloadStatus.three = { loaded: false, url: null };
      audioPreloadStatus.four = { loaded: false, url: null };
      audioPreloadStatus.five = { loaded: false, url: null };

      // 🔧 新增：清理音频实例
      if (audioStore.soundInstance) {
        audioStore.soundInstance.stop();
        audioStore.soundInstance.unload();
        audioStore.soundInstance = null;
      }
      audioStore.nowSound = null;

      // 2. 停止API调用和状态重置
      // 🔧 新增：重置API状态
      apiStatus.one = {
        completed: false,
        result: null,
        error: null,
        isError: false,
        isEnd: false,
      };
      apiStatus.two = {
        completed: false,
        result: null,
        error: null,
        isError: false,
        isEnd: false,
      };
      apiStatus.three = {
        completed: false,
        result: null,
        error: null,
        isError: false,
        isEnd: false,
      };

      // 🔧 新增：重置数据有效性标志
      hasValidData.value = false;

      // 3. 停止打字机效果
      typingQueue.value = [];
      isTypingInProgress.value = false;

      // 4. 重置加载状态
      chatStore.isLoading = false;
      chatStore.chatInput = false;
      emit("enableInput");

      // 在下一个事件循环中清空 dbqbClickRecord
      setTimeout(() => {
        chatStore.dbqbClickRecord = {};
        console.log("dbqbClickRecord 已清空");
      }, 0);
    } catch (error) {
      console.error("停止任务时发生错误:", error);
    }

    if (
      !clickRecord.value.wokeFlowData.One ||
      !clickRecord.value.wokeFlowData.Two ||
      !clickRecord.value.wokeFlowData.Three
    ) {
      return;
    }
    try {
      // 清空聊天框内容
      chatStore.messages = [];

      const userAudioArray = [
        clickRecord.value.wokeFlowData.One.link1,
        clickRecord.value.wokeFlowData.One.link,
        clickRecord.value.wokeFlowData.Two.link3,
      ];
      // if (clickRecord.value.wokeFlowData.Two.link2) {
      //   userAudioArray.push(clickRecord.value.wokeFlowData.Two.link2);
      // }
      userAudioArray.push(clickRecord.value.wokeFlowData.Two.link1);
      userAudioArray.push(clickRecord.value.wokeFlowData.Three.link);
      const userContent = {
        sender: "user",
        timestamp: clickRecord.value.createdTime,
        content: clickRecord.value.keyword,
        audioArray: userAudioArray,
        audioStatus: false,
      };

      chatStore.messages.push(userContent);

      chatStore.messages.push({
        sender: "ai",
        class: "title1",
        type: "title1",
        content: clickRecord.value.stockName + "深度共振分析图谱",
        date: clickRecord.value.wokeFlowData.One.date,
      });

      const pc1 = marked(
        clickRecord.value.wokeFlowData.One.name +
          "\n" +
          clickRecord.value.wokeFlowData.One.price +
          "\n" +
          clickRecord.value.wokeFlowData.One.date
      );

      chatStore.messages.push({
        sender: "ai",
        class: "content1",
        type: "content1",
        content: pc1,
      });

      const nineTurns = clickRecord.value.stockData.data;
      // 度牛尺K线图
      if (
        nineTurns &&
        nineTurns.DXT &&
        nineTurns.JZJG &&
        nineTurns.KLine20 &&
        nineTurns.StockInformation &&
        nineTurns.ZJQS
      ) {
        const nineTurnsData = JSON.parse(JSON.stringify(toRaw(nineTurns)));
        console.log("处理 K 线数据 - 开始");
        console.log("nineTurnsData", nineTurnsData);

        const Kline20 = {
          name: nineTurnsData.StockInformation.Name,
          Kline: nineTurnsData,
        };

        // 打印K线数据结构
        console.log("K线数据结构:", Kline20);
        console.log("K线数据名称:", Kline20.name);
        console.log("K线数据:", Kline20.Kline ? Kline20.Kline : null);

        // 设置数据有效标志
        hasValidData.value = true;
        console.log("hasValidData设置为:", hasValidData.value);

        // chatStore.messages.pop();

        // 先推送K线图消息
        const klineMessageId2 = `kline-${Date.now() + 1}`;
        console.log("生成K线消息ID:", klineMessageId2);

        chatStore.messages.push({
          sender: "ai",
          class: "content2",
          type: "content2",
          kline: true,
          chartData: Kline20,
          messageId: klineMessageId2,
          hasValidData: true, // 添加hasValidData标志
          klineType: 2,
        });

        // 在渲染完成后初始化图表
        nextTick(() => {
          console.log("nextTick开始 - 准备渲染图表");
          console.log("消息列表:", chatStore.messages);

          // 寻找最新添加的K线消息索引
          let klineIndex = -1;
          for (let i = 0; i < chatStore.messages.length; i++) {
            if (chatStore.messages[i].messageId === klineMessageId2) {
              klineIndex = i;
              break;
            }
          }

          console.log("找到的K线消息索引:", klineIndex);

          if (klineIndex !== -1) {
            const containerId = `kline-container-${klineIndex}`;
            console.log("图表容器ID:", containerId);

            // 确保DOM已经渲染完成
            setTimeout(() => {
              console.log("延时执行，确保DOM已渲染");
              KlineCanvsEcharts(containerId);
            }, 100); // 短暂延时确保DOM已渲染
          } else {
            console.warn("未找到K线消息");
          }
        });
      }
      // 添加标题-数据分析时代下的认知变现
      chatStore.messages.push({
        sender: "ai",
        class: "title2",
        type: "title2",
        content: "",
      });

      // 添加图片-数据分析时代下的认知变现
      chatStore.messages.push({
        sender: "ai",
        class: "content3",
        type: "img1",
        content:
          "https://d31zlh4on95l9h.cloudfront.net/images/5baa0a449cf74fb6a1afb1c909a21194.png",
      });

      // 添加标题-结构框架分析
      chatStore.messages.push({
        sender: "ai",
        class: "title3",
        type: "title3",
        content:
          "https://d31zlh4on95l9h.cloudfront.net/images/9ab9d76b6906eb914fa1842dbcd56841.png",
      });

      // 添加内容框1
      const pc2 = marked(clickRecord.value.wokeFlowData.One.jgkjfx);
      // 先推送初始消息
      chatStore.messages.push({
        sender: "ai",
        class: "content3",
        type: "content3",
        content: pc2,
      });
      // 添加标题-资金动向监控
      chatStore.messages.push({
        sender: "ai",
        class: "title3",
        type: "title3",
        content:
          "	https://d31zlh4on95l9h.cloudfront.net/images/f95c44f83b3e3c52e88964631c199060.png",
      });

      const ac3 = `<p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【资金异动信号】</p><p>${clickRecord.value.wokeFlowData.Two.dxtsc}</p><p style="margin:0;color:#FFD700;font-weight:bold;display:flex;justify-content:center;font-size:22px">【资金趋势导航】</p><p>${clickRecord.value.wokeFlowData.Two.zjqssc1}</p>`;

      // 先推送初始消息
      chatStore.messages.push({
        sender: "ai",
        class: "content3",
        type: "content3",
        content: ac3,
        isTyping: true,
      });

      // 添加标题-策略共振决策模型
      chatStore.messages.push({
        sender: "ai",
        class: "title3",
        type: "title3",
        content:
          "https://d31zlh4on95l9h.cloudfront.net/images/d1fa1f4cbd6452796a4c5368d9f57c4d.png",
      });

      // 添加内容框4
      const ac5 = `<p>${clickRecord.value.wokeFlowData.Three.zjqssc2}</p>`;

      // 先推送初始消息
      chatStore.messages.push({
        sender: "ai",
        class: "content3",
        type: "content3",
        content: ac5,
      });
      chatStore.messages.push({
        sender: "ai",
        class: "mianze",
        type: "mianze",
        content: "该内容由AI生成，请注意甄别",
        end: true,
      });
    } catch (e) {
      ElMessage.error("历史数据获取出错！");
      console.error("e", e);
    }
  },
  {
    deep: true, // 深度监听对象内部属性的变化
    immediate: true, // 立即执行一次回调
  }
);

function KlineCanvsEcharts(containerId) {
  function vwToPx(vw) {
    console.log((window.innerWidth * vw) / 100, "vwToPx");
    return (window.innerWidth * vw) / 100;
  }

  // console.log("KLine渲染: 开始处理数据, 容器ID:", containerId);

  // 从 chatStore 中获取数据
  const messages = chatStore.messages;
  // console.log("KLine渲染: 获取到的消息:", messages);
  let klineMessageIndex = -1;
  let klineData = null;

  klineMessageIndex = containerId.split("-")[2];
  // console.log("KLine渲染: 找到K线消息索引:", klineMessageIndex);
  if (
    messages[klineMessageIndex].kline &&
    messages[klineMessageIndex].chartData
  ) {
    klineData = messages[klineMessageIndex].chartData;
  }

  var KlineOption = {};

  // 检测设备类型
  const isMobile = window.innerWidth < 768;
  const isTablet = window.innerWidth >= 768 && window.innerWidth < 1024;
  console.log(
    "KLine渲染: 设备类型",
    isMobile ? "移动设备" : isTablet ? "平板设备" : "桌面设备"
  );

  if (messages[klineMessageIndex].klineType == 2) {
    if (!klineData || !klineData.Kline) {
      // console.warn("KLine渲染: 数据无效 - 在chatStore中找不到有效的K线数据");
      return;
    }

    // 获取容器元素
    const container = document.getElementById(containerId);
    if (!container) {
      // console.error("KLine渲染: 找不到容器元素:", containerId);
      return;
    }

    // 创建图表实例
    // console.log("KLine渲染: 创建图表实例");
    try {
      // 如果已有实例，先销毁
      if (chartInstancesMap[containerId]) {
        // console.log("KLine渲染: 销毁已有图表实例");
        chartInstancesMap[containerId].dispose();
        delete chartInstancesMap[containerId];
      }

      // 使用普通变量存储实例
      chartInstancesMap[containerId] = echarts.init(container);
      // console.log("KLine渲染: 图表实例创建成功");
    } catch (error) {
      // console.error("KLine渲染: 图表实例创建失败:", error);
      return;
    }

    const nineTurns = klineData.Kline;
    console.log("KLine渲染: Kline数据", nineTurns);

    // 拿到相应的数据
    const splitData = (b) => {
      const a = JSON.parse(JSON.stringify(b));
      let categoryData = [];
      let values = [];
      for (let i = 0; i < a.length; i++) {
        categoryData.push(a[i].splice(0, 1)[0]);
        values.push(a[i]);
      }
      return {
        categoryData,
        values,
      };
    };
    function vwToPx(vw) {
      return (window.innerWidth * vw) / 100;
    }

    // k线的数据
    var dealData = splitData(nineTurns.KLine20);

    var markPointData = [];
    const getNineNum = (KLine20, JZJG) => {
      JZJG.forEach((item, index) => {
        let low = KLine20[index][3];
        let high = KLine20[index][4];
        if (item[1] != -1) {
          if (item[1] == 9) {
            markPointData.push({
              name: "low",
              coord: [index, low],
              itemStyle: {
                normal: {
                  color: "rgba(0,0,0,0)", // 标记点透明
                },
              },
              label: {
                normal: {
                  show: true,
                  position: "bottom",
                  formatter: `${item[1]}`,
                  textStyle: {
                    color: "green",
                    fontSize: window.innerWidth > 769 ? 18 : 15,
                    textBorderColor: "#FFFFFF",
                    textBorderWidth: 2,
                    fontWeight: "bold",
                  },
                },
              },
            });
          } else {
            markPointData.push({
              name: "low",
              coord: [index, low],
              itemStyle: {
                normal: {
                  color: "rgba(0,0,0,0)", // 标记点透明
                },
              },
              label: {
                normal: {
                  show: true,
                  position: "bottom",
                  formatter: `${item[1]}`,
                  textStyle: {
                    color: "green",
                    fontSize: window.innerWidth > 769 ? 12 : 9,
                    textBorderColor: "#FFFFFF",
                    textBorderWidth: 2,
                    fontWeight: "bold",
                  },
                },
              },
            });
          }
        }
        if (item[2] != -1) {
          if (item[2] == 9) {
            markPointData.push({
              name: "high",
              coord: [index, high],
              itemStyle: {
                normal: {
                  color: "rgba(0,0,0,0)", // 标记点透明
                },
              },
              label: {
                normal: {
                  show: true,
                  position: "top",
                  formatter: `${item[2]}`,
                  textStyle: {
                    color: "#0099FF",
                    fontSize: window.innerWidth > 769 ? 18 : 15,
                    textBorderColor: "#FFFFFF",
                    textBorderWidth: 2,
                    fontWeight: "bold",
                  },
                },
              },
            });
          } else {
            markPointData.push({
              name: "high",
              coord: [index, high],
              itemStyle: {
                normal: {
                  color: "rgba(0,0,0,0)", // 标记点透明
                },
              },
              label: {
                normal: {
                  show: true,
                  position: "top",
                  formatter: `${item[2]}`,
                  textStyle: {
                    color: "#0099FF",
                    fontSize: window.innerWidth > 769 ? 12 : 9,
                    textBorderColor: "#FFFFFF",
                    textBorderWidth: 2,
                    fontWeight: "bold",
                  },
                },
              },
            });
          }
        }
      });
    };
    getNineNum(nineTurns.KLine20, nineTurns.JZJG);
    // console.log("markPointData", markPointData);

    var arrRange = [];
    var arrSwing = [];
    var arrDXTBar = [];
    var arrInvisibleBar = [];
    var markPointDXT = [];
    var arr5DXTBar = [];
    var arr6DXTBar = [];
    var arr7DXTBar = [];
    var DXTmin = 0;
    var DXTmax = 100;
    const getDXT = (DXT) => {
      DXT.forEach((item, index) => {
        arrRange.push(item[1]);
        arrSwing.push(item[2]);
        if (item[2] > 0) {
          arrDXTBar.push(item[2] * 2);
          arrInvisibleBar.push(50);
          DXTmax = Math.max(DXTmax, item[2] * 2 + 50);
        } else {
          arrDXTBar.push(-item[2] * 2);
          arrInvisibleBar.push(item[2] * 2 + 50);
        }

        if (item[5] == 1) {
          arr5DXTBar.push(100);
        } else {
          arr5DXTBar.push(0);
        }
        if (item[6] == 1) {
          arr6DXTBar.push(70);
        } else {
          arr6DXTBar.push(0);
        }
        if (item[7] == 1) {
          arr7DXTBar.push(40);
        } else {
          arr7DXTBar.push(0);
        }

        if (item[8] == 1) {
          markPointDXT.push({
            name: "DTX-8",
            coord: [index, 30],
            symbol: "triangle", // 三角形符号
            symbolSize: 10, // 符号大小
            symbolRotate: 0, // 向上的三角形（0度）
            itemStyle: {
              normal: {
                color: "#FFFF00", // 标记点透明
                borderColor: "#000000", // 边框颜色
                borderWidth: 1,
              },
            },
            label: {
              normal: {
                show: false,
              },
            },
          });
        }

        if (item[9] == 1) {
          markPointDXT.push({
            name: "DTX-9",
            coord: [index, 20],
            symbolSize: 7, // 正方形大小
            itemStyle: {
              normal: {
                color: "red", // 标记点透明
                //   borderColor: "#000000", // 边框颜色
                //   borderWidth: 1,
              },
            },
            label: {
              normal: {
                show: false,
              },
            },
          });
        }

        if (item[10] == 1) {
          markPointDXT.push({
            name: "DTX-10",
            coord: [index, 15],
            symbol: "rect", // 设置为正方形
            symbolSize: 7, // 正方形大小
            itemStyle: {
              normal: {
                color: "grey", // 标记点透明
                //   borderColor: "#000000", // 边框颜色
                //   borderWidth: 1,
              },
            },
            label: {
              normal: {
                show: false,
              },
            },
          });
        }
      });
    };
    getDXT(nineTurns.DXT);

    var arrBlue = [];
    var arrRed = [];
    var arrWhite = [];
    var arrYellow = [];
    const getZJQS = (ZJQS) => {
      ZJQS.forEach((item, index) => {
        arrBlue.push(item[1]);
        arrRed.push(item[2]);
        arrWhite.push(item[3]);
        arrYellow.push(item[4]);
      });
    };
    getZJQS(nineTurns.ZJQS);
    // console.log("arrBlue", arrBlue);
    // console.log("arrRed", arrRed);
    // console.log("arrWhite", arrWhite);
    // console.log("arrYellow", arrYellow);
    KlineOption = {
      // 手放上去显示的内容
      tooltip: {
        position: function (point, params) {
          if (params[0].seriesIndex == 1) {
            return window.innerWidth > 768 ? ["12%", "42%"] : ["18%", "40%"];
          }
        },
        // 调用接口之后方法
        formatter: function (a, b, d) {
          if (a[0].seriesIndex == 0) {
            const KlineTag = ref([]); // 判断几根K线
            const AIBullTag = ref([]);

            // 找到第一个满足条件的数据
            KlineTag.value = a.find((item) => item.data[1])?.data || [];

            // 找到第一个满足条件的非 '-' 数据
            AIBullTag.value =
              a.slice(4).find((item) => item.data[1] !== "-")?.data || [];
            return (
              a[0].name +
              "<br/>" +
              "开" +
              "：" +
              KlineTag.value[1] +
              "<br/>" +
              "收" +
              "：" +
              KlineTag.value[2] +
              "<br/>" +
              "低" +
              "：" +
              KlineTag.value[3] +
              "<br/>" +
              "高" +
              "：" +
              KlineTag.value[4]
            );
          } else if (a[0].seriesIndex == 1) {
            return (
              `<span style='color:red;'>RANGE: </span>` +
              a[0].data +
              " <span style='color:yellow'>SWING: </span>" +
              a[1].data
            );
          } else {
            return null;
            // 格式化成交量显示
            let formattedVolume;
            if (a[0].data.value >= 10000) {
              formattedVolume = (a[0].data.value / 10000).toFixed(2) + "w";
            } else {
              formattedVolume = a[0].data.value;
            }
            return a[0].name + "<br/>" + "量" + "：" + formattedVolume;
          }
        },
        trigger: "axis",
        axisPointer: {
          //坐标轴指示器配置项
          type: "cross", //‘line’直线指示器，‘cross’十字准星指示器，‘shadow’阴影指示器
        },
        backgroundColor: "rgba(119, 120, 125, 0.6)", // 提示框浮层的边框颜色。
        borderWidth: 1, // 提示框浮层的边框宽。
        borderColor: "#77787D", // 提示框浮层的边框颜色。
        padding: 10, // 提示框浮层内边距，
        textStyle: {
          fontSize: window.innerWidth > 768 ? 12 : 8,
          //提示框浮层上的文字样式
          color: "#fff",
        },
      },
      //  手放上去时拉的框
      axisPointer: {
        link: [
          {
            xAxisIndex: "all", // 同时触发所有图形的 x 坐标轴指示器
          },
        ],
        label: {
          backgroundColor: "#77787D", // 文本标签的背景颜色
        },
      },
      toolbox: {
        show: false,
      },
      grid: [
        {
          left: window.innerWidth > 768 ? "12%" : "18%",
          right: window.innerWidth > 768 ? "10%" : "12%",
          top: window.innerWidth > 768 ? "8%" : "8%",
          height: window.innerWidth > 768 ? "34%" : "32%",
          containLabel: false,
        },
        {
          left: window.innerWidth > 768 ? "12%" : "18%",
          right: window.innerWidth > 768 ? "10%" : "12%",
          top: window.innerWidth > 768 ? "48%" : "46%",
          height: window.innerWidth > 768 ? "18%" : "20%",
          containLabel: false,
        },
        {
          left: window.innerWidth > 768 ? "12%" : "18%",
          right: window.innerWidth > 768 ? "10%" : "12%",
          top: window.innerWidth > 768 ? "68%" : "68%",
          height: window.innerWidth > 768 ? "18%" : "20%",
          containLabel: false,
        },
        {
          left: window.innerWidth > 768 ? "12%" : "18%",
          right: window.innerWidth > 768 ? "10%" : "12%",
          top: window.innerWidth > 768 ? "48%" : "46%",
          height: window.innerWidth > 768 ? "18%" : "20%",
          containLabel: false,
        },
      ],
      xAxis: [
        {
          type: "category",
          data: dealData.categoryData,
          boundaryGap: true, // 坐标轴两边是否留空，false表示不留空（通常用于K线图）
          axisLine: { onZero: false }, // 设置坐标轴是否通过零点，onZero:false表示不强制穿过零点
          splitLine: { show: false }, // 是否显示分隔线，false表示不显示
          min: "dataMin", // 坐标轴最小值，'dataMin'表示从数据的最小值开始
          max: "dataMax", // 坐标轴最大值，'dataMax'表示从数据的最大值开始
          axisPointer: {
            label: {
              show: false,
            },
            z: 100, // 坐标轴指示器的层级，较大的值会让它显示在其他元素上方
          },
          axisLine: {
            lineStyle: {
              normal: {
                color: "black", // 坐标轴线的颜色
              },
            },
          }, //
          axisLabel: { show: false }, // 隐藏刻度标签
          axisTick: { show: false }, // 隐藏刻度线
        },
        // 短线通1
        {
          type: "category",
          gridIndex: 1,
          data: dealData.categoryData,
          boundaryGap: true,
          axisPointer: {
            label: {
              show: false,
            },
          },
          axisLine: { lineStyle: { normal: { color: "black" } } },
          axisLabel: {
            show: false,
            interval: "auto",
          },
          axisTick: { show: true }, // 隐藏刻度线
        },
        // 下方成交量图的X轴
        {
          type: "category",
          gridIndex: 2,
          data: dealData.categoryData,
          boundaryGap: true,
          axisLine: { lineStyle: { normal: { color: "black" } } },
          axisLabel: {
            show: true,
            fontSize: window.innerWidth > 768 ? 12 : 9,
            interval: "auto",
          },
          axisTick: { show: false }, // 隐藏刻度线
        },
        // 短线通2
        {
          type: "category",
          gridIndex: 3,
          data: dealData.categoryData,
          boundaryGap: true,
          axisPointer: {
            label: {
              show: false,
            },
          },
          axisLine: { show: false },
          axisLabel: { show: false },
          axisTick: { show: false }, // 隐藏刻度线
        },
      ],
      // 控制纵坐标展示数据
      yAxis: [
        {
          scale: true,
          gridIndex: 0,
          position: "left",
          axisLabel: {
            inside: false,
            align: "right",
            fontSize: window.innerWidth > 768 ? 12 : 9,
          },
          axisLine: {
            show: true,
            lineStyle: {
              normal: {
                color: "black",
              },
            },
          },
          axisTick: { show: false },
          splitLine: { show: false },
        },
        {
          scale: true,
          gridIndex: 1,
          min: DXTmin,
          max: DXTmax,
          axisLabel: {
            show: true,
            fontSize: window.innerWidth > 768 ? 12 : 9,
            margin: 8, // 添加边距以获得更好的间距
          },
          axisLine: { show: true, lineStyle: { normal: { color: "black" } } },
          axisTick: { show: false },
          splitLine: { show: true, lineStyle: { normal: { type: "dashed" } } }, // 添加分割线以提高可读性
          boundaryGap: ["20%", "20%"], // 为坐标轴边界添加内边距
        },
        {
          scale: true,
          gridIndex: 2,
          splitNumber: 4, // 增加分割数以获得更好的间距
          minInterval: 1, // 确保标签之间的最小间隔
          axisLabel: {
            show: true,
            fontSize: window.innerWidth > 768 ? 12 : 9,
            margin: 8, // 添加边距以获得更好的间距
          },
          axisLine: { show: true, lineStyle: { normal: { color: "black" } } },
          axisTick: { show: false },
          splitLine: { show: true, lineStyle: { normal: { type: "dashed" } } }, // 添加分割线以提高可读性
          boundaryGap: ["20%", "20%"], // 为坐标轴边界添加内边距
        },
        {
          scale: true,
          gridIndex: 3,
          min: DXTmin,
          max: DXTmax,
          axisLabel: { show: false },
          axisLine: { show: false },
          axisTick: { show: false },
          splitLine: { show: false }, // 添加分割线以提高可读性
          boundaryGap: ["20%", "20%"], // 为坐标轴边界添加内边距
        },
      ],

      // 下拉条
      dataZoom: [
        {
          type: "inside",
          xAxisIndex: [0, 1, 2, 3],
        },
        {
          show: true,
          xAxisIndex: [0, 1, 2, 3],
          type: "slider",
          top: window.innerWidth > 768 ? "90%" : "92%",
          height: window.innerWidth > 768 ? "25" : "20",
          //   left: window.innerWidth > 768 ? "10%" : "8%",
          start: 98,
          end: 100,
        },
      ],
      series: [
        {
          name: "九转结构",
          type: "candlestick",
          barWidth: "50%", // 设置和上方图表一致的柱子宽度
          data: dealData.values,
          xAxisIndex: 0, // 使用第一个 X 轴
          yAxisIndex: 0, // 使用第一个 Y 轴
          markPoint: {
            symbol: "circle",
            symbolSize: 10,
            data: markPointData,
            z: 5, // 确保标记显示在最上层
          },
          itemStyle: {
            normal: {
              color: "red", // 默认颜色
              color0: "green",
              borderColor: "red",
              borderColor0: "green",
            },
          },
          gridIndex: 0,
        },
        {
          name: "短线通-RANGE",
          type: "line",
          xAxisIndex: 1,
          yAxisIndex: 1,
          data: arrRange,
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: "#FA0096",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-SWING",
          type: "line",
          xAxisIndex: 1,
          yAxisIndex: 1,
          data: arrSwing,
          smooth: false,
          symbol: "none",
          show: false,
          itemStyle: {
            normal: {
              color: "transparent", // 设置为透明
              opacity: 0, // 透明度为0
            },
          },
          lineStyle: {
            normal: {
              width: 0, // 线宽为0
              opacity: 0, // 透明度为0
            },
          },
        },
        {
          name: "短线通-隐形柱",
          type: "bar",
          stack: "Total",
          xAxisIndex: 1,
          yAxisIndex: 1,
          data: arrInvisibleBar,
          barWidth: "2", // 设置柱子宽度
          //   barGap: "-100%", // 完全重叠
          z: 5, // 确保标记显示在最上层
          itemStyle: {
            normal: {
              color: "transparent",
              // color: "#000",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-红蓝柱",
          type: "bar",
          stack: "Total",
          xAxisIndex: 1,
          yAxisIndex: 1,
          data: arrDXTBar,
          barWidth: "20%", // 设置柱子宽度
          barGap: "-40%", // 完全重叠
          z: 5, // 确保标记显示在最上层
          itemStyle: {
            normal: {
              color: function (params) {
                // console.log(params.dataIndex);
                if (nineTurns.DXT[params.dataIndex][4] == 1) {
                  return "#FA0096";
                } else if (nineTurns.DXT[params.dataIndex][4] == 2) {
                  return "#0099FF";
                }
                return "transparent";
              },
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-黄柱",
          type: "bar",
          xAxisIndex: 3,
          yAxisIndex: 3,
          data: arr5DXTBar,
          barWidth: "40%", // 设置柱子宽度
          z: 6, // 确保标记显示在最上层
          itemStyle: {
            normal: {
              color: "rgb(154,154,16)",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-灰柱",
          type: "bar",
          xAxisIndex: 3,
          yAxisIndex: 3,
          data: arr6DXTBar,
          barWidth: "40%", // 设置柱子宽度
          z: 6, // 确保标记显示在最上层
          itemStyle: {
            normal: {
              color: "rgb(140,140,140)",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-蓝柱",
          type: "bar",
          xAxisIndex: 3,
          yAxisIndex: 3,
          data: arr7DXTBar,
          barWidth: "40%", // 设置柱子宽度
          barGap: "-100%", // 完全重叠
          z: 6, // 确保标记显示在最上层
          itemStyle: {
            normal: {
              color: "rgb(110,200,255)",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "短线通-其他指标",
          type: "line",
          xAxisIndex: 1,
          yAxisIndex: 1,
          markPoint: {
            symbol: "circle",
            symbolSize: 10,
            data: markPointDXT,
            z: 7, // 确保标记显示在最上层
          },
          data: [],
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: function (params) {
                // params.value 是当前数据点的值
                // params.dataIndex 是当前数据点的索引
                return params.value > 0 ? "#FA0096" : "#0099FF";
              },
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "资金趋势-蓝色线",
          type: "line",
          xAxisIndex: 2,
          yAxisIndex: 2,
          data: arrBlue,
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: "#00A2A2",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "资金趋势-红色线",
          type: "line",
          xAxisIndex: 2,
          yAxisIndex: 2,
          data: arrRed,
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: "#FF0000",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "资金趋势-白色线",
          type: "line",
          xAxisIndex: 2,
          yAxisIndex: 2,
          data: arrWhite,
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: "grey",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
        {
          name: "资金趋势-黄色线",
          type: "line",
          xAxisIndex: 2,
          yAxisIndex: 2,
          data: arrYellow,
          smooth: false,
          symbol: "none",
          itemStyle: {
            normal: {
              color: "#FFFF00",
            },
          },
          lineStyle: {
            normal: {
              width: 2,
              type: "solid",
            },
          },
        },
      ],
    };
  }

  // console.log("KLine渲染: 图表配置完成");

  try {
    // 应用配置
    // console.log("KLine渲染: 开始设置图表选项");
    chartInstancesMap[containerId].setOption(KlineOption);
    // console.log("KLine渲染: 图表选项设置成功");

    // 窗口大小变化时重新渲染图表
    const resizeFunc = _.throttle(
      function () {
        console.log("窗口大小改变，调整图表大小");
        if (
          chartInstancesMap[containerId] &&
          !chartInstancesMap[containerId].isDisposed()
        ) {
          // 如果设备类型发生变化，重新渲染
          const newIsMobile = window.innerWidth < 768;
          const newIsTablet =
            window.innerWidth >= 768 && window.innerWidth < 1024;

          if (newIsMobile !== isMobile || newIsTablet !== isTablet) {
            console.log("设备类型变化，重新渲染图表");
            KlineCanvsEcharts(containerId);
            return;
          }

          chartInstancesMap[containerId].resize();
        }
      },
      1000,
      { trailing: false }
    );

    // 给resize事件绑定一个特定的函数名，便于后续移除
    window[`resize_${containerId}`] = resizeFunc;

    // 绑定resize事件
    window.removeEventListener("resize", window[`resize_${containerId}`]);
    window.addEventListener("resize", window[`resize_${containerId}`]);

    // console.log("KLine渲染: 图表渲染完成");
  } catch (error) {
    // console.error("KLine渲染: 图表渲染出错", error);
  }
}

watch(
  () => audioStore.isVoiceEnabled,
  (newVal) => {
    // 添加状态锁定逻辑
    if (newVal === audioStore.lastVoiceState) return;
    audioStore.lastVoiceState = newVal;

    if (newVal) {
      console.log("开启语音播放");
      // 添加重试机制
      const tryPlay = () => {
        if (!audioStore.ttsUrl) return; // 新增空值判断
        if (audioStore.soundInstance?.playing()) return;
        playAudio(audioStore.ttsUrl);
        setTimeout(() => {
          if (!audioStore.soundInstance?.playing()) {
            Howler.unload();
          }
        }, 1000);
      };
      tryPlay();
    } else {
      console.log("关闭语音播放");
      pauseAudio();
    }
  },
  { immediate: true }
);

watch(
  () => dataStore.activeTabIndex,
  (newVal) => {
    setTimeout(() => {
      console.log("activeTabIndex变化:", newVal);
      // 当标签页切换回来时，重新渲染所有图表
      if (newVal === 0) {
        console.log("切换到AI聊天页，重新渲染图表");
        // 延迟执行以确保DOM已渲染

        renderAllKlineCharts();
      }
    }, 1000);
  },
  { immediate: true } // 添加immediate属性，确保初始化时执行一次
);

const scrollToTop = () => {
  homepageChatStore.dbqbScrollToTop = !homepageChatStore.dbqbScrollToTop;
};

// 添加渲染所有K线图的方法
async function renderAllKlineCharts() {
  console.log("重新渲染所有K线图");

  // 查找所有K线消息
  const messages = chatStore.messages;
  for (let i = 0; i < messages.length; i++) {
    if (messages[i].kline && messages[i].chartData) {
      const containerId = `kline-container-${i}`;
      console.log(`尝试渲染K线图: ${containerId}`);

      // 确保DOM已经渲染
      const container = document.getElementById(containerId);
      console.log("container", container);
      await nextTick();
      if (container) {
        // 渲染图表
        KlineCanvsEcharts(containerId);
      } else {
        console.warn(`找不到容器: ${containerId}`);
      }
    }
  }
}

const clearAudio = () => {
  // 停止音频播放
  if (audioStore.isPlaying) {
    audioStore.stop();
    console.log("组件卸载，音频已停止");
  }
  // 清理队列系统
  audioQueue.value = [];
  isPlayingAudio.value = false;
  currentPlayIndex = 0;
  isCallingPlayNext = false;

  // 清理音频实例
  audioStore.soundInstance = null;
  audioStore.nowSound = null;

  // 停止所有 Howler 实例
  Howler.stop();
  Howler.unload();

  // 重置音频状态
  audioStore.isPlaying = false;
  audioStore.isPaused = false;
  audioStore.playbackPosition = 0;

  // 清理预加载状态
  Object.keys(audioPreloadStatus).forEach((key) => {
    audioPreloadStatus[key] = { loaded: false, url: null };
  });

  chatStore.currentUserIndex = -1;
};

// 初始化随机GIF
onMounted(() => {
  clearAudio();
  // 检测移动设备
  const isMobile =
    /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
      navigator.userAgent
    );

  if (isMobile) {
    // 强制移动设备使用 Web Audio API
    Howler.html5PoolSize = 1; // 限制HTML5音频池大小
    Howler.autoSuspend = false; // 禁用自动挂起
    Howler.usingWebAudio = true; // 强制使用Web Audio API

    // 激活音频上下文
    const activateAudioContext = () => {
      if (Howler.ctx && Howler.ctx.state === "suspended") {
        Howler.ctx.resume();
        console.log("音频上下文已激活");
      }
    };

    // 监听用户交互以激活音频上下文
    document.addEventListener("touchstart", activateAudioContext, {
      once: true,
    });
    document.addEventListener("click", activateAudioContext, { once: true });
  }
  // 初始化marked组件
  marked.setOptions({
    breaks: true, // 支持换行符转换为 <br>
    gfm: true, // 启用 GitHub Flavored Markdown
    sanitize: false, // 不清理 HTML（谨慎使用）
    smartLists: true, // 智能列表
    smartypants: true, // 智能标点符号
    xhtml: false, // 不使用 XHTML 输出
    renderer: renderer,
  });
  renderAllKlineCharts();
  console.log("组件挂载完成");
  // 重置音频下标
  chatStore.currentUserIndex = null;

  chatStore.messages.forEach((item) => {
    if (item.sender == "user") {
      item.audioStatus = false;
    }
  });

  // 添加页面可见性变化监听器
  document.addEventListener("visibilitychange", handleVisibilityChange);

  // 添加DOM变化监听器
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === "childList" && mutation.addedNodes.length) {
        // 检查是否添加了图表容器
        const containers = document.querySelectorAll(
          '[id^="kline-container-"]'
        );
        if (containers.length) {
          // console.log("DOM变化监听到K线容器:", Array.from(containers).map(el => el.id));
        }
      }
    });
  });

  // 开始监听DOM变化
  observer.observe(document.body, { childList: true, subtree: true });
});

// 页面可见性变化处理
let wasPlayingBeforeHidden = false;

const handleVisibilityChange = () => {
  if (document.hidden) {
    // 页面被隐藏时，如果音频正在播放，则暂停并记录状态
    if (audioStore.isPlaying) {
      wasPlayingBeforeHidden = true;
      audioStore.pause();
      console.log("页面切换离开，音频已暂停");
    } else {
      wasPlayingBeforeHidden = false;
    }
  } else {
    // 页面重新可见时，如果之前在播放，则恢复播放
    if (wasPlayingBeforeHidden && !audioStore.isPlaying) {
      audioStore.play();
      console.log("页面切换回来，音频已恢复播放");
      wasPlayingBeforeHidden = false;
    }
  }
};

// 组件卸载时清理所有图表实例和事件监听器
onUnmounted(() => {
  // 移除页面可见性变化监听器
  document.removeEventListener("visibilitychange", handleVisibilityChange);

  clearAudio();

  // 清理所有图表实例
  Object.keys(chartInstancesMap).forEach((key) => {
    if (chartInstancesMap[key]) {
      // 移除resize事件监听
      if (window[`resize_${key}`]) {
        window.removeEventListener("resize", window[`resize_${key}`]);
        delete window[`resize_${key}`];
      }

      // 销毁图表实例
      chartInstancesMap[key].dispose();
      delete chartInstancesMap[key];
    }
  });
});
</script>

<template>
  <div class="chat-container">
    <div id="deepNine-top-anchor"></div>
    <!-- GIF区域 -->
    <div class="gif-area">
      <img
        src="https://d31zlh4on95l9h.cloudfront.net/images/a686991d0a26bdbafd938a15da93d5b4.png"
        alt="深度九大模型logo"
        class="bgc"
      />
      <img
        src="https://d31zlh4on95l9h.cloudfront.net/images/35bf808538183be0062e4647570a9abd.png"
        alt="深度九大模型logo"
        class="logo1"
      />
      <img
        src="https://d31zlh4on95l9h.cloudfront.net/images/0c09c892051e7ae16cbff6091075aee9.png"
        alt="深度九大模型标题logo"
        class="logo2"
      />
    </div>

    <div v-for="(msg, index) in chatMsg" :key="index">
      <!-- 用户消息容器，包含喇叭按钮 -->
      <div v-if="msg.sender === 'user'" class="user-message-container">
        <div class="user-msg">
          <div class="user-content">
            <img
              :src="msg.audioStatus ? voice : voiceNoActive"
              class="user-message-speaker"
              :class="{
                'speaker-active': msg.audioStatus,
              }"
              @click="toggleVoiceForUser(index)"
              alt="喇叭"
            />
            <div
              :class="{
                'message-bubble': true,
                [msg.sender]: msg.sender,
                [msg.class]: msg.class,
              }"
            >
              <div v-html="msg.content"></div>
            </div>
          </div>
          <div v-if="msg.timestamp" class="user-sendTime">
            {{ moment(msg.timestamp).format("YYYY-MM-DD HH:mm:ss") }}
          </div>
        </div>
      </div>

      <!-- AI消息和其他类型消息 -->
      <div
        v-else
        :class="{
          'message-bubble': true,
          [msg.sender]: msg.sender,
          [msg.class]: msg.class,
        }"
      >
        <div v-if="msg.type === 'kline'" class="kline-container">
          <div :id="'kline-container-' + index" class="chart-mount-point">
            <div v-if="!msg.hasValidData" class="no-data-message">
              <p>暂无K线数据</p>
            </div>
          </div>
        </div>
        <div v-else-if="msg.type == 'ing'" class="ai-message-container">
          <img
            v-if="msg.gif"
            :src="msg.gif"
            alt="思考过程"
            class="thinking-gif"
          />
          <div class="ai-message-content" :class="{ fourStep: msg.nowrap }">
            <div v-if="msg.flag">
              <span>{{ msg.content }}</span>
              <span class="loading-dots">
                <span class="dot">.</span>
                <span class="dot">.</span>
                <span class="dot">.</span>
                <span class="dot">.</span>
                <span class="dot">.</span>
                <span class="dot">.</span>
              </span>
            </div>
            <div v-else v-html="msg.content"></div>
          </div>
        </div>
        <div
          v-else-if="msg.type == 'title1'"
          style="display: flex; width: 100%"
        >
          <div class="mainTitle">
            {{ msg.content }}
          </div>
          <div class="date">
            {{ msg.date }}
          </div>
        </div>
        <div v-else-if="msg.type == 'title2'" class="title2">
          <img
            class="title1Img"
            src="https://d31zlh4on95l9h.cloudfront.net/images/c5c2887c56cde033c362cecae4cda4b4.png"
            alt="出错了"
          />
        </div>
        <div v-else-if="msg.type == 'title3'" class="title3">
          <img class="title2Img" :src="msg.content" alt="出错了" />
        </div>
        <div v-else-if="msg.type == 'content1'" class="content1">
          <div v-if="msg.kline" class="kline-container content1chart">
            <div :id="'kline-container-' + index" class="chart-mount-point">
              <div v-if="!msg.hasValidData" class="no-data-message">
                <p>暂无数据</p>
              </div>
            </div>
          </div>
          <div v-else class="content1Text">
            <div v-html="msg.content" class="text1"></div>
          </div>
        </div>
        <div v-else-if="msg.type == 'content2'" class="content2">
          <div class="kline-container content2chart">
            <div :id="'kline-container-' + index" class="chart-mount-pointJN">
              <div v-if="!msg.hasValidData" class="no-data-message">
                <p>暂无数据</p>
              </div>
            </div>
          </div>
        </div>
        <div v-else-if="msg.type == 'img1'" class="img1">
          <div class="img1Bk">
            <img class="img1Img" :src="msg.content" alt="出错了" />
          </div>
        </div>
        <div v-else-if="msg.type == 'content3'" class="content3">
          <div class="content3Text">
            <div v-html="msg.content" class="text3"></div>
          </div>
        </div>
        <div v-else-if="msg.type == 'mianze'" class="mianze">
          <div v-html="msg.content"></div>
        </div>
        <div v-else v-html="msg.content"></div>
      </div>
    </div>
  </div>
  <!-- 全局返回顶部按钮 -->
  <div v-if="chatMsg.length > 0" class="back-to-top" @click="scrollToTop">
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M12 4L12 20M12 4L6 10M12 4L18 10"
        stroke="currentColor"
        stroke-width="2"
        stroke-linecap="round"
        stroke-linejoin="round"
      />
    </svg>
  </div>
</template>

<style scoped>
p {
  font-size: 20px;
}

.bgc {
  position: absolute;
  z-index: -1;
  max-width: 440px;
  min-width: 300px;
  top: -15px;
  width: 40%;
  height: auto;
  /* 添加旋转动画 */
  animation: rotate 10s linear infinite reverse;
}

/* 定义旋转动画 */
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.logo1 {
  max-width: 350px;
  min-width: 200px;
  width: 15%;
}

.logo2 {
  margin-top: 20px;
  max-width: 350px;
  min-width: 200px;
  width: 30%;
  /* position: relative; */
}

.chat-container {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.gif-area {
  padding: 70px 0px;
  position: relative;
  /* height: 30vh; */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;

  /* 防止GIF区域被压缩 */
}

.message-area {
  margin-top: 2%;
  flex: 1;
  /* 消息区域占据剩余空间 */
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.marquee-container {
  /* position: absolute; */
  bottom: 0;
  width: 100%;
  /* ga */
}

.marquee-row {
  white-space: nowrap;
  overflow: visible;
  padding: 8px 0;
  width: 100%;
}

.marquee-item {
  display: inline-block;
  margin: 0 15px;
  padding: 8px 20px;
  background: rgba(255, 255, 255, 0.9);
  /* 白色背景 */
  border-radius: 10px;
  /* 圆角矩形 */
  color: #333;
  /* 文字颜色改为深色 */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  /* 添加阴影 */
  transition: all 0.3s;
  transition: color 0.3s;
}

.top {
  animation: marquee 25s linear infinite;
  /* 默认动画是运行状态 */
  animation-play-state: running;
}

.bottom {
  animation: marquee 15s linear infinite reverse;
  /* 默认动画是运行状态 */
  animation-play-state: running;
}

/* 返回顶部按钮样式 */
.back-to-top {
  position: sticky !important;
  bottom: 20px !important;
  left: calc(100% - 70px) !important;
  width: 50px !important;
  height: 50px !important;
  background: linear-gradient(135deg, #00d4ff 0%, #0066cc 100%) !important;
  border-radius: 50% !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  cursor: pointer !important;
  transition: all 0.3s ease !important;
  z-index: 100 !important;
  color: white !important;
  opacity: 1 !important;
  visibility: visible !important;
  margin-top: 20px !important;
  margin-bottom: 20px !important;
}

.back-to-top:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 20px rgba(0, 212, 255, 0.5);
  background: linear-gradient(135deg, #00e6ff 0%, #0077dd 100%);
}

.back-to-top:active {
  transform: translateY(-1px);
}

/* 添加PC端专用速度 */
@media (min-width: 768px) {
  .top {
    animation-duration: 35s;
    /* PC端改为35秒 */
  }

  .bottom {
    animation-duration: 35s;
    /* PC端改为35秒 */
  }
}

@keyframes marquee {
  0% {
    transform: translateX(100%);
  }

  100% {
    transform: translateX(-250%);
  }
}

.loading-dots {
  display: inline-block;
}

.dot {
  opacity: 0.4;
  animation: loading 1.4s infinite;
}

.dot:nth-child(1) {
  animation-delay: 0s;
}

.dot:nth-child(2) {
  animation-delay: 0.2s;
}

.dot:nth-child(3) {
  animation-delay: 0.4s;
}

.dot:nth-child(4) {
  animation-delay: 0.6s;
}

.dot:nth-child(5) {
  animation-delay: 0.8s;
}

.dot:nth-child(6) {
  animation-delay: 1s;
}

@keyframes loading {
  0%,
  60%,
  100% {
    opacity: 0.4;
  }

  30% {
    opacity: 1;
  }
}

.message-bubble {
  max-width: 80%;
  margin: 10px 0px;
  padding: 15px 20px;
  position: relative;
}

/* 用户消息容器样式 */
.user-message-container {
  display: flex;
  align-items: flex-end;
  margin: 10px 0px;
  justify-content: flex-end;
  gap: 10px;
  /* align-items: center; */
  flex-direction: column;
}

.user-msg {
  margin-left: auto;
  display: flex;
  flex-direction: column;
}

.user-content {
  display: flex;
  height: 100%;
  align-items: center;
  margin-right: 5px;
  justify-content: flex-end;
  padding: 0 20px;
}

.user-sendTime {
  width: 100%;
  text-align: center;
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.8rem;
}

.user-message-speaker {
  width: 32px;
  height: 32px;
  object-fit: contain;
  margin-right: 5px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.user-message-speaker:hover {
  transform: scale(1.1);
}

.user-message-speaker.speaker-active {
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.message-bubble.user {
  color: #6d22f8;
  background: white;
  font-weight: bold;
  border-radius: 10px;
  margin: 0;
  display: flex;
  align-items: center;
  word-break: break-word; /* 启用强制换行 */
}

.message-bubble.ai {
  background: #2b378d;
  color: #ffffff;
  margin: 0 auto;
  /* border-bottom-left-radius: 5px; */
}

.message-bubble.ing {
  background: #ffffff;
  color: #000000;
  font-weight: bold;
  border-radius: 10px;
  margin-left: 20px;
  margin-right: auto;
  display: flex;
  align-items: center;
  width: fit-content;
}

.message-bubble.ai.title1 {
  width: 100%;
  display: flex;
  border-radius: 10px 10px 0px 0px;
  /* border-bottom-left-radius: 5px; */
}

.mainTitle {
  font-size: 16px;
  font-weight: bold;
  background-image: url("@/assets/img/AiEmotion/bk01.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  min-width: 200px;
  width: 20vw;
  max-width: 50%;
  height: 50px;
  padding: 15px 10px;
  text-align: center;
  line-height: 20px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  box-sizing: border-box;
}

.date {
  font-size: 1.5rem;
  font-weight: bold;
  margin-left: auto;
  /* width: 100px; */
  display: flex;
  justify-content: center;
  align-items: center;
}

.message-bubble.ai.title2 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.title1Img {
  max-width: 500px;
  width: 90vw;
}

.message-bubble.ai.title3 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.title2Img {
  max-width: 500px;
  width: 90vw;
}

.message-bubble.ai.content1 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.content1chart {
  background-image: url("@/assets/img/AIchat/罗盘边框.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 50vw;
  min-width: 350px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.content1Text {
  background-image: url("@/assets/img/AIchat/框.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 50vw;
  min-width: 350px;
  /* height: 20vw; */
  /* max-height: 400px; */
  padding: 5% 0;
}

.text1 {
  font-weight: bold;
  /* margin-left: 6%; */
  /* margin-bottom: 10px; */
  margin: 0px 6% 10px 6%;
  font-size: 20px;
}

.message-bubble.ai.content2 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.content2chart {
  background-image: url("@/assets/img/AIchat/PCbackPic.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 50vw;
  min-width: 350px;
  display: flex;
  justify-content: center;
  align-items: center;
  height: calc(500px + 10vw) !important;
}

.message-bubble.ai.img1 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.img1Bk {
  background-image: url("@/assets/img/AIchat/边框.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 50vw;
  min-width: 350px;
  /* height: 20vw; */
  /* max-height: 400px; */
  padding: 5% 0px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.img1Img {
  width: 90%;
}

.message-bubble.ai.content3 {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.content3Text {
  background-image: url("@/assets/img/AIchat/边框.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  width: 50vw;
  min-width: 350px;
  /* height: 20vw; */
  /* max-height: 400px; */
  padding: 5% 0px;
}

.text3 {
  /* font-weight: bold; */
  /* margin-left: 6%; */
  /* margin-bottom: 10px; */
  margin: 0px 6% 10px 6%;
  font-size: 20px;
}

.message-bubble.ai.mianze {
  width: 100%;
  text-align: center;
  font-weight: bold;
  font-size: 24px;
  border-radius: 0px 0px 10px 10px;
}

.kline-container {
  margin-top: 10px;
  /* 最小高度 */
  min-height: 320px;
  /* 视口高度单位 */
  height: 40vh;
  width: 50vw;
}

@media (max-width: 768px) {
  .gif-area {
    padding: 0px 0px;
    position: relative;
    /* height: 30vh; */
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    flex-shrink: 0;
  }

  .logo1 {
    max-width: 350px;
    min-width: 200px;
    width: 15%;
    scale: 0.8;
  }

  .logo2 {
    margin-top: 20px;
    max-width: 350px;
    min-width: 200px;
    width: 80%;
    /* position: relative; */
  }

  .kline-container {
    min-width: 75vw;
  }

  .content1Text {
    width: 77vw;
    min-width: 0px;
    /* height: 20vw; */
    /* min-height: 150px; */
  }

  .date {
    font-size: 14px;
    text-align: end;
  }

  .text1 {
    font-size: 20px;
  }

  .content2chart {
    background-image: url("@/assets/img/AIchat/new-app-bgc.png") !important;
    height: 100vw;
  }

  .img1Bk {
    width: 77vw;
    min-width: 0px;
    /* height: 20vw; */
    /* min-height: 150px; */
  }

  .content3Text {
    width: 77vw;
    min-width: 0px;
    /* height: 20vw; */
    /* min-height: 150px; */
  }

  .text3 {
    font-size: 20px;
  }

  .message-bubble.ai.mianze {
    font-size: 18px;
  }

  .back-to-top {
    left: calc(100% - 65px) !important;
    width: 45px !important;
    height: 45px !important;
  }
}

.kline-container .chart-mount-point {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80%;
  width: 90%;
}

.kline-container .chart-mount-pointJN {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
}

/* AI消息容器样式 */
.ai-message-container {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-right: auto;
  /* max-width: 80%; */
}

/* 思考过程动图样式 */
.thinking-gif {
  width: 40px;
  height: 40px;
  object-fit: contain;
  margin-top: 5px;
  border-radius: 8px;
  animation: float 2s ease-in-out infinite;
}

@keyframes float {
  0%,
  100% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-5px);
  }
}

/* AI消息内容样式 */
.ai-message-content {
  display: flex;
  align-items: center;
  /* white-space: nowrap; */
  width: fit-content;
  overflow: visible;
}

.fourStep {
  white-space: nowrap;
}

@media only screen and (max-width: 480px) {
  .back-to-top {
    left: calc(100% - 60px) !important;
    width: 40px !important;
    height: 40px !important;
  }

  .back-to-top svg {
    width: 20px;
    height: 20px;
  }
}
</style>
