<template>
  <div v-if="state.isShowSearch" :class="['ai-float-window', currentSizeClass]"
       :style="currentSize === 'custom' ? {
      width: windowSize.width,
      height: windowSize.height,
      left: typeof windowPosition.x === 'string' ? 'auto' : windowPosition.x + 'px',
      right: typeof windowPosition.x === 'string' ? '0' : 'auto',
      top: windowPosition.y + 'px'
    } : {}">
    <div class="ai-float-main">
      <div class="ai-float-left" v-if="isShowLeft">
        <component :is="currentComponent" v-bind="currentProps" v-if="currentComponent"/>
      </div>
      <div class="ai-float-right" v-loading="aiLoading">
        <div class="ai-float-header" @mousedown="startDrag">
          <span>AI智能填报助手</span>
          <!-- 将两个图标按钮放在一个容器内 -->
          <div class="ai-float-header-actions">
            <el-icon  v-if="currentSize==='minimize'" class="ai-float-minimize" @click.stop="toggleSize">
              <Plus />
            </el-icon>
            <el-icon v-if="currentSize!=='minimize'" class="ai-float-minimize" @click.stop="toggleSize">
              <Minus />
            </el-icon>

            <el-icon class="ai-float-close" @click="close">
              <Close/>
            </el-icon>
          </div>
        </div>
        <div class="ai-float-form-list ai-float-scroll">
          <div class="form-list-top">
            <div class="ai-float-welcome">👋 欢迎使用AI智能填报助手</div>
            <div class="ai-model-selector">
              <el-select
                v-model="selectedModelId"
                placeholder="选择AI模型"
                size="small"
                popper-class="topIndex"
                style="width: 150px"
                :teleported="true"
                append-to="body"
                :disabled="aiThinking"
                @change="onModelChange"
              >
                <el-option
                  v-for="model in aiModelList"
                  :key="model.modelId"
                  :label="model.modelName"
                  :value="model.modelId"
                />
              </el-select>
            </div>
          </div>
          <div class="form-list-title">请选择需要填报的表单：</div>
          <!-- 加载状态 -->
          <div v-if="formsLoading" class="loading-container">
            <el-icon class="is-loading">
              <Loading/>
            </el-icon>
            <span>加载表单中...</span>
          </div>
          <!-- 表单列表 -->
          <div v-else class="form-list">
            <el-tag
              v-for="aiFormSetting in aiFormSettingList"
              :key="aiFormSetting.formSettingId"
              :type="aiFormSetting.formSettingId === selectedFormSettingId ? 'success' : 'info'"
              class="form-tag"
              @click="selectForm(aiFormSetting)"
              effect="dark"
            >
              {{ aiFormSetting.formName }}
            </el-tag>
            <el-button v-if="aiFormSettingList.length > 5" type="text" class="more-btn" @click="showMore = !showMore">
              更多
            </el-button>
          </div>
          <el-dialog v-model="showMore" title="选择其他表单" width="400px" @close="moreFilterText = ''">
            <el-input
              v-model="moreFilterText"
              placeholder="输入表单名称过滤"
              clearable
              style="margin-bottom: 12px;"
            />
            <el-scrollbar style="max-height:300px;">
              <el-tag
                v-for="form in filteredForms"
                :key="form.formSettingId"
                :type="form.formSettingId === selectedFormSettingId ? 'success' : 'info'"
                class="form-tag"
                style="margin-bottom: 8px;"
                @click="selectForm(form); showMore = false"
                effect="dark"
              >
                {{ form.formName }}
              </el-tag>
            </el-scrollbar>
          </el-dialog>
        </div>
        <!-- 聊天区始终渲染，内容为空时不显示消息 -->
        <div class="ai-float-chat-list" ref="chatListRef">
          <div v-for="(msg, idx) in chatList" :key="idx"
               :class="['ai-float-chat-item', msg.from === 'ai' ? 'ai-chat-ai' : 'ai-chat-user']">
            <template v-if="msg.from === 'ai'">
              <div class="ai-avatar">🤖</div>
              <div class="ai-float-chat-bubble ai-float-chat-bubble-ai">
                <div v-if="msg.type === 'select' && msg.selectLists">
                  <div class="ai-select-title" style="font-weight:bold; margin-bottom:8px;">{{ msg.text }}</div>
                  <div class="ai-select-lists">
                    <div v-for="(list, lidx) in msg.selectLists" :key="lidx" class="ai-select-list-block">
                      <div class="ai-select-list-title">{{ list.title }}</div>
                      <div class="ai-select-options">
                        <el-button v-for="opt in list.options.slice(0,4)" :key="opt" size="small"
                                   @click="() => handleSelectOption(opt,lidx)"
                                   :type="selectedOption === opt ? 'primary' : 'default'">{{ opt.fieldValue }}
                        </el-button>
                        <el-button v-if="list.options.length > 4" size="small" type="primary" link
                                   @click="() => openSelectDialog(list,lidx)">更多
                        </el-button>
                      </div>
                    </div>
                  </div>
                </div>
                <div v-else v-html="formatMsg(msg.text)"></div>
              </div>
            </template>
            <template v-else>
              <div class="ai-float-chat-bubble-user-wrap">
                <div class="ai-float-chat-bubble" v-html="formatMsg(msg.text)"></div>
                <div class="ai-avatar ai-avatar-user">👤</div>
              </div>
            </template>
          </div>
        </div>
        <el-dialog v-model="selectDialog" title="更多选项" width="400px" @close="selectDialogFilterText = ''">
          <div v-if="selectDialogList">
            <div class="ai-select-title">{{ selectDialogList.title }}</div>
            <el-input
              v-model="selectDialogFilterText"
              placeholder="输入关键字过滤"
              clearable
              style="margin-bottom: 12px;"
            />
            <div class="ai-select-options">
              <el-button v-for="opt in filteredSelectDialogOptions" :key="opt" size="small"
                         @click="() => handleSelectOption(opt)"
                         :type="selectedOption === opt ? 'primary' : 'default'">
                {{ opt.fieldValue }}
              </el-button>
            </div>
          </div>
        </el-dialog>
        <div class="ai-float-input-area">
          <div v-if="selectedFormSettingId" class="ai-float-form-info">
            <div class="form-info-title">
              当前表单：{{ aiFormSettingList.find(f => f.formSettingId === selectedFormSettingId)?.formName }}
            </div>
            <div class="form-info-tip">请根据下方示例填写内容，AI将自动为您智能填报。</div>
            <div class="form-info-example">{{ aiFormSettingList.find(f => f.formSettingId === selectedFormSettingId)?.remark ?? '如：申请10个物料A用于生产线1，计划交付日期为2024-07-01'}}</div>
          </div>
          <div class="ai-float-input-row">
            <el-button
              @click="toggleRecording"
              :class="['recording-btn', { 'recording': isRecording }]"
              v-loading="audioAsrLoading"
              :disabled="aiThinking"
              circle
              type="primary"
            >
              <template #icon>
                <el-icon v-if="isRecording"><VideoPause /></el-icon>
                <el-icon v-else><Microphone /></el-icon>
              </template>
            </el-button>
            <el-input
              v-model="inputValue"
              type="textarea"
              :rows="2"
              :autosize="{ minRows: 2, maxRows: 6 }"
              :maxlength="300"
              :disabled="!selectedFormSettingId || aiThinking"
              placeholder="请输入内容（最多300字符）"
              @keydown="onInputKeydown"
              class="ai-float-input"
              show-word-limit
              clearable
            />
            <el-button
              class="ai-float-send-btn"
              :disabled="!canSend || aiThinking"
              icon="Top"
              @click="() => handleSend()"
              circle
              type="success"
            />

          </div>
        </div>
      </div>
    </div>

    <!-- 新增：调整大小的句柄 -->
    <div class="ai-float-resize-handle" @mousedown="startResize"></div>
  </div>
</template>

<script setup lang="ts">
import {ref, reactive, computed, onMounted, onBeforeUnmount, nextTick, shallowRef, watch, getCurrentInstance} from 'vue'
import {ElMessage} from 'element-plus'
import {Close, Loading} from '@element-plus/icons-vue'
import type {ComponentInternalInstance} from 'vue'
import {getAiFormSettingList, getAiFormSettingDetailList} from '@/api/ai/base/aiFormSetting';
import {AiFormSettingVO, AiFormSettingDetailVO} from '@/api/ai/base/aiFormSetting/types';
import {aiFillForm, recognizeSpeechByUrl, uploadFile} from '@/api/ai/skill/aiAssistant';
import router from "@/router"
import {useSharedDataStore} from '@/api/monitorData'
import {getAiModelJoinList} from "@/api/ai/skill/aiChat";
import {AIModelVO} from "@/api/ai/skill/aiChat/types";

const sharedStore = useSharedDataStore()

const {proxy} = getCurrentInstance() as ComponentInternalInstance

const aiFormSettingList = ref<AiFormSettingVO[]>([])
const aiFormSettingDetailListMap = ref<Record<number, AiFormSettingDetailVO[]>>({});
const selectedFormSettingId = ref<number | null>(null)
const selectedForm = ref();
const formsLoading = ref(false)
const isShowLeft = ref(false);
const aiLoading = ref(false);
const currentSize = ref("menu");

const currentSizeClass = computed(() =>
  `size-${currentSize.value}`
);


// 用reactive对象直接定义state
const state = reactive({
  isShowSearch: false,
  menuQuery: '',
  menuList: []
});

// 搜索弹窗打开
const openSearch = () => {
  state.menuQuery = '';
  state.isShowSearch = true;
  nextTick(() => {
    setTimeout(() => {
      // layoutMenuAutocompleteRef.value.focus();
    });
  });
};

// 动态生成的表单页面映射
const formPageMap = ref<Record<number, { loader: () => Promise<any>, props: any }>>({})

// 加载表单数据并初始化formPageMap
const loadForms = async () => {
  try {
    formsLoading.value = true
    const res = await getAiFormSettingList({})
    if (res.code === 200) {
      aiFormSettingList.value = res.data || []
      // 动态生成formPageMap
      initFormPageMap()
    }
  } catch (error) {
    console.error('加载表单数据失败:', error)
    ElMessage.error('加载表单数据失败')
  } finally {
    formsLoading.value = false
  }
}

// 动态生成formPageMap
const initFormPageMap = () => {
  const newFormPageMap: Record<number, { loader: () => Promise<any>, props: any }> = {}

  aiFormSettingList.value.forEach(form => {
    // // 根据表单的formPath字段动态生成组件路径
    // let componentPath = form.formPath
    // if(!form.dialogVisibleVariable ||  form.dialogVisibleVariable===''){
    //   componentPath = '../../../views/'+componentPath;
    // }else{
    //   componentPath = "/"+componentPath;
    // }
    // 创建动态加载器
    const loader = () => {
      try {
        // const dd = new URL(`@/views/system/user/index.vue`, import.meta.url).href;
        // return import(`${componentPathUrl}`);
        if (!form.dialogVisibleVariable || form.dialogVisibleVariable === '') {
          const componentPath = '../../../views/' + form.formPath;
          return import(/* @vite-ignore */ componentPath)
        }
      } catch (error) {
        // console.error(`加载组件失败: ${componentPath}`, error)
        // return import('@/views/ai/skill/aiForm/index.vue')
      }
    }

    // 根据表单类型设置不同的props
    const props = getFormProps(form)

    newFormPageMap[form.formSettingId] = {loader, props}
  })

  formPageMap.value = newFormPageMap
}

// 根据表单信息生成props
const getFormProps = (form: AiFormSettingVO) => {
  const baseProps = {
    formSettingId: form.formSettingId,
    formName: form.formName,
    formType: form.formType,
    dialogVisibleVariable: form.dialogVisibleVariable,
    formPath: form.formPath,
    userInput: ''
  }

  // 根据表单类型添加特定props
  switch (form.formType) {
    case 'system':
      return {...baseProps, pageNum: 1, pageSize: 10}
    case 'ai':
      return {...baseProps, aiType: 'form', mode: 'edit'}
    default:
      return baseProps
  }
}

const selectForm = async (aiFormSetting: AiFormSettingVO) => {
  if( selectedFormSettingId.value === aiFormSetting.formSettingId) return;
  selectedFormSettingId.value = aiFormSetting.formSettingId
  selectedForm.value = aiFormSetting;
  aiLoading.value = true
  try {
    resetAiAssistant();
    if (!aiFormSettingDetailListMap.value[aiFormSetting.formSettingId]) {
      const res = await getAiFormSettingDetailList(
        {formSettingId: aiFormSetting.formSettingId, settingFlag: '1'})
      if (res.code === 200) {
        aiFormSettingDetailListMap.value[aiFormSetting.formSettingId] = res.data || []
      }
    }
  } finally {
    aiLoading.value = false
  }
  console.log(aiFormSettingDetailListMap.value[aiFormSetting.formSettingId])
}

const resetAiAssistant = () =>{
  chatList.value = [];
}

// function selectForm(aiFormSetting: AiFormSettingVO) {
//   selectedFormSettingId.value = aiFormSetting.formSettingId
//   if(!aiFormSettingDetailListMap[aiFormSetting.formSettingId]){
//     const res = await getAiFormSettingDetailList({formSettingId: aiFormSetting.formSettingId})
//     if (res.code === 200) {
//       aiFormSettingDetailListMap.value[aiFormSetting.formSettingId] = res.data || []
//     }
//   }
// }


const currentComponent = shallowRef(null)
const currentProps = ref({})
watch(selectedFormSettingId, async (formSettingId) => {
  if (formSettingId && formPageMap.value[formSettingId]) {
    try {
      if (formPageMap.value[formSettingId].props && formPageMap.value[formSettingId].props.dialogVisibleVariable && formPageMap.value[formSettingId].props.dialogVisibleVariable !== '') {
        isShowLeft.value = false
        currentSize.value = "menu";
        router.push({path: "/" + formPageMap.value[formSettingId].props.formPath, query: {from: "ai"}})

        // proxy.$store.commit('aiFormSettingId', formSettingId)
        // proxy.$store.commit('aiFormSetting', formPageMap.value[formSettingId])
      } else {
        isShowLeft.value = true
        currentSize.value = "form";
        const mod = await formPageMap.value[formSettingId].loader()
        console.log(formPageMap.value[formSettingId].props)
        currentComponent.value = mod.default
        currentProps.value = {...formPageMap.value[formSettingId].props, userInput: ''}
      }


    } catch (error) {
      console.error('加载表单组件失败:', error)
      ElMessage.error('加载表单组件失败')
      currentComponent.value = null
      currentProps.value = {}
    }
  } else {
    currentComponent.value = null
    currentProps.value = {}
  }
})


// 暴露变量
defineExpose({
  openSearch
});


const getAiModelList = async () => {
  // loading.value = true;
  const res = await getAiModelJoinList({modelTypeId: 1});
  aiModelList.value = res.data;
  await setDefaultAiModel();
  // console.log(res)
  // platformList.value = res.data;
  // loading.value = false;
}

const setDefaultAiModel = async () => {
  aiModelList.value.forEach((item: AIModelVO) => {
    if (item.defaultFlag === "1") {
      // alert(JSON.stringify(item))
      selectedModelId.value = item.modelId;
      selectedPlatformId.value = item.platformId;
      // provider.value = item.platformCode;
      // console.log(item.platformIcon)
      // platformIcon.value = item.platformIcon;
    }
  })
}

function onModelChange() {
  const model = aiModelList.value.find(m => m.modelId === selectedModelId.value)
  if (model) {
    selectedPlatformId.value = model.platformId
    // platformIcon.value = model.platformIcon;
  }
}

watch(state, (newVal) => {
  if (newVal.isShowSearch) {
    loadForms()
    getAiModelList();
  }
});

const selectLists = ref([]);

// 存储fieldType为1的元素及其位置信息,显示使用
const type1Elements = ref([]);
// 存储fieldType为2的元素及其位置信息，赋值使用
const type2Elements = ref([]);

// 存储选中后对应的fieldType为2的元素
const selectedType2Elements = ref([]);

// 处理数据，找出所有fieldType为1的元素
const processData = (data) => {
  type1Elements.value = [];
  type2Elements.value = [];
  let title = "";
  data.forEach((subArray, subArrayIndex) => {
    if (Array.isArray(subArray)) {
      subArray.forEach(item => {
        if (item.fieldType === '3' || item.fieldType === 3) {//请选择关联表的表名title信息
          if (title == '') title = item.fieldValue;
        }

        if (item.fieldType === '1' || item.fieldType === 1) {//赋值
          type1Elements.value.push({
            ...item,
            subArrayIndex
          });
        }

        if (item.fieldType === '2' || item.fieldType === 2) {//显示的名称
          type2Elements.value.push({
            ...item,
            subArrayIndex
          });
        }
      });

    }
  });
  selectLists.value.push({title: title, options: type2Elements.value, formOptions: type1Elements.value});
};


const sendForm = ref({});
const handleSend = async (selectedText?: string) => {
  if ((!canSend.value || aiThinking.value) && !selectedText) return
  const userMsg = selectedText || inputValue.value
  chatList.value.push({text: userMsg, from: 'user', type: 'text'})
  scrollToBottom()
  aiThinking.value = true
  inputValue.value = 'AI思考中....'
  aiLoading.value = true
  console.log(aiFormSettingDetailListMap.value[selectedFormSettingId.value]);
  try {
    let params = {
      naturalLanguageQuery: userMsg,
      formSettingId: selectedFormSettingId.value,
      formSettingDetailList: aiFormSettingDetailListMap.value[selectedFormSettingId.value],
      modelId: selectedModelId.value,
      platformId: selectedPlatformId.value
    }

    // chatList.value.push({
    //   text: '操作成功,请选择相关信息:',
    //   from: 'ai',
    //   type: 'select',
    //   selectLists: selectLists.value
    // })
    //
    // sharedStore.updateDynamicValue({
    //   message: {deptId:100},
    //   timestamp: new Date().toLocaleString()
    // })
    // return;

    const response = await aiFillForm(params)
    sendForm.value = response;
    inputValue.value = ''
    aiThinking.value = false
    traverseJSON();

    if (selectedForm.value && selectedForm.value.dialogVisibleVariable && selectedForm.value.dialogVisibleVariable !== '') {
      //打开菜单时赋值使用
      sharedStore.updateDynamicValue({
        message: sendForm.value,
        timestamp: new Date().toLocaleString()
      })
    } else {
      //直接打开表单赋值使用
      currentProps.value = sendForm.value;
    }


    // 固定AI回复+多个选择列表
    // chatList.value.push({
    //   text: '操作成功，请选择相关信息：',
    //   from: 'ai',
    //   type: 'select',
    //   selectLists: [
    //     {title: '物料信息', options: ['物料A', '物料B', '物料C', '物料D', '物料E', '物料F']},
    //     {title: 'BOM信息', options: ['BOM-001', 'BOM-002', 'BOM-003', 'BOM-004', 'BOM-005']}
    //   ]
    // })


    if (selectLists.value.length > 0) {
      chatList.value.push({
        text: '操作成功,请选择相关信息:',
        from: 'ai',
        type: 'select',
        selectLists: selectLists.value
      })
    } else {
      chatList.value.push({
        text: '操作成功',
        from: 'ai',
      })
    }


    scrollToBottom()

    console.log(1)
    console.log(response)

  } catch (error) {
    proxy?.$modal.msgError(error);
    console.log("Error:" + error)
    chatList.value.push({
      text: '请重试：'+error,
      from: 'ai',
    })
  } finally {
    aiThinking.value = false
    inputValue.value = ''
    aiLoading.value = false
  }
}


// 递归遍历JSON对象的函数
function traverseJSON() {


  // 判断是否为数组
  if (Array.isArray(sendForm.value)) {
    console.log('这是一个数组，包含 ' + sendForm.value.length + ' 个元素:');
    // 遍历数组中的每个元素
    // obj.forEach((item, index) => {
    //   console.log('  '.repeat(indent) + '索引 ' + index + ':');
    // });
  } else {
    // 遍历对象的所有key值
    for (const key in sendForm.value) {
      // 确保key是对象自身的属性（非继承）
      if (sendForm.value.hasOwnProperty(key)) {
        const value = sendForm.value[key];

        // 判断value是否为数组
        if (Array.isArray(value)) {
          // selectLists: [
          //     {title: '物料信息', options: ['物料A', '物料B', '物料C', '物料D', '物料E', '物料F']},
          //     {title: 'BOM信息', options: ['BOM-001', 'BOM-002', 'BOM-003', 'BOM-004', 'BOM-005']}
          //   ]
          sendForm.value[key] = '';
          if (value.length == 1) {

            const firstValue = value[0];
            firstValue.forEach(item => {
              if(item.fieldType ==='1' || item.fieldType===1){
                sendForm.value[key] = item.fieldValue
              }
            });

            // let selectList = {title: value[0].relateTableDesc, options: value}
            // selectLists.value.push(selectList);
          }else if (value.length > 1) {
            processData(value)
          }

          // 遍历数组中的每个元素
          // value.forEach((item, index) => {
          //   console.log('  '.repeat(indent + 1) + '数组元素 ' + index + ':');
          // });
        }
        // 如果value是对象但不是数组，递归遍历
        // else if (value !== null && typeof value === 'object') {
        //   console.log('  '.repeat(indent) + '值是一个对象:');
        //   traverseJSON(value, indent + 1);
        // }
        // 基本类型值直接输出
        // else {
        //   console.log('  '.repeat(indent) + '值:', value);
        // }
      }
    }
  }
}


// 录音相关对象
const isRecording = ref(false);
let mediaRecorder = null
let microphoneStream = null
let audioChunks = []
let audioContext = null
const targetSampleRate = 16000 // 目标采样率，可根据后端要求调整

// 状态变量
const audioAsrLoading = ref(false);
const isUploading = ref(false)
const uploadProgress = ref(0)
const recognitionResult = ref('')
const recordings = ref([])

const toggleRecording = () => {
  if (isRecording.value) {
    stopRecording();
  } else {
    startRecording();
  }
}

// 开始录音
async function startRecording() {
  try {
    // 检查浏览器支持
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      proxy.$modal.msgError('您的浏览器不支持录音功能')
      return
    }

    // 获取用户麦克风权限
    microphoneStream = await navigator.mediaDevices.getUserMedia({
      audio: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true
      }
    })

    // 初始化Web Audio API用于后续处理
    if (!audioContext) {
      audioContext = new (window.AudioContext)()
    }

    // 设置MediaRecorder
    const options = {
      mimeType: 'audio/webm;codecs=opus' // 优先使用opus编码
    }

    // 降级处理，确保兼容性
    if (!MediaRecorder.isTypeSupported(options.mimeType)) {
      options.mimeType = 'audio/webm'
      if (!MediaRecorder.isTypeSupported(options.mimeType)) {
        options.mimeType = 'audio/ogg;codecs=opus'
        if (!MediaRecorder.isTypeSupported(options.mimeType)) {
          proxy.$modal.msgError('您的浏览器不支持高质量录音格式')
          return
        }
      }
    }

    mediaRecorder = new MediaRecorder(microphoneStream, options)
    audioChunks = []

    // 收集音频数据
    mediaRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        audioChunks.push(event.data)
      }
    }

    // 录音开始
    mediaRecorder.start()
    isRecording.value = true
    // addLog('录音已开始')

  } catch (error) {
    console.error('开始录音失败:', error)
    // addLog(`开始录音失败: ${error.message}`)
    stopRecording()
  }
}

// 停止录音
function stopRecording() {

  try {
    if (!isRecording.value) return
    // 更新录音状态
    isRecording.value = false
    // 停止MediaRecorder
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
      mediaRecorder.stop()
      // 录音停止后的处理
      mediaRecorder.onstop = async () => {
        audioAsrLoading.value = true;
        try {
          // 关闭麦克风流
          if (microphoneStream) {
            microphoneStream.getTracks().forEach(track => track.stop())
            microphoneStream = null
          }

          // addLog('录音已停止，正在处理音频...')

          // 将录音数据转换为WAV格式
          const wavBlob = await convertToWav(audioChunks)

          // 保存录音到历史记录
          const recordingName = `recording_${new Date().toISOString().replace(/[:.]/g, '-')}.wav`
          const recordingUrl = URL.createObjectURL(wavBlob)
          recordings.value.unshift({
            name: recordingName,
            url: recordingUrl,
            file: wavBlob
          })

          // 限制历史记录数量
          if (recordings.value.length > 5) {
            const oldestRecording = recordings.value.pop()
            URL.revokeObjectURL(oldestRecording.url)
          }

          // addLog(`音频处理完成，文件大小: ${(wavBlob.size / 1024).toFixed(2)}KB`)

          // 自动上传录音文件
          await uploadAudioFile(wavBlob, recordingName)

        } catch (error) {
          console.error('处理录音文件失败:', error)
          proxy.$modal.msgError('处理录音文件失败，请重试', error)
          // addLog(`处理录音文件失败: ${error.message}`)
        } finally {
          audioAsrLoading.value = false;
        }
      }
    }

  } catch (error) {
    console.error('停止录音失败:', error)
    // addLog(`停止录音失败: ${error.message}`)
  } finally {

  }
}

// 将音频数据转换为WAV格式
async function convertToWav(audioChunks) {
  // 将音频块合并为单个Blob
  const audioBlob = new Blob(audioChunks)

  // 读取音频数据并转换为WAV
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader()
    fileReader.onload = async (e) => {
      try {
        // 获取ArrayBuffer
        const arrayBuffer = e.target.result

        // 使用Web Audio API解码音频数据
        const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)

        // 转换为目标采样率的WAV格式
        const wavBuffer = await resampleAndConvertToWav(audioBuffer, targetSampleRate)

        resolve(new Blob([wavBuffer], {type: 'audio/wav'}))
      } catch (error) {
        reject(error)
      }
    }
    fileReader.onerror = reject
    fileReader.readAsArrayBuffer(audioBlob)
  })
}

// 重采样并转换为WAV格式
async function resampleAndConvertToWav(audioBuffer, targetRate) {
  // 获取原始音频数据
  const channels = audioBuffer.numberOfChannels
  const sampleRate = audioBuffer.sampleRate
  const length = audioBuffer.length

  // 计算重采样后的长度
  const newLength = Math.floor(length * targetRate / sampleRate)

  // 创建目标采样率的AudioContext
  const offlineContext = new OfflineAudioContext(channels, newLength, targetRate)

  // 创建缓冲区源节点
  const source = offlineContext.createBufferSource()
  source.buffer = audioBuffer

  // 连接到输出
  source.connect(offlineContext.destination)

  // 开始播放
  source.start()

  // 渲染重采样后的音频
  const renderedBuffer = await offlineContext.startRendering()

  // 将AudioBuffer转换为WAV格式
  return encodeWAV(renderedBuffer)
}

// 将AudioBuffer编码为WAV格式
function encodeWAV(audioBuffer) {
  const numberOfChannels = audioBuffer.numberOfChannels
  const sampleRate = audioBuffer.sampleRate
  const bitDepth = 16

  // 获取所有声道的数据
  const channels = []
  for (let i = 0; i < numberOfChannels; i++) {
    channels.push(audioBuffer.getChannelData(i))
  }

  // 计算总样本数
  const sampleCount = channels[0].length
  const byteRate = sampleRate * numberOfChannels * bitDepth / 8

  // 创建WAV文件头部
  const wavHeader = new ArrayBuffer(44)
  const view = new DataView(wavHeader)

  // RIFF标识符
  writeString(view, 0, 'RIFF')
  // 文件大小
  view.setUint32(4, 36 + sampleCount * numberOfChannels * 2, true)
  // WAVE标识符
  writeString(view, 8, 'WAVE')
  // fmt子块标识符
  writeString(view, 12, 'fmt ')
  // fmt子块大小
  view.setUint32(16, 16, true)
  // 音频格式（PCM）
  view.setUint16(20, 1, true)
  // 声道数
  view.setUint16(22, numberOfChannels, true)
  // 采样率
  view.setUint32(24, sampleRate, true)
  // 字节率
  view.setUint32(28, byteRate, true)
  // 块对齐
  view.setUint16(32, numberOfChannels * 2, true)
  // 位深度
  view.setUint16(34, bitDepth, true)
  // data子块标识符
  writeString(view, 36, 'data')
  // data子块大小
  view.setUint32(40, sampleCount * numberOfChannels * 2, true)

  // 创建PCM数据
  const pcmBytes = new ArrayBuffer(wavHeader.byteLength + sampleCount * numberOfChannels * 2)
  const pcmView = new DataView(pcmBytes)

  // 复制WAV头部
  for (let i = 0; i < wavHeader.byteLength; i++) {
    pcmView.setUint8(i, new Uint8Array(wavHeader)[i])
  }

  // 写入PCM数据
  let offset = 44
  for (let i = 0; i < sampleCount; i++) {
    for (let channel = 0; channel < numberOfChannels; channel++) {
      const sample = Math.max(-1, Math.min(1, channels[channel][i]))
      // 将Float32转换为Int16
      pcmView.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7FFF, true)
      offset += 2
    }
  }

  return pcmBytes
}

// 写入字符串到DataView
function writeString(view, offset, string) {
  for (let i = 0; i < string.length; i++) {
    view.setUint8(offset + i, string.charCodeAt(i))
  }
}

// 上传音频文件
async function uploadAudioFile(blob, fileName) {
  try {
    isUploading.value = true
    uploadProgress.value = 0
    recognitionResult.value = ''

    // addLog(`开始上传音频文件: ${fileName}`)

    // 创建FormData对象
    const formData = new FormData()
    formData.append('file', blob, fileName)

    const response = await uploadFile(formData);
    console.log(response)

    // 处理响应
    if (response.code === 200) {
      // addLog('音频上传成功，正在识别')

      const response1 = await recognizeSpeechByUrl(response.data.url);
      if (response1.code === 200) {
        console.log("--" + response1);
        inputValue.value += response1.data.text
        // recognitionResult.value = response1.data.text || '识别成功，但未返回文本结果'
        // addLog('识别成功，结果为: ' + recognitionResult.value)
      }
    } else {
      // addLog(`上传失败，状态码: ${response.status}`)
    }

  } catch (error) {
    console.error('上传音频文件失败:', error)
    proxy.$message.error('上传音频文件失败', error)
    // addLog(`上传音频文件失败: ${error.message || '未知错误'}`)
  } finally {
    isUploading.value = false
    uploadProgress.value = 0
  }
}


function handleSend1(selectedText?: string) {
  if ((!canSend.value || aiThinking.value) && !selectedText) return
  const userMsg = selectedText || inputValue.value
  chatList.value.push({text: userMsg, from: 'user', type: 'text'})
  // 动态传递userInput参数给左侧组件
  if (currentComponent.value) {
    currentProps.value = {...currentProps.value, userInput: userMsg}
  }
  scrollToBottom()
  aiThinking.value = true
  inputValue.value = 'AI思考中....'
  setTimeout(() => {
    inputValue.value = ''
    aiThinking.value = false
    // 固定AI回复+多个选择列表
    chatList.value.push({
      text: '操作成功，请选择相关信息：',
      from: 'ai',
      type: 'select',
      selectLists: [
        {title: '物料信息', options: ['物料A', '物料B', '物料C', '物料D', '物料E', '物料F']},
        {title: 'BOM信息', options: ['BOM-001', 'BOM-002', 'BOM-003', 'BOM-004', 'BOM-005']}
      ]
    })
    scrollToBottom()
  }, 2000)
}


const showMore = ref(false)
const inputValue = ref('')
const canSend = computed(() => selectedFormSettingId.value && inputValue.value.trim().length > 0)

// AI模型相关数据
const aiModelList = ref([
  { modelId: 1, modelName: 'GPT-3.5' },
  { modelId: 2, modelName: 'GPT-4' },
  { modelId: 3, modelName: 'Claude-3' },
  { modelId: 4, modelName: 'Gemini-Pro' }
])
const selectedModelId = ref() // AI模型ID
const selectedPlatformId = ref() // AI平台ID

// 新增：更多弹窗过滤输入
const moreFilterText = ref('')
const filteredForms = computed(() =>
  aiFormSettingList.value.filter(form => form.formName.includes(moreFilterText.value))
)

type ChatSelectList = { title: string, options: string[] }
type ChatMsg = { text: string, from: 'user' | 'ai', type?: 'text' | 'select', selectLists?: ChatSelectList[] }
const chatList = ref<ChatMsg[]>([])
const selectDialog = ref(false)
const selectDialogList = ref<ChatSelectList | null>(null)
const selectDialogListIndex = ref();
const aiThinking = ref(false)
const chatListRef = ref<HTMLElement | null>(null)
const selectedOption = ref('')
const iframeRef = ref<HTMLIFrameElement | null>(null)

// 新增：AI更多弹窗过滤输入
const selectDialogFilterText = ref('')
const filteredSelectDialogOptions = computed(() =>
  selectDialogList.value
    ? selectDialogList.value.options.filter(opt => {
      // 检查opt是否为对象，如果是则访问其字符串属性
      // 这里假设对象有label或value属性，根据实际情况修改
      const fieldValue = typeof opt === 'string' ? opt :
        opt.fieldValue
      return fieldValue.toLowerCase().includes(selectDialogFilterText.value.toLowerCase());
    })
    : []
)



// 默认显示在最右侧
onMounted(() => {

  // 加载表单数据
  // loadForms()
  //
  // const testData = [[{"fieldKey":"relateTableDesc","fieldValue":"部门1","fieldType":"3"},
  //   {"fieldKey":"deptName","fieldValue":"测试部门1","fieldType":"2"},
  //   {"fieldKey":"deptId","fieldValue":105,"fieldType":"1"}],
  //   [{"fieldKey":"relateTableDesc","fieldValue":null,"fieldType":"3"},
  //     {"fieldKey":"deptName","fieldValue":"测试部门2","fieldType":"2"},
  //     {"fieldKey":"deptId","fieldValue":"1952572898270183426","fieldType":"1"}]
  // ]
  //
  //
  // processData(testData);
  //
  // const testData1 = [
  //   [{"fieldKey":"relateTableDesc","fieldValue":"部门2","fieldType":"3"},
  //     {"fieldKey":"deptName","fieldValue":"测试部门11","fieldType":"2"},
  //     {"fieldKey":"deptId","fieldValue":1051,"fieldType":"1"}],
  //   [{"fieldKey":"relateTableDesc","fieldValue":null,"fieldType":"3"},
  //     {"fieldKey":"deptName","fieldValue":"测试部门22","fieldType":"2"},
  //     {"fieldKey":"deptId","fieldValue":"19525728982701834261","fieldType":"1"}]
  // ]
  // processData(testData1);
})

onBeforeUnmount(() => {

})

// 组件卸载时清理资源
onUnmounted(() => {
  // 停止MediaRecorder
  if (mediaRecorder && mediaRecorder.state !== 'inactive') {
    mediaRecorder.stop()
  }

  // 关闭音频上下文
  if (audioContext) {
    audioContext.close()
    audioContext = null
  }

  // 释放URL对象
  recordings.value.forEach(recording => {
    URL.revokeObjectURL(recording.url)
  })


})


function scrollToBottom() {
  nextTick(() => {
    if (chatListRef.value) {
      chatListRef.value.scrollTop = chatListRef.value.scrollHeight
    }
  })
}


// 保证所有方法直接在<script setup>中定义
function handleSelectOption(opt, index) {
  if (index === undefined || index === null) {
    index = selectDialogListIndex.value
  }

  let selectList = selectLists.value[index];
  selectedOption.value = opt
  let selectFormOptions = selectList.formOptions;
  const subArray = selectFormOptions[opt.subArrayIndex];
  const newValueJson = {[subArray.fieldKey]: subArray.fieldValue}
  sharedStore.updateDynamicValue({
    message: newValueJson,
    timestamp: new Date().toLocaleString()
  })

  // currentProps.value= newValueJson;

}

function openSelectDialog(list: ChatSelectList,listIndex:number) {
  selectDialogList.value = list
  selectDialog.value = true
  selectDialogListIndex.value = listIndex;
}

function formatMsg(text: string) {
  // 转换换行符为<br>，并做简单转义防XSS
  if (text) {
    return text
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/\n/g, '<br>')
  }
}

function onInputKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    handleSend();
  }
  // shift+enter 默认换行，无需处理
}

function close() {
  state.isShowSearch = false
}

// 新增：拖拽相关状态
const isDragging = ref(false);
const isResizing = ref(false);
const windowPosition = ref({ x: 'auto', y: 0 });
const isSmallSize = ref(false);
const windowSize = ref({ width: '24%', height: '100vh' });


const startPos = ref({ x: 0, y: 0 });
const startSize = ref({ width: 0, height: 0 });
const isCustomPosition = ref(false); // 新增：标记是否为自定义位置

// 新增：拖拽功能实现
function startDrag(e: MouseEvent) {
  if (isResizing.value) return;
  isDragging.value = true;

  // 获取窗口当前实际位置
  const windowElement = document.querySelector('.ai-float-window') as HTMLElement;
  if (windowElement) {
    const rect = windowElement.getBoundingClientRect();
    startPos.value = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
  }

  // 标记为自定义位置
  isCustomPosition.value = true;

  document.addEventListener('mousemove', onDrag);
  document.addEventListener('mouseup', stopDrag);
}

function onDrag(e: MouseEvent) {
  if (!isDragging.value) return;
  const newX = e.clientX - startPos.value.x;
  const newY = e.clientY - startPos.value.y;

  // 确保窗口不会超出视口边界（留出一些边距）
  const maxX = window.innerWidth - 200; // 最小宽度200px
  const maxY = window.innerHeight - 100; // 最小高度100px

  windowPosition.value = {
    x: Math.max(0, Math.min(newX, maxX)),
    y: Math.max(0, Math.min(newY, maxY))
  };

  // 当窗口被拖动时，不再固定在右侧
  if (currentSize.value === 'menu' || currentSize.value === 'form' || currentSize.value === 'minimize') {
    currentSize.value = 'custom';
  }
}

function stopDrag() {
  isDragging.value = false;
  document.removeEventListener('mousemove', onDrag);
  document.removeEventListener('mouseup', stopDrag);
}

// ... existing code ...



// 新增：调整大小功能实现
function startResize(e: MouseEvent) {
  isResizing.value = true;
  startPos.value = { x: e.clientX, y: e.clientY };
  startSize.value = {
    width: window.innerWidth * parseFloat(windowSize.value.width) / 100,
    height: window.innerHeight * parseFloat(windowSize.value.height) / 100
  };

  document.addEventListener('mousemove', onResize);
  document.addEventListener('mouseup', stopResize);
  e.preventDefault(); // 防止拖动时选中文本
}

function onResize(e: MouseEvent) {
  if (!isResizing.value) return;

  const deltaX = e.clientX - startPos.value.x;
  const deltaY = e.clientY - startPos.value.y;

  // 计算新的宽度和高度，确保最小尺寸
  let newWidth = startSize.value.width + deltaX;
  let newHeight = startSize.value.height + deltaY;

  newWidth = Math.max(200, newWidth); // 最小宽度200px
  newHeight = Math.max(300, newHeight); // 最小高度300px

  // 转换为视口百分比
  windowSize.value = {
    width: `${(newWidth / window.innerWidth) * 100}%`,
    height: `${(newHeight / window.innerHeight) * 100}%`
  };

  // 当窗口大小被调整时，不再使用预设尺寸
  if (currentSize.value !== 'custom') {
    currentSize.value = 'custom';
  }
}

function stopResize() {
  isResizing.value = false;
  document.removeEventListener('mousemove', onResize);
  document.removeEventListener('mouseup', stopResize);
}

// 新增：切换预设尺寸时更新窗口大小
watch(currentSize, (newSize) => {
  if (newSize === 'menu') {
    windowSize.value = { width: '24%', height: '100vh' };
    windowPosition.value = { x: 'auto', y: 0 };
  } else if (newSize === 'form') {
    windowSize.value = { width: '80%', height: '100vh' };
    windowPosition.value = { x: 'auto', y: 0 };
  } else if(newSize === 'minimize'){
    windowSize.value = { width: '24%', height: '360px' };
    windowPosition.value = { x: 'auto', y: 0 };
  }

  // const windowSize = computed(() => {
  //   if (isSmallSize.value) {
  //     return {
  //       width: '100px',
  //       height: '100px',
  //       top: 'auto',
  //       bottom: '20px',
  //       left: 'auto',
  //       right: '20px',
  //       borderRadius: '8px',
  //       overflow: 'hidden'
  //     }
  //   }else{
  //     return {
  //       width: '24%', height: '100vh'
  //     }
  //   }
  //   return {}
  // })


});


// 新增：调整窗口大小
function toggleSize() {
  if(currentSize.value === 'minimize'){
    if (!selectedForm.value) {//没有选择form时，原始大小
      currentSize.value = 'menu';
    }else{
      if(selectedForm.value.dialogVisibleVariable && selectedForm.value.dialogVisibleVariable !== ''){
        currentSize.value = 'menu'
      } else{
        currentSize.value = 'form'
      }
    }
  }else{
    currentSize.value = 'minimize'
  }
}

</script>

<style scoped lang="less">
.ai-float-fullscreen {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  z-index: 7005;
  background: #fff;
  border-radius: 0;
  box-shadow: none;
}

.ai-float-window {
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.18);
  background: #fff;
  border-radius: 12px;
  padding: 0 0 16px 0;
  min-height: 220px;
  user-select: none;
  display: flex;
  flex-direction: column;
  height: 99vh;
  max-height:99vh;
  right: 0;
  left: auto;
  top: 0;
  position: fixed;
  z-index: 7005;
}

/* 确保Element Plus下拉列表显示在浮窗之上 */
::deep(.el-select-dropdown) {
  z-index: 9000 !important;
}
::deep(.el-popper) {
  z-index: 9000 !important;
}
::deep(.ai-select-popper) {
  z-index: 9500 !important;
}
::deep(.el-overlay) {
  z-index: 8000 !important;
}
::deep(.el-overlay .el-dialog) {
  z-index: 8001 !important;
}

// 修复动态样式
&.size-custom {
  right: v-bind('isCustomPosition ? "auto" : "0"');
  left: v-bind('isCustomPosition ? windowPosition.x + "px" : "auto"');
  top: v-bind('isCustomPosition ? windowPosition.y + "px" : "0"');
  width: v-bind('windowSize.width');
  height: v-bind('windowSize.height');
}

&.size-minimized {
  right: auto !important;
  left: v-bind('windowPosition.x + "px"') !important;
  top: v-bind('windowPosition.y + "px"') !important;
  width: v-bind('windowSize.width + "px"') !important;
  height: v-bind('windowSize.height + "px"') !important;
  border-radius: 20px;
  padding: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}


// 新增：最小化状态下隐藏内容
.size-minimized .ai-float-main,
.size-minimized .ai-float-form-list,
.size-minimized .ai-float-header > div:first-child {
  display: none;
}

// 新增：最小化按钮样式
.size-minimized .ai-float-header {
  padding: 0;
  width: 100%;
  height: 100%;
  border-bottom: none;
  cursor: default;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 确保头部右侧按钮组正确显示 */
.ai-float-header-actions {
  display: flex;
  align-items: center;
}

// 优化最小化按钮样式
.ai-float-minimize {
  font-size: 16px;
  cursor: pointer;
  color: #888;
  transition: color 0.2s;
  margin-right: 12px;
  line-height: 1;
}

.size-form {
  width: 80vw;
}

.size-menu {
  width: 24%; //80vw的30%。跟下面al-float-right的flex定义匹配宽度
}

.size-minimize {
  width: 24%;
  height:360px;
}

.ai-float-minimize:hover {
  color: #409eff;
}

// 最小化状态下隐藏关闭按钮
.size-minimized .ai-float-close {
  display: none;
}

// 优化调整大小的句柄，使用通用图标样式
.ai-float-resize-handle {
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 16px;
  height: 16px;
  border-radius: 2px;
  cursor: se-resize;
  opacity: 0.6;
  transition: opacity 0.2s;
  z-index: 10;

  // 使用CSS创建通用的调整大小图标
  &::after {
    content: '';
    position: absolute;
    right: -2px;
    bottom: -2px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 8px 8px 0;
    border-color: transparent #fff transparent transparent;
  }
}

.ai-float-resize-handle:hover {
  opacity: 1;
}

.ai-float-main {
  display: flex;
  height: 100vh;
}

.ai-float-left {
  flex: 7 7 0;
  background: #f7f8fa;
  border-right: 1px solid #e0e7ef;
  overflow: auto;
  height: 100%;
}

.ai-float-right {
  flex: 3 3 0;
  min-width: 260px;
  width: 500px;
  height: 100%;
  display: flex;
  flex-direction: column;
}

// 调整头部按钮区域布局
.ai-float-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 18px;
  font-weight: bold;
  padding: 16px 24px 8px 24px;
  cursor: move;
  border-bottom: 1px solid #f0f0f0;
}

// 调整头部右侧按钮组
.ai-float-header-actions {
  display: flex;
  align-items: center;
}

.ai-float-welcome {
  font-size: 16px;
  color: #409eff;
  margin-bottom: 10px;
  font-weight: 500;
}

.ai-float-close {
  font-size: 20px;
  cursor: pointer;
  color: #888;
  transition: color 0.2s;
}

.ai-float-close:hover {
  color: #f56c6c;
}

.ai-float-form-list {
  padding: 16px 24px 0 24px;
  flex-shrink: 0;
  max-height: 220px;
  overflow-y: auto;
}

.form-list-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.form-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.form-list-title {
  font-size: 15px;
  color: #333;
  margin: 0;
  margin-bottom:10px;
}

.form-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.form-tag {
  cursor: pointer;
  margin-bottom: 4px;
}

.more-btn {
  margin-left: 8px;
  font-size: 13px;
  padding: 0 4px;
}

.loading-container {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  color: #666;
  gap: 8px;
}

.ai-float-input-area {
  padding: 6px 24px 0 24px;
  flex-shrink: 0;
  height: 140px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.ai-float-form-info {
  margin-bottom: 8px;
  background: #f6f8fa;
  border-radius: 1px;
  padding: 10px 14px;
}

.form-info-title {
  font-weight: bold;
  color: #333;
  margin-bottom: 2px;
}

.form-info-tip {
  color: #666;
  font-size: 13px;
  margin-bottom: 2px;
}

.form-info-example {
  color: #999;
  font-size: 13px;
}

.ai-float-input-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.ai-float-input {
  flex: 1 1 auto;
}

.ai-model-selector {
  flex-shrink: 0;
  z-index:8000;
}

.ai-float-send-btn {
  margin-bottom: 4px;
}

.ai-float-chat-list {
  flex: 1 1 auto;
  margin: 0 24px;
  margin-top: 12px;
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  min-height: 0;
  max-height: calc(100vh - 170px - 140px - 32px);
}

.ai-float-chat-item {
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
}

.ai-chat-ai {
  justify-content: flex-start;
}

.ai-avatar {
  width: 32px;
  height: 32px;
  background: linear-gradient(135deg, #e0e7ef 0%, #f6f8fa 100%);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  margin-right: 8px;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.08);
}

.ai-float-chat-bubble {
  background: linear-gradient(135deg, #409eff 0%, #6ec1ff 100%);
  color: #fff;
  border-radius: 20px 20px 4px 24px;
  padding: 12px 22px;
  max-width: 80%;
  font-size: 14px;
  word-break: break-all;
  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.13);
  line-height: 1.85;
  min-height: 36px;
  display: inline-block;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.ai-float-chat-bubble-ai {
  background: linear-gradient(135deg, #f4f4f4 0%, #e9f0fb 100%);
  color: #333;
  border-radius: 16px 16px 16px 6px;
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.10);
  border: 1px solid #e0e7ef;
}

.ai-select-lists {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: stretch;
}

.ai-select-list-block {
  width: 100%;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 0;
  margin: 0;
}

.ai-select-list-title {
  font-weight: 500;
  color: #333;
  text-align: left;
  width: 100%;
  margin: 0;
  padding: 0;
}

.ai-select-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  text-align: left;
  margin: 0;
  padding: 0;
}

.ai-select-options .el-button {
  width: 100%;
  text-align: left;
  margin: 0;
  padding-left: 0 !important;
  justify-content: flex-start;
}

.el-dialog__body .ai-select-title {
  margin-bottom: 8px;
}

.el-dialog__body .ai-select-options {
  width: 100%;
  justify-content: flex-start;
  gap: 8px;
}

.ai-float-chat-bubble-user-wrap {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 8px;
}

.ai-avatar-user {
  background: linear-gradient(135deg, #e0e7ef 0%, #d0eaff 100%);
  color: #409eff;
}


.recording-btn {
  margin-bottom: 4px;
}

.recording-btn.recording {
  color: #f56c6c;
}

</style>
<style>

.topIndex {
  z-index: 99999999999999999999999 !important;
}
</style>
