<template>
  <view class="ai-chat-container">
    <!-- 聊天消息列表 -->
    <scroll-view 
      class="chat-messages" 
      scroll-y 
      :scroll-top="scrollTop"
       @scroll="onScroll"
      :scroll-with-animation="false">
      
      <!-- 加载更多历史消息 -->
      <view class="load-more" v-if="hasMoreHistory">
        <ns-loading :down-text="loadingText" :is-rotate="true" />
      </view>
      
      <!-- 消息列表 -->
      <view 
        v-for="(message, index) in messages" 
        :key="`msg-${message.id || message.timestamp}-${index}`"  
        class="message-item"
        :class="[message.role, { 'first-message': index === 0 }]">
        
        <!-- 用户消息 -->
        <view v-if="message.role === 'user'" class="user-message">
          <view class="avatar">
            <!-- 绑定本地用户头像，支持实时更新 -->
            <image :src="localUserAvatar" mode="aspectFill" />
          </view>
          <view class="message-content">
            <!-- 新增：显示用户昵称 -->
            <view class="message-nickname" v-if="localUserNickname">{{ localUserNickname }}</view>
            <view class="message-bubble">
              <text class="message-text">{{ message.content }}</text>
            </view>
                      </view>
        </view>
        
        <!-- AI消息 -->
        <view v-else class="ai-message">
          <view class="avatar">
            <!-- 直接使用内部固定的AI头像 -->
            <image :src="aiAvatar" mode="aspectFill" />
          </view>
          <view class="message-content">
            <!-- AI昵称固定，不可修改 - 左移到气泡上方 -->
            <view class="message-nickname ai-nickname">智能助手</view>
            <view class="message-bubble">
              <!-- 文本消息 -->
              <view v-if="message.type === 'text'" class="text-content">
                <rich-text :nodes="parseMarkdown(message.content)" />
              </view>
              
              <!-- Markdown文档 -->
              <view v-else-if="message.type === 'markdown'" class="markdown-content">
                <view class="markdown-header">
                  <text class="iconfont icon-markdown"></text>
                  <text class="markdown-title">文档内容</text>
                </view>
                <view class="markdown-body">
                  <rich-text :nodes="parseMarkdown(message.content)" />
                </view>
              </view>
              
              <!-- 文件链接 -->
              <view v-else-if="message.type === 'file'" class="file-content">
                <view class="file-item" @click="previewFile(message)">
                  <view class="file-icon">
                    <text class="iconfont icon-file"></text>
                  </view>
                  <view class="file-info">
                    <text class="file-name">{{ message.fileName }}</text>
                    <text class="file-size">{{ formatFileSize(message.fileSize) }}</text>
                  </view>
                  <view class="file-action">
                    <text class="iconfont icon-download"></text>
                  </view>
                </view>
              </view>
              
              <!-- 音频消息 -->
              <view v-else-if="message.type === 'audio'" class="audio-content">
                <view class="audio-player">
                  <view class="audio-info">
                    <text class="audio-title">{{ message.title || '语音消息' }}</text>
                    <text class="audio-duration">{{ formatDuration(message.duration) }}</text>
                  </view>
                  <view class="audio-controls">
                    <button 
                      class="play-btn" 
                      :class="{ playing: message.playing }"
                      @click="toggleAudio(message)">
                      <text class="iconfont" :class="message.playing ? 'icon-pause' : 'icon-play'"></text>
                    </button>
                    <slider 
                      class="audio-slider" 
                      :value="message.currentTime || 0" 
                      :max="message.duration || 0"
                      @changing="onAudioSliderChange"
                      @change="onAudioSliderChangeEnd"
                      activeColor="#8a9fb8"
                      backgroundColor="#e8edf3"
                      block-size="12" />
                  </view>
                </view>
              </view>
              
              <!-- 视频消息 -->
              <view v-else-if="message.type === 'video'" class="video-content">
                <view class="video-player">
                  <video 
                    :src="message.url" 
                    :poster="message.cover"
                    :controls="true"
                    :autoplay="false"
                    class="video-element"
                    @play="onVideoPlay(message)"
                    @pause="onVideoPause(message)">
                  </video>
                  <view class="video-info">
                    <text class="video-title">{{ message.title || '视频消息' }}</text>
                    <text class="video-duration">{{ formatDuration(message.duration) }}</text>
                  </view>
                </view>
              </view>
              
              <!-- 跳转链接 -->
              <view v-else-if="message.type === 'link'" class="link-content">
                <view class="link-card" @click="openLink(message)">
                  <view class="link-image" v-if="message.image">
                    <image :src="message.image" mode="aspectFill" />
                  </view>
                  <view class="link-info">
                    <text class="link-title">{{ message.title }}</text>
                    <text class="link-desc">{{ message.description }}</text>
                    <text class="link-url">{{ message.url }}</text>
                  </view>
                </view>
              </view>
              
              <!-- 商品卡片 -->
              <view v-else-if="message.type === 'product'" class="product-content">
                <view class="product-card" @click="viewProduct(message)">
                  <view class="product-image">
                    <image :src="message.image" mode="aspectFill" />
                  </view>
                  <view class="product-info">
                    <text class="product-title">{{ message.title }}</text>
                    <text class="product-price color-base-text">¥{{ message.price }}</text>
                    <text class="product-desc">{{ message.description }}</text>
                  </view>
                </view>
              </view>
              
              <!-- 加载中状态 -->
              <view v-else-if="message.type === 'loading'" class="loading-content">
                <view class="loading-dots">
                  <text class="dot"></text>
                  <text class="dot"></text>
                  <text class="dot"></text>
                </view>
                <text class="loading-text">AI正在思考中...</text>
              </view>
              
              <!-- 操作按钮 -->
              <view class="message-actions" v-if="message.actions && message.actions.length > 0">
                <button 
                  v-for="action in message.actions" 
                  :key="action.id"
                  class="action-btn"
                  :class="[`iconfont`, action.icon, action.type]"
                  @click="handleAction(action, message)">
                  {{ action.text }}
                </button>
              </view>
            </view>
            
          </view>
        </view>
      </view>
    </scroll-view>
    
    <!-- 输入区域 -->
    <view class="input-area">
      <view class="input-tools">
        <button class="tool-btn" @click="showMoreTools">
          <text class="iconfont icon-plus">📌</text>
        </button>
        <button class="tool-btn" @click="toggleVoiceInput">
          <text class="iconfont" :class="voiceInputing ? 'icon-stop' : 'icon-voice'">🎤</text>
        </button>
        <!-- 更换用户头像按钮 -->
        <button class="tool-btn" @click="openAvatarSelector">
          <text class="iconfont icon-user">📷</text>
        </button>
        <!-- 新增：更换用户昵称按钮 -->
        <button class="tool-btn" @click="openNicknameEditor">
          <text class="iconfont icon-edit">✏️</text>
        </button>
      </view>
      
      <view class="input-container">
        <textarea 
          v-model="inputText" 
          class="message-input"
          placeholder="请输入您的问题..."
          :maxlength="500"
          :auto-height="true"
          :show-confirm-bar="false"
          @confirm="sendMessage"
          @input="onInput" />
        
        <!-- 发送按钮 -->
        <button 
          class="send-btn" 
          :class="{ disabled: !inputText.trim() }"
          @click="sendMessage"
          :disabled="!inputText.trim()">
          <text>发送</text>
        </button>
      </view>
    </view>
    
    <!-- 更多工具面板 -->
    <view v-if="showToolsPanel" class="tools-popup">
      <view class="tools-mask" @click="hideToolsPanel"></view>
      <view class="tools-panel">
        <view class="tools-header">
          <text>更多功能</text>
          <button class="close-btn" @click="hideToolsPanel">
            <text class="iconfont icon-close"></text>
          </button>
        </view>
        <view class="tools-grid">
          <view class="tool-item" @click="selectImage">
            <view class="tool-icon">
              <text class="iconfont icon-image"></text>
            </view>
            <text class="tool-text">图片</text>
          </view>
          <view class="tool-item" @click="selectFile">
            <view class="tool-icon">
              <text class="iconfont icon-file"></text>
            </view>
            <text class="tool-text">文件</text>
          </view>
          <view class="tool-item" @click="startRecord">
            <view class="tool-icon">
              <text class="iconfont icon-voice"></text>
            </view>
            <text class="tool-text">语音</text>
          </view>
          <view class="tool-item" @click="selectLocation">
            <view class="tool-icon">
              <text class="iconfont icon-location"></text>
            </view>
            <text class="tool-text">位置</text>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 语音输入面板 -->
    <view v-if="enalbeVoicePanelShow" class="voice-popup">
      <view class="voice-mask" @click="hideVoicePanel"></view>
      <view class="voice-input-panel">
        <view class="voice-header">
          <text>语音输入</text>
          <button class="close-btn" @click="hideVoicePanel">
            <text class="iconfont icon-close"></text>
          </button>
        </view>
        <view class="voice-content">
          <view class="voice-wave" :class="{ recording: voiceInputing }">
            <view 
              v-for="i in 8" 
              :key="i" 
              class="wave-bar"
              :style="{ animationDelay: (i * 0.1) + 's' }"></view>
          </view>
          <text class="voice-tip">{{ voiceInputing ? '正在录音，松开结束' : '点击开始录音' }}</text>
        </view>
        <view class="voice-actions">
          <button class="voice-btn" @click="toggleVoiceInput">
            <text class="iconfont" :class="voiceInputing ? 'icon-stop' : 'icon-voice'"></text>
          </button>
        </view>
      </view>
    </view>
    
    <!-- 头像选择弹窗 -->
    <view v-if="showAvatarSelector" class="avatar-selector-popup">
      <view class="avatar-selector-mask" @click="closeAvatarSelector"></view>
      <view class="avatar-selector-panel">
        <view class="avatar-selector-header">
          <text>更换头像</text>
          <button class="close-btn" @click="closeAvatarSelector">
            <text class="iconfont icon-close"></text>
          </button>
        </view>
        <view class="avatar-selector-content">
          <!-- 预览当前头像 -->
          <view class="current-avatar-preview">
            <image :src="localUserAvatar" mode="aspectFill" />
          </view>
          <view class="avatar-selector-actions">
            <button class="avatar-select-action" @click="chooseAvatarFromAlbum">
              <text class="iconfont icon-album"></text>
              <text>从相册选择</text>
            </button>
            <button class="avatar-select-action" @click="takeAvatarWithCamera">
              <text class="iconfont icon-camera"></text>
              <text>拍照上传</text>
            </button>
            <button class="avatar-select-action cancel" @click="closeAvatarSelector">
              <text>取消</text>
            </button>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 新增：昵称编辑弹窗 -->
    <view v-if="showNicknameEditor" class="nickname-editor-popup">
      <view class="nickname-editor-mask" @click="closeNicknameEditor"></view>
      <view class="nickname-editor-panel">
        <view class="nickname-editor-header">
          <text>修改昵称</text>
          <button class="close-btn" @click="closeNicknameEditor">
            <text class="iconfont icon-close"></text>
          </button>
        </view>
        <view class="nickname-editor-content">
          <view class="nickname-input-container">
            <input 
              v-model="tempNickname" 
              class="nickname-input"
              placeholder="请输入您的新昵称"
              :maxlength="12"
              type="text" />
          </view>
          <view class="nickname-tip">昵称长度限制1-12个字符，仅自己可见</view>
          <view class="nickname-editor-actions">
            <button class="nickname-action-btn cancel" @click="closeNicknameEditor">
              <text>取消</text>
            </button>
            <button 
              class="nickname-action-btn confirm" 
              :class="{ disabled: !tempNickname.trim() }"
              :disabled="!tempNickname.trim()"
              @click="saveNickname">
              <text>保存</text>
            </button>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>
<script>
import aiService from '@/common/js/ai-service.js'

export default {
  name: 'ai-chat-message',
  props: {
    // 初始消息列表
    initialMessages: {
      type: Array,
      default: () => []
    },
    // 初始用户头像（外部传入，可选）
    initUserAvatar: {
      type: String,
      default: ''
    },
    // 初始用户昵称（外部传入，可选）
    initUserNickname: {
      type: String,
      default: ''
    },
    // 是否显示加载更多
    showLoadMore: {
      type: Boolean,
      default: true
    },
    // 最大消息数量
    maxMessages: {
      type: Number,
      default: 100
    },
    // 是否启用流式响应
    enableStreaming: {
      type: Boolean,
      default: true
    },
    // 流式响应速度（字符/秒）
    streamSpeed: {
      type: Number,
      default: 20
    }
  },
  data(){
    return {
      messages: [],
      inputText: '',
      scrollTop: 0,
      hasMoreHistory: false,
      loadingText: '加载更多历史消息',
      voiceInputing: false,
      audioContext: null,
      currentAudio: null,
      messageId: 0,
      showToolsPanel: false,
      enalbeVoicePanelShow: false,
      streamingMessage: null,
      streamInterval: null,
      streamContent: '',
      isStreaming: false,
      // 固定AI头像
      aiAvatar: '/static/images/ai-avatar.png',
      // 本地用户头像（优先使用缓存，无缓存则用默认图）
      localUserAvatar: '',
      // 默认头像路径
      defaultAvatar: '/static/images/default-avatar.png',
      // 头像选择弹窗控制
      showAvatarSelector: false,
      // 新增：用户昵称相关
      localUserNickname: '', // 当前用户昵称
      defaultNickname: '我', // 默认昵称
      showNicknameEditor: false, // 昵称编辑弹窗控制
      tempNickname: '', // 昵称编辑临时值
      // Dify API相关
      currentConversationId: null,
      isAIServiceAvailable: true,
      aiServiceError: null,
	  isLoadingHistory: false, // 新增：标记历史加载状态
      shouldScrollToBottom: false,
	   scrollTimer: null,
	  lastScrollTop: 0,
	  historyOffset: 0,
	   isFetchingHistory: false
    }
  },
  onShow() {
           // 优先读取本地缓存的会话 ID
           const localConvId = this.getConversationIdFromLocal();
           if (localConvId) {
             this.currentConversationId = localConvId;
             aiService.setConversationId(localConvId);
           } else {
             this.currentConversationId = aiService.getConversationId();
           }
           // 加载初始历史后，同步historyOffset
               this.loadChatHistoryIfExist().then(() => {
                 // 初始历史条数作为偏移量
                 this.historyOffset = this.messages.length;
               });
               // 移除：this.historyOffset = 0;（避免覆盖初始历史的偏移量）
             },
             // 新增：组件销毁时清除防抖定时器
             beforeDestroy() {
               if (this.scrollTimer) clearTimeout(this.scrollTimer);
             },
  created() {
    this.messages = [...this.initialMessages]
    this.messageId = this.messages.length
    this.initAudioContext()
    // 初始化用户头像（缓存优先）
    this.initUserAvatarData()
    // 初始化用户昵称（缓存优先）
    this.initUserNicknameData()
	this.currentConversationId = aiService.getConversationId();
  },
   mounted() {
      // 初始加载时滚底（仅一次）
      this.$nextTick(() => {
        this.scrollToBottom()
      })
    },
  watch: {
      messages: {
        handler() {
          this.$nextTick(() => {
            // 仅当不是加载历史、且需要滚底时，才执行滚底
            if (!this.isLoadingHistory && this.shouldScrollToBottom) {
              this.scrollToBottom()
              // 滚底后重置状态，避免重复触发
              this.shouldScrollToBottom = false
            }
          })
        },
      deep: true
    }
  },
  methods: {
	  // 【新增：会话 ID 本地缓存方法】
	   saveConversationIdToLocal(convId) {
	      if (convId) {
	        uni.setStorageSync('dify_conversation_id', convId);
	      }
	    },
	    getConversationIdFromLocal() {
	      return uni.getStorageSync('dify_conversation_id') || null;
	    },
	    clearConversationIdFromLocal() {
	      uni.removeStorageSync('dify_conversation_id');
	    },
    // 初始化音频上下文
    initAudioContext() {
      // #ifdef H5
      if (window.AudioContext) {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
      }
      // #endif
    },
        onScroll(e) {
          const currentScrollTop = e.detail.scrollTop;
          this.lastScrollTop = currentScrollTop;
          // 防抖处理：50ms内只执行一次，避免频繁触发
          if (this.scrollTimer) clearTimeout(this.scrollTimer);
          this.scrollTimer = setTimeout(() => {
            // 滚动到顶部附近（<20px）、不在加载中、显示加载更多时，触发加载
            if (currentScrollTop < 20 && !this.isLoadingHistory && this.showLoadMore) {
              this.loadMoreHistory();
            }
          }, 50);
        },
    // 初始化用户头像（支持缓存持久化）
    initUserAvatarData() {
      // 1. 优先读取本地缓存的头像
      const cachedAvatar = uni.getStorageSync('user_avatar')
      
      if (cachedAvatar) {
        this.localUserAvatar = cachedAvatar
      } 
      // 2. 无缓存时，使用外部传入的初始头像
      else if (this.initUserAvatar) {
        this.localUserAvatar = this.initUserAvatar
        // 缓存初始头像
        uni.setStorageSync('user_avatar', this.initUserAvatar)
      } 
      // 3. 最后使用默认头像
      else {
        this.localUserAvatar = this.defaultAvatar
      }
    },
    // 👇 新增：加载历史记录
   async loadChatHistoryIfExist() {
     const convId = aiService.getConversationId();
     if (convId) {
       try {
         const history = await aiService.getChatHistory();
         if (!history || !Array.isArray(history.messages)) {
           console.warn('历史记录为空或格式无效');
           return;
         }
   
         this.messages = history.messages.map(msg => {
           let content = '';
           if (msg.role === 'user') {
             content = msg.query || (typeof msg.inputs === 'string' ? msg.inputs : JSON.stringify(msg.inputs || '')) || '';
           } else {
             content = msg.answer || '';
           }
           return {
             id: msg.message_id || (Date.now() + Math.random() * 10000),
             role: msg.role === 'user' ? 'user' : 'assistant',
             content: content,
             timestamp: msg.created_at,
             actions: msg.role !== 'user' ? [
               { id: 1, text: '有帮助', type: 'like' },
               { id: 2, text: '没帮助', type: 'dislike' }
             ] : []
           };
         });
       } catch (error) {
         console.error('加载历史记录失败:', error);
         aiService.clearConversationId();
         this.clearConversationIdFromLocal();
         this.currentConversationId = null;
       }
     }
   },
    // 新增：初始化用户昵称（支持缓存持久化）
    initUserNicknameData() {
      // 1. 优先读取本地缓存的昵称
      const cachedNickname = uni.getStorageSync('user_nickname')
      
      if (cachedNickname) {
        this.localUserNickname = cachedNickname
      } 
      // 2. 无缓存时，使用外部传入的初始昵称
      else if (this.initUserNickname) {
        this.localUserNickname = this.initUserNickname
        // 缓存初始昵称
        uni.setStorageSync('user_nickname', this.initUserNickname)
      } 
      // 3. 最后使用默认昵称
      else {
        this.localUserNickname = this.defaultNickname
      }
    },
    
    // 打开头像选择弹窗
    openAvatarSelector() {
      this.showAvatarSelector = true
    },
    
    // 关闭头像选择弹窗
    closeAvatarSelector() {
      this.showAvatarSelector = false
    },
    
    // 从相册选择头像
    chooseAvatarFromAlbum() {
      this.selectAvatar('album')
    },
    
    // 拍照上传头像
    takeAvatarWithCamera() {
      this.selectAvatar('camera')
    },
    
    // 统一头像选择方法
    selectAvatar(sourceType) {
      uni.chooseImage({
        count: 1, // 仅选择1张
        sizeType: ['compressed'], // 压缩图片
        sourceType: [sourceType], // 来源：相册/相机
        success: (res) => {
          const tempFilePath = res.tempFilePaths[0]
          
          // 1. 本地预览更新
          this.localUserAvatar = tempFilePath
          
          // 2. 持久化缓存（支持页面刷新后保留）
          uni.setStorageSync('user_avatar', tempFilePath)
          
          // 3. 通知父组件（可选，用于同步到服务器等场景）
          this.$emit('avatar-changed', tempFilePath)
          
          // 4. 关闭弹窗
          this.closeAvatarSelector()
          
          // 5. 提示成功
          uni.showToast({
            title: '头像更换成功',
            icon: 'success',
            duration: 1500
          })
        },
        fail: (error) => {
          console.error('选择头像失败:', error)
          // 权限拒绝处理
          if (error.errMsg.includes('deny')) {
            uni.showToast({
              title: '请开启相册/相机权限',
              icon: 'none',
              duration: 2000
            })
          } else {
            uni.showToast({
              title: '头像选择失败，请重试',
              icon: 'none',
              duration: 2000
            })
          }
        }
      })
    },
    
    // 新增：打开昵称编辑弹窗
    openNicknameEditor() {
      // 初始化临时昵称值为当前昵称
      this.tempNickname = this.localUserNickname
      this.showNicknameEditor = true
    },
    
    // 新增：关闭昵称编辑弹窗
    closeNicknameEditor() {
      this.showNicknameEditor = false
      // 清空临时值
      this.tempNickname = ''
    },
    
    // 新增：保存用户昵称
    saveNickname() {
      if (!this.tempNickname.trim()) return
      
      // 1. 更新本地昵称
      this.localUserNickname = this.tempNickname.trim()
      
      // 2. 持久化缓存（支持页面刷新后保留）
      uni.setStorageSync('user_nickname', this.localUserNickname)
      
      // 3. 通知父组件（可选，用于同步到服务器等场景）
      this.$emit('nickname-changed', this.localUserNickname)
      
      // 4. 关闭弹窗
      this.closeNicknameEditor()
      
      // 5. 提示成功
      uni.showToast({
        title: '昵称修改成功',
        icon: 'success',
        duration: 1500
      })
    },
    
    // 发送消息
    async sendMessage() {
      if (!this.inputText.trim()) return
      
      const userMessage = {
        id: ++this.messageId,
        role: 'user',
        type: 'text',
        content: this.inputText.trim(),
        timestamp: Date.now()
      }
       this.shouldScrollToBottom = true
      this.messages.push(userMessage)
      this.inputText = ''
      
      // 显示AI正在输入
      const loadingMessage = {
        id: ++this.messageId,
        role: 'ai',
        type: 'loading',
        content: '',
        timestamp: Date.now()
      }
      this.shouldScrollToBottom = true
      this.messages.push(loadingMessage)
      
      try {
        // 检查AI服务状态
        const status = await aiService.getServiceStatus()
        this.isAIServiceAvailable = status.available
        
        if (!this.isAIServiceAvailable) {
          throw new Error('AI服务暂不可用')
        }
        
        // 使用AI服务获取回复
        if (this.enableStreaming) {
          await this.sendStreamMessage(userMessage.content)
        } else {
          await this.sendNormalMessage(userMessage.content)
        }
        
      } catch (error) {
        console.error('AI服务调用失败:', error)
        
        // 移除加载状态
        this.messages = this.messages.filter(msg => msg.type !== 'loading')
        
        // 显示错误消息
        const errorMessage = {
          id: ++this.messageId,
          role: 'ai',
          type: 'text',
          content: '抱歉，AI服务暂时不可用，请稍后重试。',
          timestamp: Date.now(),
          actions: [
            { id: 1, text: '重试', type: 'retry' }
          ]
        }
        this.shouldScrollToBottom = true
        this.messages.push(errorMessage)
        this.$emit('ai-response', errorMessage)
      }
      
      // 触发消息发送事件
      this.$emit('message-sent', userMessage)
    },
    
    // 发送普通消息
    async sendNormalMessage(userMessage) {
      const response = await aiService.sendMessage(userMessage, {
        conversationId: this.currentConversationId,
        stream: false
      })
      
      // 移除加载状态
      this.messages = this.messages.filter(msg => msg.type !== 'loading')
      
      // 更新会话ID
      if (response.conversationId) {
        this.currentConversationId = response.conversationId;
		aiService.setConversationId(response.conversationId);
		  this.saveConversationIdToLocal(response.conversationId);
      }
      
      const aiMessage = {
        id: ++this.messageId,
        role: 'ai',
        type: 'text',
        content: response.content,
        timestamp: Date.now(),
        conversationId: response.conversationId,
        messageId: response.messageId,
        actions: [
          { id: 1, text: '有帮助', type: 'like' },
          { id: 2, text: '没帮助', type: 'dislike' }
        ]
      }
      this.shouldScrollToBottom = true
      this.messages.push(aiMessage)
      this.$emit('ai-response', aiMessage)
    },
    
    // 发送流式消息
    async sendStreamMessage(userMessage) {
      // 创建流式消息对象
      const streamMessage = {
        id: ++this.messageId,
        role: 'ai',
        type: 'text',
        content: '',
        timestamp: Date.now(),
        isStreaming: true
      }
      
      // 移除加载状态，添加流式消息
      this.messages = this.messages.filter(msg => msg.type !== 'loading')
	  this.shouldScrollToBottom = true
      this.messages.push(streamMessage)
      
     // 开始流式响应
     await aiService.sendStreamMessage(
       userMessage,
       // 流式数据回调
       (chunk) => {
         streamMessage.content += chunk
         this.$forceUpdate() // 或 this.$nextTick()
       },
       // 完成回调：处理对象或字符串
       (completeResult) => {
         let finalContent = '';
         let convId = '';
     
         // 判断是对象还是字符串
         if (typeof completeResult === 'string') {
           finalContent = completeResult;
         } else {
           finalContent = completeResult.content || '';
           convId = completeResult.conversation_id || ''; // 👈 关键：提取 conversation_id
         }
     
         // 更新消息状态
         streamMessage.isStreaming = false;
         streamMessage.content = finalContent;
     
         // 添加操作按钮
         streamMessage.actions = [
           { id: 1, text: '有帮助', type: 'like' },
           { id: 2, text: '没帮助', type: 'dislike' }
         ];
     
         //  保存 conversation_id 到本地
         if (convId) {
           aiService.setConversationId(convId);
         }
     
         // 触发事件
         this.$emit('ai-response', streamMessage);
		 this.saveConversationIdToLocal(convId);
		 this.currentConversationId = convId;
       }
     );
	 },
    generateAIResponse(userMessage) {
      const responses = {
        '你好': '您好！我是AI智能客服，很高兴为您服务！有什么可以帮助您的吗？',
        '价格': '我们的产品价格根据型号和配置有所不同，具体价格请查看商品详情页面。',
        '发货': '一般情况下，订单会在24小时内发货，具体时效请查看物流信息。',
        '退货': '支持7天无理由退货，请确保商品完好无损。',
        '客服': '我们的客服工作时间是9:00-18:00，有问题可以随时联系我们。'
      };
      for (let key in responses) {
        if (userMessage.includes(key)) {
          return responses[key];
        }
      }
      return `感谢您的咨询！关于"${userMessage}"的问题，我们的专业客服会尽快为您解答。您也可以查看我们的帮助文档获取更多信息。`;
    },
  
    
    // 解析Markdown
    parseMarkdown(content) {
      if (!content) return ''
      
      // 简单的Markdown解析
      let html = content
        .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // 粗体
        .replace(/\*(.*?)\*/g, '<em>$1</em>') // 斜体
        .replace(/`(.*?)`/g, '<code>$1</code>') // 代码
        .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>') // 链接
        .replace(/\n/g, '<br>') // 换行
      
      return html
    },
    
    // 格式化时间
    formatTime(timestamp) {
      const date = new Date(timestamp)
      const now = new Date()
      const diff = now - date
      
      if (diff < 60000) { // 1分钟内
        return '刚刚'
      } else if (diff < 3600000) { // 1小时内
        return Math.floor(diff / 60000) + '分钟前'
      } else if (diff < 86400000) { // 1天内
        return Math.floor(diff / 3600000) + '小时前'
      } else {
        return date.getMonth() + 1 + '月' + date.getDate() + '日 ' + 
               date.getHours().toString().padStart(2, '0') + ':' + 
               date.getMinutes().toString().padStart(2, '0')
      }
    },
    
    // 格式化文件大小
    formatFileSize(bytes) {
      if (!bytes) return '0B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + sizes[i]
    },
    
    // 格式化时长
    formatDuration(seconds) {
      if (!seconds) return '00:00'
      const mins = Math.floor(seconds / 60)
      const secs = Math.floor(seconds % 60)
      return mins.toString().padStart(2, '0') + ':' + secs.toString().padStart(2, '0')
    },
    
    // 滚动到底部
    scrollToBottom() {
      setTimeout(() => {
        this.scrollTop = 999999
      }, 100)
    },
    
    // 加载更多历史消息
 async loadMoreHistory() {
       if (!this.currentConversationId) {
         this.currentConversationId = this.getConversationIdFromLocal();
         aiService.setConversationId(this.currentConversationId);
       }
       // 防止重复加载
       if (!this.showLoadMore || !this.currentConversationId || this.isLoadingHistory) {
         return;
       }
       this.isFetchingHistory = true;
       this.isLoadingHistory = true;
       this.loadingText = '加载历史消息中...';
       this.hasMoreHistory = true;
 
       try {
         // 关键修改：用独立的historyOffset作为偏移量，不再依赖messages.length
         const response = await aiService.getConversationHistory({
           conversation_id: this.currentConversationId,
           limit: 20,
           offset: this.historyOffset // 改用独立偏移量
         });
 
         if (response.success && Array.isArray(response.messages) && response.messages.length > 0) {
           const historyMessages = response.messages.map(msg => ({
             id: msg.id || `history-${Date.now()}-${Math.random().toString(36).slice(2)}`,
             role: msg.role === 'user' ? 'user' : 'ai',
             type: 'text',
             content: msg.content,
             timestamp: msg.create_time * 1000
           }));
 
           // 1. 记录新增消息数量
           const newMsgCount = historyMessages.length;
           // 2. 添加到消息列表开头
           this.messages = [...historyMessages, ...this.messages];
           // 3. 更新历史偏移量（累加，不是覆盖）
           this.historyOffset += newMsgCount;
 
           // 4. 等待DOM渲染后，精准计算滚动位置
           await this.$nextTick();
           // 获取新增消息的实际DOM高度
           const query = uni.createSelectorQuery().in(this);
           const heightPromises = [];
           for (let i = 0; i < newMsgCount; i++) {
             heightPromises.push(new Promise(resolve => {
               query.select(`.message-item:nth-child(${i + 1})`).boundingClientRect(rect => {
                 resolve(rect ? rect.height + 32 : 0); // 加上消息间距（32rpx）
               }).exec();
             }));
           }
           // 计算总高度
           const heights = await Promise.all(heightPromises);
           const totalNewHeight = heights.reduce((sum, h) => sum + h, 0);
           // 5. 设置scrollTop，保持滚动条在顶部附近
           this.scrollTop = totalNewHeight;
         } else {
           // 无更多历史
           this.showLoadMore = false;
         }
       } catch (error) {
         console.error('加载历史失败:', error);
         uni.showToast({ title: '加载历史失败', icon: 'none' });
         this.showLoadMore = false;
       } finally {
         this.isLoadingHistory = false;
		  this.isFetchingHistory = false;
         this.hasMoreHistory = false;
         this.loadingText = '加载更多历史消息';
       }
     },
    // 显示更多工具
    showMoreTools() {
      this.showToolsPanel = true
    },
    
    // 隐藏工具面板
    hideToolsPanel() {
      this.showToolsPanel = false
    },
    
    // 显示语音面板
    showVoicePanel() {
      this.enalbeVoicePanelShow = true
    },
    
    // 隐藏语音面板
    hideVoicePanel() {
      this.enalbeVoicePanelShow = false
      this.voiceInputing = false
    },
    
    // 切换语音输入
    toggleVoiceInput() {
      this.voiceInputing = !this.voiceInputing
      
      if (this.voiceInputing) {
        this.showVoicePanel()
        this.startVoiceInput()
      } else {
        this.stopVoiceInput()
        this.hideVoicePanel()
      }
    },
    
    // 开始语音输入
    startVoiceInput() {
      // #ifdef H5
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({ audio: true })
          .then(stream => {
            // 语音输入处理
            console.log('语音输入开始')
          })
          .catch(error => {
            console.error('语音输入错误:', error)
            uni.showToast({
              title: '语音输入失败',
              icon: 'none'
            })
          })
      }
      // #endif
    },
    
    // 停止语音输入
    stopVoiceInput() {
      this.voiceInputing = false
      // 停止语音输入逻辑
    },
    
    // 预览文件
    previewFile(message) {
      uni.showLoading({ title: '打开文件中...' })
      
      // #ifdef H5
      window.open(message.url, '_blank')
      // #endif
      
      // #ifdef APP-PLUS
      plus.runtime.openFile(message.url, {
        error: (e) => {
          uni.showToast({
            title: '文件打开失败',
            icon: 'none'
          })
        }
      })
      // #endif
      
      uni.hideLoading()
      this.$emit('file-preview', message)
    },
    // 切换音频播放
    toggleAudio(message) {
      if (message.playing) {
        this.pauseAudio(message)
      } else {
        this.playAudio(message)
      }
    },
    
    // 播放音频
    playAudio(message) {
      if (this.currentAudio && this.currentAudio !== message) {
        this.pauseAudio(this.currentAudio)
      }
      
      // 模拟音频播放
      message.playing = true
      message.currentTime = message.currentTime || 0
      
      this.currentAudio = message
      this.$emit('audio-play', message)
    },
    
    // 暂停音频
    pauseAudio(message) {
      message.playing = false
      this.$emit('audio-pause', message)
    },
    
    // 音频滑块变化
    onAudioSliderChange(e) {
      if (this.currentAudio) {
        this.currentAudio.currentTime = e.detail.value
      }
    },
    
    onAudioSliderChangeEnd(e) {
      if (this.currentAudio) {
        this.currentAudio.currentTime = e.detail.value
        this.$emit('audio-seek', this.currentAudio)
      }
    },
    
    // 视频播放
    onVideoPlay(message) {
      this.$emit('video-play', message)
    },
    
    // 视频暂停
    onVideoPause(message) {
      this.$emit('video-pause', message)
    },
    
    // 打开链接
    openLink(message) {
      // #ifdef H5
      window.open(message.url, '_blank')
      // #endif
      
      // #ifdef APP-PLUS
      plus.runtime.openURL(message.url)
      // #endif
      
      this.$emit('link-open', message)
    },
    
    // 查看商品
    viewProduct(message) {
      this.$emit('product-view', message)
    },
    
    // 处理操作
    handleAction(action, message) {
      // 处理重试操作
      if (action.type === 'retry') {
        this.retryMessage(message)
        return
      }
      
      this.$emit('action-click', { action, message })
    },
    
    // 重试消息
    async retryMessage(message) {
      // 找到对应的用户消息
      const userMessageIndex = this.messages.findIndex(msg => 
        msg.role === 'user' && msg.id < message.id
      )
      
      if (userMessageIndex !== -1) {
        const userMessage = this.messages[userMessageIndex]
        
        // 移除错误消息
        this.messages = this.messages.filter(msg => msg.id !== message.id)
        
        // 重新发送消息
        await this.sendMessageWithContent(userMessage.content)
      }
    },
    
    // 使用指定内容发送消息
    async sendMessageWithContent(content) {
      const userMessage = {
        id: ++this.messageId,
        role: 'user',
        type: 'text',
        content: content,
        timestamp: Date.now()
      }
      
      this.messages.push(userMessage)
      
      // 显示AI正在输入
      const loadingMessage = {
        id: ++this.messageId,
        role: 'ai',
        type: 'loading',
        content: '',
        timestamp: Date.now()
      }
      
      this.messages.push(loadingMessage)
      
      try {
        // 使用AI服务获取回复
        if (this.enableStreaming) {
          // 流式响应
          await this.sendStreamMessage(userMessage.content)
        } else {
          // 普通响应
          await this.sendNormalMessage(userMessage.content)
        }
        
      } catch (error) {
        console.error('AI服务调用失败:', error)
        
        // 移除加载状态
        this.messages = this.messages.filter(msg => msg.type !== 'loading')
        
        // 显示错误消息
        const errorMessage = {
          id: ++this.messageId,
          role: 'ai',
          type: 'text',
          content: '抱歉，AI服务暂时不可用，请稍后重试。',
          timestamp: Date.now(),
          actions: [
            { id: 1, text: '重试', type: 'retry' }
          ]
        }
        
        this.messages.push(errorMessage)
        this.$emit('ai-response', errorMessage)
      }
      
      // 触发消息发送事件
      this.$emit('message-sent', userMessage)
    },
    
    // 输入事件
    onInput(e) {
      this.$emit('input-change', e.detail.value)
    },
    
    // 选择图片
    selectImage() {
      uni.chooseImage({
        count: 1,
        sizeType: ['compressed'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          const tempFilePaths = res.tempFilePaths
          const imageMessage = {
            id: ++this.messageId,
            role: 'user',
            type: 'image',
            content: '',
            imageUrl: tempFilePaths[0],
            timestamp: Date.now()
          }
          this.messages.push(imageMessage)
          this.hideToolsPanel()
          this.$emit('image-selected', imageMessage)
        }
      })
    },
    
    // 选择文件
    selectFile() {
      // #ifdef H5
      const input = document.createElement('input')
      input.type = 'file'
      input.accept = '*/*'
      input.onchange = (e) => {
        const file = e.target.files[0]
        if (file) {
          const fileMessage = {
            id: ++this.messageId,
            role: 'user',
            type: 'file',
            content: '',
            fileName: file.name,
            fileSize: file.size,
            fileType: file.type,
            timestamp: Date.now()
          }
          this.messages.push(fileMessage)
          this.hideToolsPanel()
          this.$emit('file-selected', fileMessage)
        }
      }
      input.click()
      // #endif
      
      // #ifdef APP-PLUS
      uni.chooseFile({
        count: 1,
        success: (res) => {
          const file = res.tempFiles[0]
          const fileMessage = {
            id: ++this.messageId,
            role: 'user',
            type: 'file',
            content: '',
            fileName: file.name,
            fileSize: file.size,
            fileType: file.type,
            url: file.path,
            timestamp: Date.now()
          }
          this.messages.push(fileMessage)
          this.hideToolsPanel()
          this.$emit('file-selected', fileMessage)
        }
      })
      // #endif
    },
    
    // 开始录音
    startRecord() {
      this.toggleVoiceInput()
    },
    
    // 选择位置
    selectLocation() {
      uni.chooseLocation({
        success: (res) => {
          const locationMessage = {
            id: ++this.messageId,
            role: 'user',
            type: 'location',
            content: '',
            latitude: res.latitude,
            longitude: res.longitude,
            address: res.address,
            name: res.name,
            timestamp: Date.now()
          }
          this.messages.push(locationMessage)
          this.hideToolsPanel()
          this.$emit('location-selected', locationMessage)
        }
      })
    }
  }
}
</script>
<style lang="scss" scoped>
/* 引入图标字体 */
@import url('/common/css/iconfont.css');

/* 全局变量：高级低饱和配色 */
$bg-main: #f5f7fa;
$bg-card: #ffffff;
$color-primary: #6c8ebf;
$color-primary-light: #8a9fb8;
$color-user: #8675a9;
$color-text: #4e5969;
$color-text-light: #8492a6;
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
$shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
$radius-sm: 12rpx;
$radius-md: 24rpx;
$radius-lg: 36rpx;

/* 页面样式 */
.ai-chat-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  /* 仅新增：科技感粉蓝渐变背景 + 流动动画 */
  background: linear-gradient(135deg, #fde6f7 0%, #f8b7e8 20%, #c4e0ff 50%, #8cb4ff 80%, #ffffff 100%);
  background-size: 200% 200%;
  animation: gradient-flow 15s ease infinite;
  /* 原有样式保持不变 */
  overflow: hidden;
  padding-bottom: env(safe-area-inset-bottom);
  box-sizing: border-box;
  position: relative;

  .chat-messages {
    flex: 1;
    padding: 24rpx 32rpx;
    overflow-y: auto;
    box-sizing: border-box;
    min-height: 0; /* 重要：防止flex元素溢出 */

    .load-more {
      text-align: center;
      padding: 24rpx 0;
      color: $color-text-light;
    }

    .message-item {
      margin-bottom: 32rpx;
      
      &.first-message {
        margin-top: 24rpx;
      }

      .user-message, .ai-message {
        display: flex;
        align-items: flex-start;

        .avatar {
          width: 88rpx;
          height: 88rpx;
          border-radius: 50%;
          overflow: hidden;
          flex-shrink: 0;
          box-shadow: $shadow-sm;
          background-color: $bg-card;
          border: 2rpx solid #f0f4f8;
          transition: transform 0.2s ease;
          
          &:hover {
            transform: scale(1.03);
          }
          
          image {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }

        .message-content {
          flex: 1;
          margin-left: 24rpx;
          max-width: calc(100% - 112rpx);
          min-width: 0;
          width: 0; /* 添加这个属性防止flex元素溢出 */

          .message-nickname {
            font-size: 24rpx;
            color: $color-text-light;
            margin-bottom: 8rpx;
            letter-spacing: 0.5rpx;
            // 用户昵称右对齐，AI昵称左对齐
            &:not(.ai-message .message-nickname) {
              text-align: right;
            }
            // AI昵称专属样式 - 左移到气泡上方
            &.ai-nickname {
              text-align: left;
              margin-left: 0;
              padding-left: 0;
              align-self: flex-start;
              margin-bottom: 4rpx;
            }
          }

          .message-bubble {
            padding: 24rpx 32rpx;
            max-width: 100%;
            word-break: break-word;
            box-shadow: $shadow-md;
            position: relative;
            border: 1rpx solid #f0f4f8;

            .message-text {
              font-size: 28rpx;
              line-height: 1.7;
              position: relative;
              z-index: 1;
              letter-spacing: 0.8rpx;
            }
          }

          .message-time {
            font-size: 22rpx;
            color: $color-text-light;
            margin-top: 12rpx;
            opacity: 0.9;
            letter-spacing: 0.5rpx;
          }

          /* 各种消息类型样式 */
          .markdown-content {
            .markdown-header {
              display: flex;
              align-items: center;
              margin-bottom: 16rpx;
              
              .icon-markdown {
                color: $color-primary;
                margin-right: 12rpx;
                font-size: 28rpx;
              }
              
              .markdown-title {
                font-weight: 600;
                color: $color-text;
                font-size: 28rpx;
              }
            }
            
            .markdown-body {
              line-height: 1.8;
              font-size: 26rpx;
              color: $color-text;
              
              strong {
                font-weight: 600;
                color: $color-text;
              }
              
              em {
                font-style: italic;
                color: $color-text-light;
              }
              
              code {
                background-color: #f0f4f8;
                padding: 4rpx 8rpx;
                border-radius: $radius-sm;
                font-family: monospace;
                font-size: 24rpx;
                color: $color-primary;
              }
              
              a {
                color: $color-primary;
                text-decoration: underline;
                text-underline-offset: 4rpx;
                transition: color 0.2s ease;
                
                &:hover {
                  color: #5a7cb0;
                }
              }
            }
          }

          .file-content {
            .file-item {
              display: flex;
              align-items: center;
              padding: 24rpx;
              background-color: $bg-card;
              border-radius: $radius-md;
              border: 1rpx solid #f0f4f8;
              transition: all 0.3s ease;
              
              &:hover {
                background-color: #fafbfc;
                box-shadow: $shadow-md;
              }
              
              .file-icon {
                margin-right: 24rpx;
                
                .icon-file {
                  font-size: 52rpx;
                  color: $color-primary;
                }
              }
              
              .file-info {
                flex: 1;
                
                .file-name {
                  display: block;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  font-size: 26rpx;
                  color: $color-text;
                }
                
                .file-size {
                  font-size: 24rpx;
                  color: $color-text-light;
                }
              }
              
              .file-action {
                .icon-download {
                  font-size: 38rpx;
                  color: $color-primary;
                  transition: transform 0.2s ease;
                }
                
                &:hover .icon-download {
                  transform: scale(1.1);
                }
              }
            }
          }

          .audio-content {
            .audio-player {
              .audio-info {
                margin-bottom: 16rpx;
                
                .audio-title {
                  display: block;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  font-size: 26rpx;
                  color: $color-text;
                }
                
                .audio-duration {
                  font-size: 24rpx;
                  color: $color-text-light;
                }
              }
              
              .audio-controls {
                display: flex;
                align-items: center;
                
                .play-btn {
                  width: 68rpx;
                  height: 68rpx;
                  border-radius: 50%;
                  background-color: $color-primary;
                  color: white;
                  margin-right: 24rpx;
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  box-shadow: 0 4rpx 12rpx rgba(108, 142, 191, 0.3);
                  transition: all 0.2s ease;
                  
                  &.playing {
                    background-color: $color-primary-light;
                    box-shadow: 0 2rpx 8rpx rgba(138, 159, 184, 0.2);
                  }
                  
                  &:hover {
                    transform: scale(1.05);
                  }
                }
                
                .audio-slider {
                  flex: 1;
                }
              }
            }
          }

          .video-content {
            .video-player {
              .video-element {
                width: 100%;
                height: 420rpx;
                border-radius: $radius-md;
                overflow: hidden;
                box-shadow: $shadow-md;
              }
              
              .video-info {
                margin-top: 16rpx;
                
                .video-title {
                  display: block;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  font-size: 26rpx;
                  color: $color-text;
                }
                
                .video-duration {
                  font-size: 24rpx;
                  color: $color-text-light;
                }
              }
            }
          }

          .link-content {
            .link-card {
              display: flex;
              background-color: $bg-card;
              border-radius: $radius-md;
              overflow: hidden;
              border: 1rpx solid #f0f4f8;
              transition: all 0.3s ease;
              
              &:hover {
                box-shadow: $shadow-md;
                transform: translateY(-2rpx);
              }
              
              .link-image {
                width: 130rpx;
                height: 130rpx;
                flex-shrink: 0;
                border-radius: $radius-md 0 0 $radius-md;
                
                image {
                  width: 100%;
                  height: 100%;
                  object-fit: cover;
                }
              }
              
              .link-info {
                flex: 1;
                padding: 24rpx;
                
                .link-title {
                  display: block;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  font-size: 26rpx;
                  color: $color-text;
                }
                
                .link-desc {
                  display: block;
                  font-size: 24rpx;
                  color: $color-text-light;
                  margin-bottom: 6rpx;
                  display: -webkit-box;
                  -webkit-line-clamp: 1;
                  -webkit-box-orient: vertical;
                  overflow: hidden;
                }
                
                .link-url {
                  display: block;
                  font-size: 22rpx;
                  color: $color-primary;
                  white-space: nowrap;
                  overflow: hidden;
                  text-overflow: ellipsis;
                }
              }
            }
          }

          .product-content {
            .product-card {
              display: flex;
              background-color: $bg-card;
              border-radius: $radius-md;
              overflow: hidden;
              border: 1rpx solid #f0f4f8;
              transition: all 0.3s ease;
              
              &:hover {
                box-shadow: $shadow-md;
                transform: translateY(-2rpx);
              }
              
              .product-image {
                width: 130rpx;
                height: 130rpx;
                flex-shrink: 0;
                
                image {
                  width: 100%;
                  height: 100%;
                  object-fit: cover;
                }
              }
              
              .product-info {
                flex: 1;
                padding: 24rpx;
                
                .product-title {
                  display: block;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  font-size: 26rpx;
                  color: $color-text;
                  display: -webkit-box;
                  -webkit-line-clamp: 1;
                  -webkit-box-orient: vertical;
                  overflow: hidden;
                }
                
                .product-price {
                  display: block;
                  font-size: 28rpx;
                  font-weight: 600;
                  margin-bottom: 6rpx;
                  color: $color-user;
                }
                
                .product-desc {
                  display: block;
                  font-size: 24rpx;
                  color: $color-text-light;
                  display: -webkit-box;
                  -webkit-line-clamp: 1;
                  -webkit-box-orient: vertical;
                  overflow: hidden;
                }
              }
            }
          }

          .loading-content {
            display: flex;
            align-items: center;
            padding: 32rpx 0;
            
            .loading-dots {
              display: flex;
              margin-right: 16rpx;
              
              .dot {
                width: 14rpx;
                height: 14rpx;
                border-radius: 50%;
                background-color: $color-primary;
                margin: 0 6rpx;
                animation: dotPulse 1.5s infinite ease-in-out;
                
                &:nth-child(2) {
                  animation-delay: 0.2s;
                }
                
                &:nth-child(3) {
                  animation-delay: 0.4s;
                }
              }
            }
            
            .loading-text {
              color: $color-text-light;
              font-size: 26rpx;
            }
          }

          .message-actions {
            margin-top: 24rpx;
            display: flex;
            gap: 16rpx;
            justify-content: flex-start;
            
            .action-btn {
              border-radius: $radius-lg;
              font-size: 24rpx;
              background-color: $bg-card;
              padding: 12rpx 28rpx;
              display: flex;
              align-items: center;
              gap: 8rpx;
              transition: all 0.2s ease;
              border: 1rpx solid #f0f4f8;
              color: $color-text;
              
              &.like {
                color: $color-user;
                border-color: #e8e0f2;
                
                &:hover {
                  background-color: #f9f6fc;
                  transform: translateY(-2rpx);
                }
              }
              
              &.dislike {
                color: $color-text-light;
                border-color: #e9edf2;
                
                &:hover {
                  background-color: #f8fafc;
                  transform: translateY(-2rpx);
                }
              }
            }
          }
        }
      }

      /* 用户消息特有样式 */
      .user-message {
        flex-direction: row-reverse;
        
        .message-content {
          margin-left: 0;
          margin-right: 24rpx;
          text-align: right;
          
          .message-bubble {
           background: linear-gradient(135deg, #ffadd2, #f783ac) !important; /* 粉色渐变 */
             color: white !important;
             border-radius: 16rpx 16rpx 4rpx 16rpx; /* 右对齐气泡尖角适配 */
             box-shadow: 0 8rpx 20rpx rgba(247, 131, 172, 0.3) !important;
             border: none !important;
			  /* ✅ 关键：允许内容撑开高度 */
			   min-height: auto;
			   height: auto;
			   padding: 24rpx 32rpx; /* 保留内边距 */
			   display: inline-block; /* 让宽度也随内容收缩（可选） */
			   max-width: 80%; /* 防止过宽 */
			   word-break: break-word;
			   white-space: pre-wrap; /* 保留用户输入的换行符 */
			   line-height: 1.6;
            &::before {
              content: '';
              position: absolute;
              top: 20rpx;
              right: -14rpx;
              width: 24rpx;
              height: 24rpx;
              background: #ffffff !important; /* 菱形改为白色 */
              border-radius: 6rpx;
              transform: rotate(45deg);
              box-shadow: 4rpx -4rpx 4rpx rgba(0, 0, 0, 0.05);
            }
            
            &::after {
              content: '';
              position: absolute;
              top: 0;
              left: -100%;
              width: 50%;
              height: 100%;
              background: linear-gradient(
                to right,
                rgba(255, 255, 255, 0) 0%,
                rgba(255, 255, 255, 0.15) 100%
              );
              animation: shine 4s infinite linear;
            }
          }
        }
      }

      /* AI消息特有样式 */
      .ai-message {
        .message-content {
          /* 确保昵称在气泡上方的布局 */
          display: flex;
          flex-direction: column;
          align-items: flex-start;
          
          .message-bubble {
            background: linear-gradient(135deg, #dbeafe, #bfdbfe) !important; /* 蓝色浅渐变 */
              color: #2c3e50 !important;
              border-radius: 16rpx 16rpx 16rpx 4rpx; /* 左对齐气泡尖角适配 */
              box-shadow: 0 8rpx 20rpx rgba(191, 219, 254, 0.4) !important;
              border: 1rpx solid #dbeafe !important;
            min-height: auto;
              height: auto;
              padding: 24rpx 32rpx;
              display: inline-block;
              max-width: 80%;
              word-break: break-word;
              white-space: pre-wrap;
              line-height: 1.6;
            &::before {
              content: '';
              position: absolute;
              top: 20rpx;
              left: -14rpx;
              width: 24rpx;
              height: 24rpx;
              background: #ffffff !important; /* 菱形改为白色 */
              border-radius: 6rpx;
              transform: rotate(45deg);
              box-shadow: -4rpx 4rpx 4rpx rgba(0, 0, 0, 0.05);
              border: 1rpx solid #f0f4f8;
              border-right: none;
              border-top: none;
            }
          }
        }
      }
    }
  }

  /* 输入区域 */
  .input-area {
    background: linear-gradient(135deg, #fde6f7 0%, #f8b7e8 20%, #c4e0ff 50%, #8cb4ff 80%, #ffffff 100%);
    border-top: 2rpx solid #f0f4f8;
    padding: 24rpx 32rpx;
    /* 确保在微信小程序中紧贴底部 */
    flex-shrink: 0;
    /* 微信小程序安全区域适配 */
    padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
    /* 确保输入区域正确显示 */
    position: relative;
    z-index: 10;
    box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.03);

    .input-tools {
      display: flex;
      margin-bottom: 16rpx;
      
      .tool-btn {
        width: 64rpx;
        height: 64rpx;
        border-radius: 50%;
        background-color: $bg-main;
        margin-right: 16rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.2s ease;
        
        &:hover {
          background-color: #e8edf3;
          transform: scale(1.05);
        }
        
        .iconfont {
          font-size: 34rpx;
          color: $color-text-light;
        }
      }
    }

    .input-container {
      display: flex;
      align-items: flex-end;
      
      .message-input {
        flex: 1;
        min-height: 88rpx;
        max-height: 220rpx;
        background-color: $bg-main;
        border-radius: $radius-lg;
        padding: 24rpx 32rpx;
        font-size: 28rpx;
        line-height: 1.6;
        border: 1rpx solid #e8edf3;
        transition: all 0.2s ease;
        color: $color-text;
        
        &:focus {
          background-color: $bg-card;
          border-color: $color-primary-light;
          box-shadow: 0 0 0 4rpx rgba(138, 159, 184, 0.1);
        }
        
        &::placeholder {
          color: $color-text-light;
          opacity: 0.8;
        }
      }
      
      /* 发送按钮 */
      .send-btn {
        width: 112rpx;
        height: 76rpx;
        border-radius: $radius-lg;
        background-color: $color-primary;
        margin-left: 16rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 4rpx 12rpx rgba(108, 142, 191, 0.2);
        transition: all 0.2s ease;
        color: white;
        font-size: 28rpx;
        font-weight: 500;
        border: none;
         text-align: center;     /* 兼容多端文字居中 */
          white-space: nowrap;    /* 强制文字单行横向显示 */
          line-height: 1;         /* 重置行高，避免文字垂直偏移 */
          top:-10px;
        
        &.disabled {
          background-color: $color-primary-light;
          box-shadow: none;
          opacity: 0.7;
        }
        
        &:not(.disabled):hover {
          transform: scale(1.05);
          background-color: #5a7cb0;
        }
      }
    }
  }

  /* 弹窗容器：确保弹窗层级正确，不影响主布局 */
  .popups-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none; /* 让鼠标事件穿透容器，不影响主内容交互 */
    z-index: 999; /* 基础弹窗层级 */
    
    /* 子弹窗需要开启 pointer-events，否则点击无效 */
    > .tools-popup,
    > .voice-popup,
    > .avatar-selector-popup,
    > .nickname-editor-popup {
      pointer-events: auto;
    }
    
    /* 昵称编辑弹窗层级最高，避免被其他弹窗遮挡 */
    > .nickname-editor-popup {
      z-index: 1001;
    }
  }
  
  // 昵称编辑弹窗样式（修复右侧溢出问题）
  .nickname-editor-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1001;
  }

  .nickname-editor-mask {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(6rpx);
  }

  .nickname-editor-panel {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: $bg-card;
    border-radius: $radius-lg;
    padding: 24rpx 32rpx; // 统一内边距
    width: calc(100% - 80rpx); // 限制弹窗宽度（避免超出屏幕）
    max-width: 520rpx; // 最大宽度（适配不同设备）
    box-shadow: 0 8rpx 36rpx rgba(0, 0, 0, 0.15);
    box-sizing: border-box; // 确保内边距不影响宽度

    .nickname-editor-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 24rpx;
      border-bottom: 2rpx solid #f0f4f8;
      padding-bottom: 16rpx;

      text {
        font-size: 34rpx;
        font-weight: 600;
        color: $color-text;
      }

      .close-btn {
        width: 56rpx;
        height: 56rpx;
        border-radius: 50%;
        background-color: $bg-main;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.2s ease;
        border: none;

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

        .iconfont {
          font-size: 28rpx;
          color: $color-text-light;
        }
      }
    }

    .nickname-editor-content {
      .nickname-input-container {
        margin-bottom: 24rpx;
        width: 100%; // 输入框容器占满弹窗宽度
        box-sizing: border-box;

        .nickname-input {
          width: 100%;
          height: 96rpx;
          padding: 0 24rpx;
          border-radius: $radius-lg;
          border: 2rpx solid #f0f4f8;
          font-size: 28rpx;
          color: $color-text;
          background-color: $bg-main;
          transition: all 0.2s ease;
          box-shadow: none;
          box-sizing: border-box; // 确保输入框不超出容器

          &:focus {
            border-color: $color-primary;
            box-shadow: 0 0 0 4rpx rgba(108, 142, 191, 0.1);
          }

          &::placeholder {
            color: $color-text-light;
            opacity: 0.8;
          }
        }
      }

      .nickname-tip {
        font-size: 24rpx;
        color: $color-text-light;
        margin-bottom: 32rpx;
        display: block;
        line-height: 1.5;
      }

      .nickname-editor-actions {
        display: flex;
        justify-content: flex-end;
        gap: 16rpx;

        .nickname-action-btn {
          padding: 16rpx 32rpx;
          border-radius: $radius-lg;
          font-size: 28rpx;
          font-weight: 500;
          transition: all 0.2s ease;
          border: none;

          &.cancel {
            background-color: $bg-main;
            color: $color-text-light;

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

          &.confirm {
            background-color: $color-primary;
            color: white;
            box-shadow: 0 4rpx 12rpx rgba(108, 142, 191, 0.2);

            &.disabled {
              background-color: $color-primary-light;
              opacity: 0.7;
              box-shadow: none;
            }

            &:not(.disabled):hover {
              background-color: #5a7cb0;
              transform: translateY(-2rpx);
            }
          }
        }
      }
    }
  }

  /* 工具面板 */
  .tools-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 999;

    .tools-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.4);
      backdrop-filter: blur(6rpx);
    }

    .tools-panel {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      background-color: $bg-card;
      border-radius: $radius-lg $radius-lg 0 0;
      padding: 32rpx;
      box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);

      .tools-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 32rpx;
        border-bottom: 2rpx solid #f0f4f8;
        padding-bottom: 16rpx;

        text {
          font-size: 34rpx;
          font-weight: 600;
          color: $color-text;
        }

        .close-btn {
          width: 56rpx;
          height: 56rpx;
          border-radius: 50%;
          background-color: $bg-main;
          display: flex;
          align-items: center;
          justify-content: center;
          transition: all 0.2s ease;
          border: none;

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

          .iconfont {
            font-size: 28rpx;
            color: $color-text-light;
          }
        }
      }

      .tools-grid {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 24rpx;

        .tool-item {
          display: flex;
          flex-direction: column;
          align-items: center;
          padding: 24rpx 16rpx;
          border-radius: $radius-md;
          background-color: $bg-main;
          transition: all 0.2s ease;

          &:hover {
            background-color: #e8edf3;
            transform: translateY(-4rpx);
          }

          .tool-icon {
            width: 88rpx;
            height: 88rpx;
            border-radius: 50%;
            background-color: $bg-card;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-bottom: 16rpx;
            box-shadow: $shadow-sm;

            .iconfont {
              font-size: 48rpx;
              color: $color-primary;
            }
          }

          .tool-text {
            font-size: 24rpx;
            color: $color-text;
            font-weight: 500;
          }
        }
      }
    }
  }

  /* 语音输入面板 */
  .voice-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 999;

    .voice-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.4);
      backdrop-filter: blur(6rpx);
    }

    .voice-input-panel {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: $bg-card;
      border-radius: $radius-lg;
      padding: 48rpx;
      width: 60%;
      max-width: 520rpx;
      box-shadow: 0 8rpx 36rpx rgba(0, 0, 0, 0.15);

      .voice-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 32rpx;
        border-bottom: 2rpx solid #f0f4f8;
        padding-bottom: 16rpx;

        text {
          font-size: 34rpx;
          font-weight: 600;
          color: $color-text;
        }

        .close-btn {
          width: 56rpx;
          height: 56rpx;
          border-radius: 50%;
          background-color: $bg-main;
          display: flex;
          align-items: center;
          justify-content: center;
          transition: all 0.2s ease;
          border: none;

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

          .iconfont {
            font-size: 28rpx;
            color: $color-text-light;
          }
        }
      }

      .voice-content {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin-bottom: 48rpx;

        .voice-wave {
          width: 280rpx;
          height: 160rpx;
          display: flex;
          align-items: center;
          justify-content: center;
          margin-bottom: 24rpx;

          &.recording .wave-bar {
            animation: wave 1.2s infinite ease-in-out;
          }

          .wave-bar {
            width: 8rpx;
            height: 40rpx;
            margin: 0 4rpx;
            background-color: $color-primary;
            border-radius: 4rpx;
            animation: none;

            &:nth-child(1) { height: 60rpx; animation-delay: 0s; }
            &:nth-child(2) { height: 90rpx; animation-delay: 0.1s; }
            &:nth-child(3) { height: 50rpx; animation-delay: 0.2s; }
            &:nth-child(4) { height: 120rpx; animation-delay: 0.3s; }
            &:nth-child(5) { height: 70rpx; animation-delay: 0.4s; }
            &:nth-child(6) { height: 100rpx; animation-delay: 0.5s; }
            &:nth-child(7) { height: 80rpx; animation-delay: 0.6s; }
            &:nth-child(8) { height: 40rpx; animation-delay: 0.7s; }
          }
        }

        .voice-tip {
          font-size: 28rpx;
          color: $color-text-light;
        }
      }

      .voice-actions {
        display: flex;
        justify-content: center;

        .voice-btn {
          width: 120rpx;
          height: 120rpx;
          border-radius: 50%;
          background-color: $color-primary;
          display: flex;
          align-items: center;
          justify-content: center;
          box-shadow: 0 8rpx 24rpx rgba(108, 142, 191, 0.3);
          transition: all 0.2s ease;
          border: none;

          &:hover {
            transform: scale(1.05);
            background-color: #5a7cb0;
          }

          .iconfont {
            font-size: 56rpx;
            color: white;
          }
        }
      }
    }
  }

  /* 头像选择弹窗 */
  .avatar-selector-popup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1000;

    .avatar-selector-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.4);
      backdrop-filter: blur(6rpx);
    }

    .avatar-selector-panel {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: $bg-card;
      border-radius: $radius-lg;
      padding: 32rpx;
      width: calc(100% - 80rpx);
      max-width: 520rpx;
      box-shadow: 0 8rpx 36rpx rgba(0, 0, 0, 0.15);
      box-sizing: border-box;

      .avatar-selector-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 24rpx;
        border-bottom: 2rpx solid #f0f4f8;
        padding-bottom: 16rpx;

        text {
          font-size: 34rpx;
          font-weight: 600;
          color: $color-text;
        }

        .close-btn {
          width: 56rpx;
          height: 56rpx;
          border-radius: 50%;
          background-color: $bg-main;
          display: flex;
          align-items: center;
          justify-content: center;
          transition: all 0.2s ease;
          border: none;

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

          .iconfont {
            font-size: 28rpx;
            color: $color-text-light;
          }
        }
      }

      .avatar-selector-content {
        .current-avatar-preview {
          width: 180rpx;
          height: 180rpx;
          border-radius: 50%;
          overflow: hidden;
          margin: 0 auto 32rpx;
          box-shadow: $shadow-md;
          border: 4rpx solid #f0f4f8;

          image {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }

        .avatar-selector-actions {
          display: flex;
          flex-direction: column;
          gap: 16rpx;

          .avatar-select-action {
            padding: 24rpx;
            border-radius: $radius-lg;
            font-size: 28rpx;
            display: flex;
            align-items: center;
            gap: 16rpx;
            transition: all 0.2s ease;
            border: 2rpx solid #f0f4f8;
            background-color: $bg-main;
            color: $color-text;

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

            &.cancel {
              background-color: #f8fafc;
              border-color: #e9edf2;

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

            .iconfont {
              font-size: 36rpx;
              color: $color-primary;
            }
          }
        }
      }
    }
  }
}

/* 动画定义 */
@keyframes dotPulse {
  0%, 100% {
    opacity: 0.4;
    transform: scale(0.8);
  }
  50% {
    opacity: 1;
    transform: scale(1.2);
  }
}

@keyframes wave {
  0%, 100% {
    transform: scaleY(0.5);
    opacity: 0.7;
  }
  50% {
    transform: scaleY(1);
    opacity: 1;
  }
}

@keyframes shine {
  0% {
    left: -100%;
  }
  100% {
    left: 200%;
  }
}

@keyframes gradient-flow {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

/* 滚动条样式优化 */
::-webkit-scrollbar {
  width: 8rpx;
  height: 8rpx;
}

::-webkit-scrollbar-track {
  background: $bg-main;
  border-radius: 4rpx;
}

::-webkit-scrollbar-thumb {
  background: $color-primary-light;
  border-radius: 4rpx;
  opacity: 0.7;
  
  &:hover {
    background: $color-primary;
    opacity: 1;
  }
}

/* 响应式适配 */
@media (max-width: 750rpx) {
  .ai-chat-container {
    .chat-messages {
      padding: 16rpx 24rpx;
      
      .message-item {
        margin-bottom: 24rpx;
        
        .user-message, .ai-message {
          .avatar {
            width: 72rpx;
            height: 72rpx;
          }
          
          .message-content {
            margin-left: 16rpx;
            max-width: calc(100% - 88rpx);
            
            .message-bubble {
              padding: 16rpx 24rpx;
              
              .message-text {
                font-size: 26rpx;
              }
            }
          }
        }
      }
    }
    
    .input-area {
      padding: 16rpx 24rpx;
      
      .input-container {
        .message-input {
          min-height: 72rpx;
          padding: 16rpx 24rpx;
          font-size: 26rpx;
        }
        
        .send-btn {
          width: 96rpx;
          height: 68rpx;
          font-size: 26rpx;
        }
      }
    }
  }
}
</style>