<template>
  <div class="chat-widget">
    <!-- 添加网络状态提示  -->
    <div class="network-status" v-if="networkStatus === 'offline'">
      <i class="el-icon-warning"></i>
      <span>{{ $t("chat.networkError") || "网络连接已断开" }}</span>
    </div>
    <!-- 聊天图标 -->
    <div
      class="chat-icon"
      @click="toggleChat"
      :class="{ active: isChatOpen }"
      :aria-label="$t('chat.openCustomerService') || '打开客服聊天'"
      tabindex="0"
      @keydown.enter="toggleChat"
      @keydown.space="toggleChat"
    >
      <i class="el-icon-chat-dot-round"></i>
      <span v-if="unreadMessages > 0" class="unread-badge">{{
        unreadMessages
      }}</span>
    </div>

    <!-- 聊天对话框 -->
    <transition name="chat-slide">
      <div v-show="isChatOpen" class="chat-dialog">
        <div class="chat-header">
          <div class="chat-title">{{ $t("chat.title") || "在线客服" }}</div>
          <div class="chat-actions">
            <i class="el-icon-minus" @click="minimizeChat"></i>
            <i class="el-icon-close" @click="closeChat"></i>
          </div>
        </div>
        <div class="chat-body" ref="chatBody">
          <!-- 游客提示信息 -->
          <div v-if="userType === 0" class="guest-notice">
            <span class="guest-notice-content">
              <i class="el-icon-info"></i>

              <span
                >{{ $t("chat.guestNotice") || "游客模式下聊天记录不会保存，" }}
                <a @click="handleLoginClick" class="login-link">{{
                  $t("chat.loginToSave") || "登录"
                }}</a>
                {{ $t("chat.guestNotice2") || "后即可保存" }}
              </span>
            </span>
          </div>
          <!-- 连接状态提示 -->
          <div
            v-if="connectionStatus === 'connecting'"
            class="chat-status connecting"
          >
            <i class="el-icon-loading"></i>
            <p>
              {{ $t("chat.connectToCustomerService") || "正在连接客服系统..." }}
            </p>
          </div>
          <div
            v-else-if="connectionStatus === 'error'"
            class="chat-status error"
          >
            <i class="el-icon-warning"></i>
            <p>
              {{
                connectionError ||
                $t("chat.connectionFailed") ||
                "连接失败，请稍后重试"
              }}
            </p>
            <div class="error-actions">
              <button @click="handleRetryConnect" class="retry-button">
                {{ $t("chat.tryConnectingAgain") || "重试连接" }}
              </button>
              <button
                v-if="showRefreshButton"
                @click="refreshPage"
                class="refresh-button"
              >
                {{ $t("chat.refreshPage") || "刷新页面" }}
              </button>
            </div>
          </div>

          <!-- 消息列表 -->
          <template v-else>
            <!-- 历史消息加载提示 -->
            <div
              v-if="hasMoreHistory && messages.length > 0"
              class="history-indicator"
              :class="{ 'no-more': !hasMoreHistory }"
              @click.stop="loadMoreHistory"
            >
              <i class="el-icon-arrow-up"></i>
              <span>{{
                isLoadingHistory
                  ? $t("chat.loading") || "加载中..."
                  : hasMoreHistory
                  ? $t("chat.loadMore") || "加载更多历史消息"
                  : $t("chat.noMoreHistory") || "没有更多历史消息了"
              }}</span>
            </div>

            <!-- 没有消息时的欢迎提示 -->
            <div
              v-if="messages.length === 0 && userType !== 0"
              class="chat-empty"
            >
              {{
                $t("chat.welcome") || "欢迎使用在线客服，请问有什么可以帮您？"
              }}
            </div>

            <!-- 消息项 -->
            <div
              v-for="(msg, index) in displayMessages"
              :key="
                msg.id
                  ? `msg-${msg.id}`
                  : msg.isTimeDivider
                  ? `divider-${index}-${msg.time}`
                  : `sys-${index}-${Date.now()}`
              "
            >
              <!-- 时间分割条 -->
              <div v-if="msg.isTimeDivider" class="chat-time-divider">
                {{ formatTimeDivider(msg.time) }}
              </div>
              <!-- 系统提示消息，如加载中、无更多消息等 -->
              <div
                v-else-if="msg.isLoading || msg.isSystemHint"
                class="system-hint"
              >
                <i v-if="msg.isLoading" class="el-icon-loading"></i>
                <span>{{ msg.text }}</span>
              </div>
              <!-- 普通消息 -->
              <div
                v-else
                class="chat-message"
                :class="{
                  'chat-message-user': msg.type === 'user',
                  'chat-message-system': msg.type === 'system',
                  'chat-message-loading': msg.isLoading,
                  'chat-message-hint': msg.isSystemHint,
                  'chat-message-history': msg.isHistory,
                }"
              >
                <div class="message-avatar">
                  <i v-if="msg.type === 'system'" class="el-icon-service"></i>
                  <i v-else class="el-icon-user"></i>
                </div>
                <div class="message-content">
                  <!-- 时间显示在右上角（注释掉，只显示时间分割条） -->
                  <!-- <span class="message-time">{{ formatTime(msg.time) }}</span> -->
                  <div
                    v-if="!msg.isImage"
                    class="message-text"
                    v-html="formatMessageText(msg.text)"
                  ></div>
                  <div v-else class="message-image">
                    <img
                      :src="msg.imageUrl"
                      @click="previewImage(msg.imageUrl)"
                      :alt="$t('chat.picture') || '聊天图片'"
                      @load="handleImageLoad(msg)"
                    />
                  </div>
                  <!-- <div class="message-footer">
                    <span
                      v-if="msg.type === 'user'"
                      class="message-read-status"
                    >
                      {{
                        msg.isRead
                          ? $t("chat.read") || "已读"
                          : $t("chat.unread") || "未读"
                      }}
                    </span>
                  </div> -->
                </div>
              </div>
            </div>
          </template>
        </div>

        <div class="chat-footer">
          <div class="chat-toolbar">
            <label
              for="imageUpload"
              class="image-upload-label"
              :class="{ disabled: connectionStatus !== 'connected' }"
            >
              <i class="el-icon-picture-outline"></i>
            </label>
            <input
              type="file"
              id="imageUpload"
              ref="imageUpload"
              accept="image/*"
              @change="handleImageUpload"
              style="display: none"
              :disabled="connectionStatus !== 'connected'"
            />
          </div>
          <!-- :disabled="connectionStatus !== 'connected'" -->
          <div
            class="chat-input-wrapper"
            style="display: flex; align-items: center"
          >
            <input
              type="text"
              class="chat-input"
              v-model="inputMessage"
              :maxlength="maxMessageLength"
              @input="handleInputMessage"
              @keydown.enter="handleEnterKey"
              :placeholder="$t('chat.inputPlaceholder') || '请输入您的问题...'"
            
            />
            <!-- <span class="input-counter">{{ maxMessageLength - inputMessage.length }}</span> -->
          </div>
          <!-- :disabled="connectionStatus !== 'connected' || !inputMessage.trim()" -->
          <button class="chat-send" @click="sendMessage">
            {{ $t("chat.send") || "发送" }}
          </button>
        </div>

        <!-- 图片预览 -->
        <div
          v-if="showImagePreview"
          class="image-preview-overlay"
          @click="closeImagePreview"
        >
          <div class="image-preview-container">
            <img :src="previewImageUrl" class="preview-image" />
            <i
              class="el-icon-close preview-close"
              @click="closeImagePreview"
            ></i>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
import { Client, Stomp } from "@stomp/stompjs";
import {
  getUserid,
  getHistory,
  getHistory7,
  getReadMessage,
  getFileUpdate,
} from "../api/customerService";
export default {
  name: "ChatWidget",
  data() {
    return {
      isChatOpen: false,
      inputMessage: "",
      messages: [],
      unreadMessages: 0, // 仍保留，但从localStorage读取
      // 图片预览相关
      showImagePreview: false,
      previewImageUrl: "",
      // WebSocket 相关
      stompClient: null,
      receivingEmail: "",
      connectionStatus: "disconnected", // disconnected, connecting, connected, error
      userType: 0, // 0 游客 1 登录用户 2 客服
      userEmail: "", // 用户标识
      // 自动回复配置
      autoResponses: {
        hello: "您好，有什么可以帮助您的？",
        你好: "您好，有什么可以帮助您的？",
        hi: "您好，有什么可以帮助您的？",
        挖矿: "您可以查看我们的挖矿教程，或者直接创建矿工账户开始挖矿。",
        算力: "您可以在首页查看当前的矿池算力和您的个人算力。",
        收益: "收益根据您的算力贡献按比例分配，详情可以查看收益计算器。",
        帮助: "您可以查看我们的帮助文档，或者提交工单咨询具体问题。",
      },
      isLoadingHistory: false, // 是否正在加载历史消息
      hasMoreHistory: true, // 是否还有更多历史消息
      roomId: "",
      isWebSocketConnected: false,
      heartbeatInterval: null,
      lastHeartbeatTime: null,
      heartbeatTimeout: 120000, // 增加到120秒（2分钟）没有心跳就认为连接断开
      cachedMessages: {}, // 缓存各聊天室的消息
      isMinimized: false, // 区分最小化和关闭状态
      reconnectAttempts: 0,
      maxReconnectAttempts: 3, // 减少最大重连次数
      reconnectInterval: 3000, // 减少重连间隔
      isReconnecting: false,
      lastActivityTime: Date.now(),
      activityCheckInterval: null,
      networkStatus: "online",
      reconnectTimer: null,
      connectionError: null, // 添加错误信息存储
      showRefreshButton: false, // 添加刷新按钮
      heartbeatCheckInterval: 30000, // 每30秒检查一次心跳

      maxMessageLength: 300,

      // === 新增：连接验证相关 ===
      connectionVerifyTimer: null, // 连接验证定时器
      isConnectionVerified: false, // 连接是否已验证
      isHandlingError: false, // 是否正在处理错误
      lastErrorTime: 0, // 最后一次错误时间
      lastConnectedEmail: null, // 最后连接的用户email，用于防止重复连接
      userViewHistory: false, // 是否在查看历史消息
      customerIsOnline: false, // 保存客服在线状态

      jurisdiction: {
        roleKey: "",
      },
      token: "",
    };
  },
  computed: {
    /**
     * 生成带有时间分割条的消息列表
     * @returns {Array} 消息和分割条混合数组
     */
    displayMessages() {
      const result = [];
      const interval = 5 * 60 * 1000; // 5分钟
      let lastTime = null;

      this.messages.forEach((msg, idx) => {
        if (!msg.isSystemHint && !msg.isLoading) {
          const msgTime = new Date(msg.time); // 直接new即可
          if (!lastTime || msgTime - lastTime > interval) {
            result.push({
              isTimeDivider: true,
              time: msg.time, // 直接用字符串
              id: `divider-${msgTime.getTime()}-${idx}`, // 使用时间戳确保唯一性
            });
            lastTime = msgTime;
          }
        }
        result.push(msg);
      });
      return result;
    },
  },

  // 监听状态变化
  watch: {
    connectionStatus(newStatus, oldStatus) {
      if (newStatus !== oldStatus) {
        console.log(`🔄 连接状态变化: ${oldStatus} -> ${newStatus}`);
        console.log(`🔍 当前时间: ${new Date().toLocaleTimeString()}`);
        console.log(`🔍 WebSocket状态: ${this.isWebSocketConnected}`);
        console.log(`🔍 STOMP状态: ${this.stompClient?.connected}`);
        console.log(`🔍 重连状态: ${this.isReconnecting}`);
        console.log(`🔍 验证状态: ${this.isConnectionVerified}`);

        // 如果状态莫名其妙变为connecting，记录调用栈
        if (newStatus === "connecting" && oldStatus === "connected") {
          console.warn("⚠️ 连接状态从connected变为connecting，可能有问题");
          console.trace("调用栈:");
        }

        // === 新增：强制触发Vue重新渲染 ===
        if (newStatus === "connected") {
          console.log("✅ 状态已变为connected，强制触发重新渲染");
          this.$forceUpdate();
        }
      }
    },
    isChatOpen(val) {
      if (val) {
        // 聊天框每次打开都兜底滚动到底部，提升体验
        this.$nextTick(() => this.scrollToBottomOnInit());
        // === 移除 markMessagesAsRead 调用，防止切换窗口时误清未读 ===
      }
    },
    token(val) {
    console.log("token变化打印",val);
    
      if (!val) {
          // 通知所有窗口断开连接
        localStorage.setItem('cs_disconnect_all', Date.now().toString());
        this.forceDisconnectAll()
        this.$nextTick(() => {
          this.determineUserType()
        })
      }
    },
  },


  async created() {
    let jurisdiction = localStorage.getItem("jurisdiction");
    try {
      jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
    } catch (e) {
      jurisdiction = { roleKey: "" };
    }
    this.jurisdiction = jurisdiction;

    window.addEventListener("setItem", () => {
      let jurisdiction = localStorage.getItem("jurisdiction");
      try {
        jurisdiction = jurisdiction
          ? JSON.parse(jurisdiction)
          : { roleKey: "" };
      } catch (e) {
        jurisdiction = { roleKey: "" };
      }
      this.jurisdiction = jurisdiction;
    });
    // === 初始化未读消息数（从localStorage读取） ===
    this.initUnreadMessages();
    this.determineUserType();
  },
  mounted() {
    let jurisdiction = localStorage.getItem("jurisdiction");
    try {
      jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
    } catch (e) {
      jurisdiction = { roleKey: "" };
    }
    this.jurisdiction = jurisdiction;

    let customerIsOnline = localStorage.getItem("customerIsOnline");
    this.customerIsOnline = JSON.parse(customerIsOnline);
    let token = localStorage.getItem("token");
    this.token = JSON.parse(token);

    window.addEventListener("setItem", () => {
      let jurisdiction = localStorage.getItem("jurisdiction");
      try {
        jurisdiction = jurisdiction
          ? JSON.parse(jurisdiction)
          : { roleKey: "" };
      } catch (e) {
        jurisdiction = { roleKey: "" };
      }
      this.jurisdiction = jurisdiction;


      let customerIsOnline = localStorage.getItem("customerIsOnline");
      this.customerIsOnline = JSON.parse(customerIsOnline);
      let token = localStorage.getItem("token");
      this.token = JSON.parse(token);
    });

    // 添加页面卸载事件监听
    window.addEventListener("beforeunload", this.handleBeforeUnload);

    // === 添加localStorage监听，实现多窗口未读消息同步 ===
    window.addEventListener("storage", this.handleStorageChange);

    document.addEventListener("click", this.handleClickOutside);
    // === 移除滚动监听，简化逻辑 ===
    // this.$nextTick(() => {
    //   if (this.$refs.chatBody) {
    //     this.$refs.chatBody.addEventListener("scroll", this.handleChatScroll);
    //   }
    // });

    // 添加页面可见性变化监听
    document.addEventListener("visibilitychange", this.handleVisibilityChange);
    // 添加网络状态变化监听
    window.addEventListener("online", this.handleNetworkChange);
    window.addEventListener("offline", this.handleNetworkChange);

    // 添加用户活动检测
    this.startActivityCheck();

    // 添加用户活动监听
    document.addEventListener("mousemove", this.updateLastActivityTime);
    document.addEventListener("keydown", this.updateLastActivityTime);
    document.addEventListener("click", this.updateLastActivityTime);

    // 监听退出登录事件
    this.$bus.$on("user-logged-out", this.handleLogout);
    // 监听登录成功
    this.$bus.$on("user-logged-in", this.handleLoginSuccess);

    // === 新增：添加快捷键用于调试状态 ===
    this.setupDebugMode();

    // 添加聊天区滚动事件监听
    this.$nextTick(() => {
      if (this.$refs.chatBody) {
        this.$refs.chatBody.addEventListener(
          "scroll",
          this.handleChatBodyScroll
        );
      }
    });
    // 聊天框初始化时多次兜底滚动到底部，保证异步内容加载后滚动到位
    this.scrollToBottomOnInit();
  },
  methods: {
    // === 初始化未读消息数 ===
    initUnreadMessages() {
      try {
        const storageKey = this.getUnreadStorageKey();
        const stored = localStorage.getItem(storageKey);
        this.unreadMessages = stored ? parseInt(stored, 10) || 0 : 0;
        // console.log("📋 初始化未读消息数:", this.unreadMessages);
      } catch (error) {
        console.warn("读取未读消息数失败:", error);
        this.unreadMessages = 0;
      }
    },

    // === 获取未读消息的localStorage键名 ===
    getUnreadStorageKey() {
      return `chat_unread_${this.userEmail || "guest"}`;
    },

    // === 更新未读消息数到localStorage ===
    updateUnreadMessages(count) {
      try {
        const storageKey = this.getUnreadStorageKey();
        this.unreadMessages = count;
        localStorage.setItem(storageKey, String(count));
        // console.log("📝 更新未读消息数:", count);
      } catch (error) {
        console.warn("保存未读消息数失败:", error);
      }
    },

    // === 监听localStorage变化，同步多窗口 ===
    handleStorageChange(event) {
      if (event.key && event.key.startsWith("chat_unread_")) {
        // 检查是否是当前用户的未读消息
        const currentKey = this.getUnreadStorageKey();
        if (event.key === currentKey) {
          const newCount = parseInt(event.newValue, 10) || 0;
          //  console.log("🔄 检测到其他窗口更新未读消息数:", newCount);
          this.unreadMessages = newCount;
        }
      }
    },

    // 初始化聊天系统
    async initChatSystem() {
      // console.log("🔧 初始化聊天系统, userEmail:", this.userEmail);
      // console.log("🔍 当前连接状态:", this.connectionStatus);
      // console.log("🔍 当前WebSocket状态:", this.isWebSocketConnected);

      if (!this.userEmail) {
        console.log("❌ userEmail为空，跳过初始化");
        return;
      }

      // === 防止重复初始化：如果已经连接且使用相同email，跳过 ===
      if (
        this.isWebSocketConnected &&
        this.connectionStatus === "connected" &&
        this.userEmail === this.lastConnectedEmail
      ) {
        console.log("✅ 聊天系统已初始化且连接正常，跳过重复初始化");
        return;
      }

      try {
        console.log("jurisdict口服空手道咖啡豆防控ion", this.jurisdiction);

        if (
          this.jurisdiction.roleKey =="customer_service" ||
          this.jurisdiction.roleKey == "admin" ||
          this.jurisdiction.roleKey == "back_admin"
          
        ) return;
        // 获取用户ID和未读消息数
        const userData = await this.fetchUserid({ email: this.userEmail });
        if (userData) {
          this.roomId = userData.id;
          this.receivingEmail = userData.userEmail;
          // === 保存客服在线状态 ===
          this.customerIsOnline = userData.customerIsOnline;
          // === 使用localStorage管理未读消息数 ===
          this.updateUnreadMessages(userData.clientReadNum || 0);

          // === 只有在未连接或email变化时才初始化连接 ===
          if (
            !this.isWebSocketConnected ||
            this.userEmail !== this.lastConnectedEmail
          ) {
            // console.log("🔄 需要建立新连接, 用户:", userData.selfEmail);
            // 如果有旧连接且email不同，先断开
            if (
              this.isWebSocketConnected &&
              this.userEmail !== this.lastConnectedEmail
            ) {
              // console.log("🔄 用户身份变化，断开旧连接");
              await this.forceDisconnectAll();
            }
            this.initWebSocket(userData.selfEmail);
            this.lastConnectedEmail = this.userEmail; // 记录当前连接的email
          } else {
            // console.log("✅ WebSocket已连接，复用现有连接");
          }
        }
      } catch (error) {
        console.error("初始化聊天系统失败:", error);
      }
    },

    // 初始化 WebSocket 连接
    initWebSocket(selfEmail) {
      // this.determineUserType();
      this.connectWebSocket(selfEmail);
    },

    // 确定用户类型和邮箱
    async determineUserType() {

      console.log("token",this.token);
      
      try {
        const token = localStorage.getItem("token");
        // console.log("token", token);
        if (!token) {
          // === 游客身份：检查是否已有缓存的游客email ===
          const cachedGuestEmail = sessionStorage.getItem("chatGuestEmail");
          if (cachedGuestEmail && cachedGuestEmail.startsWith("guest_")) {
            // console.log("📋 复用已缓存的游客身份:", cachedGuestEmail);
            this.userType = 0;
            this.userEmail = cachedGuestEmail;
          } else {
            // 生成新的游客身份
            this.userType = 0;
            this.userEmail = `guest_${Date.now()}_${Math.random()
              .toString(36)
              .substr(2, 9)}`;
            // 缓存到sessionStorage，页面刷新前保持不变
            sessionStorage.setItem("chatGuestEmail", this.userEmail);
            // console.log("🆕 生成新游客用户:", this.userEmail);
          }
          // 页面加载时立即获取用户信息
          this.initChatSystem();
          return;
        }

        try {
          const userInfo = JSON.parse(
            localStorage.getItem("jurisdiction") || "{}"
          );
          // const email = JSON.parse(localStorage.getItem("userEmail") || "{}");
          const emailData = localStorage.getItem("userEmail") || "{}";
          let email = "";

          try {
            const emailObj = JSON.parse(emailData);
            // 如果是对象，尝试取常见的邮箱字段
            email =
              emailObj.email ||
              emailObj.value ||
              emailObj.userEmail ||
              emailObj;
            // 如果最终结果不是字符串，可能数据有问题
            if (typeof email !== "string") {
              email = "";
            }
          } catch (e) {
            // 如果 JSON.parse 失败，说明可能就是字符串
            email = emailData;
          }

          this.userEmail = email;

          if (userInfo.roleKey === "customer_service" || userInfo.roleKey === "admin") {
            // 客服用户
            this.userType = 2;
            this.userEmail = "";
          } else {
            // 登录用户
            this.userType = 1;
            this.userEmail = email;
          }

          // === 用户身份确定后，重新初始化未读消息数 ===
          this.initUnreadMessages();

          // 页面加载时立即获取用户信息
          await this.initChatSystem();
        } catch (parseError) {
          console.error("解析用户信息失败:", parseError);
          // === 解析失败时使用游客身份，复用缓存 ===
          this.setupGuestIdentity();
        }
      } catch (error) {
        console.error("获取用户信息失败:", error);
        // === 出错时使用游客身份，复用缓存 ===
        this.setupGuestIdentity();
      }
    },

    /**
     * 设置游客身份，复用已缓存的email
     */
    setupGuestIdentity() {
      const cachedGuestEmail = sessionStorage.getItem("chatGuestEmail");
      if (cachedGuestEmail && cachedGuestEmail.startsWith("guest_")) {
        // console.log("📋 异常处理时复用已缓存的游客身份:", cachedGuestEmail);
        this.userType = 0;
        this.userEmail = cachedGuestEmail;
      } else {
        this.userType = 0;
        this.userEmail = `guest_${Date.now()}_${Math.random()
          .toString(36)
          .substr(2, 9)}`;
        sessionStorage.setItem("chatGuestEmail", this.userEmail);
        // console.log("🆕 异常处理时生成新游客身份:", this.userEmail);
      }
      // 初始化聊天系统
      this.initChatSystem();
    },

    // 添加订阅消息的方法
    subscribeToPersonalMessages(selfEmail) {
      // console.log("🔗 开始订阅流程，selfEmail:", selfEmail);
      // console.log("🔍 订阅前状态检查:", {
      //   stompClient: !!this.stompClient,
      //   stompConnected: this.stompClient?.connected,
      //   isWebSocketConnected: this.isWebSocketConnected,
      //   connectionStatus: this.connectionStatus,
      // });

      if (!this.stompClient || !this.isWebSocketConnected) {
        console.error("❌ STOMP客户端未连接，无法订阅消息");
        this.connectionStatus = "error";
        this.connectionError = this.$t("chat.unableToSubscribe"); //连接状态异常，无法订阅消息
        this.isWebSocketConnected = false;
        this.showRefreshButton = false; // 连接状态异常通常可以重试解决
        this.$forceUpdate();
        return;
      }

      if (!this.stompClient.connected) {
        console.error("❌ STOMP客户端已断开，无法订阅消息");
        this.connectionStatus = "error";
        this.connectionError = "chat.unableToSubscribe"; //连接已断开，无法订阅消息
        this.isWebSocketConnected = false;
        this.showRefreshButton = false; // 连接断开通常可以重试解决
        this.$forceUpdate();
        return;
      }

      try {
        // console.log("🔗 开始订阅消息频道:", `/sub/queue/user/${selfEmail}`);

        // 订阅个人消息频道
          // console.log("🔗 调用 stompClient.subscribe...");
          // console.log("🔍 订阅目标:", `/sub/queue/user/${selfEmail}`);
          // console.log("🔍 STOMP客户端状态:", this.stompClient?.connected);

        const subscription = this.stompClient.subscribe(
          `/sub/queue/user/${selfEmail}`,
          (message) => {
            // console.log("📨 收到消息，标记连接已验证");
            // 更新最后心跳时间
            this.lastHeartbeatTime = Date.now();

            // === 强制确保连接状态正确 ===
            if (this.connectionStatus !== "connected") {
              // console.log("🔧 收到消息时发现状态不对，强制修正为connected");
              this.connectionStatus = "connected";
              this.isWebSocketConnected = true;
              this.isReconnecting = false;
              this.connectionError = null;
            }

            // === 标记连接已验证 ===
            this.markConnectionVerified();
            // 处理消息
            this.onMessageReceived(message);
          }
        );

        // console.log("🔍 订阅调用完成，subscription:", subscription);
        // console.log("🔍 subscription类型:", typeof subscription);
        // console.log("🔍 subscription.id:", subscription?.id);
        // console.log(
        //   "🔍 subscription是否为有效对象:",
        //   !!subscription && typeof subscription === "object"
        // );

        // === 关键修复：立即设置为连接状态，不等待消息到达 ===
        // console.log("🚀 立即设置连接状态为connected，解决卡顿问题");
        this.connectionStatus = "connected";
        this.isWebSocketConnected = true;
        this.isReconnecting = false;
        this.connectionError = null;
        this.reconnectAttempts = 0;
        this.markConnectionVerified();
        this.$forceUpdate();

        // === 启动活动检测和完成设置 ===
        // console.log("✅ 订阅设置完成，启动活动检测");
        this.startActivityCheck();

        // console.log("🔍 订阅最终状态检查:", {
        //   connectionStatus: this.connectionStatus,
        //   isWebSocketConnected: this.isWebSocketConnected,
        //   isReconnecting: this.isReconnecting,
        //   isConnectionVerified: this.isConnectionVerified,
        //   reconnectAttempts: this.reconnectAttempts,
        // });
      } catch (error) {
        console.error("❌ 订阅消息异常:", error);
        // console.log("🔍 订阅异常详情:", error.message);

        // === 订阅异常立即设置错误状态 ===
        this.connectionStatus = "error";
        this.connectionError = this.$t("chat.conflict"); //连接异常，可能是多窗口冲突，请关闭其他窗口重试
        this.isWebSocketConnected = false;
        this.isReconnecting = false;
        this.showRefreshButton = false; // 多窗口冲突不需要刷新页面，重试即可

        // console.log("🔥 订阅异常，立即设置错误状态");
        this.$forceUpdate();
      }
    },

    // 连接 WebSocket
    async connectWebSocket(selfEmail) {
      // 健壮恢复userEmail
      let email = selfEmail || this.userEmail;
      // 1. 优先从 localStorage 查找
      if (!email) {
        try {
          const emailData = localStorage.getItem("userEmail");
          if (emailData) {
            const emailObj = JSON.parse(emailData);
            email =
              emailObj.email ||
              emailObj.value ||
              emailObj.userEmail ||
              emailObj;
            if (typeof email !== "string") email = "";
          }
        } catch (e) {
          // 解析失败时忽略，继续后续逻辑
          console.warn("[DEBUG] 解析localStorage userEmail失败:", e);
        }
      }
      // 2. 再从 sessionStorage 查找游客邮箱
      if (!email) {
        const guestEmail = sessionStorage.getItem("chatGuestEmail");
        if (guestEmail && guestEmail.startsWith("guest_")) {
          email = guestEmail;
        }
      }
      // 3. 兜底生成游客邮箱
      if (!email) {
        email = `guest_${Date.now()}_${Math.random()
          .toString(36)
          .substr(2, 9)}`;
        sessionStorage.setItem("chatGuestEmail", email);
        console.warn("[DEBUG] 自动生成游客邮箱:", email);
      }
      this.userEmail = email;
      selfEmail = email;
      // console.log("[DEBUG] connectWebSocket called", {
      //   isWebSocketConnected: this.isWebSocketConnected,
      //   isReconnecting: this.isReconnecting,
      //   lastConnectedEmail: this.lastConnectedEmail,
      //   selfEmail,
      //   userEmail: this.userEmail,
      //   connectionStatus: this.connectionStatus,
      // });
      if (!selfEmail) {
        // console.warn("[DEBUG] connectWebSocket: 缺少用户邮箱参数");
        return Promise.reject(new Error("缺少用户邮箱参数"));
      }
      if (this.isWebSocketConnected && this.lastConnectedEmail === selfEmail) {
        // console.log("[DEBUG] connectWebSocket: 已连接，复用");
        return Promise.resolve("already_connected");
      }
      if (this.isReconnecting) {
        // console.log("[DEBUG] connectWebSocket: 正在重连中，跳过");
        return Promise.resolve("reconnecting");
      }

      this.connectionStatus = "connecting";
      this.isReconnecting = true;
      this.connectionError = null;

      // === 新增：设置连接超时检测 ===
      const connectionTimeout = setTimeout(() => {
        if (
          this.connectionStatus === "connecting" &&
          !this.isConnectionVerified
        ) {
          // console.log("连接超时（30秒），强制断开重连");
          // console.log("🔍 超时时状态检查:", {
          //   connectionStatus: this.connectionStatus,
          //   isWebSocketConnected: this.isWebSocketConnected,
          //   isConnectionVerified: this.isConnectionVerified,
          //   stompConnected: this.stompClient?.connected,
          // });
          this.handleConnectionTimeout();
        } else {
          // console.log("连接超时检查：连接已验证或状态已变化，跳过超时处理");
        }
      }, 30000); // 缩短到30秒超时

      try {
        const apiUrl = process.env.VUE_APP_BASE_API;
        let baseUrl=""
          // 将 https 替换为 wss
        if (apiUrl.startsWith("https://")) {
          baseUrl= apiUrl.replace("https://", "wss://");
        }
        if (apiUrl.startsWith("http://")) {
          baseUrl=apiUrl.replace("http://", "ws://");
        }
      
        const wsUrl = `${baseUrl}chat/ws`;

        // console.log(wsUrl,"接地极低等级点击都觉得点击都觉得点击的的的的记得到点击");
        
        // === 彻底释放旧的stompClient和WebSocket对象 ===
        if (this.stompClient) {
          try {
            this.stompClient.disconnect();
            // console.log("[DEBUG] 旧stompClient已disconnect");
          } catch (e) {
            console.warn("[DEBUG] stompClient.disconnect异常", e);
          }
          this.stompClient = null;
        }
        // === 新建连接前详细日志 ===
        // console.log("[DEBUG] 即将新建stompClient:", wsUrl);
        this.stompClient = Stomp.client(wsUrl);
        // console.log("[DEBUG] stompClient对象已创建:", this.stompClient);

        // === 新增：设置WebSocket连接超时 ===
        this.stompClient.webSocketFactory = () => {
          const ws = new WebSocket(wsUrl);
          ws.binaryType = "arraybuffer";

          // 设置WebSocket级别的错误处理
          ws.onerror = (error) => {
            console.error("WebSocket连接错误:", error);
            clearTimeout(connectionTimeout);
            this.handleWebSocketError(error);
          };

          // 监听WebSocket状态变化
          ws.onopen = () => {
            // console.log("WebSocket连接已建立");
          };

          ws.onclose = (event) => {
            // console.log("WebSocket连接已关闭:", event.code, event.reason);
            clearTimeout(connectionTimeout);
            if (!this.isReconnecting) {
              this.handleWebSocketClose(event);
            }
          };

          return ws;
        };

        const headers = {
          email: selfEmail,
          type: this.userType,
        };

        // 修改错误处理
        this.stompClient.onStompError = (frame) => {
          // 只用frame.headers.message判断
          const errorMessage = frame.headers?.message || "";
          console.error("🔴 STOMP 错误:", errorMessage);

          // 只要包含1020就处理
          if (errorMessage.includes("1020")) {
            this.handleConnectionLimitError();
            return;
          }

          // 其他错误可选处理
          this.connectionError = errorMessage || this.$t("chat.abnormal"); //连接异常
          this.connectionStatus = "error";
          this.isWebSocketConnected = false;
          this.isReconnecting = false;
          this.showRefreshButton = true;
          this.$forceUpdate();
        };

        return new Promise((resolve, reject) => {
          this.stompClient.connect(
            headers,
            (frame) => {
              // console.log("🎉 WebSocket Connected:", frame);
              clearTimeout(connectionTimeout);
              this.isWebSocketConnected = true;
              this.connectionStatus = "connecting"; // 保持connecting状态，直到订阅完成
              this.reconnectAttempts = 0;
              this.isReconnecting = false;
              this.connectionError = null;
              // console.log("🔗 开始订阅个人消息...");
              this.subscribeToPersonalMessages(selfEmail);
              this.startHeartbeat();
              // === 注意：不在这里启动验证，而是在订阅成功后 ===
              // console.log("⚡ 连接成功，等待订阅完成后验证");

              // === 设置订阅超时检查（缩短到5秒） ===
              setTimeout(() => {
                if (
                  this.connectionStatus === "connecting" &&
                  !this.isConnectionVerified
                ) {
                  console.warn(
                    "⚠️ 连接成功但5秒内未完成订阅验证，可能是多窗口冲突或订阅失败"
                  );
                  // console.log("🔍 订阅超时时的状态:", {
                  //   connectionStatus: this.connectionStatus,
                  //   isWebSocketConnected: this.isWebSocketConnected,
                  //   isConnectionVerified: this.isConnectionVerified,
                  //   stompConnected: this.stompClient?.connected,
                  // });
                  this.connectionStatus = "error";
                  this.connectionError = this.$t("chat.conflict"); //订阅失败，可能是多窗口冲突，请关闭其他窗口重试
                  this.isWebSocketConnected = false;
                  this.isReconnecting = false;
                  this.showRefreshButton = true;
                  this.$forceUpdate();
                }
              }, 5000); // 增加到5秒，给订阅更多时间

              resolve(frame);
            },
            (error) => {
              console.error("WebSocket Error:", error);
              clearTimeout(connectionTimeout);

              // === 新增：处理特殊的握手错误 ===
              if (this.isHandshakeError(error)) {
                this.handleHandshakeError(error);
                reject(error);
                return;
              }

              // 检查是否是连接数上限错误
              if (this.isConnectionLimitError(error.headers.message)) {
                this.connectionError = error.headers.message;
                this.connectionStatus = "error"; // 立即设置为错误状态
                this.isReconnecting = false;
                this.handleConnectionLimitError();
                reject(error);
                return;
              }

              // === 简化连接错误消息，避免技术细节 ===
              if (error.headers.message.includes("503")) {
                this.connectionError = this.$t("chat.server500"); // "服务器暂时不可用，请稍后重试";
              } else if (error.headers.message.includes("handshake")) {
                this.connectionError = this.$t("chat.networkAnomaly"); //网络连接异常，正在重试
              } else {
                this.connectionError = this.$t(`chat.abnormal`); //连接异常，正在重试
              }
              this.isReconnecting = false;
              this.handleDisconnect();
              reject(error);
            }
          );
          // 设置 STOMP 心跳
          this.stompClient.heartbeat.outgoing = 30000; // 30秒发送一次心跳
          this.stompClient.heartbeat.incoming = 30000; // 30秒接收一次心跳
        });
      } catch (error) {
        console.error("初始化 WebSocket 失败:", error);
        clearTimeout(connectionTimeout);
        this.connectionError = this.$t("chat.initializationFailed"); //初始化失败，请刷新页面重试
        this.isReconnecting = false;
        this.handleDisconnect();
        return Promise.reject(error);
      }
    },
    // 添加新重连最多重连5次
    handleDisconnect() {
      // console.log("[DEBUG] handleDisconnect", {
      //   isWebSocketConnected: this.isWebSocketConnected,
      //   isReconnecting: this.isReconnecting,
      //   reconnectAttempts: this.reconnectAttempts,
      //   connectionStatus: this.connectionStatus,
      // });
      if (this.isReconnecting) return;

      // console.log("🔌 处理连接断开...");

      // === 移除自动保持对话框打开的逻辑，只有用户主动打开才保持打开 ===
      // if (this.isChatOpen) {
      //   console.log("📱 聊天窗口已打开，保持打开状态");
      //   // 不改变 isChatOpen 和 isMinimized 状态
      // }

      this.isWebSocketConnected = false;
      this.connectionStatus = "error";
      this.isReconnecting = true;
      // === 新增：清除连接验证定时器 ===
      this.clearConnectionVerification();

      // 清除之前的重连定时器
      if (this.reconnectTimer) {
        clearTimeout(this.reconnectTimer);
      }

      // ===检查是否是连接数上限错误 ===
      if (this.isConnectionLimitError(this.connectionError)) {
        // 如果是连接数上限错误，直接调用专门的处理方法
        this.handleConnectionLimitError();
        return;
      }

      // ===统一处理其他类型的连接错误 ===
      if (this.handleConnectionError(this.connectionError)) {
        return;
      }
      // === 新增结束 ===

      // 使用现有的重连逻辑
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        this.reconnectAttempts++;
            // console.log(
            //   `🔄 尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
            // );

        // === 在自动重连期间，如果聊天窗口已经打开，才显示连接中状态 ===
        if (this.isChatOpen) {
          this.connectionStatus = "connecting";
        }

        // === 移除自动重连提示：后台静默处理，不打扰用户 ===
        // console.log(
        //   `🔄 自动重连中 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
        // );

        // 只记录日志，不显示toast提示

        this.reconnectTimer = setTimeout(() => {
          this.isReconnecting = false; // 兜底重置，确保重连能进入
          if (!this.isWebSocketConnected) {
            const connectionPromise = this.connectWebSocket(this.userEmail);
            if (
              connectionPromise &&
              typeof connectionPromise.catch === "function"
            ) {
              connectionPromise.catch((error) => {
                console.error("[DEBUG] 自动重连失败:", error);
              });
            }
          }
        }, this.reconnectInterval);
      } else {
        // console.log("❌ 达到最大重连次数，停止重连");

        // === 只在达到最大重连次数时才提示用户，因为需要用户手动刷新 ===
        // this.$message.error(this.$t("chat.connectionFailed") || "连接异常，请刷新页面重试");

        this.isReconnecting = false;
        this.showRefreshButton = true;
      }
    },
    // 处理网络状态变化
    handleNetworkChange() {
      this.networkStatus = navigator.onLine ? "online" : "offline";
      // console.log("[DEBUG] handleNetworkChange", {
      //   online: navigator.onLine,
      //   isWebSocketConnected: this.isWebSocketConnected,
      //   isReconnecting: this.isReconnecting,
      //   connectionStatus: this.connectionStatus,
      // });
      if (navigator.onLine) {
        // === 强制重置状态，兜底 ===
        location.reload(); // 重新加载当前页面
        this.isChatOpen = false;
        this.isMinimized = false;
        this.isLoadingHistory = false;
        this.isLoading = false;
        this.isWebSocketConnected = false;
        this.isReconnecting = false;
        // if (!this.isWebSocketConnected) {
        //   console.log('[DEBUG] 网络恢复，触发 handleDisconnect');
        //   this.handleDisconnect();
        // }
      }
    },
    // 开始活动检测
    startActivityCheck() {
      this.activityCheckInterval = setInterval(() => {
        const now = Date.now();
        const inactiveTime = now - this.lastActivityTime;

        // 如果用户超过5分钟没有活动，且连接断开，则尝试重连
        if (inactiveTime > 5 * 60 * 1000 && !this.isWebSocketConnected) {
          this.handleDisconnect();
        }
      }, 60000); // 每分钟检查一次
    },

    // 更新最后活动时间
    updateLastActivityTime() {
      this.lastActivityTime = Date.now();
    },

    // 页面关闭时的处理
    handleBeforeUnload() {
      this.disconnectWebSocket();
    },
    //只能输入300个字符
    handleInputMessage() {
      if (this.inputMessage.length > this.maxMessageLength) {
        this.inputMessage = this.inputMessage.slice(0, this.maxMessageLength);
      }
    },

    /**
     * 处理Enter键事件
     * @param {KeyboardEvent} event - 键盘事件对象
     */
    handleEnterKey(event) {
      // 检查是否按下了Enter键（不包含Shift+Enter）
      if (event.key === "Enter" && !event.shiftKey) {
        // 阻止默认的换行行为
        event.preventDefault();

        // 检查是否有内容可以发送
        if (this.inputMessage.trim() && this.connectionStatus === "connected") {
          this.sendMessage();
        }
      }
      // 如果是Shift+Enter，允许默认行为（换行）
      // 注意：当前使用的是input标签，不支持多行，如果需要支持Shift+Enter换行，
      // 应该将input改为textarea
    },
    // 发送消息
    sendMessage() {





      // 网络断开时阻止发送消息并提示
      if (this.networkStatus !== "online") {
        this.$message({
          message:
            this.$t("chat.networkError") || "网络连接已断开，无法发送消息",
          type: "error",
          showClose: true,
        });
        return;
      }
      // === 游客且客服离线时提示 ===
      console.log("客服状态",this.customerIsOnline,`用户身份`,this.userType,`用户邮箱`,this.userEmail);
      if (this.userType === 0 && this.customerIsOnline === false) {
        this.$message({
          message:
            this.$t("chat.customerServiceOffline") ||
            "客服离线，请登录账号发送留言消息",
          type: "warning",
          showClose: true,
        });
        return;
      }
      if (!this.inputMessage.trim()) {
        this.$message({
          message: this.$t("chat.sendMessageEmpty") || "发送消息不能为空",
          type: "warning",
          showClose: true,
        });
        return;
      }
      if (this.inputMessage.length > this.maxMessageLength) {
        this.$message.warning(
          this.$t("chat.contentMax") ||
            "超出发送内容大小限制，请删除部分内容(300字以内)"
        ); //超出发送内容大小限制，请删除部分内容 300个字符
        return;
      }

      // 检查 WebSocket 连接状态
      if (!this.stompClient || !this.stompClient.connected) {
        // console.log("发送消息时连接已断开，尝试重连...");
        // === 移除重连提示：会自动重连，不需要打扰用户 ===
        this.handleDisconnect();
        return;
      }

      const messageText = this.inputMessage.trim();

      // === 立即本地显示机制 ===
      const timestamp = Date.now();
      const random = Math.random().toString(36).substr(2, 9);
      const localMessageId = `local_${timestamp}_${random}`;

      // 创建本地消息对象
      const localMessage = {
        id: localMessageId,
        content: messageText,
        type: 1,
        sendEmail: this.userEmail,
        sendTime: new Date().toISOString(),
        roomId: this.roomId,
        isLocalMessage: true, // 标记为本地消息
      };

      // 立即添加到本地聊天记录
      // console.log("📤 立即显示本地消息:", localMessage);
      this.addMessageToChat(localMessage, true);

      try {
        const message = {
          content: messageText,
          type: 1, // 1 表示文字消息
          email: this.receivingEmail,
          receiveUserType: 2,
          roomId: this.roomId,
        };

        // 发送消息到服务器
        this.stompClient.send(
          "/point/send/message/to/customer",
          {},
          JSON.stringify(message)
        );

        this.inputMessage = "";
      } catch (error) {
        console.error("发送消息失败:", error);
        // === 优化发送失败提示：只在明确需要用户重试时提示 ===
        this.$message.error(this.$t("chat.failInSend") || "发送失败，请重试");
      }
    },

    // 断开 WebSocket 连接
    disconnectWebSocket() {
      this.stopHeartbeat();
      // === 新增：清除连接验证定时器 ===
      this.clearConnectionVerification();
      if (this.stompClient) {
        try {
          // 取消所有订阅
          if (this.stompClient.subscriptions) {
            Object.keys(this.stompClient.subscriptions).forEach((id) => {
              this.stompClient.unsubscribe(id);
            });
          }

          // 断开连接
          this.stompClient.deactivate();
          this.isWebSocketConnected = false;
          this.connectionStatus = "disconnected";
          this.reconnectAttempts = 0;
          this.isReconnecting = false;
        } catch (error) {
          console.error("断开 WebSocket 连接失败:", error);
        }
      }
    },
    // 处理页面可见性变化
    // 处理页面可见性变化
    handleVisibilityChange() {
      // 当页面变为可见且聊天窗口已打开时，标记消息为已读
      // if (!document.hidden && this.isChatOpen && this.roomId) {
      //   this.markMessagesAsRead();
      // }

      // 添加新的重连逻辑
      if (!document.hidden) {
        // 页面变为可见时，检查连接状态
        if (!this.isWebSocketConnected) {
          this.handleDisconnect();
        }
        // 更新最后活动时间
        this.updateLastActivityTime();
      }
    },

    // 修改标记消息为已读的方法
    async markMessagesAsRead() {
      if (!this.roomId || !this.userEmail) {
        console.log("缺少必要参数，跳过标记已读");
        return;
      }

      try {
        const data = {
          roomId: this.roomId,
          userType: this.userType,
          email: this.userEmail,
        };

        // 添加重试机制
        let retryCount = 0;
        const maxRetries = 3;
        let success = false;

        while (retryCount < maxRetries && !success) {
          try {
            const response = await getReadMessage(data);
            if (response && response.code === 200) {
              // console.log("消息已标记为已读");
              // === 使用localStorage管理未读消息数 ===
              this.updateUnreadMessages(0);
              // 更新所有用户消息的已读状态
              this.messages.forEach((msg) => {
                if (msg.type === "user") {
                  msg.isRead = true;
                }
              });
              success = true;
            } else {
              console.warn(
                `标记消息已读失败 (尝试 ${retryCount + 1}/${maxRetries}):`,
                response
              );
              retryCount++;
              if (retryCount < maxRetries) {
                // 等待一段时间后重试
                await new Promise((resolve) =>
                  setTimeout(resolve, 1000 * retryCount)
                );
              }
            }
          } catch (error) {
            // console.error(
            //   `标记消息已读出错 (尝试 ${retryCount + 1}/${maxRetries}):`,
            //   error
            // );
            retryCount++;
            if (retryCount < maxRetries) {
              // 等待一段时间后重试
              await new Promise((resolve) =>
                setTimeout(resolve, 1000 * retryCount)
              );
            }
          }
        }

        if (!success) {
          console.warn("标记消息已读失败，已达到最大重试次数");
          // 即使标记已读失败，也更新本地状态
          this.updateUnreadMessages(0);
          this.messages.forEach((msg) => {
            if (msg.type === "user") {
              msg.isRead = true;
            }
          });
        }
      } catch (error) {
        console.error("标记消息已读出错:", error);
        // 即使出错，也更新本地状态
        this.updateUnreadMessages(0);
        this.messages.forEach((msg) => {
          if (msg.type === "user") {
            msg.isRead = true;
          }
        });
      }
    },

    // 加载历史消息
    async loadHistoryMessages() {
      if (this.isLoadingHistory || !this.roomId) return;
      this.isLoadingHistory = true;
      try {
        const response = await getHistory7({
          roomId: this.roomId,
          userType: this.userType,
          email: this.userEmail,
        });
        if (response?.code === 200 && Array.isArray(response.data)) {
          const historyMessages = this.formatHistoryMessages(response.data);
          if (historyMessages.length > 0) {
            this.messages = historyMessages.sort(
              (a, b) => new Date(a.time) - new Date(b.time)
            );
            // 不自动弹窗，只滚动
            await this.$nextTick();
            setTimeout(() => {
              this.scrollToBottom(true);
            }, 100);
          } else {
            this.messages = [
              {
                type: "system",
                text: this.$t("chat.noHistory") || "暂无历史消息",
                isSystemHint: true,
                time: new Date().toISOString(),
              },
            ];
          }
        } else {
          this.messages = [
            {
              type: "system",
              text: this.$t("chat.noHistory") || "暂无历史消息",
              isSystemHint: true,
              time: new Date().toISOString(),
            },
          ];
        }
      } catch (error) {
        console.error("加载历史消息失败:", error);
        this.$message.error(
          this.$t("chat.loadHistoryFailed") || "加载历史消息失败"
        );
        this.messages = [
          {
            type: "system",
            text: "加载历史消息失败，请重试",
            isSystemHint: true,
            time: new Date().toISOString(),
            isError: true,
          },
        ];
      } finally {
        this.isLoadingHistory = false;
      }
    },

    // === 简化的历史消息加载逻辑 ===
    async loadMoreHistory() {
      if (this.isLoadingHistory || !this.roomId) return;
      this.isLoadingHistory = true;
      try {
        // === 记录当前第一个可见消息的DOM和offsetTop ===
        let prevFirstMsgId = null;
        let prevFirstMsgOffset = 0;
        const chatBody = this.$refs.chatBody;
        if (chatBody && chatBody.children && chatBody.children.length > 0) {
          for (let i = 0; i < chatBody.children.length; i++) {
            const el = chatBody.children[i];
            if (el.classList.contains("chat-message")) {
              prevFirstMsgId = this.messages[i]?.id;
              prevFirstMsgOffset = el.offsetTop;
              break;
            }
          }
        }
        const oldestMessage = this.messages.find(
          (msg) => !msg.isSystemHint && !msg.isLoading
        );
        const response = await getHistory7({
          roomId: this.roomId,
          userType: this.userType,
          email: this.userEmail,
          id: oldestMessage?.id,
        });
        if (
          response &&
          response.code === 200 &&
          response.data &&
          Array.isArray(response.data) &&
          response.data.length > 0
        ) {
          const historyMessages = this.formatHistoryMessages(response.data);
          if (historyMessages.length > 0) {
            const existingIds = new Set(
              this.messages.map((msg) => msg.id).filter((id) => id)
            );
            const newMessages = historyMessages.filter(
              (msg) => !existingIds.has(msg.id)
            );
            if (newMessages.length > 0) {
              this.messages = [...newMessages, ...this.messages];
              this.$nextTick(() => {
                if (chatBody && prevFirstMsgId) {
                  let newIndex = this.messages.findIndex(
                    (msg) => msg.id === prevFirstMsgId
                  );
                  if (newIndex !== -1 && chatBody.children[newIndex]) {
                    const newOffset = chatBody.children[newIndex].offsetTop;
                    chatBody.scrollTop = newOffset - prevFirstMsgOffset;
                  }
                }
              });
            } else {
              this.hasMoreHistory = false;
              this.messages.unshift({
                type: "system",
                text: this.$t("chat.noMoreHistory") || "没有更多历史消息了",
                isSystemHint: true,
                time: new Date().toISOString(),
              });
            }
          } else {
            this.hasMoreHistory = false;
            this.messages.unshift({
              type: "system",
              text: this.$t("chat.noMoreHistory") || "没有更多历史消息了",
              isSystemHint: true,
              time: new Date().toISOString(),
            });
          }
        } else {
          this.hasMoreHistory = false;
          this.messages.unshift({
            type: "system",
            text: this.$t("chat.noMoreHistory") || "没有更多历史消息了",
            isSystemHint: true,
            time: new Date().toISOString(),
          });
        }
      } catch (error) {
        this.$message.error(
          this.$t("chat.loadHistoryFailed") || "加载历史消息失败，请重试"
        );
      } finally {
        this.isLoadingHistory = false;
      }
    },

    // === 简化的历史消息格式化函数 ===
    formatHistoryMessages(messagesData) {
      if (
        !messagesData ||
        !Array.isArray(messagesData) ||
        messagesData.length === 0
      ) {
        return [];
      }

      const formattedMessages = messagesData
        .filter((msg) => {
          // 简单过滤：必须有ID和内容（图片消息除外）
          return msg && msg.id && (msg.content || msg.type === 2);
        })
        .map((msg) => ({
          type: msg.isSelf === 1 ? "user" : "system",
          text: msg.content || "",
          isImage: msg.type === 2,
          imageUrl: msg.type === 2 ? msg.content : null,
          time:
            typeof msg.createTime === "string"
              ? msg.createTime
              : msg.createTime
              ? new Date(msg.createTime).toISOString()
              : new Date().toISOString(),
          id: msg.id,
          roomId: msg.roomId,
          sender: msg.sendEmail,
          isHistory: true,
          isRead: true,
        }))
        .sort((a, b) => {
          // === 使用与客服系统相同的排序逻辑：ID + 时间 ===
          // 1. 首先按ID排序（如果都有ID）
          if (a.id && b.id) {
            const idDiff = parseInt(a.id) - parseInt(b.id);
            if (idDiff !== 0) return idDiff;
          }

          // 2. 然后按时间排序
          const aTime = new Date(a.time).getTime();
          const bTime = new Date(b.time).getTime();
          return aTime - bTime;
        });

      console.log("✅ 格式化历史消息完成，数量:", formattedMessages.length);
      return formattedMessages;
    },

    // 修改 fetchUserid 方法，添加 token 检查
    async fetchUserid(params) {
      try {
        

        const res = await getUserid(params);
        if (res && res.code == 200) {
          // console.log("获取用户ID成功:", res);
          this.receivingEmail = res.data.userEmail;
          this.roomId = res.data.id;
          this.customerIsOnline = res.data.customerIsOnline;
          localStorage.setItem(`customerIsOnline`,JSON.stringify(this.customerIsOnline))

          return res.data;
        } else {
          console.warn("获取用户ID未返回有效数据");
          return null;
        }
      } catch (error) {
        console.error("获取用户ID失败:", error);
        throw error;
      }
    },

    // 添加新方法：更新消息已读状态
    updateMessageReadStatus(messageIds) {
      if (!Array.isArray(messageIds) || messageIds.length === 0) {
        // 如果没有具体的消息ID，就更新所有用户消息为已读
        this.messages.forEach((msg) => {
          if (msg.type === "user") {
            msg.isRead = true;
          }
        });
      } else {
        // 更新指定ID的消息为已读
        this.messages.forEach((msg) => {
          if (msg.id && messageIds.includes(msg.id)) {
            msg.isRead = true;
          }
        });
      }
    },

    // 接收消息处理
    onMessageReceived(message) {
      try {
        const data = JSON.parse(message.body);
        // console.log("收到新消息:", data);

        // === 新增：标记连接已验证 ===
        this.markConnectionVerified();

        // === 新增：过滤系统验证消息，不显示在对话框中 ===
        if (
          data.type === 99 ||
          (data.content &&
            (data.content.includes("__SYSTEM_PING__") ||
              data.content.includes("connection_test_ping") ||
              data.content.includes("SYSTEM_PING")))
        ) {
          // console.log("收到系统验证消息，跳过显示");
          return;
        }

        // === 新增：处理回环消息 ===
        this.handleIncomingMessage(data);
      } catch (error) {
        console.error("处理消息失败:", error);
      }
    },

    /**
     * 处理接收到的消息（包括回环处理）
     * @param {Object} data - 消息数据
     */
    handleIncomingMessage(data) {
      // 判断是否是自己发送的消息（回环消息）
      const isSentByMe = data.sendEmail === this.userEmail;

      // console.log(`📨 处理消息: ${isSentByMe ? "自己发送的" : "对方发送的"}`, {
      //   sendEmail: data.sendEmail,
      //   userEmail: this.userEmail,
      //   messageId: data.id,
      // });

      // === 创建标准化的消息数据对象，与客服页面保持一致 ===
      const messageData = {
        id: data.id,
        sender: data.sendEmail,
        content: data.content,
        // === 修复：保持原始字段，让createMessageObject方法处理时间格式 ===
        createTime: data.createTime, // 后端返回的时间，格式如"2025-06-12T03:23:52"
        sendTime: data.sendTime, // 发送时的时间
        type: data.type,
        roomId: data.roomId,
        sendEmail: data.sendEmail,
        isImage: data.type === 2,
        clientReadNum: data.clientReadNum,
        isLocalMessage: data.isLocalMessage || false,
      };

      // === 服务器消息确认机制 ===
      if (isSentByMe) {
        // 查找对应的本地消息并更新
        const localMessageIndex = this.messages.findIndex((msg) => {
          if (!msg.isLocalMessage) return false;

          // 检查内容是否相同
          const contentMatch = msg.text === messageData.content;

          // === 修复：兼容不同的时间字段格式 ===
          const msgTime = new Date(msg.time);
          // 从messageData中获取时间，优先使用createTime
          const serverTime = messageData.createTime || messageData.sendTime;
          if (!serverTime) return contentMatch; // 如果没有时间信息，只匹配内容

          const dataTime = new Date(serverTime);
          const timeDiff = Math.abs(dataTime - msgTime);
          const timeMatch = timeDiff < 30000; // 30秒内

          return contentMatch && timeMatch;
        });

        if (localMessageIndex !== -1) {
          // console.log("🔄 找到对应本地消息，更新为服务器消息:", {
          //   localId: this.messages[localMessageIndex].id,
          //   serverId: messageData.id,
          // });

          // 更新本地消息为服务器消息，与客服页面保持一致
          // === 修复：使用createMessageObject确保时间格式正确 ===
          const serverMessageObj = this.createMessageObject(messageData);
          this.$set(this.messages, localMessageIndex, {
            ...this.messages[localMessageIndex],
            id: messageData.id,
            time: serverMessageObj.time, // 使用格式化后的时间
            isLocalMessage: false,
          });

          return; // 不需要添加新消息
        }
      }

      // 检查是否已经存在相同的消息（防止重复）
      if (this.checkDuplicateMessage(messageData)) {
        // console.log("⚠️ 发现重复消息，跳过添加");
        return;
      }

      // 添加消息到聊天列表
      this.addMessageToChat(messageData, isSentByMe);

      // === 新增未读数逻辑 ===
      if (!isSentByMe) {
        // 聊天框打开且在底部，自动已读
        if (this.isChatOpen && this.isAtBottom()) {
          this.updateUnreadMessages(0);
          // 可选：自动标记已读
          // this.markMessagesAsRead();
        } else {
          // 聊天框未打开或不在底部，显示未读数
          if (data.clientReadNum !== undefined) {
            this.updateUnreadMessages(data.clientReadNum);
          } else {
            this.updateUnreadMessages(this.unreadMessages + 1);
          }
          // 显示消息通知
          const messageObj = this.createMessageObject(data);
          this.showNotification(messageObj);
        }
      }
    },

    /**
     * 检查是否存在重复消息
     * === 修复：参考客服页面，只检查回环消息的重复，避免误判对方快速发送的相同消息 ===
     * @param {Object} data - 消息数据
     * @returns {boolean} 是否重复
     */
    checkDuplicateMessage(data) {
      const timeValue = data.time || data.createTime || data.sendTime;
      if (!timeValue) return false;

      const messageContent = data.content;
      const sendEmail = data.sendEmail;
      const messageId = data.id;

      // === 与客服页面保持一致：如果有相同ID直接判定为重复 ===
      if (messageId && this.messages.some((msg) => msg.id === messageId)) {
        // console.log("🔍 发现相同ID的消息，判定为重复:", messageId);
        return true;
      }

      // === 关键修复：只检查自己发送的消息的重复（回环消息） ===
      // 这样可以避免误判对方快速发送的相同内容消息
      const isSentByMe = sendEmail === this.userEmail;
      if (!isSentByMe) {
        // 对方发送的消息不做重复检查，让其正常显示
        return false;
      }

      // === 只检查自己发送的消息是否重复（回环消息处理） ===
      const thirtySecondsAgo = Date.now() - 30 * 1000;
      const serverMsgTime = new Date(timeValue).getTime();

      return this.messages.some((msg) => {
        // 跳过本地消息的检查，因为本地消息会被服务器消息替换
        if (msg.isLocalMessage) return false;

        // 只检查自己发送的消息
        if (msg.type !== "user" || msg.text !== messageContent) return false;

        const msgTime = new Date(msg.time).getTime();

        // 检查时间差是否在合理范围内（30秒内且内容完全匹配）
        const timeDiff = Math.abs(msgTime - serverMsgTime);
        const isRecent = msgTime > thirtySecondsAgo;
        const isTimeClose = timeDiff < 30000; // 30秒内

        if (isRecent && isTimeClose) {
          // console.log("🔍 发现重复的回环消息:", {
          //   existingTime: msg.time,
          //   newTime: timeValue,
          //   timeDiff: timeDiff,
          //   content: messageContent.substring(0, 50),
          // });
          return true;
        }

        return false;
      });
    },

    /**
     * 创建消息对象
     * @param {Object} data - 原始消息数据
     * @returns {Object} 格式化的消息对象
     */
    createMessageObject(data) {
      // 统一时间处理逻辑，确保时间格式正确
      let messageTime;
      if (data.sendTime) {
        // 如果有sendTime，直接使用（快速发送消息的情况）
        messageTime =
          typeof data.sendTime === "string"
            ? data.sendTime
            : new Date(data.sendTime).toISOString();
      } else if (data.createTime) {
        // 如果有createTime，使用createTime（服务器返回消息的情况）
        messageTime =
          typeof data.createTime === "string"
            ? data.createTime
            : new Date(data.createTime).toISOString();
      } else {
        // 兜底：使用当前时间
        messageTime = new Date().toISOString();
      }

      return {
        type: data.sendEmail === this.userEmail ? "user" : "system",
        text: data.content,
        isImage: data.type === 2,
        imageUrl: data.type === 2 ? data.content : null, // 图片消息直接使用content作为imageUrl
        time: messageTime,
        id: data.id,
        roomId: data.roomId,
        sender: data.sendEmail,
        isRead: false,
        isLocalMessage: data.isLocalMessage || false, // 保留本地消息标记
      };
    },

    /**
     * 添加消息到聊天列表
     * @param {Object} data - 消息数据
     * @param {boolean} isSentByUser - 是否为用户主动发送
     */
    addMessageToChat(data, isSentByUser = false) {
      const messageObj = this.createMessageObject(data);
      this.messages.push(messageObj);

      this.$nextTick(() => {
        if (isSentByUser || data.isNewMessage) {
          // 自己发消息/图片，始终滚动到底部
          this.scrollToBottom(true, "new");
          setTimeout(() => this.scrollToBottom(true, "new"), 100);
          this.userViewHistory = false;
        } else if (!this.userViewHistory) {
          // 对方新消息，只有用户没在看历史时才滚动
          this.scrollToBottom(false, "new");
          setTimeout(() => this.scrollToBottom(false, "new"), 100);
        }
        // 用户在翻历史消息时，不滚动
      });
    },

    // 显示消息通知
    showNotification(message) {
      if (!("Notification" in window)) {
        return;
      }

      // 检查通知权限
      if (Notification.permission === "granted") {
        this.createNotification(message);
      } else if (Notification.permission !== "denied") {
        // 请求权限
        Notification.requestPermission().then((permission) => {
          if (permission === "granted") {
            this.createNotification(message);
          }
        });
      }
    },
    // 创建通知
    createNotification(message) {
      const notification = new Notification(
        this.$t("chat.newMessage") || "新消息",
        {
          body: message.isImage
            ? `[ ${this.$t("chat.pictureMessage")}]` || "[图片消息]"
            : message.text,
          icon: "/path/to/notification-icon.png", // 添加适当的图标
        }
      );

      notification.onclick = () => {
        // 点击通知时打开聊天窗口
        window.focus();
        this.openChat(message.roomId);
      };
    },

    // 打开聊天窗口
    async openChat(roomId) {
      this.isChatOpen = true;
      this.isMinimized = false;

      if (roomId) {
        this.currentContactId = roomId;
        this.messages = this.cachedMessages[roomId] || [];
        this.markMessagesAsRead(roomId);

        // 等待 DOM 更新后滚动到底部
        await this.$nextTick();
        // console.log("[SCROLL] openChat: 打开对话触发滚动");
        this.scrollToBottom(true, "new");
      }
    },

    // 打开聊天框
    async toggleChat() {
      // console.log("🎯 toggleChat被调用, 当前状态:", {
      //   isChatOpen: this.isChatOpen,
      //   userEmail: this.userEmail,
      //   connectionStatus: this.connectionStatus,
      //   isWebSocketConnected: this.isWebSocketConnected,
      // });
      this.fetchUserid({ email: this.userEmail })
      console.log("请求客服状态",this.userEmail);
      
      const wasOpen = this.isChatOpen;
      this.isChatOpen = !this.isChatOpen;

      // 1. 判别身份
      const userInfo = JSON.parse(localStorage.getItem("jurisdiction") || "{}");

      if (
        userInfo.roleKey === "customer_service" ||
        userInfo.roleKey === "admin"
      ) {
        // 客服用户 跳转到客服页面
        this.userType = 2;
        const lang = this.$i18n.locale;
        this.$router.push(`/${lang}/customerService`);
        return;
      }

      if (!wasOpen && this.isChatOpen) {
        // 只有弹出聊天框且当前在底部时才请求已读
        this.$nextTick(() => {
          if (this.isAtBottom()) {
            this.markMessagesAsRead();
          }
        });
      }

      if (this.isChatOpen) {
        try {
          // === 确保用户身份已确定，但避免重复初始化 ===
          if (!this.userEmail) {
            // console.log("🔧 用户身份未确定，需要初始化");
            await this.determineUserType();
          } else {
            // console.log("✅ 用户身份已确定:", this.userEmail);
          }

          // === 检查是否需要建立连接 ===
          if (
            !this.isWebSocketConnected ||
            this.connectionStatus === "disconnected" ||
            this.connectionStatus === "error"
          ) {
            // console.log("🔄 需要重新连接WebSocket");
            await this.connectWebSocket(this.userEmail);
          } else if (
            this.connectionStatus === "connected" &&
            this.isWebSocketConnected &&
            this.stompClient?.connected
          ) {
            // 如果已经连接成功，直接标记验证成功
            // console.log("✅ 连接状态良好，直接标记验证成功");
            this.markConnectionVerified();
          } else {
            // 如果状态不明确，启动验证监控
            // console.log("🔍 连接状态不明确，启动验证监控");
            this.startConnectionVerification();
          }

          // === 修复：无论消息列表是否为空，都需要正确处理滚动 ===
          if (this.messages.length === 0) {
            await this.loadHistoryMessages();
          } else {
            // 如果已有消息，确保滚动到底部
            await this.$nextTick();
            setTimeout(() => {
              this.scrollToBottom(true, "new");
            }, 100);
          }

          // === 新增：额外的滚动保障机制，确保多窗口场景下也能正确滚动 ===
          // 无论走哪个分支，都在更长的延时后再次确保滚动到底部
          setTimeout(() => {
            if (this.isChatOpen && this.$refs.chatBody) {
              // console.log("🔄 多窗口滚动保障：确保滚动到底部");
              this.scrollToBottom(true, "new");
            }
          }, 300);
        } catch (error) {
          console.error("初始化聊天失败:", error);
          // === 简化初始化失败提示 ===
          // this.$message.error("连接失败，请重试");
        }
      } else {
        // === 新增：关闭聊天时清除连接验证 ===
        this.clearConnectionVerification();
      }
    },

    minimizeChat() {
      this.isChatOpen = false;
      this.isMinimized = true;
    },

    closeChat() {
      this.isChatOpen = false;
      this.isMinimized = true;
      //   this.disconnectWebSocket(); // 关闭 WebSocket 连接
    },

    // 添加系统消息
    addSystemMessage(text) {
      this.messages.push({
        type: "system",
        text: text,
        isImage: false,
        time: new Date().toISOString(),
      });
      // 不做任何滚动
    },

    // 自动回复 (仅在无法连接服务器时使用)
    handleAutoResponse(message) {
      setTimeout(() => {
        let response =
          this.$t("chat.beSorry") ||
          "抱歉，我暂时无法回答这个问题。请排队等待人工客服或提交工单。";

        // 检查是否匹配自动回复关键词
        for (const [keyword, reply] of Object.entries(this.autoResponses)) {
          if (message.toLowerCase().includes(keyword.toLowerCase())) {
            response = reply;
            break;
          }
        }

        // 添加系统回复
        this.messages.push({
          type: "system",
          text: response,
          isImage: false,
          time: new Date().toISOString(),
        });

        if (!this.isChatOpen) {
          this.unreadMessages++;
        }
        // 不做任何滚动
      }, 1000);
    },

    // === 移除滚动自动加载功能，简化逻辑 ===
    // handleChatScroll() {
    //   // 不再自动加载历史消息，只有用户主动点击才加载
    // },

    // <!-- 新增加载完成事件 -->
    handleImageLoad(msg) {
      if (msg && msg.isHistory) {
        // console.log("[SCROLL] handleImageLoad: 历史消息图片加载，不滚动");
        return;
      }
      // console.log("[SCROLL] handleImageLoad: 新消息图片加载触发滚动");
      this.scrollToBottom(true, "new");
    },
    //滚动到底部
    scrollToBottom(force = false, reason = "new") {
      if (!this.$refs.chatBody) {
        console.warn("[DEBUG] scrollToBottom: chatBody不存在");
        return;
      }
      const chatBody = this.$refs.chatBody;
      const before = chatBody.scrollTop;
      const scrollHeight = chatBody.scrollHeight;
      const clientHeight = chatBody.clientHeight;
      // console.log(
      //   `[DEBUG] scrollToBottom called. force=${force}, reason=${reason}, before=${before}, scrollHeight=${scrollHeight}, clientHeight=${clientHeight}`
      // );
      const performScroll = () => {
        chatBody.scrollTop = chatBody.scrollHeight;
        // console.log(`[DEBUG] performScroll: after=${chatBody.scrollTop}`);
      };
      this.$nextTick(() => {
        this.$nextTick(() => {
          performScroll();
          if (force) {
            setTimeout(() => {
              if (this.$refs.chatBody) {
                performScroll();
              }
            }, 50);
          }
        });
      });
    },

    formatTime(date) {
      if (!date) return "";

      try {
        let timeStr = "";

        if (typeof date === "string") {
          // 后端返回的时间字符串，格式如 "2025-06-11T03:10:09"
          timeStr = date;
        } else if (date instanceof Date) {
          // 本地时间对象，转换为ISO字符串
          timeStr = date.toISOString();
        } else {
          return String(date);
        }

        // 处理后端时间：直接去掉T，提取年月日时分
        if (timeStr.includes("T")) {
          // 分离日期和时间部分
          const [datePart, timePart] = timeStr.split("T");
          if (datePart && timePart) {
            // 提取时分（去掉秒和毫秒）
            const timeOnly = timePart.split(":").slice(0, 2).join(":");

            // === 使用与客服页面完全相同的时间判断逻辑 ===
            const now = new Date();
            const nowUTC = now.toISOString().split("T")[0]; // 当前UTC日期
            const msgUTC = datePart; // 消息日期部分

            if (nowUTC === msgUTC) {
              return `UTC ${this.$t("chat.today")} ${timeOnly}`;
            }

            // 判断昨天
            const yesterdayUTC = new Date(Date.now() - 24 * 60 * 60 * 1000)
              .toISOString()
              .split("T")[0];
            if (yesterdayUTC === msgUTC) {
              return `UTC ${this.$t("chat.yesterday")} ${timeOnly}`;
            }

            return `UTC ${datePart} ${timeOnly} `;
          }
        }

        // 兜底处理：使用Date对象解析
        const dateObj = new Date(timeStr);
        if (isNaN(dateObj.getTime())) {
          return timeStr; // 如果解析失败，返回原始字符串
        }

        const year = dateObj.getUTCFullYear();
        const month = String(dateObj.getUTCMonth() + 1).padStart(2, "0");
        const day = String(dateObj.getUTCDate()).padStart(2, "0");
        const hours = String(dateObj.getUTCHours()).padStart(2, "0");
        const minutes = String(dateObj.getUTCMinutes()).padStart(2, "0");

        return `UTC ${year}-${month}-${day} ${hours}:${minutes} `;
      } catch (error) {
        console.error("格式化时间失败:", error);
        return String(date);
      }
    },

    //  聊天分割条时间格式化
    /**
     * 聊天分割条时间格式化
     * @param {string|Date} date
     * @returns {string}
     */
    formatTimeDivider(date) {
      if (!date) return "";

      try {
        let timeStr = "";

        if (typeof date === "string") {
          // 后端返回的时间字符串，格式如 "2025-06-11T03:10:09"
          timeStr = date;
        } else if (date instanceof Date) {
          // 本地时间对象，转换为ISO字符串
          timeStr = date.toISOString();
        } else {
          return String(date);
        }

        // 处理后端时间：直接去掉T，提取年月日时分
        if (timeStr.includes("T")) {
          // 分离日期和时间部分
          const [datePart, timePart] = timeStr.split("T");
          if (datePart && timePart) {
            // 提取时分（去掉秒和毫秒）
            const timeOnly = timePart.split(":").slice(0, 2).join(":");

            // === 使用与客服页面完全相同的时间判断逻辑 ===
            const now = new Date();
            const nowUTC = now.toISOString().split("T")[0]; // 当前UTC日期
            const msgUTC = datePart; // 消息日期部分

            if (nowUTC === msgUTC) {
              return `UTC ${this.$t("chat.today")} ${timeOnly}`;
            }

            // 判断昨天
            const yesterdayUTC = new Date(Date.now() - 24 * 60 * 60 * 1000)
              .toISOString()
              .split("T")[0];
            if (yesterdayUTC === msgUTC) {
              return `UTC ${this.$t("chat.yesterday")} ${timeOnly}`;
            }

            return `UTC ${datePart} ${timeOnly} `;
          }
        }

        // 兜底处理：使用Date对象解析
        const dateObj = new Date(timeStr);
        if (isNaN(dateObj.getTime())) {
          return timeStr; // 如果解析失败，返回原始字符串
        }

        const y = dateObj.getUTCFullYear();
        const m = String(dateObj.getUTCMonth() + 1).padStart(2, "0");
        const day = String(dateObj.getUTCDate()).padStart(2, "0");
        const hour = String(dateObj.getUTCHours()).padStart(2, "0");
        const min = String(dateObj.getUTCMinutes()).padStart(2, "0");

        return `UTC ${y}-${m}-${day} ${hour}:${min} `;
      } catch (error) {
        console.error("格式化分割条时间失败:", error);
        return String(date);
      }
    },

    handleClickOutside(event) {
      if (this.isChatOpen) {
        const chatElement = this.$el.querySelector(".chat-dialog");
        const chatIcon = this.$el.querySelector(".chat-icon");
        const historyIndicator = this.$el.querySelector(".history-indicator");

        // 如果点击的是历史消息加载指示器，不关闭对话框
        if (historyIndicator && historyIndicator.contains(event.target)) {
          return;
        }

        if (
          chatElement &&
          !chatElement.contains(event.target) &&
          !chatIcon.contains(event.target)
        ) {
          this.isChatOpen = false;
        }
      }
    },

    // 处理图片上传
    async handleImageUpload(event) {
      if (this.connectionStatus !== "connected") {
        // console.log("当前连接状态:", this.connectionStatus);
        return;
      }
      const file = event.target.files[0];
      if (!file) return;
      if (!file.type.startsWith("image/")) {
        this.$message({
          message: this.$t("chat.onlyImages") || "只能上传图片文件!",
          type: "warning",
        });
        return;
      }
      const maxSize = 5 * 1024 * 1024;
      if (file.size > maxSize) {
        this.$message({
          message: this.$t("chat.imageTooLarge") || "图片大小不能超过5MB!",
          type: "warning",
        });
        return;
      }
      try {
        // === 移除上传提示：图片上传通常很快，不需要提示 ===
        // console.log("📤 正在上传图片...");
        // 创建 FormData
        const formData = new FormData();
        formData.append("file", file);

        // 上传图片
        const response = await this.$axios({
          method: "post",
          url: `${process.env.VUE_APP_BASE_API}pool/ticket/uploadFile`,
          data: formData,
          headers: {
            "Content-Type": "multipart/form-data",
          },
        });

        if (response.data.code === 200) {
          const imageUrl = response.data.data.url;
          // 发送图片消息
          this.sendImageMessage(imageUrl);
        } else {
          throw new Error(
            response.data.msg ||
              this.$t("chat.pictureFailed") ||
              "发送图片失败，请重试"
          );
        }
      } catch (error) {
        console.error("图片处理失败:", error);
        // === 简化错误提示 ===
        this.$message.error("图片处理失败，请重试");
      } finally {
        this.$refs.imageUpload.value = "";
      }
    },

    // 发送图片消息
    sendImageMessage(imageUrl) {
      if (!this.stompClient || !this.stompClient.connected) {
        // console.log("发送图片时连接已断开，尝试重连...");
        // === 移除重连提示：会自动重连，不需要打扰用户 ===
        this.handleDisconnect();
        return;
      }

      // === 立即本地显示机制 ===
      const timestamp = Date.now();
      const random = Math.random().toString(36).substr(2, 9);
      const localMessageId = `local_img_${timestamp}_${random}`;

      // 创建本地图片消息对象
      const localMessage = {
        id: localMessageId,
        content: imageUrl,
        type: 2,
        sendEmail: this.userEmail,
        sendTime: new Date().toISOString(),
        roomId: this.roomId,
        isLocalMessage: true, // 标记为本地消息
      };

      // 立即添加到本地聊天记录
      // console.log("📤 立即显示本地图片消息:", localMessage);
      this.addMessageToChat(localMessage, true);

      try {
        const message = {
          type: 2, // 2 表示图片消息
          email: this.receivingEmail,
          receiveUserType: 2,
          roomId: this.roomId,
          content: imageUrl, // 使用接口返回的url
        };

        this.stompClient.send(
          "/point/send/message/to/customer",
          {},
          JSON.stringify(message)
        );
      } catch (error) {
        console.error("发送图片消息失败:", error);
        // === 简化图片发送失败提示 ===
        // this.$message.error("图片发送失败，请重试");
      }
    },

    // 预览图片
    previewImage(imageUrl) {
      this.previewImageUrl = imageUrl;
      this.showImagePreview = true;
    },

    // 关闭图片预览
    closeImagePreview() {
      this.showImagePreview = false;
      this.previewImageUrl = "";
    },

    /**
     * 优化：重试连接按钮处理 - 直接重连，不自动打开对话框
     */
    async handleRetryConnect() {
      try {
        // console.log("🔄 用户点击重试连接...");

        // === 多窗口切换：抢占活跃权 ===
        // this.setWindowActive(); // 移除此方法调用，因为setWindowActive方法在代码中没有定义

        // === 重置连接状态，立即显示连接中 ===
        this.connectionStatus = "connecting";
        this.connectionError = null;
        this.showRefreshButton = false;
        this.isReconnecting = false; // 不标记为自动重连
        this.isConnectionVerified = false;

        // === 重置错误处理状态 ===
        this.isHandlingError = false;
        this.lastErrorTime = 0;
        this.reconnectAttempts = 0;

        // 清除连接验证定时器
        this.clearConnectionVerification();

        // === 强制断开旧连接 ===
        // console.log("⚡ 强制断开旧连接...");
        await this.forceDisconnectAll();

        // 等待断开完成
        await new Promise((resolve) => setTimeout(resolve, 500));

        // === 确保用户身份已确定 ===
        if (!this.userEmail) {
          // console.log("🔍 重新初始化用户身份...");
          await this.determineUserType();
        }

        // === 重新连接 WebSocket ===
        // console.log("🌐 开始重新连接 WebSocket...");
        await this.connectWebSocket(this.userEmail);

        // 连接成功后的处理
        if (this.connectionStatus === "connected") {
          // console.log("✅ 重试连接成功");

          // 如果消息列表为空，加载历史消息
          if (this.messages.length === 0) {
            await this.loadHistoryMessages();
          }

          // 滚动到底部
          this.$nextTick(() => {
            this.scrollToBottom(true);
          });
        }
      } catch (error) {
        console.error("❌ 重试连接失败:", error);

        this.connectionStatus = "error";
        this.isReconnecting = false;

        // === 优化：只在严重错误时显示刷新按钮，一般连接失败只显示重试 ===
        if (
          error.message &&
          (error.message.includes("handshake") ||
            error.message.includes("503") ||
            error.message.includes("网络"))
        ) {
          this.connectionError =
            this.$t("chat.networkAnomaly") || "网络连接异常，请稍后重试";
          this.showRefreshButton = false; // 网络问题不显示刷新按钮
        } else {
          this.connectionError = this.$t("chat.abnormal") || "连接异常，请重试";
          this.showRefreshButton =
            error.message && error.message.includes("1020"); // 只有1020错误才显示刷新按钮
        }
      }
    },

    // 添加刷新页面方法
    refreshPage() {
      window.location.reload();
    },

    // 添加心跳检测方法
    startHeartbeat() {
      this.stopHeartbeat();

      this.lastHeartbeatTime = Date.now();
      this.heartbeatInterval = setInterval(() => {
        const now = Date.now();
        if (now - this.lastHeartbeatTime > this.heartbeatTimeout) {
          // console.log("心跳超时，检查连接状态...");
          // 只有在确实连接状态为已连接时才重连
          if (
            this.connectionStatus === "connected" &&
            this.stompClient &&
            this.stompClient.connected
          ) {
            // 再次确认连接状态
            if (this.stompClient.ws.readyState === WebSocket.OPEN) {
              // console.log("WebSocket 连接仍然活跃，更新心跳时间");
              this.lastHeartbeatTime = now;
              return;
            }
            // console.log("连接状态异常，准备重连...");
            this.handleDisconnect();
          }
        }
      }, this.heartbeatCheckInterval);
    },

    stopHeartbeat() {
      if (this.heartbeatInterval) {
        clearInterval(this.heartbeatInterval);
        this.heartbeatInterval = null;
      }
    },

    handleLoginClick() {
      this.isChatOpen = false;
      const currentLang = this.$i18n.locale;
      this.$router.push(`/${currentLang}/login`);
    },

    /**
     * 解析Socket错误信息，提取错误码
     * @param {string|Error} error - 错误信息
     * @returns {Object} 包含错误码和消息的对象
     */
    parseSocketError(error) {
      let errorMessage = "";
      if (typeof error === "string") {
        errorMessage = error;
      } else if (error && error.message) {
        errorMessage = error.message;
      } else if (error && error.body) {
        errorMessage = error.body;
      }

      // console.log("🔍 parseSocketError 输入:", errorMessage);

      // === 新增：处理多种错误格式 ===

      // 1. 处理 "ERROR message:1020连接数上限" 格式
      if (errorMessage.includes("ERROR message:")) {
        const afterMessage = errorMessage.split("ERROR message:")[1];
        // console.log("🔍 发现ERROR message格式，提取:", afterMessage);

        // 检查是否是 "1020连接数上限" 这种格式
        if (afterMessage && afterMessage.match(/^\d+/)) {
          const match = afterMessage.match(/^(\d+)(.*)$/);
          if (match) {
            const code = match[1];
            const message = match[2] || "";
            // console.log(
            //   "🔍 解析ERROR message格式，码:",
            //   code,
            //   "消息:",
            //   message
            // );
            return { code, message: message.trim(), original: errorMessage };
          }
        }
      }

      // 2. 处理逗号分隔的错误格式：如 "1020,本机连接已达上限,请先关闭已有链接"
      if (errorMessage.includes(",")) {
        const parts = errorMessage.split(",");
        if (parts.length >= 2) {
          const code = parts[0].trim();
          const message = parts.slice(1).join(",").trim();
          // console.log("🔍 解析逗号分隔格式，码:", code, "消息:", message);
          return { code, message, original: errorMessage };
        }
      }

      // 3. 处理纯数字开头的格式：如 "1020连接数上限"
      const numMatch = errorMessage.match(/^(\d+)(.*)$/);
      if (numMatch) {
        const code = numMatch[1];
        const message = numMatch[2].trim();
        // console.log("🔍 解析数字开头格式，码:", code, "消息:", message);
        return { code, message, original: errorMessage };
      }

      // console.log("🔍 未匹配到任何格式，返回原始消息");
      return { code: null, message: errorMessage, original: errorMessage };
    },

    /**
     * 检查是否是连接数上限错误
     * @param {string} errorMessage - 错误消息
     * @returns {boolean} 是否是连接数上限错误
     */
    isConnectionLimitError(errorMessage) {
      // console.log("🔍 检查是否为连接数上限错误，输入:", errorMessage);
      // console.log("🔍 错误信息类型:", typeof errorMessage);

      if (!errorMessage) {
        // console.log("🔍 错误信息为空，返回false");
        return false;
      }

      // === 确保错误信息是字符串 ===
      const errorStr = String(errorMessage);
      // console.log("🔍 转换为字符串后:", errorStr);

      // === 新增：使用解析方法检查错误码 ===
      const { code, message } = this.parseSocketError(errorStr);
      // console.log("🔍 解析后的错误码:", code, "消息:", message);

      // 检查错误码
      if (code === "1020") {
        // console.log("✅ 发现1020错误码");
        return true;
      }

      // 检查错误消息内容
      const lowerMessage = message.toLowerCase();
      // console.log("🔍 小写后的消息:", lowerMessage);

      const isLimitError =
        lowerMessage.includes("连接数已达上限") ||
        lowerMessage.includes("本机连接数已达上限") ||
        lowerMessage.includes("本机连接已达上限") ||
        lowerMessage.includes("无法连接到已上线") ||
        lowerMessage.includes("请先关闭已有链接") ||
        lowerMessage.includes("maximum connections") ||
        lowerMessage.includes("connection limit") ||
        lowerMessage.includes("too many connections") ||
        lowerMessage.includes("1020"); // 错误码1020

      // console.log("🔍 连接数上限错误检查结果:", isLimitError);

      // === 兜底检查：多种方式检测1020错误 ===
      if (!isLimitError) {
        if (errorStr.includes("1020")) {
          // console.log("🔍 兜底检查1：发现1020字符串");
          return true;
        }

        if (errorStr.includes("ERROR message:1020")) {
          // console.log("🔍 兜底检查2：发现ERROR message:1020");
          return true;
        }

        if (
          errorStr.includes("连接数上限") ||
          errorStr.includes("连接数已达上限")
        ) {
          // console.log("🔍 兜底检查3：发现连接数上限关键词");
          return true;
        }
      }

      return isLimitError;
    },

    /**
     * 处理连接数上限错误的特殊逻辑
     * === 多连接优化：后端支持最多10个连接，简化错误处理 ===
     */
    async handleConnectionLimitError() {
      // console.log("🚫 检测到连接数上限错误（超过10个连接）");

      // === 立即设置错误状态 ===
      this.connectionStatus = "error";
      this.connectionError =
        this.$t("chat.connectionLimitError") ||
        "连接数已达上限（超过10个窗口），请关闭一些窗口后重试";
      this.isWebSocketConnected = false;
      this.isReconnecting = false;
      this.showRefreshButton = false; // 不显示刷新按钮，用户只需关闭多余窗口

      // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
      // this.isChatOpen = true;
      // this.isMinimized = false;

      this.$forceUpdate();
      // console.log("🔥 连接数上限错误处理完成，提示用户关闭多余窗口");
    },

    /**
     * 强制断开所有连接
     */
    async forceDisconnectAll() {
      // console.log("强制断开所有现有连接...");

      // 停止心跳
      this.stopHeartbeat();

      // 清除所有定时器
      if (this.reconnectTimer) {
        clearTimeout(this.reconnectTimer);
        this.reconnectTimer = null;
      }

      if (this.activityCheckInterval) {
        clearInterval(this.activityCheckInterval);
        this.activityCheckInterval = null;
      }

      // === 新增：清除连接验证定时器 ===
      this.clearConnectionVerification();

      // 断开当前STOMP连接
      if (this.stompClient) {
        try {
          // 取消所有订阅
          if (this.stompClient.subscriptions) {
            Object.keys(this.stompClient.subscriptions).forEach((id) => {
              try {
                this.stompClient.unsubscribe(id);
              } catch (error) {
                // console.warn("取消订阅失败:", error);
              }
            });
          }

          // 强制断开连接
          if (this.stompClient.connected) {
            this.stompClient.disconnect();
          }

          // 如果有底层WebSocket，直接关闭
          if (
            this.stompClient.ws &&
            this.stompClient.ws.readyState === WebSocket.OPEN
          ) {
            this.stompClient.ws.close();
          }
        } catch (error) {
          // console.warn("断开STOMP连接时出错:", error);
        }

        // 清空stompClient引用
        this.stompClient = null;
      }

      // 重置连接状态
      this.isWebSocketConnected = false;
      this.reconnectAttempts = 0;
      this.connectionError = null;

      // console.log("所有连接已强制断开");
    },

    /**
     * 统一处理Socket连接错误（支持多语言和后端错误码）
     * @param {Object|string} errorInput - 错误信息
     * @returns {boolean} 是否已处理（true=已处理，不再重连）
     */
    handleConnectionError(errorInput) {
      if (!errorInput) return false;

      let parsedError;
      if (typeof errorInput === "string") {
        parsedError = this.parseSocketError(errorInput);
      } else if (errorInput.message) {
        parsedError = this.parseSocketError(errorInput.message);
      } else {
        parsedError = this.parseSocketError(errorInput);
      }

      // console.log("🔍 解析的错误信息:", parsedError);

      // 获取错误码（字符串格式）
      const errorCode = parsedError.code;
      const errorMessage = parsedError.message || parsedError.original;

      // 根据错误码处理不同情况
      switch (errorCode) {
        case "1020": // IP_LIMIT_CONNECT
          // console.log("🚫 处理1020错误：连接数上限");
          // 连接数上限错误已由 handleConnectionLimitError 专门处理
          return false;

        case "1021": // MAX_LIMIT_CONNECT
          // console.log("🚫 处理1021错误：服务器连接数上限");
          this.connectionError =
            this.$t("chat.serverBusy") || "服务器繁忙，请稍后刷新重试";
          this.connectionStatus = "error";
          this.isReconnecting = false;
          this.showRefreshButton = true;
          this.$message.error(this.connectionError);
          return true;

        case "1022": // SET_PRINCIPAL_FAIL
          // console.log("🚫 处理1022错误：身份设置失败");
          this.connectionError =
            this.$t("chat.identityError") || "身份验证失败，请刷新页面重试";
          this.connectionStatus = "error";
          this.isReconnecting = false;
          this.showRefreshButton = true;
          this.$message.error(this.connectionError);
          return true;

        case "1023": // GET_PRINCIPAL_FAIL
          // console.log("🚫 处理1023错误：用户信息获取失败");
          this.connectionError =
            this.$t("chat.emailError") || "用户信息获取失败，请刷新页面重试";
          this.connectionStatus = "error";
          this.isReconnecting = false;
          this.showRefreshButton = true;
          this.$message.error(this.connectionError);
          return true;

        default:
          // console.log("🔄 未知错误码或无错误码，使用默认处理");
          return false;
      }
    },

    // === 新增：连接验证相关方法 ===

    /**
     * 启动连接验证机制
     * 在连接建立后的1分钟内验证连接是否真正可用
     * 通过订阅成功和接收任何消息来验证，不主动发送ping消息
     * 无论是否在connecting状态，只要1分钟没有验证成功都强制重连
     */
    startConnectionVerification() {
        // console.log("🔍 启动连接验证机制（被动验证）...");
        // console.log("当前连接状态:", this.connectionStatus);
        // console.log("当前WebSocket连接状态:", this.isWebSocketConnected);
        // console.log("当前STOMP连接状态:", this.stompClient?.connected);

      this.isConnectionVerified = false;

      // 清除之前的验证定时器
      this.clearConnectionVerification();

      // 如果已经是connected状态且STOMP也连接成功，检查是否可以立即验证
      if (
        this.connectionStatus === "connected" &&
        this.isWebSocketConnected &&
        this.stompClient?.connected
      ) {
        // console.log("✅ 连接状态良好，立即标记为已验证");
        this.markConnectionVerified();
        return;
      }

      // 设置1分钟验证超时 - 无论在什么状态下
      this.connectionVerifyTimer = setTimeout(() => {
        if (!this.isConnectionVerified) {
          // console.log(
          //   "⏰ 连接验证超时（1分钟），当前状态:",
          //   this.connectionStatus
          // );
          // console.log("WebSocket连接状态:", this.isWebSocketConnected);
          // console.log("STOMP连接状态:", this.stompClient?.connected);
          // console.log("强制断开重连");

          // 无论当前状态如何，都强制重连
          if (
            this.connectionStatus === "connecting" ||
            this.connectionStatus === "connected"
          ) {
            this.handleConnectionTimeout();
          } else {
            this.handleConnectionVerificationFailure();
          }
        }
      }, 60000); // 60秒超时

      // console.log("⏲️ 已设置1分钟验证超时定时器");
      // 注意：采用被动验证方式，不发送ping消息，避免在对话框中显示验证消息
    },

    /**
     * 标记连接已验证
     */
    markConnectionVerified() {
      if (!this.isConnectionVerified) {
        // console.log("🎉 连接验证成功！清除所有定时器并确保状态正确");
        this.isConnectionVerified = true;
        this.clearConnectionVerification();

        // === 重要：清除所有可能影响连接状态的定时器和状态 ===
        this.isHandlingError = false;
        this.isReconnecting = false;
        this.reconnectAttempts = 0;
        this.connectionError = null;

        // 确保连接状态是正确的
        this.connectionStatus = "connected";
        this.isWebSocketConnected = true;

        // console.log("✅ 连接验证完成，当前状态:", {
        //   connectionStatus: this.connectionStatus,
        //   isWebSocketConnected: this.isWebSocketConnected,
        //   isConnectionVerified: this.isConnectionVerified,
        //   reconnectAttempts: this.reconnectAttempts,
        //   isHandlingError: this.isHandlingError,
        // });

        // === 强制Vue重新渲染，确保界面更新 ===
        this.$forceUpdate();
      } else {
        // console.log("🔄 连接已经验证过了，跳过重复验证");
      }
    },

    /**
     * 设置调试模式，用于快速排查状态问题
     */
    setupDebugMode() {
      // 按 Ctrl+Shift+D 快速查看连接状态
      document.addEventListener("keydown", (event) => {
        if (event.ctrlKey && event.shiftKey && event.key === "D") {
          this.debugConnectionStatus();
        }
      });
    },

    /**
     * 调试连接状态
     */
    debugConnectionStatus() {
      // console.log("🔍 === 连接状态调试信息 ===");
      // console.log("connectionStatus:", this.connectionStatus);
      // console.log("isWebSocketConnected:", this.isWebSocketConnected);
      // console.log("isConnectionVerified:", this.isConnectionVerified);
      // console.log("isReconnecting:", this.isReconnecting);
      // console.log("isHandlingError:", this.isHandlingError);
      // console.log("reconnectAttempts:", this.reconnectAttempts);
      // console.log("maxReconnectAttempts:", this.maxReconnectAttempts);
      // console.log("connectionError:", this.connectionError);
      // console.log("userEmail:", this.userEmail);
      // console.log("lastConnectedEmail:", this.lastConnectedEmail);
      // console.log("roomId:", this.roomId);
      // console.log("STOMP connected:", this.stompClient?.connected);
      // console.log("connectionVerifyTimer:", !!this.connectionVerifyTimer);
      // console.log("reconnectTimer:", !!this.reconnectTimer);
      // console.log("activityCheckInterval:", !!this.activityCheckInterval);
      // console.log("heartbeatInterval:", !!this.heartbeatInterval);
      // console.log("showRefreshButton:", this.showRefreshButton);
      // console.log("isChatOpen:", this.isChatOpen);
      // console.log("isMinimized:", this.isMinimized);

      // 强制检查状态一致性
      if (this.connectionStatus === "connecting" && this.isConnectionVerified) {
        console.warn("⚠️ 状态不一致：连接中但已验证");
        this.connectionStatus = "connected";
        this.$forceUpdate();
      }

      if (this.connectionStatus === "connected" && !this.isWebSocketConnected) {
        console.warn("⚠️ 状态不一致：已连接但WebSocket未连接");
        this.connectionStatus = "connecting";
        this.$forceUpdate();
      }

      // console.log("🔍 === 调试信息结束 ===");
    },

    /**
     * 清除连接验证定时器
     */
    clearConnectionVerification() {
      if (this.connectionVerifyTimer) {
        // console.log("🧹 清除连接验证定时器"); 
        clearTimeout(this.connectionVerifyTimer);
        this.connectionVerifyTimer = null;
      } else {
        // console.log("🔍 没有需要清除的验证定时器");
      }
    },

    /**
     * 处理连接验证失败
     */
    handleConnectionVerificationFailure() {
      // console.log("⚠️ 连接验证失败，连接可能无法正常收发消息");

      // 防止重复处理
      const now = Date.now();
      if (this.isHandlingError && now - this.lastErrorTime < 5000) {
        // console.log("正在处理错误中，跳过重复处理");
        return;
      }

      this.isHandlingError = true;
      this.lastErrorTime = now;

      // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
      // this.isChatOpen = true;
      // this.isMinimized = false;

      // 清除验证定时器
      this.clearConnectionVerification();

      // 重置连接状态
      this.isWebSocketConnected = false;
      this.connectionStatus = "connecting"; // 改为connecting而不是error
      this.connectionError = this.$t("chat.reconnecting") || "正在重新连接...";

      // 2秒后重新连接
      setTimeout(() => {
        // console.log("🔄 连接验证失败，开始重新连接...");
        this.isHandlingError = false;

        // 断开当前连接
        if (this.stompClient) {
          try {
            this.stompClient.disconnect();
          } catch (error) {
            // console.warn("断开连接时出错:", error);
          }
        }

        // 重新连接
        this.connectWebSocket(this.userEmail).catch((error) => {
          // console.error("❌ 重新连接失败:", error);
          this.isHandlingError = false;

          // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
          // this.isChatOpen = true;
          // this.isMinimized = false;
          this.connectionStatus = "error";
          this.showRefreshButton = true;
        });
      }, 2000);
    },

    /**
     * 处理连接超时
     */
    handleConnectionTimeout() {
      // console.log("⏰ 连接超时，开始处理超时重连");

      // 防止重复处理
      const now = Date.now();
      if (this.isHandlingError && now - this.lastErrorTime < 5000) {
        // console.log("⚠️ 正在处理连接超时中，跳过重复处理");
        return;
      }

      this.isHandlingError = true;
      this.lastErrorTime = now;

      // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
      // this.isChatOpen = true;
      // this.isMinimized = false;

      // === 增加重连次数并检查限制 ===
      this.reconnectAttempts++;
      //    console.log(
      //   `🔄 连接超时重连计数: ${this.reconnectAttempts}/${this.maxReconnectAttempts}`
      // );

      // 如果达到最大重连次数，直接设置错误状态
      if (this.reconnectAttempts >= this.maxReconnectAttempts) {
        console.log("❌ 连接超时且已达最大重连次数，停止重连");
        this.isHandlingError = false;
        this.connectionStatus = "error";
        this.connectionError = "连接超时，请刷新页面重试";
        this.showRefreshButton = true;
        return;
      }

      // 清除连接验证定时器
      this.clearConnectionVerification();

      // 强制断开当前连接
      this.forceDisconnectAll()
        .then(() => {
          // 设置connecting状态而不是error状态
          this.connectionStatus = "connecting";
          this.connectionError =
            this.$t("chat.connectionTimedOut") || "连接超时，稍后重试...";

          // 2秒后重新连接
          setTimeout(() => {
            // console.log("🔄 连接超时处理完成，开始重新连接...");
            this.isHandlingError = false;

            this.connectWebSocket(this.userEmail).catch((error) => {
              console.error("❌ 超时重连失败:", error);
              this.isHandlingError = false;

              // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
              // this.isChatOpen = true;
              // this.isMinimized = false;
              this.connectionStatus = "error";
              this.connectionError =
                this.$t("chat.reconnectFailed") || "重连失败，请稍后重试";

              // 如果已达最大重连次数，显示刷新按钮
              if (this.reconnectAttempts >= this.maxReconnectAttempts) {
                this.showRefreshButton = true;
                this.connectionError =
                  this.$t("chat.connectionFailed") ||
                  "连接失败，请刷新页面重试";
              }
            });
          }, 2000);
        })
        .catch((error) => {
          console.error("❌ 强制断开连接失败:", error);
          this.isHandlingError = false;

          // === 移除自动打开对话框的逻辑，只有用户主动点击才打开 ===
          // this.isChatOpen = true;
          // this.isMinimized = false;
          this.connectionStatus = "error";
          this.connectionError =
            this.$t("chat.connectionFailed") || "连接处理失败，请稍后重试";

          // 如果已达最大重连次数，显示刷新按钮
          if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            this.showRefreshButton = true;
            this.connectionError =
              this.$t("chat.connectionFailed") || "连接失败，请刷新页面重试";
          }
        });
    },

    /**
     * 检查是否是握手错误
     */
    isHandshakeError(error) {
      if (!error || !error.message) return false;
      const message = error.message.toLowerCase();
      return (
        // WebSocket握手相关错误
        message.includes("handshake") ||
        message.includes("websocket") ||
        // HTTP状态码错误（WebSocket升级失败）
        message.includes("unexpected response code: 200") ||
        message.includes("unexpected response code: 404") ||
        message.includes("unexpected response code: 500") ||
        message.includes("unexpected response code: 502") ||
        message.includes("unexpected response code: 503") ||
        // 连接被拒绝错误
        message.includes("connection refused") ||
        message.includes("connection denied") ||
        message.includes("connection reset") ||
        // 网络相关错误
        message.includes("network error") ||
        message.includes("connection failed") ||
        // 协议升级失败
        message.includes("upgrade required") ||
        message.includes("bad handshake")
      );
    },

    /**
     * 处理握手错误
     */
    handleHandshakeError(error) {
      // console.log("🤝 检测到握手错误:", error.message);

      // 防止重复处理
      const now = Date.now();
      if (this.isHandlingError && now - this.lastErrorTime < 5000) {
        // console.log("⚠️ 正在处理握手错误中，跳过重复处理");
        return;
      }

      this.isHandlingError = true;
      this.lastErrorTime = now;

      // === 立即设置为错误状态，避免卡在连接中 ===
      this.isWebSocketConnected = false;
      this.connectionStatus = "error";
      this.isReconnecting = false;

      // === 增强握手错误处理，针对不同错误码提供准确的错误信息 ===
      if (error.message.includes("unexpected response code: 200")) {
        this.connectionError =
          this.$t("chat.serviceConfigurationError") ||
          "服务配置异常，请稍后重试";
        // console.log("🔴 WebSocket握手失败：服务器返回200而非101升级响应");
      } else if (error.message.includes("unexpected response code: 404")) {
        this.connectionError =
          this.$t("chat.serviceAddressUnavailable") ||
          "服务地址不可用，请稍后重试";
        // console.log("🔴 WebSocket握手失败：服务地址404");
      } else if (error.message.includes("unexpected response code: 500")) {
        this.connectionError =
          this.$t("chat.server500") || "服务器暂时不可用，请稍后重试";
        // console.log("🔴 WebSocket握手失败：服务器500错误");
      } else if (error.message.includes("connection refused")) {
        this.connectionError =
          this.$t("chat.connectionFailedService") ||
          "无法连接到服务器，请稍后重试";
        // console.log("🔴 WebSocket握手失败：连接被拒绝");
      } else {
        this.connectionError =
          this.$t("chat.connectionFailed") || "连接失败，请稍后重试";
        // console.log("🔴 WebSocket握手失败：", error.message);
      }

      // === 增加重连次数并检查限制 ===
      this.reconnectAttempts++;
      // console.log(
      //   `🔄 握手错误重连计数: ${this.reconnectAttempts}/${this.maxReconnectAttempts}`
      // );

      // 如果达到最大重连次数，不再重试
      if (this.reconnectAttempts >= this.maxReconnectAttempts) {
        // console.log("❌ 握手错误重连次数已达上限，停止重连"); 
        this.isHandlingError = false;
        this.showRefreshButton = true;
        this.connectionError =
          this.$t("chat.connectionFailed") || "连接失败，请刷新页面重试";
        return;
      }

      // 等待3秒后重试连接
      setTimeout(() => {
        // console.log("🔄 握手错误处理完成，开始重新连接...");
        this.isHandlingError = false;

        // 设置为连接中状态
        this.connectionStatus = "connecting";

        this.connectWebSocket(this.userEmail).catch((retryError) => {
          // console.error("❌ 握手错误重连失败:", retryError);
          this.isHandlingError = false;
          this.connectionStatus = "error";
          this.connectionError =
            this.$t("chat.reconnectFailed") || "重连失败，请稍后重试";
        });
      }, 3000);
    },

    /**
     * 处理WebSocket错误
     */
    handleWebSocketError(error) {
      // console.log("WebSocket级别错误:", error);
      // 防止重复处理
      const now = Date.now();
      if (this.isHandlingError && now - this.lastErrorTime < 3000) {
        // console.log("正在处理错误中，跳过重复处理");
        return;
      }
      this.isHandlingError = true;
      this.lastErrorTime = now;
      // === 关键修复：立即显示错误状态和重试按钮 ===
      this.isWebSocketConnected = false;
      this.connectionStatus = "error";
      this.connectionError =
        this.$t("chat.connectionFailedCustomer") ||
        "连接客服系统失败，请检查网络或稍后重试";
      this.showRefreshButton = false;
      // 1秒后可自动重连（不影响UI）
      setTimeout(() => {
        this.isHandlingError = false;
        this.handleDisconnect();
      }, 1000);
    },

    /**
     * 处理WebSocket关闭
     */
    handleWebSocketClose(event) {
      // console.log("WebSocket连接关闭:", event.code, event.reason);
      // 如果不是正常关闭，处理异常关闭
      if (event.code !== 1000) {
        this.isWebSocketConnected = false;
        // === 关键修复：立即显示错误状态和重试按钮 ===
        this.connectionStatus = "error";
        this.connectionError =
          this.$t("chat.connectionFailedCustomer") ||
          "连接客服系统失败，请检查网络或稍后重试";
        this.showRefreshButton = false;
        // 延迟重连
        setTimeout(() => {
          if (!this.isWebSocketConnected) {
            this.handleDisconnect();
          }
        }, 1000);
      }
    },

    // 处理退出登录
    handleLogout() {
      // 断开 WebSocket 连接
      this.disconnectWebSocket();
      // 重置状态
      this.isChatOpen = false;
      this.isMinimized = true;
      this.messages = [];
      this.updateUnreadMessages(0); // === 使用localStorage管理 ===
      this.connectionStatus = "disconnected";
      this.isWebSocketConnected = false;
      this.userType = 0;
      this.userEmail = "";
      this.roomId = "";

      // === 清除游客身份缓存，为下次访问做准备 ===
      sessionStorage.removeItem("chatGuestEmail");
      this.lastConnectedEmail = null;
      // console.log("🧹 退出登录时清除游客身份缓存");
    },
    // 处理登录成功
    async handleLoginSuccess() {
      // 断开原有连接
      this.disconnectWebSocket();

      // === 清除游客身份缓存，确保使用登录用户身份 ===
      sessionStorage.removeItem("chatGuestEmail");
      this.lastConnectedEmail = null;
      // console.log("🧹 登录成功时清除游客身份缓存");

      // 等待一小段时间，确保 localStorage 已更新
      await new Promise((resolve) => setTimeout(resolve, 100));

      // 重试机制：最多重试 3 次
      let retryCount = 0;
      const maxRetries = 3;

      while (retryCount < maxRetries) {
        try {
          // 重新判别身份
          await this.determineUserType();

          // console.log(this.userEmail, "userEmail 重新登录成功");

          // 检查是否成功获取到 userEmail
          if (this.userEmail && this.userEmail !== "") {
            // 用新身份重新连接
            if (!this.isWebSocketConnected) {
              await this.connectWebSocket(this.userEmail);
            }
            // 重新加载历史消息
            await this.loadHistoryMessages();
            break; // 成功后跳出循环
          } else {
            throw new Error("未获取到有效的用户邮箱");
          }
        } catch (error) {
          retryCount++;
          console.warn(
            `登录处理失败 (尝试 ${retryCount}/${maxRetries}):`,
            error
          );

          if (retryCount < maxRetries) {
            // 等待一段时间后重试
            await new Promise((resolve) =>
              setTimeout(resolve, 500 * retryCount)
            );
          } else {
            // console.error("登录处理最终失败，已达到最大重试次数");
            // this.$message.error("聊天功能初始化失败，请刷新页面");
          }
        }
      }
    },

    /**
     * 判断是否应自动滚动到底部
     * - 聊天窗口已打开
     * - 当前滚动条已在底部（或距离底部不超过50px）
     * @returns {boolean}
     */
    shouldAutoScrollOnNewMessage() {
      if (!this.isChatOpen) return false;
      const chatBody = this.$refs.chatBody;
      if (!chatBody) return false;
      const { scrollTop, scrollHeight, clientHeight } = chatBody;
      const distanceToBottom = Math.abs(
        scrollHeight - (scrollTop + clientHeight)
      );
      const atBottom = distanceToBottom < 100; // 阈值可根据实际体验调整
      // console.log(
      //   "[DEBUG] scrollTop:",
      //   scrollTop,
      //   "clientHeight:",
      //   clientHeight,
      //   "scrollHeight:",
      //   scrollHeight,
      //   "distanceToBottom:",
      //   distanceToBottom,
      //   "atBottom:",
      //   atBottom
      // );
      return atBottom;
    },

    /**
     * 判断是否在聊天框底部（允许2px误差）
     * @returns {boolean}
     */
    isAtBottom() {
      const chatBody = this.$refs.chatBody;
      if (!chatBody) return true;
      return (
        chatBody.scrollHeight - chatBody.scrollTop - chatBody.clientHeight < 2
      );
    },

    /**
     * 聊天区滚动事件处理，标记用户是否在查看历史
     * 到底部时自动清零未读数，并请求已读
     */
    handleChatBodyScroll() {
      if (!this.$refs.chatBody) return;
      if (this.isAtBottom()) {
        this.userViewHistory = false;
        // 到底部时自动清零未读数，并请求已读
        this.markMessagesAsRead();
      } else {
        this.userViewHistory = true;
      }
    },

    /**
     * 聊天框初始化时多次兜底滚动到底部，保证异步内容加载后滚动到位
     * 只在初始化/刷新/首次加载时调用，不影响其他功能
     */
    scrollToBottomOnInit() {
      let tries = 0;
      const maxTries = 5;
      const interval = 100;
      const tryScroll = () => {
        this.scrollToBottom(true, "init");
        tries++;
        if (tries < maxTries) {
          setTimeout(tryScroll, interval);
        }
      };
      tryScroll();
    },

    /**
     * 格式化消息文本：将\n换行符转为<br />，并转义HTML，防止XSS
     * @param {string} text
     * @returns {string}
     */
    formatMessageText(text) {
      if (!text) return "";
      // 转义HTML
      const escapeHtml = (str) =>
        str
          .replace(/&/g, "&amp;")
          .replace(/</g, "&lt;")
          .replace(/>/g, "&gt;")
          .replace(/"/g, "&quot;")
          .replace(/'/g, "&#39;");
      return escapeHtml(text).replace(/\n/g, "<br />");
    },
  },

  beforeDestroy() {
    // 移除退出登录事件监听
    this.$bus.$off("user-logged-out", this.handleLogout);

    // 调用退出登录处理方法
    this.handleLogout();

    // === 移除滚动监听（已禁用） ===
    // if (this.$refs.chatBody) {
    //   this.$refs.chatBody.removeEventListener("scroll", this.handleChatScroll);
    // }
    // 移除页面可见性变化监听
    document.removeEventListener(
      "visibilitychange",
      this.handleVisibilityChange
    );
    // 确保在销毁时断开连接
    if (this.stompClient) {
      this.stompClient.disconnect();
      this.stompClient = null;
    }
    // 断开 WebSocket 连接
    this.disconnectWebSocket();

    // 清除活动检测定时器
    if (this.activityCheckInterval) {
      clearInterval(this.activityCheckInterval);
    }

    // 清除重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
    }

    // === 新增：清除连接验证定时器 ===
    this.clearConnectionVerification();

    // 移除新添加的事件监听
    window.removeEventListener("online", this.handleNetworkChange);
    window.removeEventListener("offline", this.handleNetworkChange);
    document.removeEventListener("mousemove", this.updateLastActivityTime);
    document.removeEventListener("keydown", this.updateLastActivityTime);
    document.removeEventListener("click", this.updateLastActivityTime);

    // === 移除localStorage监听器 ===
    window.removeEventListener("storage", this.handleStorageChange);

    this.stopHeartbeat();

    this.$bus.$off("user-logged-in", this.handleLoginSuccess); //移除登录成功事件监听
    if (this.$refs.chatBody) {
      this.$refs.chatBody.removeEventListener(
        "scroll",
        this.handleChatBodyScroll
      );
    }
  },
};
</script>
  
  <style scoped lang="scss">
.chat-widget {
  position: fixed;
  bottom: 40px;
  right: 60px;
  z-index: 1000;
  font-family: Arial, sans-serif;
}

.chat-icon {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background-color: #ac85e0;
  color: white;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
  position: relative;

  i {
    font-size: 28px;
  }

  &:hover {
    transform: scale(1.05);
    background-color: #6e3edb;
  }

  &.active {
    background-color: #6e3edb;
  }
}

.unread-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  background-color: #e74c3c;
  color: white;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  font-size: 12px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.chat-dialog {
  position: absolute;
  bottom: 80px;
  right: 0;
  width: 350px;
  height: 450px;
  background-color: white;
  border-radius: 10px;
  box-shadow: 0 5px 25px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chat-header {
  background-color: #ac85e0;
  color: white;
  padding: 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.chat-title {
  font-weight: bold;
  font-size: 16px;
}

.chat-actions {
  display: flex;
  gap: 15px;

  i {
    cursor: pointer;
    font-size: 16px;

    &:hover {
      opacity: 0.8;
    }
  }
}

.chat-body {
  flex: 1;
  overflow-y: auto;
  padding: 15px;
  background-color: #f8f9fa;
}

.chat-status {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;

  i {
    font-size: 32px;
    margin-bottom: 16px;
  }

  p {
    margin: 8px 0;
    color: #666;
  }

  &.connecting i {
    color: #ac85e0;
  }

  &.error {
    i {
      color: #e74c3c;
    }

    p {
      color: #e74c3c;
    }
  }

  &.disconnected {
    i {
      color: #f39c12;
    }

    p {
      color: #f39c12;
    }
  }

  .retry-button {
    margin-top: 16px;
    padding: 8px 16px;
    background-color: #ac85e0;
    color: white;
    border: none;
    border-radius: 20px;
    cursor: pointer;

    &:hover {
      background-color: #6e3edb;
    }
  }
}

.chat-empty {
  color: #777;
  text-align: center;
  margin-top: 30px;
}

.chat-message {
  display: flex;
  margin-bottom: 15px;

  &.chat-message-user {
    flex-direction: row-reverse;

    .message-content {
      background-color: #ac85e0;
      color: white;
      border-radius: 18px 18px 0 18px;
    }

    .message-time {
      text-align: right;
      color: rgba(255, 255, 255, 0.7);
    }
  }

  &.chat-message-system {
    .message-content {
      background-color: white;
      border-radius: 18px 18px 18px 0;
    }
  }
}

.message-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #e0e0e0;
  margin: 0 10px;

  i {
    font-size: 18px;
    color: #555;
  }
}

.message-content {
  position: relative;
  max-width: 70%;
  padding: 18px 15px 10px 15px; // 上方多留空间给时间
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);

  .message-time {
    position: absolute;
    top: 6px;
    right: 15px;
    font-size: 11px;
    color: #bbb;
    pointer-events: none;
    user-select: none;
  }
  // 用户消息气泡内时间颜色适配
  .chat-message-user & .message-time {
    color: rgba(255, 255, 255, 0.7);
  }
}

.message-text {
  line-height: 1.4;
  font-size: 14px;
  word-break: break-word;
}

.message-image {
  img {
    max-width: 200px;
    max-height: 200px;
    border-radius: 8px;
    cursor: pointer;
    transition: transform 0.2s;

    &:hover {
      transform: scale(1.03);
    }
  }
}

.message-time {
  font-size: 11px;
  color: #999;
  margin-top: 4px;
}

.chat-footer {
  padding: 10px;
  display: flex;
  border-top: 1px solid #e0e0e0;
  align-items: center;
}

.chat-toolbar {
  margin-right: 8px;
}

.image-upload-label {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  cursor: pointer;
  color: #666;

  &:hover:not(.disabled) {
    color: #ac85e0;
  }

  &.disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  i {
    font-size: 20px;
  }
}

.chat-input {
  flex: 1;
  border: 1px solid #ddd;
  border-radius: 20px;
  padding: 8px 15px;
  outline: none;

  &:focus:not(:disabled) {
    border-color: #ac85e0;
  }

  &:disabled {
    background-color: #f5f5f5;
    cursor: not-allowed;
  }
}

.chat-send {
  background-color: #ac85e0;
  color: white;
  border: none;
  border-radius: 20px;
  padding: 8px 15px;
  margin-left: 10px;
  cursor: pointer;
  font-weight: bold;

  &:hover:not(:disabled) {
    background-color: #6e3edb;
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
}

// 图片预览
.image-preview-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 1100;
  display: flex;
  justify-content: center;
  align-items: center;
}

.image-preview-container {
  position: relative;
  max-width: 90%;
  max-height: 90%;
}

.preview-image {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
}

.preview-close {
  position: absolute;
  top: -40px;
  right: 0;
  color: white;
  font-size: 24px;
  cursor: pointer;
  background-color: rgba(0, 0, 0, 0.5);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;

  &:hover {
    background-color: rgba(0, 0, 0, 0.8);
  }
}

// 动画效果
.chat-slide-enter-active,
.chat-slide-leave-active {
  transition: all 0.3s ease;
}

.chat-slide-enter,
.chat-slide-leave-to {
  transform: translateY(20px);
  opacity: 0;
}

// 移动端适配
@media (max-width: 768px) {
  .chat-widget {
    bottom: 20px;
    right: 20px;
  }

  .chat-dialog {
    width: 300px;
    height: 400px;
    bottom: 70px;
  }

  .message-image img {
    max-width: 150px;
    max-height: 150px;
  }
}

.system-hint {
  text-align: center;
  font-size: 12px;
  color: #999;
  margin: 10px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.history-indicator {
  text-align: center;
  font-size: 12px;
  color: #666;
  margin: 10px 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 5px;
  border-radius: 15px;
  background-color: #f0f0f0;
  width: fit-content;
  margin: 0 auto 10px;

  &:hover {
    background-color: #e0e0e0;
    color: #333;
  }
}

.chat-message-history {
  opacity: 0.8;
}

.chat-message-loading,
.chat-message-hint {
  margin: 5px 0;
  justify-content: center;

  span {
    color: #999;
    font-size: 12px;
  }
}

.message-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 4px;
  font-size: 11px;
}

.message-time {
  color: #999;
}

.message-read-status {
  color: #999;
  font-size: 10px;
  margin-left: 5px;
}

.chat-message-user .message-read-status {
  color: rgba(255, 255, 255, 0.7);
}

.network-status {
  position: fixed;
  top: 80px;
  right: 20px;
  padding: 8px 16px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  z-index: 1000;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  background-color: #fef0f0;
  color: #f56c6c;
}

.guest-notice {
  background-color: #f8f9fa;
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 10px;
  text-align: center;
  border: 1px solid #e0e0e0;

  .guest-notice-content {
    display: inline-flex;
    gap: 2px;
    color: #666;
    font-size: 13px;
    line-height: 1.4;

    i {
      color: #ac85e0;
      font-size: 16px;
      flex-shrink: 0;
    }

    .login-link {
      color: #ac85e0;
      text-decoration: none;
      font-weight: bold;
      cursor: pointer;
      transition: color 0.3s;
      margin: 0 2px;

      &:hover {
        color: #6e3edb;
        text-decoration: underline;
      }
    }
  }
}

.error-actions {
  display: flex;
  gap: 10px;
  margin-top: 16px;
  justify-content: center;

  .retry-button,
  .refresh-button {
    padding: 8px 16px;
    border: none;
    border-radius: 20px;
    cursor: pointer;
    font-weight: bold;
    transition: all 0.3s ease;

    &:hover {
      transform: translateY(-1px);
    }
  }

  .retry-button {
    background-color: #ac85e0;
    color: white;

    &:hover {
      background-color: #6e3edb;
    }
  }

  .refresh-button {
    background-color: #f0f0f0;
    color: #666;
    padding: 0px 16px;

    &:hover {
      background-color: #e0e0e0;
    }
  }
}

.chat-time-divider {
  text-align: center;
  margin: 16px 0;
  font-size: 12px;
  color: #fff;
  background: rgba(180, 180, 180, 0.6);
  display: inline-block;
  padding: 2px 12px;
  border-radius: 10px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  left: 50%;
  transform: translateX(-50%);
  position: relative;
}

/* === 移除本地消息的视觉反馈（小黄点） === */
/* .chat-message-local {
  // 不再显示任何特殊样式
} */
</style>