<template>
    <div class="main-content"

        @dragstart="handleDragStart"
        @dragenter.prevent="handleDragEnter"
        @dragover.prevent="handleDragOver"
        @mouseup="handleMainMouseUp">
        <div class="inner-dropzone"  v-show="isDragging" @dragleave.prevent="handleDragLeave">
            <div class="inner-dropzone-content" >
                <div class="inner-dropzone-icon">
                    <img :src="isDarkMode? 'icons/upload-dark.svg':'icons/upload-light.svg'" alt=""   class="inner-dropzone-icon-icon"/>
                    <!-- <svgIcon :icon="isDarkMode? 'icons/upload-dark.svg':'icons/upload-light.svg'" class="inner-dropzone-icon-icon"/> --> 
                </div>
                <div class="inner-dropzone-text"> <span class="inner-dropzone-text-span">{{(store.loadTranslations['Drag files here to add them.'])}}</span></div>
                <div class="inner-dropzone-text-suffix"> <span class="inner-dropzone-text-suffix-span" id="innerDropzoneTextSuffix">{{(store.loadTranslations['You can only add one file, supported file types include: txt, doc, docx, xls, xlsx, ppt, pptx, pdf.'])}}</span></div>
            </div>
        </div>
        <!-- 历史会话列表 -->
        <ConversionList class="conversion-list-wrapper"
            :historyList="historyList" 
            :isDarkMode="isDarkMode"
            :show="showConversionList"
            @close="closeHistoryList" 
            @selectHistoryItem="selectHistoryItem"
            @showAlertDialog="showAlertDialog"/>
        <ChatTop />
        <WelcomePage ref="welcomePageRef" 
            v-model:question="question" 
            :recording="recording" 
            :historyLength="history.length"
            :currentAssistant="currentAssistant"
            :isKnowledgeBaseExist="isKnowledgeBaseExist"
            :isEmbeddingPluginsExist="isEmbeddingPluginsExist"
            :isLLMExist="isLLMExist"
            :currentAccount="currentAccount"
            :assistantList="assistantList"
            :shortcutList="shortcutList"
            @update:currentAssistant="updateCurrentAssistant"
            @showAssistantList="showAssistantList"
            v-show="history.length === 0" />
        <div class="chat-history" v-show="history.length > 0" @mousewheel="handleHistoryScroll">
            <custom-scrollbar class="history-scrollbar" id="chatHistory" ref="chatHistoryScrollbarRef"
                :autoHideDelay="2000" :thumbWidth="6" 
                :wrapperStyle="{height: '100%'}" :style="{ width: '100%', height: '100%'}" >
                <div class="bubble-div">
                    <!-- 重写聊天气泡 -->
                    <ChatBubble v-for="(item, index) in history" :key="index"
                        v-model:playAudioID="playAudioID" 
                        :historyIndex="index"
                        :item="item" :showStop="showStop"
                        :isLast="history.length === index + 1" 
                        :recording="recording" 
                        :netState="netState" 
                        :hasOutput="hasOutput"
                        :isKnowledgeBaseExist="isKnowledgeBaseExist"
                        :isEmbeddingPluginsExist="isEmbeddingPluginsExist"
                        @handleShowTip="handleShowTip" 
                        @retryRequest="retryRequest" 
                        @updateLikeOrDislike="updateLikeOrDislike" 
                        :currentAssistant="currentAssistant"
                        :isLLMExist="isLLMExist"
                        :isDarkMode="isDarkMode"
                        :isWindowMode="isWindowMode"
                    />
                </div>
            </custom-scrollbar>
        </div>
        <div class="chat-bottom">
            <div class="handle-tip">
                <div class="tip-item" v-show="showTopTip">
                    {{ topTipMsg }}
                </div>
                <div class="tip-item" v-show="showCount" v-if="store.loadTranslations['Stop recording after %1 seconds']">
                    {{ store.loadTranslations['Stop recording after %1 seconds'].replace('%1', countDown) }}
                </div>
                <div class="top-stop tip-item" v-show="showStop"  @click="stopRequest">
                    <svgIcon icon="stop" /> {{ store.loadTranslations['Stop'] }}
                </div>
            </div>
            <div class="top-returnBtnOut">
                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                    :show-after="1000" :offset="2" :content="store.loadTranslations['Back to bottom']">
                    <div class="top-returnBtn" @click="returnBottom" v-show="showReturnBottom && history.length > 0">
                        <SvgIcon icon="combobox-arrow"/>
                    </div>
                </el-tooltip>
            </div>
            <!-- 添加MCP服务器 -->
            <AddMcpServer ref="addMcpServerRef"
                    :show="showAddMcpServer"
                    :resultMsg="addMcpServeResultMsg"
                    @close="closeAddMcpServer"
                    @confirm="confirmAddMcpServer"
                    @keepMcpListShow="keepMcpListShow"
                    @jsonFormatError="jsonFormatError"/>            
            <div class="top" v-show="!showPropmptList && !showMcpServerList">
                <!-- 创建新会话记录按钮 -->
                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                    :show-after="1000" :offset="2" :content="store.loadTranslations['New Conversation']">
                    <div class="add-new-conversation" :class="{'disabled': history.length === 0 || disabled || recording}"
                         :style="{ 'margin-right': '6px'}"
                        @click="createNewConversation">
                        <SvgIcon icon="new-conversation"/>
                    </div>
                </el-tooltip>
                <!-- 历史记录按钮 -->
                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                    :show-after="1000" :offset="2" :content="store.loadTranslations['History']">
                    <div class="prompt-btn" :class="{'disabled': (recording || disabled)}"
                         :style="{ 'margin-right': ((currentAssistant.type === store.AssistantType.UOS_AI || currentAssistant.id === 'PPT Assistant') && (isShowPromptBtn || isEnableMcp)) ? '6px' : 'auto' }"
                        @click="openHistoryList">
                        <SvgIcon icon="open-history" />
                    </div>
                </el-tooltip>
                <!-- 指令按钮 -->
                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                    :show-after="1000" :offset="2" :content="store.loadTranslations['Instruction']" 
                    :class="{ 'disabled': !(recording || disabled) }">
                    <div class="prompt-btn" @click="selectPrompt" 
                        :style="{ 'margin-right': ((currentAssistant.type === store.AssistantType.UOS_AI || currentAssistant.id === 'PPT Assistant') && isShowPromptBtn && isEnableMcp) ? '6px' : 'auto' }"
                        :class="{ 'disabled': (recording || disabled) }"
                        v-show="(currentAssistant.type === store.AssistantType.UOS_AI || currentAssistant.id === 'PPT Assistant') && isShowPromptBtn">
                        <SvgIcon icon="prompt"/>
                    </div>
                </el-tooltip>
                <!-- mcp开关按钮 -->
                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                    :show-after="1000" :offset="2" :content="store.loadTranslations['MCP Server']" 
                    :class="{ 'disabled': !(recording || disabled) }">
                    <div class="prompt-btn" @click="clickMcpServerIcon" 
                        ref="mcpServerIconRef"
                        style="margin-right: auto;"
                        :class="{ 'disabled': (recording || disabled) }"
                        v-show="(currentAssistant.type === store.AssistantType.UOS_AI || currentAssistant.id === 'PPT Assistant') && isEnableMcp">
                        <SvgIcon icon="mcp-switch" :style="{'fill': store.IsOpenMcpServer && store.IsInstallUOSAiAgent?  'var(--activityColor)' : 'var(--uosai-color-flat-btn-icon)', 'width': '13.54px', 'height': '12.77px'}"/>
                    </div>
                </el-tooltip>
                <!-- 切换助手模型下拉框 -->
                <SwitchModel ref="switchModel" class="switchModel"
                    v-model:currentAccount="currentAccount" v-model:accountList="accountList" 
                    v-model:assistantList="assistantList" v-model:currentAssistant="currentAssistant"
                    :showGuide="showGuide"
                    :disabled="disabled || recording"  @update:currentAssistant="updateCurAssistant" @update:currentAccountChanged="currentAccountChanged"/>
                <!-- 引导界面 -->
                <GuideOverlay
                    :targetRef="mcpServerIconRef"
                    :visible="showGuide"
                    @close="closeGuide"
                    @install="installUOSAiAgent"
                    />
            </div>
            <div class="input-content" @mouseup="handleMouseUp" :class="{ 'foucs': isFocus}">
                <!-- MCP服务器列表 -->
                <McpServerList class="mcp-server-list"
                    :show="showMcpServerList"
                    :mcpServerList="mcpServerList"
                    @close="closeMcpServerList"
                    @removeMcpSeverItem="removeMcpSeverItem"
                    @showAddMcpServerDialog="showAddMcpServerDialog"
                    @mcpCheckChange="handleMcpCheckChange"/>
                <!-- 指令列表 -->
                <PromptList ref="promptListRef" class="propmpt-list"
                    :showPropmptList="showPropmptList" 
                    :searchQuery="searchQuery"
                    :promptInfos="promptInfos"
                    @sigHidePromptLists="sigHidePromptLists" 
                    @sigSelectOnePrompt="sigSelectOnePrompt"/>
                <div class="input-content-all" :style="{'border-radius': showPropmptList || showMcpServerList ? '0px 0px 8px 8px' : '8px', }">
                    <!-- 功能按钮列表 -->
                    <FunctionButtons 
                        ref="functionButtonsRef"
                        :functionList="functionList"
                        :isWindowMode="isWindowMode"
                        :currentAssistant="currentAssistant"
                        v-show="currentAssistant.type === store.AssistantType.AI_WRITING_ASSISTANT||currentAssistant.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT"
                        @selectFunction="handleFunctionSelect"
                        @clearFunction="handleFunctionClear"
                    />
                    <!-- 挂起来的标签部分 -->
                    <div class="input-tag">
                        <!-- 文档总结 -->
                        <DocumentParsing ref="documentParsingRef" v-show="isShowFile"
                            style="display: auto; top: 0; left: 0;margin-top: 8px;margin-left: 10px;"
                            @sigDeleteFile="sigDeleteFile" :filePath="filePath" :fileNameText="fileNameText" :imgBase64="imgBase64"/>
                        <!-- 指令标签 -->
                        <PromptTag v-show="showPromptTag" :promptTag="promptTag" 
                            style="margin-top: 8px;margin-left: 10px;"/>
                    </div>
                    <el-input v-model="question" 
                        ref="questionInput" 
                        resize="none"
                        :autosize="{ minRows: 4, maxRows: 10 }"
                        type="textarea" 
                        :placeholder="placeHolder" 
                        @focus="handleInputFocus"
                        @blur="handleInputNoFocus"  
                        @keydown.enter.native="handeleEnter" 
                        @input="handleInput"
                        @keydown.up="highlightPrevious"
                        @keydown.down="highlightNext"
                        @keydown.left="handleKeyLeft"
                        @keydown.right="handleKeyRight"
                        @keydown.enter="handleEnterKeyDown"
                        @keydown.backspace="handleBackspace"
                        @mousedown="handleMouseDown"
                        @mouseup="handleInputMouseUp"
                        :disabled="recording || (currentAssistant.type === store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isKnowledgeBaseExist ||!isEmbeddingPluginsExist)&& history.length === 0)
                        || ((currentAssistant.type === store.AssistantType.UOS_SYSTEM_ASSISTANT||currentAssistant.type === store.AssistantType.DEEPIN_SYSTEM_ASSISTANT) && !isEmbeddingPluginsExist && history.length === 0)
                        || showGuide" />
                    <div class="bottom">
                        <div style="margin-left: 10px; display: flex;">
                            <ModelSwitch 
                                    v-model:currentAccount="currentAccount" 
                                    v-model:accountList="accountList"
                                    :disabled="disabled || recording"
                                    @update:currentAccountChanged="currentAccountChanged"
                                    style="margin-right: 10px;"/>
                            <div v-show="showDeepThinkAndSearchOnline"  style="display: flex;">
                                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                                :show-after="1000" :offset="2"
                                :content="store.loadTranslations['DeepThink(R1)']">
                                    <div class="deep-think-btn" @click="deepThinkClick" :style="{'color': store.IsDeepThink ? 'var(--activityColor)' : 'var(--uosai-think-search-color)', 'width' : deepThinkWidth}">
                                        <SvgIcon icon="deep-think" :style="{'fill': store.IsDeepThink ?  'var(--activityColor)' : 'var(--uosai-think-search-color)', 'margin-right': isWindowMode ? '5px' : '0px'}"/>
                                        <span v-show="isWindowMode">{{ store.loadTranslations['DeepThink(R1)'] }}</span>
                                    </div>
                                </el-tooltip>
                                <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                                :show-after="1000" :offset="2"
                                :content="store.loadTranslations['Search']">
                                    <div class="deep-think-btn" @click="searchOnlineClick" :style="{'color': store.IsSearchOnline? 'var(--activityColor)' : 'var(--uosai-think-search-color)', 'width' : onlineSearchWidth, 'margin-left': '10px'}">
                                        <SvgIcon icon="search-online" :style="{'fill': store.IsSearchOnline ?  'var(--activityColor)' : 'var(--uosai-think-search-color)', 'margin-right': isWindowMode ? '5px' : '0px'}"/>
                                        <span v-show="isWindowMode">{{ store.loadTranslations['Search'] }}</span>
                                    </div>
                                </el-tooltip>
                            </div>
                        </div>
                        <div class="send-btn">
                            <!-- 文档总结按钮 -->
                            <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                                :show-after="1000" :offset="2"
                                :content="isFileInInput? store.loadTranslations['You can only add a maximum of one file.'] : store.loadTranslations['Upload a document']"
                                :class="{ 'disabled': !(isFileInInput || recording || disabled || (currentAssistant.type != store.AssistantType.UOS_AI && currentAssistant.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.id != 'PPT Assistant'))}">
                                <div class="file-btn btn"
                                v-show="(currentAssistant.type === store.AssistantType.UOS_AI || currentAssistant.type === store.AssistantType.AI_TRANSLATION_ASSISTANT || currentAssistant.type === store.AssistantType.AI_WRITING_ASSISTANT || currentAssistant.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT || currentAssistant.id === 'PPT Assistant')"
                                :class="{ 'disabled': (isFileInInput || recording || disabled || (currentAssistant.type != store.AssistantType.UOS_AI && currentAssistant.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.id != 'PPT Assistant')) }"
                                    @click="selectFile">
                                    <SvgIcon icon="file" />
                                </div>
                            </el-tooltip>
                            <el-tooltip popper-class="uos-tooltip" effect="light" :show-arrow="false" :enterable="false"
                                :show-after="1000" :offset="2"
                                :content="netState ? !isAudioInput ? store.loadTranslations['Please connect the microphone and try again'] : store.loadTranslations['Voice input'] : store.loadTranslations['Voice input is temporarily unavailable, please check the network!']">
                                <div class="voice-btn btn"
                                    :class="{ recording, disabled: !isAudioInput || showStop || !netState || 
                                        (currentAssistant.type === store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isKnowledgeBaseExist ||!isEmbeddingPluginsExist) && history.length === 0)
                                        || ((currentAssistant.type === store.AssistantType.UOS_SYSTEM_ASSISTANT||currentAssistant.type === store.AssistantType.DEEPIN_SYSTEM_ASSISTANT) && !isEmbeddingPluginsExist && history.length === 0 )
                                        , notalking: audioLevel === 0 }"
                                    @click="handleRecorder">
                                    <SvgIcon icon="voice" />
                                </div>
                            </el-tooltip>
                            <div class="send btn" :class="{ 'disabled': (question.trim().length === 0  && !isFileInInput) || disabled 
                                || (currentAssistant.type === store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isKnowledgeBaseExist ||!isEmbeddingPluginsExist) && history.length === 0)
                                || ((currentAssistant.type === store.AssistantType.UOS_SYSTEM_ASSISTANT||currentAssistant.type === store.AssistantType.DEEPIN_SYSTEM_ASSISTANT)&& !isEmbeddingPluginsExist  && history.length === 0)
                                || (isFileInInput && !isFileParsingSuccess)}"
                                @click="sendQuestion">
                                <SvgIcon icon="send" />
                            </div>
                        </div>
                    </div>
                    
                </div>
            </div>
            <!-- 提示信息 -->
            <div class="tip">
                {{ store.loadTranslations[`The content generated by AI is for reference only, please pay attention to the accuracy of the information.`] }}
            </div>
        </div>
    </div>
</template>

<script setup>
import { useGlobalStore } from "@/store/global";
import { Qrequest } from "@/utils";
import _ from "lodash";
import ModelSwitch from "./components/ModelSwitch.vue";
import SwitchModel from "./components/SwitchModel.vue";
import WelcomePage from "./components/welcomePage.vue";
import ChatBubble from "./components/ChatBubble.vue";
import ChatTop from "./components/ChatTop.vue";
import PromptList from "./components/PromptList.vue";
import McpServerList from "./components/McpServerList.vue";
import PromptTag from "./components/PromptTag.vue";
import GuideOverlay from "./components/GuideOverlay.vue";
import AddMcpServer from "./components/AddMcpServer.vue";
import ConversionList from "./components/ConversionList.vue"
import CustomScrollbar from 'custom-vue-scrollbar';
import 'custom-vue-scrollbar/dist/style.css';
import { ref } from "vue";
import { useRouter } from "vue-router";
import FunctionButtons from "./components/FunctionButtons.vue";

//*******************************************************************************
/**
 * 拖拽蒙版js
 */
import DocumentParsing from "./components/DocumentParsing.vue"
import SvgIcon from "@/components/svgIcon/svgIcon.vue";
const documentParsingRef = ref()
const showFile=ref(false)
const fileNameText=ref('')
const filePath= ref('')
const imgBase64= ref('')
const isDragging = ref(false); // 控制蒙版显示的变量
const isFileInInput = ref(false)  //输入框是否存在文件
const isFileParsingSuccess = ref(false)  //文件解析状态成功
const isDarkMode = ref(false)  //是否为深色主题
const isShowDocInHistory = ref(false)

//历史记录中文件属性
const fileContentParam = {
            isShowDoc:false,
            docPath:"",
            iconData:""
        }

function handleDragEnter(event) {
    event.preventDefault(); // 阻止默认事件
    event.stopPropagation();

    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中
    if(showGuide.value) return  //引导页不处理拖拽
    // if(isFileInInput.value) return  //文件存在
    if(currentAssistant.value.type != store.AssistantType.UOS_AI && currentAssistant.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.value.id != 'PPT Assistant') return  //非UOS AI助手
    const messageElement = document.getElementById('innerDropzoneTextSuffix');
    if(currentAssistant.value.type === store.AssistantType.UOS_AI || currentAssistant.value.type === store.AssistantType.AI_TRANSLATION_ASSISTANT || currentAssistant.value.type === store.AssistantType.AI_WRITING_ASSISTANT || currentAssistant.value.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT) {
       messageElement.textContent = store.loadTranslations['You can only add one file, supported file types include: txt, doc, docx, xls, xlsx, ppt, pptx, pdf.']
    } else if(currentAssistant.value.id === 'PPT Assistant') {
       messageElement.textContent = "最多只能添加一个文件，文件类型：docx"
    }
    isDragging.value = true;
}


function handleDragOver(event) {
    event.preventDefault(); // 阻止默认事件

    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中
    if(showGuide.value) return  //引导页不处理拖拽
    // if(isFileInInput.value) return  //文件存在
    if(currentAssistant.value.type != store.AssistantType.UOS_AI && currentAssistant.value.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.value.id != 'PPT Assistant') return  //非UOS AI助手
    const messageElement = document.getElementById('innerDropzoneTextSuffix');
    if(currentAssistant.value.type === store.AssistantType.UOS_AI || currentAssistant.value.type === store.AssistantType.AI_TRANSLATION_ASSISTANT || currentAssistant.value.type === store.AssistantType.AI_WRITING_ASSISTANT || currentAssistant.value.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT) {
       messageElement.textContent = store.loadTranslations['You can only add one file, supported file types include: txt, doc, docx, xls, xlsx, ppt, pptx, pdf.']
    } else if(currentAssistant.value.id === 'PPT Assistant') {
       messageElement.textContent = "最多只能添加一个文件，文件类型：docx"
    }
    isDragging.value = true;
}

function handleDragLeave(event) {
    event.stopPropagation();
    isDragging.value = false;
}

function handleDragLeaveChild(event) {
    event.stopPropagation();
    event.preventDefault(); // 阻止默认事件
}

function handleDragEnterChild(event) {
    event.preventDefault(); // 阻止默认事件
    event.stopPropagation();
}

/**
 * 文档显示图标js
 */

//*******************************************************************************

const router = useRouter();
const { chatQWeb, updateActivityColor, updateTheme, updateFont, updateMainContentBackgroundColor} = useGlobalStore()
const store = useGlobalStore()
const instance = getCurrentInstance()
const question = ref('')
const isFocus = ref(false)
const showTopTip = ref(false)
// showStop控制 底部的清除icon、发送按钮、语音图标、模型切换、状态切换按钮、<>置灰，播放按钮置灰，设置不置灰，可正常点击
const showStop = ref(false)
const topTipMsg = ref('')
const accountList = ref([])
const assistantList = ref([])
const currentAccount = ref('')
const currentAssistant = ref('')
const playAudioID = ref('')
const isKnowledgeBaseExist = ref(false)
const isEmbeddingPluginsExist = ref(false)
const isLLMExist = ref(false)
const disabled = computed(() => {
    return showStop.value
})
const isAudioInput = ref(false)
const isWindowMode = ref(false);
const isChineseLanguage = ref(false);

const isEnableMcp = ref(false);

const initChat = async () => {
    const resAccount = await Qrequest(chatQWeb.queryLLMAccountList)
    const resCurAccountID = await Qrequest(chatQWeb.currentLLMAccountId)
    const resAssistant = await Qrequest(chatQWeb.queryAssistantList)
    const resCurAssistantID = await Qrequest(chatQWeb.currentAssistantId)
    isAudioInput.value = await Qrequest(chatQWeb.isAudioInputAvailable)
    hasOutput.value = await Qrequest(chatQWeb.isAudioOutputAvailable)
    netState.value = await Qrequest(chatQWeb.isNetworkAvailable)
    isKnowledgeBaseExist.value = await Qrequest(chatQWeb.isKnowledgeBaseExist)
    isEmbeddingPluginsExist.value = await Qrequest(chatQWeb.isEmbeddingPluginsExist)

    isChineseLanguage.value = await Qrequest(chatQWeb.isChineseLanguage)

    // 获取当前对话信息
    await getNowConversationInfo(resCurAssistantID)

    //新版查询历史记录
    const _history = await Qrequest(chatQWeb.getConversations)
    history.value = JSON.parse(_history)

    //查询当前系统主题
    const theme = await Qrequest(chatQWeb.getThemeType)
    sigThemeChanged(theme)

    //查询窗口模式
    isWindowMode.value = await Qrequest(chatQWeb.isWindowMode);

    //查询当前后端统一背景色
    const backgroundColor = await Qrequest(chatQWeb.getMainContentbackgroundColor);
    sigMainContentBackgroundColor(backgroundColor)

    console.log("assistant list: ", resAssistant);
    console.log("current assistant id: ", resCurAssistantID);
    if (resAssistant) {
        const list = JSON.parse(resAssistant);
        assistantList.value = list;

        for (const element of list) {
            if (element.id === resCurAssistantID) {
                element.active = true
                currentAssistant.value = element
                //查询功能按钮list
                const functionListStr = await Qrequest(chatQWeb.getAssistantFunctions, currentAssistant.value.type)
                if (functionListStr !== "") {
                    functionList.value = JSON.parse(functionListStr)
                }
            }
            
        }
    }
    if (resAccount) {
        const list = JSON.parse(resAccount)
        isLLMExist.value = list.length > 0;
        list.forEach(element => {
            if (element.id === resCurAccountID) {
                element.active = true
                currentAccount.value = element
            }
        });
        accountList.value = list;
    }

    //查询指令列表
    currentAccountChanged(currentAccount)

    //查询是否启用mcp
    isEnableMcp.value = await Qrequest(chatQWeb.isEnableMcp);

    //渲染完成，通知后端
    Qrequest(chatQWeb.webViewLoadFinished)
    Qrequest(chatQWeb.chatInitFinished)

    isMouseScroll.value = false  //初始化滚轮状态
    showReturnBottom.value = false  //初始化返回底部按钮状态
    nextTick(() => handelScrol())

    // 解决输入框重新计算行高导致页面跳动问题
    question.value = " "
    setTimeout(() => {
        question.value = ""
    }, 5); 
}

const currentTime = () => {
    //获取当前年月日时分秒
    var today = new Date().toISOString().slice(0, 10);

    const now = new Date();
    const hours = String(now.getHours()).padStart(2, '0');
    const minutes = String(now.getMinutes()).padStart(2, '0');
    const seconds = String(now.getSeconds()).padStart(2, '0');
    const milliseconds = String(now.getMilliseconds()).padStart(3, '0');

    return `${today} ${hours}:${minutes}:${seconds}.${milliseconds}`;
}

const likeOrNotAgent = ['ztbbd', 'xxzsk', 'yzsbs']
const initLikeOrNotExt = () => {
    //招投标初始化ext
    if(likeOrNotAgent.includes(currentAssistant.value.id)){
        let questionVec = []
        for (let index = 0; index < history.value.length; index++) {
            const element = history.value[index];
            
            questionVec.push({
                content: element.question.content,
                role:"user"
            })

            if (index < history.value.length - 1) {
                questionVec.push({
                    content: _.last(element.answers).displayContent,
                    role:"assistant"
                })
            }
        }

        let ext = [{
            type: store.ExtentionType.LikeOrNot,
            question: JSON.stringify(questionVec),
            questionTime:currentTime(),
            answer: "",
            answerTime: currentTime(),
            assistantName: currentAssistant.value.displayname ? currentAssistant.value.displayname : '',
            modelType:currentAccount.value.model ? currentAccount.value.model : '',
            llm:currentAccount.value.displayname ? currentAccount.value.displayname : '',
            likeOrNot: store.LikeOrNot.NONE
        }]
        _.last(_.last(history.value).answers).extention = JSON.stringify(ext)
    }
}

const talkID = ref('')
const waitSend = ref(false)
//修改历史记录结构体
const history = ref([])
const isShowFile = ref(false)
const sendQuestion = async () => {
//*****************************************************************************************************************
    if ((question.value.trim().length === 0 && !isFileInInput.value) || disabled.value) return
    if (currentAssistant.value.type == store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isEmbeddingPluginsExist.value || !isKnowledgeBaseExist.value) && history.value.length === 0) return
    if (currentAssistant.value.type == store.AssistantType.DEEPIN_SYSTEM_ASSISTANT && !isEmbeddingPluginsExist.value && history.value.length === 0) return
    if (currentAssistant.value.type == store.AssistantType.UOS_SYSTEM_ASSISTANT && !isEmbeddingPluginsExist.value && history.value.length === 0) return
    if (isFileInInput.value && !isFileParsingSuccess.value) return  //文件存在但解析失败

    // 录音中点击发送按钮
    if (recording.value) {
        waitSend.value = true
        sigAudioASRError()
        return
    }
    await Qrequest(chatQWeb.stopPlayTextAudio)
    playAudioID.value = ''
    if (recording.value) sigAudioASRError()
//*****************************************************************************************************************

    /**
     * TODO:
     * 1.发送问题：只传question结构体
     * 2.应答：只回复answer结构体
     * 3.维护历史记录结构体
     */


    /**
     * 后期改接口
     */
     if(isFileInInput.value && isFileParsingSuccess.value && question.value.trim().length === 0){
        if (showPromptTag.value ) {
            question.value = ''
        } else if (currentAssistant.value.id === 'PPT Assistant') {
            question.value = '根据文档生成PPT。'
        } else if (currentAssistant.value.type != store.AssistantType.UOS_AI){
            switch(currentAssistant.value.type){
                case store.AssistantType.AI_WRITING_ASSISTANT:  //写作
                    question.value = store.loadTranslations["Write an article based on the following document:"]
                    break
                case store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT:  //文本处理
                    {
                        const idx = store.CurrentAssistantFunctionButtonActiveIndex.find(item => item.assistantId === currentAssistant.value.type).index
                        if (idx === -1) {
                            question.value = store.loadTranslations['Summarize the key content of the file.']
                        }
                    }
                    break
                case store.AssistantType.AI_TRANSLATION_ASSISTANT:  //翻译
                    question.value = store.loadTranslations["Translate the following document into English:"]
                    break
                default:
                    question.value = ''
                    break
            }
        } else {
            question.value = docParsingPlaceHolder.value
        }
     }
    // const { id, model, icon, displayname } = currentAccount.value
    const extention = []
    const ques = {
        displayContent:question.value,
        reqId:"0",
        chatType:0,
        isRetry:false,
        onlineSearch: store.IsSearchOnline,
	    extention:JSON.stringify(extention)
    }
    // ques添加openThink字段
    if (showDeepThinkAndSearchOnline.value) {
        ques.openThink = store.IsDeepThink
        ques.onlineSearch = store.IsSearchOnline
    }else{
        ques.openThink = false
        ques.onlineSearch = false
    }
    
    //文档存在
    if(isFileInInput.value && isFileParsingSuccess.value){
        isShowFile.value = false
        isFileInInput.value = false
        isFileParsingSuccess.value = false
        extention.push({
            type: store.ExtentionType.DocSummary,
        	docPath: filePath.value,
        	docName:fileNameText.value,
		    iconData:imgBase64.value,
		    docContent:docContent.value
        })
        ques.extention = JSON.stringify(extention)
    }
    //标签存在
    if(showPromptTag.value){
        extention.push({
            type: store.ExtentionType.PromptTag,
            tagType:promptInfo.value.tagType,
            tagName:promptInfo.value.tagName,
            content:promptInfo.value.content,
            description:promptInfo.value.content
        })
        ques.extention = JSON.stringify(extention)
        showPromptTag.value = false
    }

    // MCP开关 uos ai智能体才支持 且uos ai智能体已安装
    if (store.McpServerListCheckedName.length > 0 && currentAssistant.value.type == store.AssistantType.UOS_AI && store.IsInstallUOSAiAgent) {
        extention.push({
            type: store.ExtentionType.McpBtnStatus,
            McpServers: store.McpServerListCheckedName
        })
        ques.extention = JSON.stringify(extention)
    }


    //标签列表存在
    if (showPropmptList.value) {
        showPropmptList.value = false
    }
    
    // 功能按钮存在
    if (currentAssistant.value.type === store.AssistantType.AI_WRITING_ASSISTANT||currentAssistant.value.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT) {
        const idx = store.CurrentAssistantFunctionButtonActiveIndex.find(item => item.assistantId === currentAssistant.value.type).index
        if (idx !== -1) {
            extention.push({
                type: store.ExtentionType.FunctionButton,
                functionButton:functionList.value[idx].Function,
            })
            ques.extention = JSON.stringify(extention)
        }
    }

    // 写作智能体
    if (currentAssistant.value.type === store.AssistantType.AI_WRITING_ASSISTANT) {
        // 发送问题后功能按钮取消选中
        const found = store.CurrentAssistantFunctionButtonActiveIndex.find(item => item.assistantId === currentAssistant.value.type)
        if (found) {
            found.index = -1
            functionButtonsRef.value.resetActiveIndex()
        }
        
    }

    // 文本处理智能体
    if (currentAssistant.value.type === store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT) {
        const idx = store.CurrentAssistantFunctionButtonActiveIndex.find(item => item.assistantId === currentAssistant.value.type).index
        if (idx !== -1) {
            if (ques.displayContent !== ""){
                ques.displayContent = "[" + functionList.value[idx].Name + "]\n " + ques.displayContent
            }else{
                ques.displayContent = "[" + functionList.value[idx].Name + "]"
            }
        }
    }

    let sendQuestionAccount = currentAccount.value
    const { id, model, icon, displayname } = sendQuestionAccount

    history.value.push({
        question:ques,
        answers:[
            {
                displayContent:"",
                content:"",
                displayHash:"",
                reqId:"0",
                llmIcon: icon ? icon : '',
                llmName: displayname ? displayname : '',
                llmId: id ? id : '',
                llmModel:model,
                assistantId: currentAssistant.value.id ? currentAssistant.value.id : '',
                assistantName : currentAssistant.value.displayname,
                errCode:0,
                errInfo:{},  //补充json
                chatType:0,  //问答、文生图、FunctionCall
                isRetry:false,
                extention:"[]",
                thinkTime: "-1",
                openThink: false,
                onlineSearch: false
            }
        ]
     })

    showStop.value = true
    question.value = ''
    const quesResp = await Qrequest(chatQWeb.sendRequest, id ? id : '', JSON.stringify(ques))
    closeMcpServerList()  //关闭mcp列表
   
    try{
        JSON.parse(quesResp)
    }
    catch(e){
        return
    }

    isFoundThinkStart.value = false
    isFoundThinkStop.value = false
    
    
    _.last(history.value).question = JSON.parse(quesResp)
    _.last(_.last(history.value).answers).reqId = JSON.parse(quesResp).reqId
    
    //初始化like or not
    initLikeOrNotExt()

    talkID.value = JSON.parse(quesResp).reqId

    isMouseScroll.value = false  //初始化滚轮状态
    showReturnBottom.value = false  //初始化返回底部按钮状态
    handelScrol()

    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))
    
}
const sendEmptyAnswers = async () => {
    let sendQuestionAccount = currentAccount.value
    const { id, model, icon, displayname } = sendQuestionAccount
    const extention = []

    const reqId = _.last(_.last(history.value).answers).reqId

    history.value.push({
        // question:ques,
        answers:[
            {
                displayContent:"",
                content:"",
                displayHash:"",
                reqId:"0",
                llmIcon: icon ? icon : '',
                llmName: displayname ? displayname : '',
                llmId: id ? id : '',
                llmModel: model,
                assistantId: currentAssistant.value.id ? currentAssistant.value.id : '',
                assistantName : currentAssistant.value.displayname,
                errCode:0,
                errInfo:{},  //补充json
                chatType:0,  //问答、文生图、FunctionCall
                isRetry:false,
                extention:"[]",
                thinkTime: "-1",
                openThink: store.IsDeepThink,
                onlineSearch: store.IsSearchOnline
            }
        ]
     })

    showStop.value = true
    question.value = ''
   
    try{
        JSON.parse(quesResp)
    }
    catch(e){
        return
    }
    
    _.last(_.last(history.value).answers).reqId = reqId

    talkID.value = reqId
}
const clearHistory = async () => {
    if (history.value.length === 0 || disabled.value || recording.value) return
    await Qrequest(chatQWeb.clearConversations)
    await Qrequest(chatQWeb.stopPlayTextAudio)
    playAudioID.value = ''
    history.value = []
    handleShowTip(store.loadTranslations['Chat history cleared'])
    // Qrequest(chatQWeb.showToast,1)
    showFile.value = false  //清除后历史记录不显示文件标签在聊天窗口
    // act.value = 1
    store.QuestionAiAction = 1
}

const selectFile = async () => {
    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中
    if(isFileInInput.value) return  //文件存在
    if(currentAssistant.value.type != store.AssistantType.UOS_AI && currentAssistant.value.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.value.id != 'PPT Assistant') return  //非UOS AI助手
    await Qrequest(chatQWeb.onDocSummarySelect)

}

const handeleEnter = (event) => {
    if (!event.ctrlKey) {
        // sendQuestion()
    } else {
        event.preventDefault();
        event.stopPropagation();
        document.execCommand('insertText', false, '\n')
    }

}

const handleShowTip = (msg) => {
    showTopTip.value = true
    topTipMsg.value = msg
    setTimeout(() => {
        showTopTip.value = false
    }, 3000)
}

const updateCurAssistant = async (assistant) => {
    console.log("current assistant id changed: ", assistant.id);
    await getNowConversationInfo(assistant.id)
    const _history = await Qrequest(chatQWeb.getConversations)
    history.value = JSON.parse(_history)
    question.value = ''

    //切换助手，聊天窗口存在文件则删除
    if(isFileInInput.value){
        isShowFile.value = false
        isFileInInput.value = false
        isFileParsingSuccess.value = false
        // await Qrequest(chatQWeb.onDocSummaryRemove, documentParsingRef.value.filePath)  //通知后端删除当前的文件
        
        filePath.value = ''
        imgBase64.value = ''
        fileNameText.value = ''
    }

    //切换助手，聊天窗口存在标签则删除
    if (showPromptTag.value) {
        showPromptTag.value = false
        showPropmptList.value = false
    }

    /**
     * TODO:
     * 查询当前助手指令列表
     */
     currentAccountChanged()

    //查询功能按钮list
    const functionListStr = await Qrequest(chatQWeb.getAssistantFunctions, assistant.type)
    if (functionListStr !== "") {
        functionList.value = JSON.parse(functionListStr)
    }else{
        functionList.value = []
    }

     isMouseScroll.value = false  //初始化滚轮状态
     showReturnBottom.value = false  //初始化返回底部按钮状态
     nextTick(() => handelScrol())

     nextTick(() => {
        questionInput.value.focus()  //页面加载完成，自动聚焦到输入框
    }, 5)

}

const isShowPromptBtn = ref(false)
const currentAccountChanged  = async (accent) => {
    /**
     * TODO:
     * 查询当前助手指令列表
     */
     const getInstList_ = await Qrequest(chatQWeb.getInstList)
    try {
        promptInfos.value = JSON.parse(getInstList_)
    } catch (error) {
        isShowPromptBtn.value = false
        showPropmptList.value = false
        showPromptTag.value = false
        return
    }
    
    if (promptInfos.value.length == 0) {
        isShowPromptBtn.value = false
        showPropmptList.value = false
        showPromptTag.value = false
        return
    }
    isShowPromptBtn.value = true

    //当前模型不支持当前指令，清空
    let promptNameLists = []
    promptInfos.value.forEach(element => {
        promptNameLists.push(element.tagName)
    })
    
    if (showPromptTag.value && !promptNameLists.includes(promptTag.value)) {
        showPromptTag.value = false
    }  
}
//*********************************************
//提示词相关
const showPropmptList = ref(false)
const promptListRef=ref()
const searchQuery = ref('')
const showPromptTag = ref(false)
const promptTag = ref("")
const promptInfos = ref([])
const isInputPrompt = ref(false)
const handleInput = async (value) => {
    // 引导页不处理输入
    if(showGuide.value) {
        return
    }
    
    const selectionStart = questionInput.value.$el.querySelector('textarea').selectionStart
    searchQuery.value = ''
    if (value.startsWith('/') || value.startsWith('、')) {
        /**
         * TODO:
         * 查询当前助手指令列表
         */
        const getInstList_ = await Qrequest(chatQWeb.getInstList)
        try {
            promptInfos.value = JSON.parse(getInstList_)
        } catch (error) {
            return
        }
        
        if (promptInfos.value.length == 0) {
            showPropmptList.value = false;
            return
        }

        showPropmptList.value = true;
        if (value.startsWith('/')) {
            searchQuery.value = value.substr(0,selectionStart).replace('/','')
        }
        if (value.startsWith('、')) {
            searchQuery.value = value.substr(0,selectionStart).replace('、','')
            question.value = question.value.replace('、','/')
            nextTick(() => questionInput.value.$refs.textarea.setSelectionRange(1, 1))  //解决中文状态下修改question导致光标跑到最后的问题
            
        }
        
        promptListRef.value.highlightedIndex = 0 
        // question.value = question.value.replace('/','、')
        isInputPrompt.value = true
    } else {
      showPropmptList.value = false;
      isInputPrompt.value = false;
    }

    // 输入则关闭mcp列表
    showMcpServerList.value = false
};

const sigHidePromptLists = async (value) => {
    showPropmptList.value = false
    if (value && !isInputPrompt.value) {  //非手动输入状态关闭列表时删除/
        question.value = question.value.replace('/','')
    }
    isInputPrompt.value = false
}

const promptInfo = ref({})
const sigSelectOnePrompt = async (promptInfo_) => {
    questionInput.value.focus()
    /**
     * TODO:
     * 聊天框中显示指令
     */
     
    promptTag.value = promptInfo_.tagName
    promptInfo.value = promptInfo_
    showPromptTag.value = true
    question.value = question.value.replace('/'+searchQuery.value,'')

    // 有指令的情况，清空mcp勾选
    store.McpServerList = []
    store.McpServerListCheckedName = []
    store.IsOpenMcpServer = false
}

const highlightPrevious = (event) => {
    if (showPropmptList.value) {
        promptListRef.value.highlightPrevious()
        nextTick(() => event.target.setSelectionRange(1, 1))
    }
};
const highlightNext = (event) => {
    if (showPropmptList.value) {
        promptListRef.value.highlightNext()
        nextTick(() => event.target.setSelectionRange(1, 1))
    }
};

const handleKeyLeft = async (event) => {
    // handleInput(question.value)
};
const handleKeyRight = (event) => {
    // handleInput(question.value)
};

const handleEnterKeyDown = (event) => {
    if (showPropmptList.value) {
        promptListRef.value.handleEnterKeyDown()
        nextTick(() => event.target.setSelectionRange(0, 0))
    }
};

const handleBackspace = (event) => {
    // Backspace键被按下时执行的逻辑
    // start用于判断光标在第一位
    // end用于判断是否为全选，全选时end != 0
    if (showPromptTag.value 
        && questionInput.value.$el.querySelector('textarea').selectionStart == 0 
        && questionInput.value.$el.querySelector('textarea').selectionEnd == 0) {
        showPromptTag.value = false
    }
};

const inputSelectStart = ref(0)
const inputSelectEnd = ref(0)
const handleMouseDown = (event) => {
    //获取鼠标按下时选中的文本范围
    inputSelectStart.value = questionInput.value.$el.querySelector('textarea').selectionStart 
    inputSelectEnd.value = questionInput.value.$el.querySelector('textarea').selectionEnd
}

const handleInputMouseUp = (event) => {
    //获取鼠标按下时选中的文本范围
    //与鼠标按下时选中的文本范围比较，如果范围相同，则取消选中状态，将光标设置到最后
    if (questionInput.value.$el.querySelector('textarea').selectionStart == inputSelectStart.value
        && questionInput.value.$el.querySelector('textarea').selectionEnd == inputSelectEnd.value) {
        nextTick(() => event.target.setSelectionRange(question.value.length, question.value.length))
    }
    event.preventDefault(); // 阻止默认事件
    event.stopPropagation();
}

const handleMouseUp = (event) => {
    questionInput.value.focus()
    event.preventDefault(); // 阻止默认事件
    event.stopPropagation();
};

const handleMainMouseUp = (event) => {
    if (!event.target.classList.contains('guide-mask')) {
        isFocus.value = false
    } else {
        // 点击guide-mask时，重新聚焦到输入框，保持光标和聚焦效果
        nextTick(() => {
            questionInput.value.focus()
        })
    }
    if (showPropmptList.value && !isFocus.value) {
        nextTick(() => {
            if (!isInputPrompt.value) {
                sigHidePromptLists(true)
            }else{
                sigHidePromptLists(false)
            }
        }) 
    }

    if (showMcpServerList.value && !isFocus.value) {
        // 检查是否点击的是添加MCP服务器页面，如果是则不关闭列表
        const isClickingAddMcpServer = event.target.closest('.add-mcp-server-mask') || 
                                      event.target.closest('.add-mcp-server-modal')
        if (!isClickingAddMcpServer) {
            closeMcpServerList()
        }
    }
};

const handleDragStart = (event) => {
    event.preventDefault();
    event.stopPropagation();
}

const handleInputFocus = (event) => {
    isFocus.value = true  
    if (showPropmptList.value) {
        nextTick(() =>event.target.setSelectionRange(1, 1))
    }
    

    if (isAudioInInpit.value) {  //语音录入的文字
        nextTick(() =>event.target.setSelectionRange(question.value.length, question.value.length))
        isAudioInInpit.value = false
        return
    }
};
const handleInputNoFocus = (event) => {
    // isFocus.value = false
    // if (showPropmptList.value) {
        // nextTick(() => sigHidePromptLists(false))
    // }
};

const selectPrompt = async (event)  => {
    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中

    question.value = "/" + question.value
    // handleInput(question.value)

    /**
     * TODO:
     * 查询当前助手指令列表
     */
     const getInstList_ = await Qrequest(chatQWeb.getInstList)
    try {
        promptInfos.value = JSON.parse(getInstList_)
    } catch (error) {
        showPropmptList.value = false;
        return
    }
    
    if (promptInfos.value.length == 0) {
        showPropmptList.value = false;
        return
    }

    showPropmptList.value = true;
    searchQuery.value = ''
    promptListRef.value.highlightedIndex = 0 
    questionInput.value.focus()

    nextTick(() => {

        if (focus.value) {
            nextTick(() =>event.target.setSelectionRange(1, 1))
        }
    })
};

const mcpServerList = ref([])
const showMcpServerList = ref(false)
const mcpServerIconRef = ref(null)
const clickMcpServerIcon = async () => {
    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中

    showMcpServerList.value = true
    questionInput.value.focus()
    closeGuide(false)

    // 查询当前MCP服务器列表
    const mcpServerList_ = await Qrequest(chatQWeb.getMcpServers, store.DefaultAgentName)

    try {
        mcpServerList.value = []
        const mcpServerListRes = JSON.parse(mcpServerList_)
        if (mcpServerListRes.success == 0) {
            mcpServerList.value = mcpServerListRes.servers
            store.IsInstallUOSAiAgent = true
        } else {
            // TODO : 提示错误信息
            switch (mcpServerListRes.success) {
                case 1:
                    {
                        // 未安装UOSAI Agent
                        store.IsInstallUOSAiAgent = false
                        store.IsOpenMcpServer = false
                        store.McpServerListCheckedName = []
                    }
                    break;
            
                default:
                    break;
            }
        }
    } catch (error) {
        mcpServerList.value = []
        return
    }
}

const removeMcpSeverItem = async (item) => {
    const ret = await Qrequest(chatQWeb.removeCustomMcpServer, store.DefaultAgentName, item.name)
    try {
        const result = JSON.parse(ret)
        if (result.error != 0) {
            // TODO : 提示错误信息
        } else {
            clickMcpServerIcon()
        }
    } catch (error) {
        return
    }
}

const closeMcpServerList = () => {
    showMcpServerList.value = false
}

const handleMcpCheckChange = (isChecked) => {
    // 当MCP被勾选时， 如果输入框有指令，则清空输入框的指令和文字
    if (isChecked && showPromptTag.value) {
        // 清空指令标签
        showPromptTag.value = false
        promptTag.value = ''
        promptInfo.value = {}
        // 清空输入框文字
        question.value = ''
    }
}

const addMcpServerRef = ref(null)
const showAddMcpServer = ref(false)
const showAddMcpServerDialog = async () => {
    const getThirdPartyMcpAgreement = await Qrequest(chatQWeb.getThirdPartyMcpAgreement)  // 查询是否同意使用三方mcp服务
    if (!getThirdPartyMcpAgreement) {
        Qrequest(chatQWeb.writeVueLog, store.LogLevel.WARN, 'getThirdPartyMcpAgreement: ' + getThirdPartyMcpAgreement)
        return
    }

    clickMcpServerIcon()

    showAddMcpServer.value = true
    addMcpServeResultMsg.value = ''

    // titlebar mask 透明遮罩
    Qrequest(chatQWeb.setTitleBarMaskBgColorAndShow, 0, 0, 0, 0)
}

const closeAddMcpServer = () => {
    showAddMcpServer.value = false
    showMcpServerList.value = true
    nextTick(() => {
        questionInput.value.focus()
    })
    Qrequest(chatQWeb.setTitleBarMaskStatus, false)
}

const addMcpServeResultMsg = ref('')
const confirmAddMcpServer = async (jsonCode) => {
    const ret = await Qrequest(chatQWeb.addCustomMcpServer, store.DefaultAgentName, jsonCode)
    try {
        const result = JSON.parse(ret)
        if (result.error != 0) {
            addMcpServeResultMsg.value = store.loadTranslations["Add failed! Error reason:"] + result.errInfo
        } else {
            closeAddMcpServer()
            clickMcpServerIcon()
        }
    } catch (error) {
        return
    }    
}

const jsonFormatError = () => {
    addMcpServeResultMsg.value = store.loadTranslations["Add failed! Error reason:"] + store.loadTranslations["The JSON file format is incorrect, please check and submit again"]
}

const keepMcpListShow = () => {
    showMcpServerList.value = true
}

//输入框暗文
const docParsingPlaceHolder = ref('')
const placeHolder = computed(() => {
    // 开启mcp
    if (store.IsOpenMcpServer && store.IsInstallUOSAiAgent && currentAssistant.value.type === store.AssistantType.UOS_AI) {
        let placeHolder = store.loadTranslations["Enter MCP Server command, e.g., \"Change system to dark mode for me\""]
        if (currentAccount.value.model !== store.DeepSeek_Uos_Free) {
            // 如果当前助手是UOS_AI，且开启了MCP服务器，且当前模型不是DeepSeek-Trial Account，则提示切换到正式版模型
            placeHolder += "\n* " + store.loadTranslations["For MCP Server, switch to officially released model \"DeepSeek-Trial Account\""]
        }
        return placeHolder
    }

    //没有文件或标签
    //没有文件或标签
    if (!isFileInInput.value && !showPromptTag.value) {
        if (currentAssistant.value.id === 'PPT Assistant') {
            return '请输入PPT主题或者内容；'
        }
        if (currentAssistant.value.id === 'ai-writing') {
            return store.loadTranslations["Please Describe the Content Theme and Requirements for Your Creation."]
        }
        if (currentAssistant.value.id === 'ai-text-processing') {
            return store.loadTranslations["Please Enter the Text You Need to Process and Specify Your Requirements."]
        }
        if (currentAssistant.value.id === 'ai-translation') {
            return store.loadTranslations["Please Enter the Content You Want to Translate and Specify the Target Language. Default Translation is to Chinese."]
        }
        return store.loadTranslations["Enter your question, or enter \"/\" to select a command\n\"Ctrl+Enter\"  to start a new line"]
    }

    //文件和标签同时存在, 或标签单独存在
    if (showPromptTag.value) {
        return promptInfo.value.content
    }

    //文件存在，标签不存在
    if (isFileInInput.value) {
        if (currentAssistant.value.id === 'PPT Assistant') {
            return '根据文档生成PPT。'
        }
        if (currentAssistant.value.type != store.AssistantType.UOS_AI) {
            return ''
        }
        return docParsingPlaceHolder.value
    }
});

// 点赞踩变化
const updateLikeOrDislike = () => {
    // Qrequest(chatQWeb.logConversations,  JSON.stringify(history.value))
    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))
};

// 会话记录添加状态控制
const showConversionList = ref(false);
const historyList = ref(null);
const alertMessage = ref('确定要永久删除此聊天记录吗？');
// const currentConversationId = ref(null);
const createNewConversation= async () => {
    if (history.value.length === 0 || disabled.value || recording.value) return
    await Qrequest(chatQWeb.stopPlayTextAudio)  //停止播放
    await Qrequest(chatQWeb.createNewConversation)
    await getNowConversationInfo(currentAssistant.value.id)  //设置当前助手的最后一个会话信息
    //新版查询历史记录
    const _history = await Qrequest(chatQWeb.getConversations)
    history.value = JSON.parse(_history)
    const found = store.CurrentAssistantFunctionButtonActiveIndex.find(item => item.assistantId === currentAssistant.value.type)
    if (found) {
        found.index = -1
        functionButtonsRef.value.resetActiveIndex()
    }
}

const openHistoryList =  async () => {
    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中
    showConversionList.value = true;
    const historyList_ = await  Qrequest(chatQWeb.getConversationHistoryList)
    historyList.value = JSON.parse(historyList_)
}

const lastConversationInfo = ref({})
const getNowConversationInfo = async (assistantId) => {
    //更新最后会话信息情况：
    //1. 切换助手
    //2. 新建会话 已做
    //3. 切换会话
    //4. 初始化 已做
    // TODO:重新获取当前助手会话的信息，再根据conversationTitle去判断当前是否为新会话
    const lastConversationInfo_= await Qrequest(chatQWeb.getLastConversation, assistantId)  //拿到当前助手的最后一个会话信息
    lastConversationInfo.value = JSON.parse(lastConversationInfo_)  //解析当前助手的最后一个会话信息
    await Qrequest(chatQWeb.setCurrentConversationId, assistantId, lastConversationInfo.value.conversationId)  //设置当前助手的最后一个会话信息
}

const closeHistoryList = () => {
    showConversionList.value = false
    Qrequest(chatQWeb.setTitleBarMaskStatus, false)  //设置当前助手的最后一个会话信息
}

const selectHistoryItem = async (item) => {        // 新增助手存在性检查
    if (assistantList.value.some(a => a.id === item.assistantId)) {
        //切换助手和模型
        assistantList.value.forEach(element => {
            if (element.id === item.assistantId) {
                element.active = true
                currentAssistant.value.active = false
                currentAssistant.value = element
            }
        });
    }else{
        //当前助手被删除，弹窗提示
        alertMessage.value = store.loadTranslations['The %1 agent used in this conversation has been deleted'] + "_&_" + store.loadTranslations['This conversation cannot be viewed. To view it, please install the %1 agent and try again.'] 
        alertMessage.value = alertMessage.value.replace(/%1/g, item.assistantDisplayName)
        await Qrequest(chatQWeb.showWarningDialog, item.assistantId, item.conversationId, alertMessage.value, false, false)
        return
    }

    //输入框内容清空
    question.value = ''

    //切换助手，聊天窗口存在文件则删除
    if(isFileInInput.value){
        isShowFile.value = false
        isFileInInput.value = false
        isFileParsingSuccess.value = false
        // await Qrequest(chatQWeb.onDocSummaryRemove, documentParsingRef.value.filePath)  //通知后端删除当前的文件
        
        filePath.value = ''
        imgBase64.value = ''
        fileNameText.value = ''
    }

    //切换助手，聊天窗口存在标签则删除
    if (showPromptTag.value) {
        showPromptTag.value = false
        showPropmptList.value = false
    }

    //新版查询历史记录
    await Qrequest(chatQWeb.setCurrentConversationId, item.assistantId, item.conversationId)  //设置当前助手的最后一个会话信息
    const _history = await Qrequest(chatQWeb.getConversations)
    history.value = JSON.parse(_history)
    lastConversationInfo.value = item

    if (accountList.value.some(a => a.id === _.last(_.last(history.value).answers).llmId)) {
        accountList.value.forEach(element => {
            if (element.id === _.last(_.last(history.value).answers).llmId) {
                element.active = true
                currentAccount.value.active = false
                currentAccount.value = element
            }
        });
        /**
         * TODO:
         * 查询当前助手指令列表
         */
        await Qrequest(chatQWeb.setCurrentLLMAccountId, currentAccount.value.id)
        currentAccountChanged()
    }else{
        alertMessage.value = store.loadTranslations['The original conversation model has been deleted. We have switched to a new model for you to continue the conversation.']
        await Qrequest(chatQWeb.showWarningDialog, item.assistantId, item.conversationId, alertMessage.value, false, true)
        // 当前模型被删除时，自动切换第一个可用模型
        if (accountList.value.length > 0) {
            const firstAccount = accountList.value[0]
            firstAccount.active = true
            currentAccount.value.active = false
            currentAccount.value = firstAccount
        }
        return
    }
    Qrequest(chatQWeb.setTitleBarMaskStatus, false)  //设置当前助手的最后一个会话信息
    showConversionList.value = false
    
}

const updateCurrentAssistant = (item) => {
    switchModel.value.clickAssistantItem(item)
}

const showAssistantList = () => {
    switchModel.value.clickAssistantSwitch()
}

const showAlertDialog = async (item) => {
    alertMessage.value = store.loadTranslations['Are you sure to delete the conversation? It will be unrecoverable once deleted.']
    await Qrequest(chatQWeb.showWarningDialog, item.assistantId, item.conversationId, alertMessage.value, true, false)
}
//*********************************************

// 写作、文本处理智能体功能按钮
const functionButtonsRef = ref(null)
const functionList = ref([])
const shortcutList = ref([])
const handleFunctionSelect = async (item) => {
    
    if (history.value.length == 0) {
        //获取随机问题
        const questions = await Qrequest(chatQWeb.getAiFAQByFunction, currentAssistant.value.type, item.Function)
        if (questions != "") {
            shortcutList.value = JSON.parse(questions)
        }
    }

    let quesionModel = await Qrequest(chatQWeb.getFunctionTemplate, currentAssistant.value.type, item.Function, "")
    if (quesionModel !== "") {
        question.value = quesionModel
    }

    nextTick(() => {
        questionInput.value.focus()
    })
}
const handleFunctionClear = async () => {
    question.value = ""
    welcomePageRef.value.getAiFAQ()
}

// 新增智能体引导界面
const showGuide = ref(false)
const closeGuide = (isTryClicked) => {
    if (isTryClicked) {
        clickMcpServerIcon()
    } 
    showGuide.value = false
    Qrequest(chatQWeb.setTitleBarMaskStatus, false)  //关闭标题栏遮罩
    //记数据库，不再弹起引导界面
    Qrequest(chatQWeb.updateUpdatePromptDB, true)  

    // 把目标元素的层级设置为1
    mcpServerIconRef.value.style.zIndex = 1 
    // 把目标元素的pointerEvents属性设置为auto
    mcpServerIconRef.value.style.pointerEvents = 'auto'
}

const installUOSAiAgent = () => {
    Qrequest(chatQWeb.installUosAiAgent)
}

// 接受AI文本信息
const thinkStart = ref("<think>\n\n")
const thinkEnd = ref("\n\n</think>\n\n")
const startThinkTime = ref('')
const endThinkTime = ref('')
const isFoundThinkStart = ref(false)  //是否找到think开始标签
const isFoundThinkStop = ref(false)  //是否找到think结束标签

const isThinking = ref(false)
const replyMsg = ref({})
const answerDisplayMsg = ref([])

// 处理可能的多信号叠加情况
// 上次接收到的message对象
const lastMsg = ref({chatType: store.ChatAction.ChatNone})
const processSingleMessage = (msgValue, errCode) => {
    try {
        replyMsg.value = JSON.parse(msgValue);

        // 如果answerDisplayMsg为空，且当前chatType为工具调用且status不为调用中，则直接返回
        if (answerDisplayMsg.value.length == 0 && replyMsg.value.message.chatType == store.ChatAction.ChatToolUse && replyMsg.value.message.status != store.ToolUseStatus.Calling) {
            return true;
        }

        // 获取思考开始时间
        if (!isThinking.value && replyMsg.value.message.chatType == store.ChatAction.ChatTextThink){
            isThinking.value = true
            startThinkTime.value = new Date().getTime()
            _.last(_.last(history.value).answers).thinkTime = "-1"  //初始化think时间
        }

        // 获取思考结束时间
        if (isThinking.value && replyMsg.value.message.chatType != store.ChatAction.ChatTextThink){
            endThinkTime.value = new Date().getTime()
            _.last(_.last(history.value).answers).thinkTime = (Math.floor((endThinkTime.value - startThinkTime.value) / 1000)).toString()
            isThinking.value = false
        }

        /**
         * 直接push的情况
         * 1.上一个chatType不等于当前chatType且当前chatType不为工具调用
         * 2.当前chatType为工具调用且status为调用中
         */
        if((lastMsg.value.chatType !== replyMsg.value.message.chatType && replyMsg.value.message.chatType !== store.ChatAction.ChatToolUse) 
        || (replyMsg.value.message.chatType  === store.ChatAction.ChatToolUse && replyMsg.value.message.status === store.ToolUseStatus.Calling)){
            switch (errCode) {
                case -11000:  //智能体服务不可用
                    replyMsg.value.message.content = store.loadTranslations['Agent server is not available']
                    break;
                case -11001:  //智能体服务异常
                    replyMsg.value.message.content = store.loadTranslations['Agent server exception']
                    break;
                case -11100:  //MCP服务不可用
                    // replyMsg.value.message.content =  store.loadTranslations['MCP server is not available']
                    break;
                default:
            } 
            answerDisplayMsg.value.push(replyMsg.value.message)
        }

        /**
         * ++的情况
         * 思考内容，上一个也是思考内容
         * 正文内容，上一个也是正文内容
         */
        if (replyMsg.value.message.chatType === lastMsg.value.chatType && replyMsg.value.message.chatType !== store.ChatAction.ChatToolUse) {
            // 在answerDisplayMsg数组中找到最后一个chatType为replyMsg.value.message.chatType的元素
            for (let index = answerDisplayMsg.value.length - 1; index >= 0; index--) {
                const element = answerDisplayMsg.value[index];
                if (element.chatType === replyMsg.value.message.chatType) {
                    answerDisplayMsg.value[index].content += replyMsg.value.message.content
                    break
                }
            }
        }

        /**
         * 修改工具调用状态的情况
         */
        if (replyMsg.value.message.chatType === store.ChatAction.ChatToolUse ) {
            for (let index = 0; index < answerDisplayMsg.value.length; index++) {
                // 根据index和name更新工具调用状态
                if (answerDisplayMsg.value[index].index === replyMsg.value.message.index && answerDisplayMsg.value[index].name === replyMsg.value.message.name) {
                    answerDisplayMsg.value[index] = replyMsg.value.message
                }
            }
        }
        

        _.last(_.last(history.value).answers).displayContent = JSON.stringify(answerDisplayMsg.value)

        lastMsg.value = replyMsg.value.message
        
        return true;
    } catch (e) {
        Qrequest(chatQWeb.writeVueLog, store.LogLevel.CRITICAL, "index.vue processSingleMessage error:" + e.message)
        return false;
    }
};

const sigAiReplyStream = async (type, value, status) => {
    // 尝试处理原始value
    if (!processSingleMessage(value, status)) {
        
        // 如果处理失败，尝试分割可能的多信号数据
        const potentialMessages = value.split('}\n{').map((msg, i) => 
            i === 0 ? msg + '}' : 
            i === value.split('}\n{').length - 1 ? '{' + msg : 
            '{' + msg + '}'
        );
        
        for (const msg of potentialMessages) {
            processSingleMessage(msg, status);
        }
    }
    if (status !== 0) {
        const { icon, displayname } = currentAccount.value
        _.last(_.last(history.value).answers).reqId = _.last(history.value).question.reqId
        // _.last(_.last(history.value).answers).llmIcon = icon
        // _.last(_.last(history.value).answers).llmName = displayname
        // _.last(_.last(history.value).answers).llmId = currentAccount.value.id
        _.last(_.last(history.value).answers).assistantId = currentAssistant.value.id
        _.last(_.last(history.value).answers).assistantName =  currentAssistant.value.displayname,
        _.last(_.last(history.value).answers).errCode = status
        _.last(_.last(history.value).answers).errInfo = JSON.stringify(judgeInstallOrConfig(status))

        if(likeOrNotAgent.includes(currentAssistant.value.id)){
            //填充点赞踩结束时间
            let ext = JSON.parse(_.last(_.last(history.value).answers).extention)
            let answer = {
                answer: _.last(_.last(_.last(history.value).answers).displayContent).content,
                reference:""
            }

            for (let index = 0; index < ext.length; index++) {
                const element = ext[index];
                if (element.type == store.ExtentionType.PerView) {
                    answer.reference = element.sources[0].docContents
                }
            }

            let rate = {}
            for (let index = 0; index < ext.length; index++) {
                const element = ext[index];
                if (element.type == store.ExtentionType.LikeOrNot) {
                    ext[index].answer = JSON.stringify(answer)
                    ext[index].answerTime = currentTime()
                    rate = ext[index]
                }
            }

            _.last(_.last(history.value).answers).extention = JSON.stringify(ext)

            //写数据库
            Qrequest(chatQWeb.rateAnwser, history.value.length - 1, _.last(history.value).answers.length - 1, store.LikeOrNot.EMPTY, JSON.stringify(rate))
        }

         //存日志
        //  Qrequest(chatQWeb.logConversations,  JSON.stringify(history.value))
         Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

         /**
         * TODO
         * 发送完成，需要复制应答的answer
         */

        showStop.value = false
        isRetry.value = false
        isThinking.value = false
        answerDisplayMsg.value = []
        lastMsg.value = {chatType: store.ChatAction.ChatNone}
    }

    handelScrol()
}

//判断当前历史记录为去安装还是去配置
const needConfigErrCodeArr = [-9000, -9001, -9003, -9002, -9004, -9100]
const judgeInstallOrConfig = (errCode) => {
    const errInfo = {
        info:"",
        exec:''
    }
    
    if(!needConfigErrCodeArr.includes(errCode)){
        errInfo.info = 'Not Need Config'        
        return errInfo
    }

    //无模型
    if(!isLLMExist.value){
        errInfo.info = store.loadTranslations['Go to configuration']
        errInfo.exec = 'Qrequest(chatQWeb.launchLLMConfigWindow, false)'
        return errInfo
    }

    if(currentAssistant.value.type == store.AssistantType.UOS_SYSTEM_ASSISTANT 
        || currentAssistant.value.type == store.AssistantType.DEEPIN_SYSTEM_ASSISTANT 
        || currentAssistant.value.type == store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT){
        if(!isEmbeddingPluginsExist.value){
            errInfo.info = store.loadTranslations['To install']
            errInfo.exec = 'Qrequest(chatQWeb.installEmbeddingPlugins)'
            return errInfo
        }
        if(!isKnowledgeBaseExist.value && currentAssistant.value.type == store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT){
            errInfo.info = store.loadTranslations['Go to configuration']
            errInfo.exec = 'Qrequest(chatQWeb.launchKnowledgeBaseConfigWindow)'  //TODO:跳转到具体配置位置
            return errInfo
        }
    }

    errInfo.info = store.loadTranslations['Go to configuration']
    errInfo.exec = 'Qrequest(chatQWeb.launchLLMConfigWindow, false)'
    return errInfo
}

const isMouseScroll = ref(false)  //是否鼠标滚动
const showReturnBottom = ref(false)  //是否显示返回按钮
const handleHistoryScroll = () => {
    setTimeout(() => {
       if (chatHistory.scrollHeight - chatHistory.clientHeight > chatHistory.scrollTop + 50) {
            isMouseScroll.value = true
            showReturnBottom.value = true
        }else {
            isMouseScroll.value = false
            showReturnBottom.value = false
        }
    }, 20)
}

const returnBottom = () => {
    isMouseScroll.value = false
    showReturnBottom.value = false
    handelScrol()
}

const handelScrol = () => {
    if (isMouseScroll.value) {
        return
    }
    
    let chatHistory = document.getElementById('chatHistory')
    if (chatHistory.scrollHeight > chatHistory.clientHeight) {
        setTimeout(() => {
            chatHistory.scrollTop = chatHistory.scrollHeight;
            showReturnBottom.value = false
        }, 0);  
    }else {
        setTimeout(() => {
            showReturnBottom.value = true
        }, 20);  
    }

    handleHistoryScroll()
}

const stopRequest = async () => {
    await Qrequest(chatQWeb.cancelAiRequest, talkID.value)

    if(likeOrNotAgent.includes(currentAssistant.value.id)){
        //填充结束时间
        let ext = JSON.parse(_.last(_.last(history.value).answers).extention)
        for (let index = 0; index < ext.length; index++) {
            const element = ext[index];
            if (element.type == store.ExtentionType.LikeOrNot) {
                ext[index].answerTime = currentTime()
            }
        }
        _.last(_.last(history.value).answers).extention = JSON.stringify(ext)
    }    

    _.last(_.last(history.value).answers).errCode = 298  //请求被取消

    //存日志
    // Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

    showStop.value = false
    isRetry.value = false
    isFoundThinkStart.value = false
    isFoundThinkStop.value = false

    isThinking.value = false
    answerDisplayMsg.value = []
    lastMsg.value = {chatType: store.ChatAction.ChatNone}

    nextTick(() => handelScrol())
}

// 重新生成
const isRetry = ref(false)
const retryRequest = async () => {
    answerDisplayMsg.value = []
    lastMsg.value = {chatType: store.ChatAction.ChatNone}
    _.last(history.value).question.isRetry = true
    const _question = history.value[history.value.length - 1].question
    await Qrequest(chatQWeb.stopPlayTextAudio)
    playAudioID.value = ''
    if (recording.value) sigAudioASRError()
    // 重试时，开关性的按钮以当前状态为准
    try {
        let extention = JSON.parse(_question.extention)
        // 如果store.McpServerListCheckedName的长度为0或store.IsOpenMcpServer为false，则删除extention中element.type == store.ExtentionType.McpBtnStatus的元素
        if ( currentAssistant.value.type == store.AssistantType.UOS_AI) {
            if (store.McpServerListCheckedName.length == 0 || !store.IsInstallUOSAiAgent) {
                extention = extention.filter(element => element.type != store.ExtentionType.McpBtnStatus)
            }else {
                if (extention.filter(element => element.type == store.ExtentionType.McpBtnStatus).length == 0) {
                    // 如果找不到element.type == store.ExtentionType.McpBtnStatus的元素，则添加一个新的元素
                    extention.push({
                        type: store.ExtentionType.McpBtnStatus,
                        McpServers: store.McpServerListCheckedName
                    })
                } else {
                    // 如果能找到element.type == store.ExtentionType.McpBtnStatus的元素，则更新McpServers
                    for (let index = 0; index < extention.length; index++) {
                        const element = extention[index];
                        if (element.type == store.ExtentionType.McpBtnStatus) {
                            element.McpServers = store.McpServerListCheckedName
                            break
                        }
                    }
                }
            }
        }
        
        _question.extention = JSON.stringify(extention)
    }catch(e) {
        
    }
    // ques添加openThink字段
    if (showDeepThinkAndSearchOnline.value) {
        _question.openThink = store.IsDeepThink
        _question.onlineSearch = store.IsSearchOnline
    }else{
        _question.openThink = false
        _question.onlineSearch = false
    }

    let sendQuestionAccount = currentAccount.value
    const { id, model, icon, displayname } = sendQuestionAccount
        
    _.last(history.value).answers.push(
        {
            displayContent:"",
            content:"",
            displayHash:"",
            reqId:"0",
            llmIcon: icon ? icon : '',
            llmName: displayname ? displayname : '',
            llmModel: model,
            llmId :  id ? id : '',
            assistantId : currentAssistant.value.id,
            assistantName : currentAssistant.value.displayname,
            errCode:0,
            errInfo:JSON.stringify(judgeInstallOrConfig(0)),  //补充json
            chatType:0,  //问答、文生图、FunctionCall
            isRetry:true,
            extention:"[]",
            thinkTime: "-1",
            openThink: false,
            onlineSearch: false
        }
    )

    const quesResp = await Qrequest(chatQWeb.sendRequest, id ? id : '', JSON.stringify(_question))
    try{
        JSON.parse(quesResp)
    }catch(e){
        return
    }

    //开始时间
    isFoundThinkStart.value = false
    isFoundThinkStop.value = false

    _.last(history.value).question = JSON.parse(quesResp)
    _.last(_.last(history.value).answers).reqId = JSON.parse(quesResp).reqId

    //初始化like or not
    initLikeOrNotExt()

    talkID.value = JSON.parse(quesResp).reqId
    isRetry.value = true
    showStop.value = true
    // question.value = ''
}

// 是否显示深度思考和联网搜索
const showDeepThinkAndSearchOnline = computed(() => {
    return currentAccount.value.model == store.DeepSeek_Uos_Free && (!store.IsOpenMcpServer || !store.IsInstallUOSAiAgent)
})
// 深度思考
const deepThinkClick = async () => {
    if (store.IsDeepThink) {
        store.IsDeepThink = false
    }else {
        store.IsDeepThink = true
    }
}

// 联网搜索
const searchOnlineClick = async () => {
    if (store.IsSearchOnline) {
        store.IsSearchOnline = false
    }else {
        store.IsSearchOnline = true
    }
}

const deepThinkWidth = computed(() => {
    if (isWindowMode.value) {
        return isChineseLanguage.value ? '88px' : '120px'
    }else{
        return '30px'
    }
})

const onlineSearchWidth = computed(() => {
    if (isWindowMode.value) {
        return isChineseLanguage.value ? '88px' : '78px'
    }else{
        return '30px'
    }
})


const recording = ref(false)
const startQus = ref('')
const endQus = ref('')

const handleRecorder = async () => {

    console.log("handleRecorder:clicked: currentAccount.displayname:", currentAccount.value.displayname);
    console.log(recording.value)
    if (!isAudioInput.value || showStop.value || !netState.value) return
    if (currentAssistant.value.type == store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isKnowledgeBaseExist.value || !isEmbeddingPluginsExist.value) && history.value.length === 0) return
    if (currentAssistant.value.type == store.AssistantType.UOS_SYSTEM_ASSISTANT && !isEmbeddingPluginsExist.value && history.value.length === 0) return
    if (currentAssistant.value.type == store.AssistantType.DEEPIN_SYSTEM_ASSISTANT && !isEmbeddingPluginsExist.value && history.value.length === 0) return
    if (recording.value) return sigAudioASRError()
    if (!recording.value) {
        isAudioInput.value = await Qrequest(chatQWeb.isAudioInputAvailable)
        await Qrequest(chatQWeb.stopPlayTextAudio)
        if (isAudioInput.value) {
            await Qrequest(chatQWeb.startRecorder, 0)
            const start = questionInput.value.textarea.selectionStart;
            const end = questionInput.value.textarea.selectionEnd;
            startQus.value = questionInput.value.textarea.value.substr(0, start)
            endQus.value = questionInput.value.textarea.value.substr(end)
            recording.value = true
            playAudioID.value = ''
        }
    }
}

// AI模型列表更新
const llmAccountLstChanged = (id, list) => {
    isLLMExist.value = id.trim().length > 0;
    console.log("index.vue: llmAccountLstChanged.........  id: ", id);
    console.log("index.vue: llmAccountLstChanged.........  list: ", list);
    if (list) {
        const accounts = JSON.parse(list)
        isLLMExist.value = accounts.length > 0;
        accounts.forEach(element => {
            if (element.id === id) {
                element.active = true
                currentAccount.value = element
            }
        });
        accountList.value = list;
    }
    instance.proxy.$Bus.emit("llmAccountLstChanged", { id, list });

    /**
     * TODO:
     * 查询当前助手指令列表
     */
     currentAccountChanged()
}

const questionInput = ref(null)
const isAudioInInpit = ref(false)
const sigAudioASRStream = (res, isEnd) => {
    if (!(isEnd && res == "")) {
        question.value = startQus.value + res + endQus.value
    }
    // console.log('sigAudioASRStream', res, isEnd)
    if (isEnd) {
        if (waitSend.value) {
            waitSend.value = false
            sendQuestion()
        }
        sigAudioASRError()

        //添加指令匹配
        handleInput(question.value)

        isAudioInInpit.value = true

        questionInput.value.focus()
    }
}

const countDown = ref(0)
const showCount = ref(false)
const sigAudioCountDown = (res) => {
    countDown.value = res
    if (res > 0) showCount.value = true
    if (res === 0) {
        setTimeout(() => showCount.value = false, 1000)
    }
}

const sigAudioASRError = () => {
    recording.value = false
    countDown.value = 0
    audioLevel.value = 0
    showCount.value = false
    Qrequest(chatQWeb.stopRecorder)
}
// 语音播放结束
const sigPlayTTSFinished = (res) => {
    console.log('sigPlayTTSFinished', res)
    if (playAudioID.value === res) playAudioID.value = ''
}

const sigPlayTTSError = (res) => playAudioID.value = ''

// const sigAudioRecShortcutPressed = () => handleRecorder()
const sigAudioInputDevChange = (res) => {
    isAudioInput.value = res
    if (!res) recording.value = false
}
const hasOutput = ref(true)
const sigAudioOutputDevChanged = (res) => {
    if (!res) playAudioID.value = ''
    hasOutput.value = res
}

const sigChatConversationType = (id, type) => {
    // console.log(id, action)
    if (_.last(history.value) === undefined)
        return;
    _.last(_.last(history.value).answers).chatType = type
}

// 接受AI图片信息
const sigText2PicFinish = (id, paths) => {
    _.last(_.last(history.value).answers).displayContent = JSON.stringify(paths)

    //存日志
    // Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

    handelScrol()
    showStop.value = false
    isRetry.value = false
}
// 接受PPT图片信息
const sigPPTCreateSuccess = (id, paths) => {
    sendEmptyAnswers()
    _.last(_.last(history.value).answers).displayContent = JSON.stringify(paths)
    _.last(_.last(history.value).answers).chatType = store.ChatAction.ChatText2Image
    let extention = []
    extention.push({
            type: store.ExtentionType.PictureId,
        	idValue: id
        })
    _.last(_.last(history.value).answers).extention = JSON.stringify(extention)

    //存日志
    // Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

    handelScrol()
    showStop.value = false
    isRetry.value = false
}
const sigPPTChangeSuccess = (id, paths) => {
    for (let index = 0; index < history.value.length; index++) {
        for(let answerIndex = 0; answerIndex < history.value.at(index).answers.length; answerIndex++) {
            const ext = JSON.parse(history.value.at(index).answers[answerIndex].extention);
            for(let extIndex = 0; extIndex < ext.length; extIndex++) {
                const element = ext[extIndex];
                if (element.type == store.ExtentionType.PictureId && element.idValue == id) {
                    history.value.at(index).answers[answerIndex].displayContent = JSON.stringify(paths)
                    //存日志
                    // Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
                    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))
                    break
                }
            }
        }
    }
}
const sigPosterCreateSuccess = (id, paths) => {
    sendEmptyAnswers()
    _.last(_.last(history.value).answers).displayContent = JSON.stringify(paths)
    _.last(_.last(history.value).answers).chatType = store.ChatAction.ChatText2Image
    let extention = []
    extention.push({
            type: store.ExtentionType.PictureId,
        	idValue: id
        })
    _.last(_.last(history.value).answers).extention = JSON.stringify(extention)

    //存日志
    // Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
    Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

    handelScrol()
    showStop.value = false
    isRetry.value = false
}
const welcomePageRef = ref()
const sigWebchat2BeHiden = () => {
    Qrequest(chatQWeb.stopPlayTextAudio)
    playAudioID.value = ''
    welcomePageRef.value.getAiFAQ()
    sigAudioASRError()
}
// 监听AI进程被杀
// const connectStateChanged = (status) => instance.proxy.$Bus.emit("connectStateChanged", status)
// 活动色改变
const sigActiveColorChanged = (res) => updateActivityColor(res)
const audioLevel = ref(0)
const sigAudioSampleLevel = (res) => audioLevel.value = res
const sigThemeChanged = (res) => {
    updateTheme(res)
    //切换深色主题时，文档图标用深色图标
    if(res == 2){
        documentParsingRef.value.isDarkMode = true
        isDarkMode.value = true
    }else{
        documentParsingRef.value.isDarkMode = false
        isDarkMode.value = false
    }
}

const sigFontChanged = (family, pixelSize) => {
    updateFont(family, pixelSize)
    //字号切换时
    documentParsingRef.value.sysFontPixelSize = pixelSize
}
const netState = ref(true)
const sigNetStateChanged = (res) => {
    netState.value = res;
    if (recording.value) {
        recording.value = false;
        Qrequest(chatQWeb.stopRecorder)
    }
}
//ctrl+super+c跳转到数字人
// const chatTopRef = ref()
const sigDigitalModeActive = () => {
    if (router.currentRoute.value.name == "DigitalImage") {

    } else {
        Qrequest(chatQWeb.stopPlayTextAudio)
        router.push("/DigitalImage");
    }
};

const sigChatModeActive = () => {

}

const isModalState = ref(false)
const handleActive = (res) => {
    let maskDom = document.querySelector('#drop-mask');
    if (!maskDom) {
        maskDom = document.createElement("div");
        maskDom.id = "drop-mask"
        document.body.appendChild(maskDom);
    }
    maskDom.style.height = '100vh'
    maskDom.style.width = '100vw'
    maskDom.style.display = res ? 'flex' : 'none'
    isModalState.value = res
}
const switchModel = ref()
const switchModelRoot = ref(null)
const sigWebchatActiveChanged = (res) => {
    if (!res) {
        switchModel.value.showSwitchMenu = false
        switchModel.value.showAssistantMenu = false
        // chatTopRef.value.showSeting = false
    }
    // handleActive(res)
}
const sigWebchatModalityChanged = (res) => handleActive(res)

const sigMainContentBackgroundColor = (color) => {
    updateMainContentBackgroundColor(color);
}

const sigKnowledgeBaseStatusChanged = (status) => {
    console.log("knowledge base status changed: ", status);
    isKnowledgeBaseExist.value = status;
}

const sigEmbeddingPluginsStatusChanged = (status) => {
    console.log("EmbeddingPlugins base status changed: ", status);
    isEmbeddingPluginsExist.value = status;
}

const sigWindowModeChanged = (res) => {
    console.log("onWindowModeChanged, is window mode: ", res);
    isWindowMode.value = res;
}

const sigDocSummaryParsingStart = async (filePath_, iconPath, defaultPrompt, status) => {
    isDragging.value = false;
    if(disabled.value) return  //回答中
    if(recording.value) return  //录音中
    if(showGuide.value) return  //引导页不处理拖拽
    // if(isFileInInput.value) return  //文件存在
    if(currentAssistant.value.type != store.AssistantType.UOS_AI && currentAssistant.value.type != store.AssistantType.AI_TRANSLATION_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_WRITING_ASSISTANT && currentAssistant.value.type != store.AssistantType.AI_TEXT_PROCESSING_ASSISTANT && currentAssistant.value.id != 'PPT Assistant') return  //非UOS AI助手 非PPT助手
    switch (status) {
        case store.DocParsingStatusType.Success:
            break
        case store.DocParsingStatusType.MoreOneError:
            handleShowTip(store.loadTranslations['You can only add a maximum of one file.'])
            return
        case store.DocParsingStatusType.SuffixError:
            handleShowTip(store.loadTranslations['The file format is not supported.'])
            return
        case store.DocParsingStatusType.NoDocError:
            handleShowTip(store.loadTranslations['The file format is not supported.'])
            return
        case store.DocParsingStatusType.ExceedSize:
            handleShowTip(store.loadTranslations['The file size exceeds the 100MB limit.'])
        return
    }
   
    if (!isFileInInput.value) {
        isShowFile.value = true  //drop后显示
        documentParsingRef.value.isEnabledMouthOver = true
        isFileInInput.value = true
        
        filePath.value = filePath_
        //通过正则表达式在完整路径中获取文件名
        // documentParsingRef.value.fileNameText = filePath.substring(filePath.lastIndexOf('/') + 1)  
        fileNameText.value = documentParsingRef.value.handleFileNameLength(filePath_.substring(filePath_.lastIndexOf('/') + 1))
        imgBase64.value = iconPath 
        // question.value = store.loadTranslations['Summarize the key content of the file.'] 

        /**
         * TODO
         * 1.文件拖入就调用后端接口进行解析
         * 2.解析中和解析失败情况下都将发送按钮置灰
         */
        await Qrequest(chatQWeb.onDocSummaryParsing, filePath_)  //开始解析
        documentParsingRef.value.isShowParsingStatus = true
        documentParsingRef.value.isParsingStatusEnd = false
        documentParsingRef.value.parsingStatusText = store.loadTranslations['Parsing...']

        if (defaultPrompt != '') {
            docParsingPlaceHolder.value = defaultPrompt
            nextTick(() => {
                questionInput.value.focus()  //全局搜索带入文档时直接让输入框可编辑
            })
        }else{
            docParsingPlaceHolder.value = store.loadTranslations['Summarize the key content of the file.']
        }
        
    }else{
        handleShowTip(store.loadTranslations['You can only add a maximum of one file.'])
    }
}

const docContent = ref("")
const sigDocSummaryParserResult = (status, fileName, docContent_) => {
    if(isFileInInput.value && !isFileParsingSuccess.value){
        console.log("status : ", status)
        //解析中和解析失败情况下都将发送按钮置灰
        if(status == 0){//解析成功
            documentParsingRef.value.isShowParsingStatus = false
            isFileParsingSuccess.value = true
            docContent.value = docContent_
        }else{
            documentParsingRef.value.isShowParsingStatus = true
            isFileParsingSuccess.value = false
            documentParsingRef.value.isParsingStatusEnd = true
            if(status == 1){//解析失败
                documentParsingRef.value.parsingStatusText = store.loadTranslations['File Error']
            }else{ //未解析出文字
                documentParsingRef.value.parsingStatusText = store.loadTranslations['No text was parsed']
            }
            fileNameText.value = documentParsingRef.value.handleFileNameLength(filePath.value.substring(filePath.value.lastIndexOf('/') + 1))
        }
    }
   
}

const sigOpenFileFromPathResult = (status) => {
    if(!status){
        handleShowTip(store.loadTranslations['File has been deleted.'])
    }
}

const sigAppendWordWizardConv = async (type) => {
    //打断正在进行的对话
    if(showStop.value){
        await Qrequest(chatQWeb.cancelAiRequest, talkID.value)

        _.last(_.last(history.value).answers).errCode = 298  //请求被取消

        //存日志
        // await Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
        await Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

        //打断语音播放
        await Qrequest(chatQWeb.stopPlayTextAudio)

        showStop.value = false
        isRetry.value = false
    }

     

    //通知后端添加划词对话历史记录到UOS AI历史记录
    Qrequest(chatQWeb.appendWordWizardConv, type)

    //切助手到UOS AI
    assistantList.value.forEach(element => {
        if (element.type === type) {
            switchModel.value.clickAssistantItem(element)
        }
    });
    
}

const sigPreviewReference = async (preViewList) => {
    let extention = []
    extention = extention.concat(JSON.parse(_.last(_.last(history.value).answers).extention))
    extention.push(JSON.parse(preViewList))
    _.last(_.last(history.value).answers).extention = JSON.stringify(extention)
}

const sigOverrideQues = async (inputQuestion) => {
    if (
        (currentAssistant.value.type === store.AssistantType.PERSONAL_KNOWLEDGE_ASSISTANT && (!isKnowledgeBaseExist.value ||!isEmbeddingPluginsExist.value)&& history.value.length === 0)||
        ((currentAssistant.value.type === store.AssistantType.UOS_SYSTEM_ASSISTANT||currentAssistant.value.type === store.AssistantType.DEEPIN_SYSTEM_ASSISTANT) && !isEmbeddingPluginsExist.value && history.value.length === 0))
        return
    
    question.value = question.value + inputQuestion
    endQus.value =  endQus.value + inputQuestion //如果中断语音输入，可能会延迟返回语音输入信号，需要将随航带过来的值追加
    nextTick(() => {
        questionInput.value.focus()  //随航带入文档时直接让输入框可编辑
    })
}

const sigAsyncWorker = async (type) => {
    if (type === 1) {
        //中断当前对话，切助手
        //打断正在进行的对话
        if(showStop.value){
            await Qrequest(chatQWeb.cancelAiRequest, talkID.value)

            _.last(_.last(history.value).answers).errCode = 298  //请求被取消

            //存日志
            // await Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
            await Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))


            showStop.value = false
            isRetry.value = false
        }

        //打断语音播报

        //打断正在进行的语音输入
        if (recording.value) {
            recording.value = false;
            Qrequest(chatQWeb.stopRecorder)
        }

        question.value = ''

        //切换助手，聊天窗口存在文件则删除
        if(isFileInInput.value){
            isShowFile.value = false
            isFileInInput.value = false
            isFileParsingSuccess.value = false
            // await Qrequest(chatQWeb.onDocSummaryRemove, documentParsingRef.value.filePath)  //通知后端删除当前的文件
            
            filePath.value = ''
            imgBase64.value = ''
            fileNameText.value = ''
        }

        //切换助手，聊天窗口存在标签则删除
        if (showPromptTag.value) {
            showPromptTag.value = false
            showPropmptList.value = false
        }

        //切换助手为UOS AI
        assistantList.value.forEach(element => {
            if (element.type === store.AssistantType.UOS_AI) {
                Qrequest(chatQWeb.setCurrentAssistantId, element.id)
            }
        });    

        //切助手和模型
        currentAssistant.value.active = false
        const resCurAccountID = await Qrequest(chatQWeb.currentLLMAccountId)
        const resCurAssistantID = await Qrequest(chatQWeb.currentAssistantId)
        assistantList.value.forEach(element => {
            if (element.id === resCurAssistantID) {
                element.active = true
                currentAssistant.value = element
            }
        });
        
        currentAccount.value.active = false
        accountList.value.forEach(element => {
            if (element.id === resCurAccountID) {
                element.active = true
                currentAccount.value = element
            }
        });

        /**
         * TODO:
         * 查询当前助手指令列表
         */
        currentAccountChanged()

        const _history = await Qrequest(chatQWeb.getConversations)
        history.value = JSON.parse(_history)
        await Qrequest(chatQWeb.onAsyncWorkerFinished, type)
      } else if (type === 2) {
             //打断正在进行的语音输入
        if (recording.value) {
            recording.value = false;
            await Qrequest(chatQWeb.stopRecorder)
        }

        await Qrequest(chatQWeb.onAsyncWorkerFinished, type)
      }
}

const sigAssistantListChanged = async () => {
    const resAssistant = await Qrequest(chatQWeb.queryAssistantList)
    const resCurAssistantID = await Qrequest(chatQWeb.currentAssistantId)
    if (resAssistant) {
        const list = JSON.parse(resAssistant);
        //判断当前助手ID是否在列表中
        const isExist = list.some(item => item.id === resCurAssistantID)
        assistantList.value = list;
        if (!isExist) {
            //打断正在进行的语音输入
            if (recording.value) {
                recording.value = false;
                await Qrequest(chatQWeb.stopRecorder)
            }
            //打断正在进行的对话
            if(showStop.value){
                await Qrequest(chatQWeb.cancelAiRequest, talkID.value)

                _.last(_.last(history.value).answers).errCode = 298  //请求被取消

                //存日志
                // await Qrequest(chatQWeb.logConversations, JSON.stringify(history.value))
                await Qrequest(chatQWeb.logCurrentConversations, currentAssistant.value.id, lastConversationInfo.value.conversationId, currentAssistant.value.displayname,  JSON.stringify(history.value))

                //打断语音播放
                await Qrequest(chatQWeb.stopPlayTextAudio)

                showStop.value = false
                isRetry.value = false
            }
            //切助手到UOS AI
            assistantList.value.forEach(element => {
                if (element.type === store.AssistantType.UOS_AI) {
                    switchModel.value.clickAssistantItem(element)
                }
            });
        }else {
            //切助手到当前助手
            assistantList.value.forEach(element => {
                if (element.id === resCurAssistantID) {
                    currentAssistant.value.active = true
                }
            });
        }
    }
}

const sigGetNewHistoryList = async (currentConversationId) => {
    //重新查询历史记录列表
    await openHistoryList()

    // 如果删除的是当前会话，需要重新创建新会话
    if (currentConversationId === lastConversationInfo.value.conversationId) {
        await createNewConversation()
    }
}

const sigHideHistoryList = async () => {
    showConversionList.value = false
}

const sigToShowPromptWindow = async () => {
    // ********************************************************************************
    // 2.9需求
    if (!isEnableMcp.value) {
        return  //未启用mcp，不显示引导
    }

    //切助手到UOS AI
    if (currentAssistant.value.type !== store.AssistantType.UOS_AI) {
        assistantList.value.forEach(element => {
            if (element.type === store.AssistantType.UOS_AI) {
                switchModel.value.clickAssistantItem(element)
            }
        });

        //切换助手为UOS AI
        for (let index = 0; index < assistantList.value.length; index++) {
            const element = assistantList.value[index];
            if (element.type === store.AssistantType.UOS_AI) {
                await Qrequest(chatQWeb.setCurrentAssistantId, element.id)
                break
            }
        }

        //切助手和模型
        currentAssistant.value.active = false
        const resCurAssistantID = await Qrequest(chatQWeb.currentAssistantId)
        assistantList.value.forEach(element => {
            if (element.id === resCurAssistantID) {
                element.active = true
                currentAssistant.value = element
            }
        });
    }
    
    
    // ********************************************************************************

    showGuide.value = true
    Qrequest(chatQWeb.setTitleBarMaskStatus, true)  //打开标题栏遮罩
}

const sigDeleteFile = async () => {
    isFileInInput.value = false
    isFileParsingSuccess.value = false
    isShowFile.value = false
    // question.value=''
}

const sigInputFocus = async () => {
    questionInput.value.focus()  //页面加载完成，自动聚焦到输入框
}

// const sigKnowledgeBaseFAQGenFinished = () => {

// }

function handleKeyDown(event) {
    if (event.key === "Enter" && showPropmptList.value) {
        event.stopPropagation()
        event.preventDefault()
        showPropmptList.value = false
        return
    }
    if (event.key === "Enter") {
        event.stopPropagation()
        event.preventDefault()
        console.log('chat ')
        sendQuestion()
    }
}

const responseAIFunObj = {
    sigAiReplyStream,
    llmAccountLstChanged,
    sigActiveColorChanged,
    sigAudioASRStream,
    sigAudioASRError,
    sigAudioCountDown,
    sigPlayTTSFinished,
    sigPlayTTSError,
    // sigAudioRecShortcutPressed,
    sigAudioInputDevChange,
    sigAudioOutputDevChanged,
    sigChatConversationType,
    sigText2PicFinish,
    sigPPTCreateSuccess,
    sigPPTChangeSuccess,
    sigPosterCreateSuccess,
    sigThemeChanged,
    sigFontChanged,
    sigWebchat2BeHiden,
    sigAudioSampleLevel,
    sigNetStateChanged,
    sigDigitalModeActive,
    sigChatModeActive,
    sigWebchatActiveChanged,
    sigWebchatModalityChanged,
    sigMainContentBackgroundColor,
    sigKnowledgeBaseStatusChanged,
    sigEmbeddingPluginsStatusChanged,
    // sigKnowledgeBaseFAQGenFinished,
    sigWindowModeChanged,
    sigDocSummaryParsingStart,  //拖入文档
    sigDocSummaryParserResult,  //文档解析结果
    sigOpenFileFromPathResult,  //文档打开结果
    sigAppendWordWizardConv,  //随航继续对话接口 : 停止当前对话,获取随航历史记录
    sigPreviewReference, //预览列表
    sigAsyncWorker,
    sigOverrideQues,
    sigAssistantListChanged,  //助手列表变化
    sigGetNewHistoryList,
    sigHideHistoryList,
    sigToShowPromptWindow, //显示提示窗口
    sigInputFocus,
}

const chatHistoryScrollbarRef = ref(null);
onMounted(async () => {
    for (const key in responseAIFunObj) {
        if (Object.hasOwnProperty.call(responseAIFunObj, key)) {
            chatQWeb[key].connect(responseAIFunObj[key]);
        }
    }
    document.addEventListener("keydown", handleKeyDown);
    initChat()

    useGlobalStore().loadTranslations = await Qrequest(chatQWeb.loadTranslations)
    console.log(useGlobalStore().loadTranslations)

    var fontInfo = await Qrequest(chatQWeb.fontInfo);
    var fontInfoList = fontInfo.split('#');
    document.documentElement.style.fontFamily = fontInfoList[0];
    document.documentElement.style.fontSize = fontInfoList[1] + 'px';
    documentParsingRef.value.sysFontPixelSize = fontInfoList[1]  //设置字体大小，计算宽度

    if (chatHistoryScrollbarRef.value) {
        document.getElementById('chatHistory').addEventListener('scroll', handleHistoryScroll);
    }

    nextTick(() => {
        questionInput.value.focus()  //页面加载完成，自动聚焦到输入框
    }, 5)

    // 这里要等SwitchModel渲染好
    switchModelRoot.value = switchModel.value?.rootEl
})
onBeforeUnmount(() => {
    for (const key in responseAIFunObj) {
        if (Object.hasOwnProperty.call(responseAIFunObj, key)) {
            chatQWeb[key].disconnect(responseAIFunObj[key]);
        }
    }
    document.removeEventListener("keydown", handleKeyDown);

    if (chatHistoryScrollbarRef.value) {
        document.getElementById('chatHistory').removeEventListener('scroll', handleHistoryScroll);
    }
})
</script>

<style lang="scss" scoped>
.main-content {
    display: flex;
    flex-direction: column; /* 垂直方向顺序布局 */  
    align-items: center; /* 水平方向居中 */  
    justify-content: center; /* 垂直方向居中 */
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    background-color: var(--main-content-background-color);

    position: relative; /* 为蒙版层定位 */
    // user-select: none;
    img {
        user-select: none;
    }

    .chat-history {
        width: calc(100% - 8px);
        padding: 15px 0;
        max-width: 1020px;
        flex: 1 1 0;
        overflow: hidden;
        // background-color: aquamarine;

        .history-scrollbar {
            overflow-y: overlay;
            overflow-x: hidden;
            height: 100%;

            .bubble-div {
                width: calc(100% - 12px);
                margin-left: 16px;
            }
        }
    }

    .chat-bottom {
        padding: 0;
        margin-top: auto;
        margin-bottom: 10px;
        position: relative;
        max-width: 1000px;
        width: calc(100% - 20px);

        .handle-tip {
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            top: -50px;

            .tip-item {
                color: var(--uosai-color-tip);
                font-size: 0.93rem;
                font-weight: 500;
                font-style: normal;
                padding: 6px 15px;
                border-radius: 18px;
                border: 1px solid rgba(0, 0, 0, 0.05);
                box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.05);
                background-color: var(--uosai-color-tip-bg);
                margin: 0 auto;
                text-align: center;
                margin-bottom: 10px;
                width: fit-content;
                user-select: none;
            }

            .top-stop {
                color: var(--activityColor);
                background-color: var(--uosai-color-stop-bg);
                border-radius: 8px;
                display: flex;
                align-items: center;

                cursor: pointer;
                box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.08);
                border: none;

                svg {
                    width: 15px;
                    height: 15px;
                    margin-right: 4px;
                }
            }

            
        }

        .top-returnBtnOut {
            position: absolute;
            left: 98%;
            transform: translateX(-50%);
            top: -50px;
            cursor: pointer;

            

            .top-returnBtn {
                display: flex;
                align-items: center;
                justify-content: center;
                transform: translateX(-50%);
                // border: 1px solid rgba(0, 0, 0, 0.05);
                box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.2);
                background-color: var(--uosai-color-tip-bg);
                width: 32px;
                height: 32px;
                border-radius: 50%;

                svg {
                    width: 8px;
                    height: 8px;
                    fill: var(--uosai-color-modelbtn);
                }

                &:not(.disabled):active {

                    svg {
                        fill: var(--activityColor);
                    }
                }
            }
        }


        .top {
            position: relative;
            margin-bottom: 10px;
            padding-left: 5px;
            display: flex;
            align-items: center;

            .add-new-conversation {
                width: 36px;
                height: 36px;
                background-color: var(--activityAddNewConversationBtnBgNormal);
                border-radius: 8px;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                // margin-right: auto;
                margin-right: 6px;

                &:not(.disabled):hover {
                    background-color: var(--activityAddNewConversationBtnBgHover);
                }

                &:not(.disabled):active {
                    background-color: var(--activityAddNewConversationBtnBgActive);
                }

                svg {
                    height: 20px;
                    width: 20px;
                    color: var(--activityColor);
                }
            }

            .prompt-btn{
                width: 36px;
                height: 36px;
                background-color: var(--uosai-color-flat-btn-bg);
                border-radius: 8px;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                margin-right: 10px;

                &:not(.disabled):hover {
                    background-color: var(--uosai-color-flat-btn-bg-hover);

                    svg {
                        fill: var(--uosai-color-flat-btn-icon);
                    }
                }

                &:not(.disabled):active {
                    background-color: var(--uosai-color-flat-btn-bg-press);

                    svg {
                        fill: var(--uosai-color-flat-btn-icon);
                    }
                }

                svg {
                    height: 20px;
                    width: 20px;
                    fill: var(--uosai-color-flat-btn-icon);
                }
            }
        }

        .input-content {
            position: relative;
            min-height: 120px;
            border-radius: 8px;
            // opacity: 1;
            background-color: var(--uosai-color-inputcontent-bg);
            margin-bottom: 7px;
            // padding-bottom: 8px;
            border: 2px solid rgba(0, 0, 0, 0);

            .input-content-all{
                // background-color: var(--uosai-color-inputcontent-bg);
                opacity: 1;
                // margin-bottom: 7px;
                padding-bottom: 8px; 
                border-radius: 8px;
                // overflow: hidden;
                // border: 2px solid rgba(0, 0, 0, 0);

                .input-tag{
                    display: block;
                    align-content: center;
                }
            }

            // user-select:auto;
            &.foucs {
                border: 2px solid rgba(0, 0, 0, 0);
                
                &::before {
                    content: '';
                    position: absolute;
                    top: -2px;
                    left: -2px;
                    right: -2px;
                    bottom: -2px;
                    border: 2px solid var(--activityColor);
                    border-radius: 8px;
                    pointer-events: none;
                    z-index: 10;
                }
            }

            :deep(.el-textarea) {
                padding-top: 10px;
                max-height: 185px;
                display: flex;

                .el-textarea__inner {
                    box-shadow: none;
                    background: none;
                    color: var(--uosai-color-inputcontent);
                    max-height: 185px;
                    font-size: 0.93rem;  // 会影响高度 

                    &::placeholder {
                        color: var(--uosai-color-inputcontent-placeholder);
                        font-size: 0.93rem;
                        font-weight: 500;
                        user-select: none;
                    }

                    &::-webkit-scrollbar {
                        background: none;
                        width: 6px;
                        height: 6px;

                        &:hover {
                            width: 8px;
                            height: 8px;
                        }
                    }

                    &::-webkit-scrollbar-thumb {
                        border-radius: 4px;
                        background: var(--uosai-color-scroll-bg);
                        border: 1px solid var(--uosai-color-border);
                        // box-shadow: 0px 0px 10px 0px var(--uosai-color-border);
                    }

                    &:focus {
                        outline: 0;
                        box-shadow: none;
                    }
                }
            }

            .bottom {
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .deep-think-btn {
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                width: 88px;
                height: 30px;
                border-radius: 8px;
                // border: 1px solid rgba(0, 0, 0, 0.05);
                margin-top: 6px;
                background-color: var(--uosai-think-search-normal-bg);
                user-select: none;
                color: var(--uosai-think-search-color);
                font-size: 12px;

                svg {
                    width: 16px;
                    height: 16px;
                    fill: var(--uosai-color-flat-btn-icon);
                }
            }

            .send-btn {
                height: 30px;
                display: flex;
                justify-content: flex-end;
                margin-top: 6px;
                // background-color: violet;

                .btn {
                    // box-shadow: 0px 4px 6px rgba(44, 167, 248, 0.4);
                    background-color: var(--activityColor);
                    width: 30px;
                    height: 30px;
                    border-radius: 50%;
                    margin-right: 8px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    cursor: pointer;

                    &.send {
                        box-shadow: 0 4px 6px 0 var(--boxShadow);

                        svg {
                            fill: #fff;
                        }
                    }

                    svg {
                        width: 16px;
                        height: 16px;
                    }

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

                    &.send:not(.disabled):hover {
                        filter: brightness(1.2);
                    }

                    &.send:not(.disabled):active {
                        filter: brightness(1.1);

                        svg {
                            fill: rgba(255, 255, 255, 0.6);
                        }
                    }

                }

                .voice-btn {
                    background-color: var(--uosai-color-voicebtn-bg);
                    margin-right: 15px;

                    &:not(.disabled):hover {
                        background-color: var(--uosai-color-voicebtn-bg-hover);
                    }

                    &:not(.disabled):active {
                        background-color: var(--uosai-color-voicebtn-bg-active);

                        svg {
                            opacity: 0.6;
                        }
                    }

                    svg {
                        width: 12px;
                        height: 17px;
                        fill: var(--activityColor);
                    }

                    &.recording::before {
                        content: '';
                        position: absolute;
                        opacity: 0.4;
                        border-radius: 50%;
                    }

                    &.recording::after {
                        content: '';
                        position: absolute;
                        opacity: 0.1;
                        border-radius: 50%;

                    }

                    @keyframes Wave1 {
                        0% {
                            border: 2px solid var(--activityColor);
                            width: 30px;
                            height: 30px;
                        }

                        100% {
                            border: 6px solid var(--activityColor);
                            width: 30px;
                            height: 30px;
                        }
                    }

                    @keyframes Wave2 {
                        0% {
                            border: 3px solid var(--activityColor);
                            width: 34px;
                            height: 34px;
                        }

                        100% {
                            border: 5px solid var(--activityColor);
                            width: 40px;
                            height: 40px;

                        }
                    }

                    &:not(.notalking).recording::before {
                        animation: Wave1 0.4s ease-in-out infinite;
                        animation-direction: alternate-reverse;

                    }

                    &:not(.notalking).recording::after {
                        animation: Wave2 0.4s ease-in-out infinite;
                        animation-direction: alternate-reverse;
                    }

                    @keyframes notalking1 {
                        0% {
                            border: 1px solid var(--activityColor);
                            width: 30px;
                            height: 30px;
                        }

                        100% {
                            border: 3px solid var(--activityColor);
                            width: 30px;
                            height: 30px;
                        }
                    }

                    @keyframes notalking2 {
                        0% {
                            border: 3px solid var(--activityColor);
                            width: 32px;
                            height: 32px;
                        }

                        100% {
                            border: 4px solid var(--activityColor);
                            width: 36px;
                            height: 36px;

                        }
                    }

                    &.notalking::before {
                        animation: notalking1 0.8s ease-in-out infinite;
                        animation-direction: alternate-reverse;

                    }

                    &.notalking::after {
                        animation: notalking2 0.8s ease-in-out infinite;
                        animation-direction: alternate-reverse;
                    }
                }

                .file-btn{
                    background-color: var(--uosai-color-voicebtn-bg);
                    margin-right: 15px;

                    &:not(.disabled):hover {
                        background-color: var(--uosai-color-voicebtn-bg-hover);
                    }

                    &:not(.disabled):active {
                        background-color: var(--uosai-color-voicebtn-bg-active);

                        svg {
                            fill: var(--activityColor);
                        }
                    }

                    svg {
                        height: 20px;
                        width: 20px;
                        fill: var(--uosai-color-flat-btn-icon);
                    }
                }
            }
        }

        .tip {
            color: var(--uosai-bottom-tip-color);
            font-size: 12px;
            font-weight: 500;
            font-style: normal;
            text-align: left;
            padding-left: 10px;
            user-select: none;
        }
    }

    .inner-dropzone {
        /* 确保子div可以接收拖拽事件 */
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(rgba(255, 255, 255, 0) 5%,
                                    rgba(255, 255, 255, 0.35) 10%,
                                    rgba(255, 255, 255, 0.65) 15%,
                                    rgba(255, 255, 255, 0.75) 23%,
                                    rgba(255, 255, 255, 0.85) 30%, 
                                    rgba(255, 255, 255, 0.95) 42%, 
                                    rgba(255, 255, 255, 0.95) 100%); /* 半透明渐变蒙版 */
        z-index: 9999; /* 确保蒙版在内容之上 */
        align-items: center; /* 水平方向居中 */  
        justify-content: center; /* 垂直方向居中 */
        display: grid;

        .inner-dropzone-content{
            width: 230px;
            // height: 186px;
            display: flex;
            // place-items: center;
            align-items: center; /* 水平方向居中 */  
            justify-content: center; /* 垂直方向居中 */
            z-index: 1; 
            // border: 1px solid black;
            pointer-events: none; /* 使层不响应鼠标事件 ,防止蒙版闪烁*/
            flex-direction: column; /* 子元素垂直排列 */
            margin-top: -40%;

            .inner-dropzone-icon{
                display: grid;
                // width: 94px;
                // height: 106px;
                width: 150px;
                height: 150px;
                display: flex;
                align-items: center; /* 水平方向居中 */  
                justify-content: center; /* 垂直方向居中 */
                // border: 1px solid black;
                z-index: 1; 

                .inner-dropzone-icon-icon{
                    // width: 94px;
                    // height: 106px;
                    width: 150px;
                    height: 150px;
                }
            }

            .inner-dropzone-text{
                // width: 187px;
                // height: 25px;
                height: auto; /* 让容器根据内容自动调整高度 */
                display: flex;
                font-size: 1.21rem;
                font-weight: 500;
                font-style: normal;
                font-family: var(--font-family);
                color:rgba(0, 0, 0, 0.9);
                align-items: center; /* 水平方向居中 */  
                justify-content: center; /* 垂直方向居中 */
                margin-top: none;

                z-index: 1; 
                white-space: nowrap; /* 不换行 */
                // border: 1px solid red;
            }

            .inner-dropzone-text-suffix{
                // width: 230px;
                height: auto;
                display: flex;
                font-size: 0.85rem;
                font-weight: 500;
                font-style: normal;
                font-family: var(--font-family);
                font-weight: 500;
                color:rgba(0, 0, 0, 0.6);
                align-items: center; /* 水平方向居中 */  
                justify-content: center; /* 垂直方向居中 */
                text-align: center;
                margin-top: 8px;
                // border: 1px solid blue;
                z-index: 1; 
            }
        }

    }

    .conversion-list-wrapper {
        position: absolute;
        // top: 60px;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 1000;
    }

    .mcp-list {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        z-index: 999;
    }
}


.dark {
    .top-stop {
        box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15) !important;
    }

    .inner-dropzone{
        background: linear-gradient(rgba(33, 33, 33, 0) 5%,
                                    rgba(33, 33, 33, 0.35) 10%,
                                    rgba(33, 33, 33, 0.65) 15%,
                                    rgba(33, 33, 33, 0.75) 23%,
                                    rgba(33, 33, 33, 0.85) 30%, 
                                    rgba(33, 33, 33, 0.95) 42%, 
                                    rgba(33, 33, 33, 0.95) 100%); /* 半透明渐变蒙版 */
        // background: linear-gradient(rgba(33, 33, 33, 0) 0%, rgba(33, 33, 33, 0.1) 5%,rgba(33, 33, 33, 0.85) 21%, rgba(33, 33, 33, 0.95) 42%, rgba(33, 33, 33, 0.95) 100%); /* 半透明渐变蒙版 */
    }

    .inner-dropzone-text-span{
        color: rgba(255, 255, 255, 0.9);
    }

    .inner-dropzone-text-suffix-span{
        color: rgba(255, 255, 255, 0.6);
    }
}
</style>
