Преглед на файлове

[Feat 0000] 接入二维模型

hongrunxia преди 4 месеца
родител
ревизия
0a10b62e22
променени са 39 файла, в които са добавени 2140 реда и са изтрити 1879 реда
  1. 2 1
      .env.development
  2. 1 1
      package.json
  3. 1 1
      pnpm-lock.yaml
  4. 1362 1344
      src/components/AIChat/MiniChat.vue
  5. 1 0
      src/components/Application/src/AppProvider.vue
  6. 3 3
      src/components/Container/src/Adaptive.vue
  7. 3 5
      src/components/vent/micro/needAir.vue
  8. 4 6
      src/components/vent/micro/ventDoc.vue
  9. 5 7
      src/components/vent/micro/ventModal.vue
  10. 7 8
      src/components/vent/micro/ventModal2D.vue
  11. 2 0
      src/enums/cacheEnum.ts
  12. 5 5
      src/layouts/default/header/components/VoiceBroadcast.vue
  13. 1 1
      src/layouts/default/header/components/VoiceBroadcastGsd.vue
  14. 19 1
      src/layouts/default/header/index.vue
  15. 1 1
      src/layouts/default/setting/handler.ts
  16. 5 16
      src/layouts/default/sider/bottomSideder.vue
  17. 1 0
      src/logics/theme/updateBackground.ts
  18. 4 2
      src/main.ts
  19. 1 0
      src/qiankun/apps.ts
  20. 14 42
      src/qiankun/index.ts
  21. 1 0
      src/qiankun/state.ts
  22. 10 6
      src/router/guard/index.ts
  23. 19 0
      src/router/guard/permissionGuard.ts
  24. 33 0
      src/router/routes/basic.ts
  25. 17 1
      src/store/modules/app.ts
  26. 2 0
      src/utils/cache/persistent.ts
  27. 2 2
      src/views/vent/gas/gasHome/index.vue
  28. 241 235
      src/views/vent/home/clique/components/icon-light.vue
  29. 3 5
      src/views/vent/home/colliery/index.vue
  30. 3 0
      src/views/vent/home/configurable/components/MonitorBar.vue
  31. 81 21
      src/views/vent/home/configurable/vent182.vue
  32. 6 4
      src/views/vent/home/configurable/ventV5.vue
  33. 68 68
      src/views/vent/monitorManager/alarmMonitor/warn/waterLevel.vue
  34. 2 2
      src/views/vent/monitorManager/balancePressMonitor/index1.vue
  35. 121 31
      src/views/vent/monitorManager/deviceMonitor/components/device/index.vue
  36. 6 6
      src/views/vent/monitorManager/deviceMonitor/index.vue
  37. 0 2
      src/views/vent/monitorManager/fireDoorMonitor/fireDoor.threejs.fire.redGate.ts
  38. 2 3
      src/views/vent/monitorManager/footageMonitor/index.vue
  39. 81 49
      src/views/vent/monitorManager/mainFanMonitor/index.vue

+ 2 - 1
.env.development

@@ -31,5 +31,6 @@ VITE_GLOB_API_URL_PREFIX=
 #VITE_APP_SUB_APP = [["micro-need-air", "//10.10.150.72:8099/"], ["micro-vent-3dModal", "//localhost:8091/"], ["micro-fire-front", "//localhost:8090/"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.183.154:8091/", "micro-vent-3dModal"], ["micro-need-air", "//192.168.183.88:8093/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.1.16:8091/", "micro-vent-3dModal"], ["micro-need-air", "//192.168.183.88:8093/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
-VITE_APP_SUB_APP = [["micro-vent-3dModal", "//182.92.126.35:8091/", "micro-vent-3dModal"],["micro-vent-2dModal", "//localhost:8088/", "micro-vent-2dModal"],["micro-vent-doc", "//localhost:5173/", "micro-vent-doc"],["micro-need-air", "//182.92.126.35:8093/", "micro-need-air"], ["micro-fire-front", "//182.92.126.35:8097/", "fire-Micro"]]
+# VITE_APP_SUB_APP = [["micro-vent-3dModal", "//182.92.126.35:8091", "micro-vent-3dModal"],["micro-vent-2dModal", "//localhost:8088", "micro-vent-2dModal"],["micro-vent-doc", "//localhost:5173", "micro-vent-doc"],["micro-need-air", "//182.92.126.35:8093", "micro-need-air"], ["micro-fire-front", "//182.92.126.35:8097", "fire-Micro"]]
+VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.1.16:8091", "micro-vent-3dModal"],["micro-vent-2dModal", "//localhost:8088", "micro-vent-2dModal"],["micro-vent-doc", "//localhost:5173", "micro-vent-doc"],["micro-need-air", "//182.92.126.35:8093", "micro-need-air"], ["micro-fire-front", "//182.92.126.35:8097", "fire-Micro"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//localhost:8091/"], ["micro-need-air", "//localhost:8099/"], ["micro-fire-front", "//localhost:8090/"]]

+ 1 - 1
package.json

@@ -73,7 +73,7 @@
     "pinia": "2.1.6",
     "plyr": "^3.7.8",
     "print-js": "^1.6.0",
-    "qiankun": "^2.8.4",
+    "qiankun": "^2.10.16",
     "qrcode": "^1.5.3",
     "qrcodejs2": "0.0.2",
     "qs": "^6.11.2",

+ 1 - 1
pnpm-lock.yaml

@@ -162,7 +162,7 @@ importers:
         specifier: ^1.6.0
         version: 1.6.0
       qiankun:
-        specifier: ^2.8.4
+        specifier: ^2.10.16
         version: 2.10.16
       qrcode:
         specifier: ^1.5.3

+ 1362 - 1344
src/components/AIChat/MiniChat.vue

@@ -5,7 +5,7 @@
       <img src="@/assets/images/vent/home/wakeBtn.png" />
     </div>
   </div>
-  <div class="container">
+  <div class="mini-container">
     <div v-if="isShowChatBroad" class="mini-chat">
       <!-- 左侧折叠区域 -->
       <div class="left-side" :class="{ collapsed: isFold }" id="leftSide">
@@ -157,7 +157,7 @@
           <div class="file-preview" v-else-if="uploadedFiles.name && uploadedFiles.size && uploadfileType !== 'image'">
             <div class="file-info">
               📄{{ uploadedFiles.name }} (大小:{{ (uploadedFiles.size / 1024).toFixed(2) }}KB)
-              <DeleteOutlined @click="deleteFile()"></DeleteOutlined>
+              <DeleteOutlined @click="deleteFile()" />
             </div>
           </div>
           <a-textarea
@@ -199,7 +199,7 @@
               :remove="handleRemove"
             >
               <a-button class="upload-btn">
-                <UploadOutlined></UploadOutlined>
+                <UploadOutlined />
                 从本地上传
               </a-button>
             </a-upload>
@@ -245,1486 +245,1504 @@
 </template>
 
 <script lang="ts" setup>
-import VueOfficePdf from '@vue-office/pdf/lib/v3/vue-office-pdf.mjs';
-import VueOfficeDocx from '@vue-office/docx/lib/v3/vue-office-docx.mjs';
-import VueOfficeExcel from '@vue-office/excel/lib/v3/vue-office-excel.mjs';
-import { ref, onMounted, nextTick, watch, onUnmounted } from 'vue';
-import { SvgIcon } from '../Icon';
-import { Space, Button, Modal, Input, message } from 'ant-design-vue';
-// import AIChat from './index.vue';
-import { useUserStore } from '/@/store/modules/user';
-import {
-  EditOutlined,
-  DeleteOutlined,
-  UploadOutlined,
-  CopyOutlined,
-  RightOutlined,
-  DownOutlined,
-  FastForwardFilled,
-  RedoOutlined,
-} from '@ant-design/icons-vue';
-import { createVNode } from 'vue';
-import { marked } from 'marked';
-import katex from 'katex';
-import 'katex/dist/katex.min.css';
-import * as echarts from 'echarts';
-const TextArea = Input.TextArea; // 直接导入TextArea组件使用时打包报错
-const inputText = ref(''); // 输入框内容
-const refreshText = ref(''); //重新生成文本
-const sessionHistory = ref([]);
-const isShowChatBroad = ref(false);
-const editingId = ref<number | null>(null);
-const editText = ref('');
-const currentSessionID = ref('');
-const taskID = ref('');
-const messageID = ref('');
-const open = ref<boolean>(false);
-const isThinking = ref(false); //深度思考是否开启
-const Thinking = ref(false);
-const isShowDoc = ref(false);
-const fileType = ref('');
-const fileUrl = ref('');
-const APIKEY = ref('Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd');
-interface ListItem {
-  id: number;
-  name?: string;
-}
-interface Message {
-  id: string; // 唯一标识(可用时间戳生成)
-  type: 'user' | 'system' | 'response';
-  content: String; // 原始 Markdown 字符串(用于拼接)
-  parsedContent: String; // 解析后的 HTML(用于渲染)
-  contentR1: String; // 原始思考过程 Markdown
-  parsedContentR1: String; // 解析后的思考过程 HTML
-  timestamp: number; // 排序依据
-  isShowThink: boolean; //深度思考展示
-  message_files?: Array<[]>; //文件信息
-  echartsOption?: Object; //echart图表
-}
-// 定义消息历史数组类型
-const messageHistory = ref<Message[]>([]);
-const isFold = ref(true); // 是否折叠
-const userid = useUserStore().getUserInfo.id as string;
-const uploadedFiles = ref({}); //接口获取文件信息
-const askFile = ref({});
-const uploadfileType = ref(''); //提问框文件展示
-const askFileType = ref(''); //回答区域文件展示
-const message_files = ref([]);
-const fileList = ref([]);
-const suggestList = ref([]); //建议列表
-const loading = ref(false);
-// const chartRef = ref(null);
-const validEchartsOption = ref(null);
-const optionTextRef = ref(null);
-const echartsOption = ref({});
-let myChart: echarts.EChartsType | null = null;
-const chartDom = ref<HTMLDivElement | null>(null);
-// 初始化图表
-const initChart = () => {
-  const targetNode = document.getElementById('chart-target');
-  if (!targetNode) {
-    console.error('目标插入节点不存在!');
-    return;
+  import VueOfficePdf from '@vue-office/pdf/lib/v3/vue-office-pdf.mjs';
+  import VueOfficeDocx from '@vue-office/docx/lib/v3/vue-office-docx.mjs';
+  import VueOfficeExcel from '@vue-office/excel/lib/v3/vue-office-excel.mjs';
+  import { ref, onMounted, nextTick, watch, onUnmounted } from 'vue';
+  import { SvgIcon } from '../Icon';
+  import { Space, Button, Modal, Input, message } from 'ant-design-vue';
+  // import AIChat from './index.vue';
+  import { useUserStore } from '/@/store/modules/user';
+  import {
+    EditOutlined,
+    DeleteOutlined,
+    UploadOutlined,
+    CopyOutlined,
+    RightOutlined,
+    DownOutlined,
+    FastForwardFilled,
+    RedoOutlined,
+  } from '@ant-design/icons-vue';
+  import { createVNode } from 'vue';
+  import { marked } from 'marked';
+  import katex from 'katex';
+  import 'katex/dist/katex.min.css';
+  import * as echarts from 'echarts';
+  const TextArea = Input.TextArea; // 直接导入TextArea组件使用时打包报错
+  const inputText = ref(''); // 输入框内容
+  const refreshText = ref(''); //重新生成文本
+  const sessionHistory = ref([]);
+  const isShowChatBroad = ref(false);
+  const editingId = ref<number | null>(null);
+  const editText = ref('');
+  const currentSessionID = ref('');
+  const taskID = ref('');
+  const messageID = ref('');
+  const open = ref<boolean>(false);
+  const isThinking = ref(false); //深度思考是否开启
+  const Thinking = ref(false);
+  const isShowDoc = ref(false);
+  const fileType = ref('');
+  const fileUrl = ref('');
+  const APIKEY = ref('Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd');
+  interface ListItem {
+    id: number;
+    name?: string;
   }
+  interface Message {
+    id: string; // 唯一标识(可用时间戳生成)
+    type: 'user' | 'system' | 'response';
+    content: String; // 原始 Markdown 字符串(用于拼接)
+    parsedContent: String; // 解析后的 HTML(用于渲染)
+    contentR1: String; // 原始思考过程 Markdown
+    parsedContentR1: String; // 解析后的思考过程 HTML
+    timestamp: number; // 排序依据
+    isShowThink: boolean; //深度思考展示
+    message_files?: Array<[]>; //文件信息
+    echartsOption?: Object; //echart图表
+  }
+  // 定义消息历史数组类型
+  const messageHistory = ref<Message[]>([]);
+  const isFold = ref(true); // 是否折叠
+  const userid = useUserStore().getUserInfo.id as string;
+  const uploadedFiles = ref({}); //接口获取文件信息
+  const askFile = ref({});
+  const uploadfileType = ref(''); //提问框文件展示
+  const askFileType = ref(''); //回答区域文件展示
+  const message_files = ref([]);
+  const fileList = ref([]);
+  const suggestList = ref([]); //建议列表
+  const loading = ref(false);
+  // const chartRef = ref(null);
+  const validEchartsOption = ref(null);
+  const optionTextRef = ref(null);
+  const echartsOption = ref({});
+  let myChart: echarts.EChartsType | null = null;
+  const chartDom = ref<HTMLDivElement | null>(null);
+  // 初始化图表
+  const initChart = () => {
+    const targetNode = document.getElementById('chart-target');
+    if (!targetNode) {
+      console.error('目标插入节点不存在!');
+      return;
+    }
 
-  // 2. 创建 ECharts 容器(带唯一 id,方便后续清理)
-  const chartContainer = document.createElement('div');
-  chartContainer.id = 'dynamic-echarts-container';
-  // 必须设置宽高(继承目标节点宽高,或自定义)
-  chartContainer.style.width = '100%';
-  chartContainer.style.height = '100%';
-  chartContainer.style.border = '1px solid #eee';
+    // 2. 创建 ECharts 容器(带唯一 id,方便后续清理)
+    const chartContainer = document.createElement('div');
+    chartContainer.id = 'dynamic-echarts-container';
+    // 必须设置宽高(继承目标节点宽高,或自定义)
+    chartContainer.style.width = '100%';
+    chartContainer.style.height = '100%';
+    chartContainer.style.border = '1px solid #eee';
 
-  // 3. 初始化 ECharts 实例到新建容器
-  myChart = echarts.init(chartContainer);
-  myChart.setOption(echartsOption.value);
+    // 3. 初始化 ECharts 实例到新建容器
+    myChart = echarts.init(chartContainer);
+    myChart.setOption(echartsOption.value);
 
-  // 4. 将容器插入目标节点(清空原有内容,可选)
-  targetNode.innerHTML = ''; // 清空目标节点原有内容(如需保留可注释)
-  targetNode.appendChild(chartContainer);
+    // 4. 将容器插入目标节点(清空原有内容,可选)
+    targetNode.innerHTML = ''; // 清空目标节点原有内容(如需保留可注释)
+    targetNode.appendChild(chartContainer);
 
-  // 5. 监听窗口resize,自适应图表
-  window.addEventListener('resize', handleResize);
-};
-// 图表自适应方法
-const handleResize = () => {
-  myChart?.resize();
-};
-// 监听配置变化,确保DOM更新后初始化
-watch(
-  () => echartsOption.value,
-  async (newOption) => {
-    if (!newOption || Object.keys(newOption).length === 0) return;
-    await nextTick(); // 等待 DOM 渲染
-    initChart();
-  },
-  { deep: true, immediate: true }
-);
+    // 5. 监听窗口resize,自适应图表
+    window.addEventListener('resize', handleResize);
+  };
+  // 图表自适应方法
+  const handleResize = () => {
+    myChart?.resize();
+  };
+  // 监听配置变化,确保DOM更新后初始化
+  watch(
+    () => echartsOption.value,
+    async (newOption) => {
+      if (!newOption || Object.keys(newOption).length === 0) return;
+      await nextTick(); // 等待 DOM 渲染
+      initChart();
+    },
+    { deep: true, immediate: true }
+  );
 
-// 文件预览
-const handleRendered = () => {
-  loading.value = false;
-  console.log('文件渲染完成');
-};
-const handleError = (error) => {
-  loading.value = false;
-  console.error('文件预览错误:', error);
-};
-// function previewFile(data) {
-//   fileType.value = data.extension;
-//   fileUrl.value = data.source_url;
-// }
-//启用深度思考
-const toggleThinking = () => {
-  isThinking.value = !isThinking.value;
-  if (isThinking.value) {
-    APIKEY.value = 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi';
-  } else {
-    APIKEY.value = 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd';
-  }
-};
-// 折叠思考过程
-const isShow = (message) => {
-  message.isShowThink = !message.isShowThink;
-};
-const dialogAreaRef = ref(null);
-// 滚动到底部的方法
-const scrollToBottom = async () => {
-  // 等待 DOM 更新(如消息渲染完成)
-  await nextTick();
-  if (dialogAreaRef.value) {
-    const el = dialogAreaRef.value;
-    // 关键:scrollTop = scrollHeight(滚动内容总高度)
-    el.scrollTop = el.scrollHeight;
-  }
-};
+  // 文件预览
+  const handleRendered = () => {
+    loading.value = false;
+    console.log('文件渲染完成');
+  };
+  const handleError = (error) => {
+    loading.value = false;
+    console.error('文件预览错误:', error);
+  };
+  // function previewFile(data) {
+  //   fileType.value = data.extension;
+  //   fileUrl.value = data.source_url;
+  // }
+  //启用深度思考
+  const toggleThinking = () => {
+    isThinking.value = !isThinking.value;
+    if (isThinking.value) {
+      APIKEY.value = 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi';
+    } else {
+      APIKEY.value = 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd';
+    }
+  };
+  // 折叠思考过程
+  const isShow = (message) => {
+    message.isShowThink = !message.isShowThink;
+  };
+  const dialogAreaRef = ref(null);
+  // 滚动到底部的方法
+  const scrollToBottom = async () => {
+    // 等待 DOM 更新(如消息渲染完成)
+    await nextTick();
+    if (dialogAreaRef.value) {
+      const el = dialogAreaRef.value;
+      // 关键:scrollTop = scrollHeight(滚动内容总高度)
+      el.scrollTop = el.scrollHeight;
+    }
+  };
 
-// 点击建议项时的处理函数
-const handleSuggestClick = (text) => {
-  // 将选中的建议填充到文本框
-  inputText.value = text;
-};
-function showAIChat() {
-  isShowChatBroad.value = !isShowChatBroad.value;
-  if (isShowChatBroad) {
-    isShowDoc.value = false;
+  // 点击建议项时的处理函数
+  const handleSuggestClick = (text) => {
+    // 将选中的建议填充到文本框
+    inputText.value = text;
+  };
+  function showAIChat() {
+    isShowChatBroad.value = !isShowChatBroad.value;
+    if (isShowChatBroad.value) {
+      isShowDoc.value = false;
+    }
   }
-}
-//复制消息
-function copyToClipboard(text) {
-  if (!text || text.trim() === '') {
-    message.warn('没有可复制的内容');
-    return;
-  }
-  // 2. 创建临时textarea 元素
-  const textarea = document.createElement('textarea');
-  textarea.value = text;
-  textarea.style.position = 'fixed';
-  textarea.style.top = '-999px';
-  textarea.style.left = '-999px';
-  textarea.style.width = '200px';
-  textarea.style.height = '200px';
-  document.body.appendChild(textarea);
-  try {
-    textarea.select();
-    textarea.setSelectionRange(0, text.length);
-    const isSuccessful = document.execCommand('copy');
-    if (isSuccessful) {
-      message.success('复制成功!');
-    } else {
-      throw new Error('复制命令执行失败');
+  //复制消息
+  function copyToClipboard(text) {
+    if (!text || text.trim() === '') {
+      message.warn('没有可复制的内容');
+      return;
     }
-  } catch (err) {
-    console.error('复制失败:', err);
-    message.error('复制失败,请手动复制');
-  } finally {
-    document.body.removeChild(textarea);
-  }
-}
-const initMarked = () => {
-  marked.setOptions({
-    gfm: true, // 启用GitHub风格的Markdown,包含表格
-    breaks: false, // 禁用换行符转换
-  });
-};
-// LaTeX 公式渲染
-const renderLatexInHtml = (html) => {
-  // 匹配块级公式($$...$$)
-  const blockRegex = /\$\$(.*?)\$\$/gs;
-  // 匹配行内公式($...$)
-  const inlineRegex = /\$(.*?)\$/g;
-  // // 替换块级公式(居中显示)
-  html = html.replace(blockRegex, (match, formula) => {
-    return katex.renderToString(formula.trim(), {
-      displayMode: true,
-      throwOnError: false,
-      strict: false,
-      trust: true,
+    // 2. 创建临时textarea 元素
+    const textarea = document.createElement('textarea');
+    textarea.value = text;
+    textarea.style.position = 'fixed';
+    textarea.style.top = '-999px';
+    textarea.style.left = '-999px';
+    textarea.style.width = '200px';
+    textarea.style.height = '200px';
+    document.body.appendChild(textarea);
+    try {
+      textarea.select();
+      textarea.setSelectionRange(0, text.length);
+      const isSuccessful = document.execCommand('copy');
+      if (isSuccessful) {
+        message.success('复制成功!');
+      } else {
+        throw new Error('复制命令执行失败');
+      }
+    } catch (err) {
+      console.error('复制失败:', err);
+      message.error('复制失败,请手动复制');
+    } finally {
+      document.body.removeChild(textarea);
+    }
+  }
+  const initMarked = () => {
+    marked.setOptions({
+      gfm: true, // 启用GitHub风格的Markdown,包含表格
+      breaks: false, // 禁用换行符转换
     });
-  });
-  // 替换行内公式(行内显示)
-  html = html.replace(inlineRegex, (match, formula) => {
-    return katex.renderToString(formula.trim(), {
-      displayMode: false,
-      throwOnError: false,
-      strict: false,
+  };
+  // LaTeX 公式渲染
+  const renderLatexInHtml = (html) => {
+    // 匹配块级公式($$...$$)
+    const blockRegex = /\$\$(.*?)\$\$/gs;
+    // 匹配行内公式($...$)
+    const inlineRegex = /\$(.*?)\$/g;
+    // // 替换块级公式(居中显示)
+    html = html.replace(blockRegex, (match, formula) => {
+      return katex.renderToString(formula.trim(), {
+        displayMode: true,
+        throwOnError: false,
+        strict: false,
+        trust: true,
+      });
+    });
+    // 替换行内公式(行内显示)
+    html = html.replace(inlineRegex, (match, formula) => {
+      return katex.renderToString(formula.trim(), {
+        displayMode: false,
+        throwOnError: false,
+        strict: false,
+      });
     });
-  });
-  return html;
-};
-// Markdown + LaTeX 解析
-const parseMarkdownWithLatex = (mdStr) => {
-  if (!mdStr) return '';
-  try {
-    let html = marked(mdStr); // Markdown → HTML
-    html = renderLatexInHtml(html); // 替换公式
     return html;
-  } catch (error) {
-    console.error('解析失败:', error);
-    return mdStr; // 降级显示原始字符串
-  }
-};
-// echart 数据解析
-const parseEchart = (data) => {
-  const reg = /```[\s\S]*?\n([\s\S]*?)```/;
-  const match = data.match(reg);
+  };
+  // Markdown + LaTeX 解析
+  const parseMarkdownWithLatex = (mdStr) => {
+    if (!mdStr) return '';
+    try {
+      let html = marked(mdStr); // Markdown → HTML
+      html = renderLatexInHtml(html); // 替换公式
+      return html;
+    } catch (error) {
+      console.error('解析失败:', error);
+      return mdStr; // 降级显示原始字符串
+    }
+  };
+  // echart 数据解析
+  const parseEchart = (data) => {
+    const reg = /```[\s\S]*?\n([\s\S]*?)```/;
+    const match = data.match(reg);
 
-  if (match && match[1]) {
-    // 提取匹配到的JSON部分并解析
-    echartsOption.value = JSON.parse(match[1].trim());
-  }
-  return match;
-};
-const triggerChart = async () => {
-  await nextTick();
-  initChart();
-};
-//重新生成
-const refresh = () => {
-  handleSend(refreshText.value);
-};
-//重新编辑
-const editAsk = (data) => {
-  inputText.value = data;
-};
-//获取消息列表
-async function handleSend(data, files?) {
-  refreshText.value = data;
-  inputText.value = '';
-  if (files) {
-    askFileType.value = files?.mime_type?.startsWith('image') ? 'image' : 'document';
-  }
-  // message_files.value.push(files);
-  const fileList = files ? [files] : [];
-  uploadfileType.value = '';
-  if (isThinking) {
-    const newMessage = {
-      id: `user_${Date.now()}`,
-      type: 'user',
-      content: '',
-      parsedContent: data,
-      contentR1: '',
-      parsedContentR1: '',
-      timestamp: Date.now(),
-      isShowThink: true,
-      message_files: fileList,
-    };
-    messageHistory.value.push(newMessage);
-    message_files.value.push(files);
-  } else {
-    const newMessage = {
-      id: `user_${Date.now()}`,
-      type: 'user',
-      content: '',
-      parsedContent: data,
-      contentR1: '',
-      parsedContentR1: '',
-      timestamp: Date.now(),
-      isShowThink: false,
-      message_files: fileList,
-    };
-    messageHistory.value.push(newMessage);
-    message_files.value.push(files);
-  }
-  try {
-    const response = await fetch('http://39.97.59.228:8000/v1/chat-messages', {
-      method: 'POST',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: APIKEY.value,
-      },
-      body: JSON.stringify({
-        conversation_id: currentSessionID.value ? currentSessionID.value : '',
-        query: data,
-        ...(askFile.value?.id
-          ? {
-              files: [
-                {
-                  type: askFileType.value == 'image' ? 'image' : 'document',
-                  transfer_method: 'local_file',
-                  upload_file_id: askFile.value.id,
-                  url: '',
-                },
-              ],
-            }
-          : {}),
-        response_mode: 'streaming',
-        user: userid,
-        inputs: {},
-      }),
-    });
-    if (!response.ok) {
-      throw new Error(`HTTP error! status: ${response.status}`);
+    if (match && match[1]) {
+      // 提取匹配到的JSON部分并解析
+      echartsOption.value = JSON.parse(match[1].trim());
     }
-    uploadedFiles.value = {};
-    const decoder = new TextDecoder('utf-8');
-    const reader = response.body.getReader();
-    let textBuffer = ''; // 使用字符串缓冲区来累积数据
-    // 在组件中定义
-    const currentProcessingMessage = ref(null);
-    if (isThinking) {
+    return match;
+  };
+  const triggerChart = async () => {
+    await nextTick();
+    initChart();
+  };
+  //重新生成
+  const refresh = () => {
+    handleSend(refreshText.value);
+  };
+  //重新编辑
+  const editAsk = (data) => {
+    inputText.value = data;
+  };
+  //获取消息列表
+  async function handleSend(data, files?) {
+    refreshText.value = data;
+    inputText.value = '';
+    if (files) {
+      askFileType.value = files?.mime_type?.startsWith('image') ? 'image' : 'document';
+    }
+    // message_files.value.push(files);
+    const fileList = files ? [files] : [];
+    uploadfileType.value = '';
+    if (isThinking.value) {
       const newMessage = {
-        id: `response_${Date.now()}`,
-        type: 'response',
+        id: `user_${Date.now()}`,
+        type: 'user',
         content: '',
-        parsedContent: '',
+        parsedContent: data,
         contentR1: '',
         parsedContentR1: '',
         timestamp: Date.now(),
         isShowThink: true,
+        message_files: fileList,
       };
       messageHistory.value.push(newMessage);
-      currentProcessingMessage.value = newMessage; // 保存引用
+      message_files.value.push(files);
     } else {
       const newMessage = {
-        id: `response_${Date.now()}`,
-        type: 'response',
+        id: `user_${Date.now()}`,
+        type: 'user',
         content: '',
-        parsedContent: '',
+        parsedContent: data,
         contentR1: '',
         parsedContentR1: '',
         timestamp: Date.now(),
         isShowThink: false,
+        message_files: fileList,
       };
       messageHistory.value.push(newMessage);
-      currentProcessingMessage.value = newMessage; // 保存引用
+      message_files.value.push(files);
     }
-    while (true) {
-      const { done, value } = await reader.read();
-      if (done) {
-        if (textBuffer) {
-          processLine(textBuffer);
-        }
-        break;
+    try {
+      const response = await fetch('http://39.97.59.228:8000/v1/chat-messages', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: APIKEY.value,
+        },
+        body: JSON.stringify({
+          conversation_id: currentSessionID.value ? currentSessionID.value : '',
+          query: data,
+          ...(askFile.value?.id
+            ? {
+                files: [
+                  {
+                    type: askFileType.value == 'image' ? 'image' : 'document',
+                    transfer_method: 'local_file',
+                    upload_file_id: askFile.value.id,
+                    url: '',
+                  },
+                ],
+              }
+            : {}),
+          response_mode: 'streaming',
+          user: userid,
+          inputs: {},
+        }),
+      });
+      if (!response.ok) {
+        throw new Error(`HTTP error! status: ${response.status}`);
+      }
+      uploadedFiles.value = {};
+      const decoder = new TextDecoder('utf-8');
+      const reader = response.body.getReader();
+      let textBuffer = ''; // 使用字符串缓冲区来累积数据
+      // 在组件中定义
+      const currentProcessingMessage = ref(null);
+      if (isThinking.value) {
+        const newMessage = {
+          id: `response_${Date.now()}`,
+          type: 'response',
+          content: '',
+          parsedContent: '',
+          contentR1: '',
+          parsedContentR1: '',
+          timestamp: Date.now(),
+          isShowThink: true,
+        };
+        messageHistory.value.push(newMessage);
+        currentProcessingMessage.value = newMessage; // 保存引用
+      } else {
+        const newMessage = {
+          id: `response_${Date.now()}`,
+          type: 'response',
+          content: '',
+          parsedContent: '',
+          contentR1: '',
+          parsedContentR1: '',
+          timestamp: Date.now(),
+          isShowThink: false,
+        };
+        messageHistory.value.push(newMessage);
+        currentProcessingMessage.value = newMessage; // 保存引用
       }
-      textBuffer += decoder.decode(value, { stream: true });
-      // 处理每一行数据
-      let lineIndex;
-      while ((lineIndex = textBuffer.indexOf('\n')) !== -1) {
-        const line = textBuffer.substring(0, lineIndex).trim();
-        textBuffer = textBuffer.substring(lineIndex + 1);
+      while (true) {
+        const { done, value } = await reader.read();
+        if (done) {
+          if (textBuffer) {
+            processLine(textBuffer);
+          }
+          break;
+        }
+        textBuffer += decoder.decode(value, { stream: true });
+        // 处理每一行数据
+        let lineIndex;
+        while ((lineIndex = textBuffer.indexOf('\n')) !== -1) {
+          const line = textBuffer.substring(0, lineIndex).trim();
+          textBuffer = textBuffer.substring(lineIndex + 1);
 
-        if (line) {
-          processLine(line);
+          if (line) {
+            processLine(line);
+          }
         }
       }
-    }
-    function processLine(line) {
-      if (line.startsWith('data: ')) {
-        try {
-          const jsonStr = line.substring('data: '.length);
-          const data = JSON.parse(jsonStr);
-          switch (data.event) {
-            case 'message':
-              if (data.answer) {
-                const targetMessage = messageHistory.value.find((msg) => msg.id === currentProcessingMessage.value.id);
-                if (!targetMessage) break;
-                let currentChunk = data.answer;
+      function processLine(line) {
+        if (line.startsWith('data: ')) {
+          try {
+            const jsonStr = line.substring('data: '.length);
+            const data = JSON.parse(jsonStr);
+            switch (data.event) {
+              case 'message':
+                if (data.answer) {
+                  const targetMessage = messageHistory.value.find((msg) => msg.id === currentProcessingMessage.value.id);
+                  if (!targetMessage) break;
+                  let currentChunk = data.answer;
 
-                // 检查是否包含起始标签
-                const startIndex = currentChunk.indexOf('<think>');
-                if (startIndex !== -1) {
-                  // 找到起始标签:将标签前的内容作为正文
-                  if (startIndex > 0) {
-                    targetMessage.content += currentChunk.substring(0, startIndex);
-                    targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
-                  }
-                  // 进入思考模式,将标签后的内容追加到contentR1
-                  Thinking.value = true;
-                  const remainingContent = currentChunk.substring(startIndex + '<think>'.length);
-                  if (remainingContent) {
-                    targetMessage.contentR1 += remainingContent;
-                    targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
-                  }
-                } else if (Thinking.value) {
-                  // 结束标签
-                  const endIndex = currentChunk.indexOf('</think>');
-                  if (endIndex !== -1) {
-                    // 找到结束标签:标签前的内容追加到contentR1
-                    if (endIndex > 0) {
-                      targetMessage.contentR1 += currentChunk.substring(0, endIndex);
-                      targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
+                  // 检查是否包含起始标签
+                  const startIndex = currentChunk.indexOf('<think>');
+                  if (startIndex !== -1) {
+                    // 找到起始标签:将标签前的内容作为正文
+                    if (startIndex > 0) {
+                      targetMessage.content += currentChunk.substring(0, startIndex);
+                      targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
                     }
-                    // 将标签后的内容作为正文
-                    const remainingContent = currentChunk.substring(endIndex + '</think>'.length);
+                    // 进入思考模式,将标签后的内容追加到contentR1
+                    Thinking.value = true;
+                    const remainingContent = currentChunk.substring(startIndex + '<think>'.length);
                     if (remainingContent) {
-                      targetMessage.content += remainingContent;
-                      targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
+                      targetMessage.contentR1 += remainingContent;
+                      targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
+                    }
+                  } else if (Thinking.value) {
+                    // 结束标签
+                    const endIndex = currentChunk.indexOf('</think>');
+                    if (endIndex !== -1) {
+                      // 找到结束标签:标签前的内容追加到contentR1
+                      if (endIndex > 0) {
+                        targetMessage.contentR1 += currentChunk.substring(0, endIndex);
+                        targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
+                      }
+                      // 将标签后的内容作为正文
+                      const remainingContent = currentChunk.substring(endIndex + '</think>'.length);
+                      if (remainingContent) {
+                        targetMessage.content += remainingContent;
+                        targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
+                      }
+                      targetMessage.content += currentChunk;
+                      Thinking.value = false;
+                      targetMessage.isShowThink = false;
+                    } else {
+                      // 没有结束标签,继续追加到contentR1
+                      targetMessage.contentR1 += currentChunk;
+                      targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
                     }
-                    targetMessage.content += currentChunk;
-                    Thinking.value = false;
-                    targetMessage.isShowThink = false;
                   } else {
-                    // 没有结束标签,继续追加到contentR1
-                    targetMessage.contentR1 += currentChunk;
-                    targetMessage.parsedContentR1 = parseMarkdownWithLatex(targetMessage.contentR1);
+                    targetMessage.content += currentChunk;
+                    targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
                   }
-                } else {
-                  targetMessage.content += currentChunk;
-                  targetMessage.parsedContent = parseMarkdownWithLatex(targetMessage.content);
+                  scrollToBottom(); // 每次接收消息都滚动
                 }
-                scrollToBottom(); // 每次接收消息都滚动
-              }
-              if (data.task_id && !taskID.value) taskID.value = data.task_id;
-              if (data.conversation_id && !currentSessionID.value) currentSessionID.value = data.conversation_id;
-              if (data.message_id && !messageID.value) {
-                messageID.value = data.message_id;
-              }
-              break;
+                if (data.task_id && !taskID.value) taskID.value = data.task_id;
+                if (data.conversation_id && !currentSessionID.value) currentSessionID.value = data.conversation_id;
+                if (data.message_id && !messageID.value) {
+                  messageID.value = data.message_id;
+                }
+                break;
+            }
+          } catch (error) {
+            console.warn('Error parsing stream chunk:', error, 'Chunk:', line);
           }
-        } catch (error) {
-          console.warn('Error parsing stream chunk:', error, 'Chunk:', line);
         }
       }
+      getNextSuggest();
+    } catch (error) {
+      console.error('Error in handleSend:', error);
+      // 在 UI 上显示错误信息
+      messageHistory.value.push({
+        id: `system_${Date.now()}`,
+        type: 'system',
+        content: '',
+        parsedContent: '请求错误',
+        contentR1: '',
+        parsedContentR1: '',
+        timestamp: Date.now(),
+        isShowThink: false,
+      });
     }
-    getNextSuggest();
-  } catch (error) {
-    console.error('Error in handleSend:', error);
-    // 在 UI 上显示错误信息
-    messageHistory.value.push({
-      id: `system_${Date.now()}`,
-      type: 'system',
-      content: '',
-      parsedContent: '请求错误',
-      contentR1: '',
-      parsedContentR1: '',
-      timestamp: Date.now(),
-      isShowThink: false,
-    });
   }
-}
-//创建新对话
-async function addNew() {
-  messageHistory.value = [];
-  currentSessionID.value = '';
-  taskID.value = '';
-  messageID.value = '';
-}
-// 上传文件
-const showModal = (data) => {
-  open.value = data;
-};
-const close = () => {
-  isShowDoc.value = false;
-};
-const showPreview = (data) => {
-  fileType.value = data[0].extension ? data[0].extension : data[0].filename.split('.').pop();
-  fileUrl.value = data[0].source_url ? data[0].source_url : data[0].url;
-  isShowDoc.value = true;
-};
-//删除文件
-const deleteFile = () => {
-  uploadedFiles.value = {};
-};
-// 上传文件
-const handleBeforeUpload = async (file) => {
-  const formData = new FormData();
-  formData.append('file', file);
-  formData.append('user', userid);
+  //创建新对话
+  async function addNew() {
+    messageHistory.value = [];
+    currentSessionID.value = '';
+    taskID.value = '';
+    messageID.value = '';
+  }
+  // 上传文件
+  const showModal = (data) => {
+    open.value = data;
+  };
+  const close = () => {
+    isShowDoc.value = false;
+  };
+  const showPreview = (data) => {
+    fileType.value = data[0].extension ? data[0].extension : data[0].filename.split('.').pop();
+    fileUrl.value = data[0].source_url ? data[0].source_url : data[0].url;
+    isShowDoc.value = true;
+  };
+  //删除文件
+  const deleteFile = () => {
+    uploadedFiles.value = {};
+  };
+  // 上传文件
+  const handleBeforeUpload = async (file) => {
+    const formData = new FormData();
+    formData.append('file', file);
+    formData.append('user', userid);
 
-  try {
-    const response = await fetch(`http://39.97.59.228:8000/v1/files/upload`, {
-      method: 'POST',
-      headers: {
-        Authorization: APIKEY.value,
-      },
-      body: formData,
-    });
+    try {
+      const response = await fetch(`http://39.97.59.228:8000/v1/files/upload`, {
+        method: 'POST',
+        headers: {
+          Authorization: APIKEY.value,
+        },
+        body: formData,
+      });
 
-    const result = await response.json();
-    if (response.ok) {
-      uploadedFiles.value = result;
-      askFile.value = result;
-      uploadfileType.value = result.mime_type.startsWith('image') ? 'image' : 'document';
-      // previewFile(result);
-    } else {
-      message.error(`上传失败: ${result.message || '网络错误'}`);
+      const result = await response.json();
+      if (response.ok) {
+        uploadedFiles.value = result;
+        askFile.value = result;
+        uploadfileType.value = result.mime_type.startsWith('image') ? 'image' : 'document';
+        // previewFile(result);
+      } else {
+        message.error(`上传失败: ${result.message || '网络错误'}`);
+      }
+    } catch (error) {
+      console.error('保存失败:', error);
+      message.error('上传失败,请重试');
     }
-  } catch (error) {
-    console.error('保存失败:', error);
-    message.error('上传失败,请重试');
-  }
-  return false;
-};
+    return false;
+  };
 
-const handleRemove = (file) => {
-  const index = fileList.value.findIndex((item) => item.uid === file.uid);
-  if (index !== -1) {
-    fileList.value.splice(index, 1);
-  }
-};
-//停止响应
-async function stopReq() {
-  try {
-    let response = await fetch(`http://39.97.59.228:8000/v1/chat-messages/${taskID.value}/stop`, {
-      method: 'POST',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: APIKEY.value,
-      },
-      body: JSON.stringify({
-        user: userid,
-      }),
-    });
-    if (!response) {
-      throw new Error('Network response was not ok');
+  const handleRemove = (file) => {
+    const index = fileList.value.findIndex((item) => item.uid === file.uid);
+    if (index !== -1) {
+      fileList.value.splice(index, 1);
     }
-  } catch (error) {
-    console.error('保存失败:', error);
-  }
-}
-//获取具体会话记录
-async function sessionsHistory(id: string, retryCount = 0) {
-  const API_KEYS = ['Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd', 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi'];
-  // 最大重试次数
-  const maxRetries = API_KEYS.length - 1;
-  try {
-    let response = await fetch(`http://39.97.59.228:8000/v1/messages?conversation_id=${id}&user=${userid}`, {
-      method: 'GET',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: API_KEYS[retryCount],
-      },
-    });
-    if (!response.ok) {
-      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+  };
+  //停止响应
+  async function stopReq() {
+    try {
+      let response = await fetch(`http://39.97.59.228:8000/v1/chat-messages/${taskID.value}/stop`, {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: APIKEY.value,
+        },
+        body: JSON.stringify({
+          user: userid,
+        }),
+      });
+      if (!response) {
+        throw new Error('Network response was not ok');
+      }
+    } catch (error) {
+      console.error('保存失败:', error);
     }
-    const data = await response.json();
-    if (data.data.length > 0) {
-      messageHistory.value = [];
-      data.data.forEach((item: any) => {
-        currentSessionID.value = item.conversation_id;
-        messageHistory.value.push({
-          id: `user_${Date.now()}`,
-          type: 'user',
-          content: '',
-          parsedContent: item.query,
-          contentR1: '',
-          parsedContentR1: '',
-          message_files: item.message_files,
-          timestamp: Date.now(),
-          isShowThink: false,
-        });
-        const answer = item.answer;
-        // 查找<think>
-        const startIndex = answer.indexOf('<think>');
-        const endIndex = answer.indexOf('</think>');
-        const isChart = answer.indexOf('echarts');
-        let content = '';
-        let contentR1 = '';
-        // 根据标签判断
-        if (startIndex !== -1 && endIndex !== -1) {
-          content = answer.substring(0, startIndex) + answer.substring(endIndex + '</think>'.length);
-          contentR1 = answer.substring(startIndex + '<think>'.length, endIndex);
-        } else if (startIndex !== -1) {
-          // 只有起始标签
-          content = answer.substring(0, startIndex);
-          contentR1 = answer.substring(startIndex + '<think>'.length);
-        } else if (endIndex !== -1) {
-          // 只有结束标签
-          content = answer.substring(endIndex + '</think>'.length);
-          contentR1 = answer.substring(0, endIndex);
-        } else {
-          // 没有标签
-          content = answer;
-        }
-        if (isChart != -1) {
-          // 添加到消息历史
-          messageHistory.value.push({
-            id: `system_${Date.now()}`,
-            type: 'system',
-            content: '',
-            parsedContent: '',
-            contentR1: '',
-            parsedContentR1: parseMarkdownWithLatex(contentR1.trim()),
-            timestamp: Date.now(),
-            isShowThink: contentR1.length > 0, // 如果有思考内容则显示
-            echartsOption: parseEchart(content.trim()),
-          });
-          triggerChart();
-        } else {
-          // 添加到消息历史
+  }
+  //获取具体会话记录
+  async function sessionsHistory(id: string, retryCount = 0) {
+    const API_KEYS = ['Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd', 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi'];
+    // 最大重试次数
+    const maxRetries = API_KEYS.length - 1;
+    try {
+      let response = await fetch(`http://39.97.59.228:8000/v1/messages?conversation_id=${id}&user=${userid}`, {
+        method: 'GET',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: API_KEYS[retryCount],
+        },
+      });
+      if (!response.ok) {
+        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+      }
+      const data = await response.json();
+      if (data.data.length > 0) {
+        messageHistory.value = [];
+        data.data.forEach((item: any) => {
+          currentSessionID.value = item.conversation_id;
           messageHistory.value.push({
-            id: `system_${Date.now()}`,
-            type: 'system',
+            id: `user_${Date.now()}`,
+            type: 'user',
             content: '',
-            parsedContent: parseMarkdownWithLatex(content.trim()),
+            parsedContent: item.query,
             contentR1: '',
-            parsedContentR1: parseMarkdownWithLatex(contentR1.trim()),
+            parsedContentR1: '',
+            message_files: item.message_files,
             timestamp: Date.now(),
-            isShowThink: contentR1.length > 0, // 如果有思考内容则显示
+            isShowThink: false,
           });
-        }
-      });
+          const answer = item.answer;
+          // 查找<think>
+          const startIndex = answer.indexOf('<think>');
+          const endIndex = answer.indexOf('</think>');
+          const isChart = answer.indexOf('echarts');
+          let content = '';
+          let contentR1 = '';
+          // 根据标签判断
+          if (startIndex !== -1 && endIndex !== -1) {
+            content = answer.substring(0, startIndex) + answer.substring(endIndex + '</think>'.length);
+            contentR1 = answer.substring(startIndex + '<think>'.length, endIndex);
+          } else if (startIndex !== -1) {
+            // 只有起始标签
+            content = answer.substring(0, startIndex);
+            contentR1 = answer.substring(startIndex + '<think>'.length);
+          } else if (endIndex !== -1) {
+            // 只有结束标签
+            content = answer.substring(endIndex + '</think>'.length);
+            contentR1 = answer.substring(0, endIndex);
+          } else {
+            // 没有标签
+            content = answer;
+          }
+          if (isChart != -1) {
+            // 添加到消息历史
+            messageHistory.value.push({
+              id: `system_${Date.now()}`,
+              type: 'system',
+              content: '',
+              parsedContent: '',
+              contentR1: '',
+              parsedContentR1: parseMarkdownWithLatex(contentR1.trim()),
+              timestamp: Date.now(),
+              isShowThink: contentR1.length > 0, // 如果有思考内容则显示
+              echartsOption: parseEchart(content.trim()),
+            });
+            triggerChart();
+          } else {
+            // 添加到消息历史
+            messageHistory.value.push({
+              id: `system_${Date.now()}`,
+              type: 'system',
+              content: '',
+              parsedContent: parseMarkdownWithLatex(content.trim()),
+              contentR1: '',
+              parsedContentR1: parseMarkdownWithLatex(contentR1.trim()),
+              timestamp: Date.now(),
+              isShowThink: contentR1.length > 0, // 如果有思考内容则显示
+            });
+          }
+        });
+      }
+    } catch (error) {
+      // 判断是否达到最大重试次数
+      if (retryCount < maxRetries) {
+        console.warn(`请求失败,正在尝试第 ${retryCount + 2} 个 API Key...`);
+        return sessionsHistory(id, retryCount + 1);
+      } else {
+        console.error('所有 API Key 均尝试失败:', error);
+        throw error;
+      }
     }
-  } catch (error) {
-    // 判断是否达到最大重试次数
-    if (retryCount < maxRetries) {
-      console.warn(`请求失败,正在尝试第 ${retryCount + 2} 个 API Key...`);
-      return sessionsHistory(id, retryCount + 1);
-    } else {
-      console.error('所有 API Key 均尝试失败:', error);
-      throw error;
+    editingId.value = null;
+  }
+  //获取下一轮建议问题列表
+  //停止响应
+  async function getNextSuggest() {
+    try {
+      let response = await fetch(`http://39.97.59.228:8000/v1/messages/${messageID.value}/suggested?user=${userid}`, {
+        method: 'GET',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: APIKEY.value,
+        },
+      });
+      const data = await response.json();
+      suggestList.value = data.data;
+      if (!response) {
+        throw new Error('Network response was not ok');
+      }
+    } catch (error) {
+      console.error('保存失败:', error);
     }
   }
-  editingId.value = null;
-}
-//获取下一轮建议问题列表
-//停止响应
-async function getNextSuggest() {
-  try {
-    let response = await fetch(`http://39.97.59.228:8000/v1/messages/${messageID.value}/suggested?user=${userid}`, {
-      method: 'GET',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: APIKEY.value,
-      },
-    });
-    const data = await response.json();
-    suggestList.value = data.data;
-    if (!response) {
-      throw new Error('Network response was not ok');
+  //编辑标题
+  const startEditing = (item: ListItem) => {
+    editingId.value = item.id;
+    editText.value = item.name || '';
+  };
+  // 保存修改
+  const handleSave = async (item: ListItem) => {
+    try {
+      let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}/name`, {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: APIKEY.value,
+        },
+        body: JSON.stringify({
+          name: editText.value,
+          user: userid,
+        }),
+      });
+      if (!response.ok) {
+        throw new Error('Network response was not ok');
+      }
+      item.name = editText.value;
+    } catch (error) {
+      console.error('保存失败:', error);
     }
-  } catch (error) {
-    console.error('保存失败:', error);
-  }
-}
-//编辑标题
-const startEditing = (item: ListItem) => {
-  editingId.value = item.id;
-  editText.value = item.name || '';
-};
-// 保存修改
-const handleSave = async (item: ListItem) => {
-  try {
-    let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}/name`, {
-      method: 'POST',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: APIKEY.value,
+    editingId.value = null;
+  };
+  // 删除会话
+  const startDelete = async (item: ListItem) => {
+    Modal.confirm({
+      title: '确认删除',
+      content: `确定要删除会话 "${item.name || '新会话'}" 吗?此操作不可撤销。`,
+      okText: '确认',
+      cancelText: '取消',
+      onOk: async () => {
+        // 原有删除逻辑不变
+        try {
+          let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}`, {
+            method: 'DELETE',
+            headers: {
+              'Content-Type': 'application/json',
+              Authorization: APIKEY.value,
+            },
+            body: JSON.stringify({
+              user: userid,
+            }),
+          });
+          if (!response.ok) {
+            throw new Error('Network response was not ok');
+          }
+          getHistoryList();
+        } catch (error) {
+          console.error('删除失败:', error);
+          Modal.error({
+            title: '删除失败',
+            content: '删除会话时出现错误,请稍后重试。',
+          });
+        }
       },
-      body: JSON.stringify({
-        name: editText.value,
-        user: userid,
-      }),
     });
-    if (!response.ok) {
-      throw new Error('Network response was not ok');
+  };
+  const fold = () => {
+    isFold.value = !isFold.value;
+    if (!isFold.value) {
+      getHistoryList();
     }
-    item.name = editText.value;
-  } catch (error) {
-    console.error('保存失败:', error);
-  }
-  editingId.value = null;
-};
-// 删除会话
-const startDelete = async (item: ListItem) => {
-  Modal.confirm({
-    title: '确认删除',
-    content: `确定要删除会话 "${item.name || '新会话'}" 吗?此操作不可撤销。`,
-    okText: '确认',
-    cancelText: '取消',
-    onOk: async () => {
-      // 原有删除逻辑不变
-      try {
-        let response = await fetch(`http://39.97.59.228:8000/v1/conversations/${item.id}`, {
-          method: 'DELETE',
-          headers: {
-            'Content-Type': 'application/json',
-            Authorization: APIKEY.value,
-          },
-          body: JSON.stringify({
-            user: userid,
-          }),
-        });
-        if (!response.ok) {
-          throw new Error('Network response was not ok');
-        }
-        getHistoryList();
-      } catch (error) {
-        console.error('删除失败:', error);
-        Modal.error({
-          title: '删除失败',
-          content: '删除会话时出现错误,请稍后重试。',
-        });
-      }
-    },
-  });
-};
-const fold = () => {
-  isFold.value = !isFold.value;
-  if (!isFold.value) {
-    getHistoryList();
-  }
-};
-// 获取历史会话列表
-async function getHistoryList() {
-  sessionHistory.value = [];
-  try {
-    const fetch1 = fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
-      method: 'get',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd',
-      },
-    })
-      .then((res) => {
-        return res.json();
+  };
+  // 获取历史会话列表
+  async function getHistoryList() {
+    sessionHistory.value = [];
+    try {
+      const fetch1 = fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
+        method: 'get',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: 'Bearer app-tSFRUnv0Qkbtik1dwtlhnpkd',
+        },
       })
-      .catch((err) => {
-        console.error('第一个请求错误:', err);
-        return { data: [] }; // 失败时返回空数组
-      });
+        .then((res) => {
+          return res.json();
+        })
+        .catch((err) => {
+          console.error('第一个请求错误:', err);
+          return { data: [] }; // 失败时返回空数组
+        });
 
-    const fetch2 = fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
-      method: 'get',
-      headers: {
-        'Content-Type': 'application/json',
-        Authorization: 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi',
-      },
-    })
-      .then((res) => {
-        return res.json();
+      const fetch2 = fetch(`http://39.97.59.228:8000/v1/conversations?user=${userid}`, {
+        method: 'get',
+        headers: {
+          'Content-Type': 'application/json',
+          Authorization: 'Bearer app-7iLQR9T77YtwDYUYGPk1PFbi',
+        },
       })
-      .catch((err) => {
-        console.error('第二个请求错误:', err);
-        return { data: [] }; // 失败时返回空数组
-      });
+        .then((res) => {
+          return res.json();
+        })
+        .catch((err) => {
+          console.error('第二个请求错误:', err);
+          return { data: [] }; // 失败时返回空数组
+        });
 
-    // 等待两个请求完成
-    const [data1, data2] = await Promise.all([fetch1, fetch2]);
-    // 合并两个数组(确保是数组)
-    const list1 = Array.isArray(data1.data) ? data1.data : [];
-    const list2 = Array.isArray(data2.data) ? data2.data : [];
-    // 合并数组并赋值给 sessionHistory
-    sessionHistory.value = [...list1, ...list2];
-    // 设置当前会话ID(如果有数据)
-    if (sessionHistory.value.length > 0) {
-      currentSessionID.value = sessionHistory.value[0].id;
+      // 等待两个请求完成
+      const [data1, data2] = await Promise.all([fetch1, fetch2]);
+      // 合并两个数组(确保是数组)
+      const list1 = Array.isArray(data1.data) ? data1.data : [];
+      const list2 = Array.isArray(data2.data) ? data2.data : [];
+      // 合并数组并赋值给 sessionHistory
+      sessionHistory.value = [...list1, ...list2];
+      // 设置当前会话ID(如果有数据)
+      if (sessionHistory.value.length > 0) {
+        currentSessionID.value = sessionHistory.value[0].id;
+      }
+    } catch (error) {
+      console.error('获取历史数据失败:', error);
+      // 错误处理(比如提示用户)
     }
-  } catch (error) {
-    console.error('获取历史数据失败:', error);
-    // 错误处理(比如提示用户)
-  }
-}
-//格式化消息
-const formatMessage = (text) => {
-  if (!text) return '';
-  let formatted = text
-    // 处理换行
-    .replace(/\n\n/g, '<br>')
-    .replace(/\n###/g, '<br>')
-    .replace(/###/g, '')
-    .replace(/---/g, '')
-    .replace(/^- /gm, '<br> - ')
-    // 处理粗体
-    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
-    // 处理斜体
-    .replace(/\*(.*?)\*/g, '<em>$1</em>')
-    // 处理行内代码
-    .replace(/`([^`]+)`/g, '<code>$1</code>');
-  return formatted;
-};
-// 初始化按钮定位
-onMounted(() => {
-  getHistoryList();
-  // 初始化(仅执行一次)
-  initMarked();
-  triggerChart();
-});
-onUnmounted(() => {
-  // 卸载时销毁实例,清理 DOM
-  if (myChart) {
-    myChart.dispose();
-    myChart = null;
-  }
-  const chartContainer = document.getElementById('dynamic-echarts-container');
-  if (chartContainer && chartContainer.parentNode) {
-    chartContainer.parentNode.removeChild(chartContainer);
-  }
-  window.removeEventListener('resize', handleResize);
-});
+  }
+  //格式化消息
+  const formatMessage = (text) => {
+    if (!text) return '';
+    let formatted = text
+      // 处理换行
+      .replace(/\n\n/g, '<br>')
+      .replace(/\n###/g, '<br>')
+      .replace(/###/g, '')
+      .replace(/---/g, '')
+      .replace(/^- /gm, '<br> - ')
+      // 处理粗体
+      .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
+      // 处理斜体
+      .replace(/\*(.*?)\*/g, '<em>$1</em>')
+      // 处理行内代码
+      .replace(/`([^`]+)`/g, '<code>$1</code>');
+    return formatted;
+  };
+  // 初始化按钮定位
+  onMounted(() => {
+    getHistoryList();
+    // 初始化(仅执行一次)
+    initMarked();
+    triggerChart();
+  });
+  onUnmounted(() => {
+    // 卸载时销毁实例,清理 DOM
+    if (myChart) {
+      myChart.dispose();
+      myChart = null;
+    }
+    const chartContainer = document.getElementById('dynamic-echarts-container');
+    if (chartContainer && chartContainer.parentNode) {
+      chartContainer.parentNode.removeChild(chartContainer);
+    }
+    window.removeEventListener('resize', handleResize);
+  });
 </script>
 
 <style lang="less" scoped>
-.btn-header {
-  width: 40px;
-  height: 40px;
-  margin-right: 5px;
-  margin-bottom: 5px;
-}
-.container {
-  display: flex;
-  flex-direction: row;
-}
-.mini-chat {
-  display: flex;
-  min-width: none;
-  width: 950px;
-  height: 85%;
-  border-radius: 4px;
-  position: fixed;
-  top: 50px;
-  right: 20px;
-  padding: 10px;
-  background-color: #0a1a2f;
-  background-image: linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f),
-    linear-gradient(to top, #0b69b6, #0a1a2f), linear-gradient(to right, #0b69b6, #0a1a2f);
-  background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
-  background-position: top left, top right, bottom right, bottom left;
-  background-repeat: no-repeat;
-  z-index: 9999999;
-  color: #fff;
-}
-.doc {
-  display: flex;
-  flex-direction: column;
-  min-width: 600px;
-  height: 85%;
-  border-radius: 4px;
-  position: fixed;
-  top: 50px;
-  right: 51%;
-  padding: 10px;
-  background-color: #0a1a2f;
-  background-image: linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f),
-    linear-gradient(to top, #0b69b6, #0a1a2f), linear-gradient(to right, #0b69b6, #0a1a2f);
-  background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
-  background-position: top left, top right, bottom right, bottom left;
-  background-repeat: no-repeat;
-  z-index: 9999999;
-  color: #fff;
-}
-
-.close {
-  display: flex;
-  justify-content: flex-end;
-  align-items: center;
-  width: 100%;
-  padding: 1px;
-  border-radius: 8px;
-}
-
-.closeBtn {
-  background-color: #007bff;
-  color: white;
-  border: none;
-  border-radius: 4px;
-  cursor: pointer;
-  transition: all 0.3s ease;
-}
-
-.closeBtn:hover {
-  background-color: #0056b3;
-}
-.left-side {
-  background: #0c2842;
-  transition: width 0.5s ease; /* 平滑过渡动画 */
-  width: 140px; /* 展开时宽度 */
-  position: relative; /* 用于按钮定位 */
-}
-.left-side.collapsed {
-  width: 40px; /* 折叠时宽度 */
-}
-
-.addBtn {
-  height: 30px;
-  position: absolute;
-  background-size: 100% 100%;
-  background-position: center;
-  padding: 2px;
-  right: 10px;
-  bottom: 40px;
-  left: 10px;
-  align-items: center;
-  border-radius: 3px;
-  cursor: pointer;
-}
-.custom-list {
-  height: 650px;
-  overflow-y: auto;
-}
-.text-container {
-  display: flex;
-  justify-content: space-between;
-  width: 100%;
-  overflow: hidden;
-}
-.btn-container {
-  display: flex;
-}
-.jeecg-layout-header-action span[role='img'] {
-  padding: 0;
-}
-.text-ellipsis {
-  flex: 1;
-}
-.edit-text {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 90px;
-  color: #fff;
-  font-size: 12px;
-  cursor: pointer;
-}
-.edit-icon {
-  flex-shrink: 0;
-  margin-left: auto;
-  line-height: 23px;
-}
-.delete-icon {
-  flex-shrink: 0;
-  margin-left: auto;
-  line-height: 23px;
-}
-.edit-icon:hover {
-  color: #1890ff !important;
-  cursor: pointer;
-}
-.delete-icon:hover {
-  color: #1890ff !important;
-  cursor: pointer;
-}
-.edit-input {
-  font-size: 10px;
-}
-.btn-text-bg {
-  width: 14px;
-  height: 14px;
-  position: absolute;
-  background-size: 100% 100%;
-  right: 10px;
-  top: 10px;
-  left: 10px;
-  bottom: 10px;
-}
-.btn-text {
-  margin-left: 3px;
-  font-size: 12px;
-  color: #fff;
-  white-space: nowrap;
-  margin-left: 30px;
-  line-height: 29px;
-}
-.historyBtn {
-  width: 20px;
-  height: 20px;
-  position: absolute;
-  background-size: 100% 100%;
-  background-position: center;
-  padding: 2px;
-  right: 10px;
-  top: 10px;
-}
-.historyBtn1 {
-  width: 20px;
-  height: 20px;
-  position: absolute;
-  background-size: 100% 100%;
-  background-position: center;
-  left: 3px;
-}
-.divider0 {
-  border-bottom: 1px solid #1074c1;
-  width: auto;
-  margin: 0 10px;
-  height: 13%;
-  display: block;
-  background: transparent;
-}
-.foldBtn {
-  width: 20px;
-  height: 20px;
-  position: absolute;
-  background-size: 100% 100%;
-  background-position: center;
-  padding: 2px;
-  right: 10px;
-  bottom: 10px;
-  cursor: pointer;
-}
-
-.right-side {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  width: calc(100% - 134px) !important;
-  .title {
-    text-align: center;
-    font-size: 14px;
-    padding: 5px;
+  .btn-header {
+    width: 40px;
+    height: 40px;
+    margin-right: 5px;
+    margin-bottom: 5px;
   }
-  .dialog-area {
-    flex: 1;
-    gap: 30px;
-    overflow-y: auto;
-    padding: 5px;
+  .mini-container {
     display: flex;
-    flex-direction: column;
+    flex-direction: row;
+  }
+  .mini-chat {
+    display: flex;
+    min-width: none;
+    width: 950px;
+    height: 85%;
+    border-radius: 4px;
+    position: fixed;
+    top: 50px;
+    right: 20px;
+    padding: 10px;
+    background-color: #0a1a2f;
+    background-image:
+      linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f), linear-gradient(to top, #0b69b6, #0a1a2f),
+      linear-gradient(to right, #0b69b6, #0a1a2f);
+    background-size:
+      100% 5px,
+      5px 100%,
+      100% 5px,
+      5px 100%;
+    background-position:
+      top left,
+      top right,
+      bottom right,
+      bottom left;
+    background-repeat: no-repeat;
+    z-index: 9999999;
     color: #fff;
-
-    .ask-message {
-      padding: 10px;
-      border-radius: 5px;
-      background: #0c2842;
-      max-width: 300px;
-      min-width: 50px;
-      white-space: pre-wrap;
-      word-wrap: break-word;
-      overflow-wrap: break-word;
-      overflow: auto;
-      line-height: 1.5;
-    }
-    .answer-message {
-      padding: 10px;
-      border-radius: 5px;
-      background: #0c2842;
-      max-width: 90%;
-    }
   }
-
-  .input-area {
-    padding: 5px;
-    background-color: #043256;
-    border: 1px solid #2cb6ff;
-    border-radius: 5px;
+  .doc {
     display: flex;
     flex-direction: column;
-    justify-content: space-around;
-    gap: 5px;
-    min-height: 170px;
-    height: auto;
-    margin: 5px;
-    position: relative;
-  }
-  /* 文件展示区域 */
-  .img-preview {
-    position: relative;
-    width: 50px;
-    height: 50px;
-  }
-  .img-preview img {
-    width: 100%;
-    height: 100%;
-    object-fit: contain;
-    display: block;
-  }
-  .file-preview {
-    position: relative;
-    margin-bottom: 10px;
-    padding: 8px;
-    border: 1px solid #e5e7eb;
+    min-width: 600px;
+    height: 85%;
     border-radius: 4px;
-    background: #f9fafb;
-    box-sizing: border-box;
+    position: fixed;
+    top: 50px;
+    right: 51%;
+    padding: 10px;
+    background-color: #0a1a2f;
+    background-image:
+      linear-gradient(to bottom, #0b69b6 1%, #0a1a2f 100%), linear-gradient(to left, #0b69b6, #0a1a2f), linear-gradient(to top, #0b69b6, #0a1a2f),
+      linear-gradient(to right, #0b69b6, #0a1a2f);
+    background-size:
+      100% 5px,
+      5px 100%,
+      100% 5px,
+      5px 100%;
+    background-position:
+      top left,
+      top right,
+      bottom right,
+      bottom left;
+    background-repeat: no-repeat;
+    z-index: 9999999;
+    color: #fff;
   }
-  .file-info {
+
+  .close {
     display: flex;
-    justify-content: space-between;
+    justify-content: flex-end;
     align-items: center;
-    font-size: 14px;
-    color: #333;
+    width: 100%;
+    padding: 1px;
+    border-radius: 8px;
   }
-  .clear-btn {
-    border: none;
-    background: #ff4d4f;
+
+  .closeBtn {
+    background-color: #007bff;
     color: white;
-    border-radius: 50%;
-    width: 20px;
-    height: 20px;
-    cursor: pointer;
-    font-size: 12px;
-  }
-  .file-content {
-    margin-top: 6px;
-    font-size: 13px;
-    color: #666;
-    line-height: 1.4;
-  }
-  /* 文件列表容器 */
-  .uploaded-files {
-    padding: 8px;
-    background-color: #f5f5f5;
+    border: none;
     border-radius: 4px;
-    min-height: 40px;
+    cursor: pointer;
+    transition: all 0.3s ease;
   }
 
-  /* 单个文件项 */
-  .file-item {
-    display: inline-flex;
-    align-items: center;
-    padding: 4px 8px;
-    margin-right: 8px;
-    margin-bottom: 8px;
-    background-color: #fff;
-    border: 1px solid #e9e9e9;
-    border-radius: 4px;
+  .closeBtn:hover {
+    background-color: #0056b3;
   }
-
-  /* 文件名 */
-  .file-name {
-    margin-left: 8px;
-    margin-right: 8px;
-    max-width: 150px;
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
+  .left-side {
+    background: #0c2842;
+    transition: width 0.5s ease; /* 平滑过渡动画 */
+    width: 140px; /* 展开时宽度 */
+    position: relative; /* 用于按钮定位 */
+  }
+  .left-side.collapsed {
+    width: 40px; /* 折叠时宽度 */
   }
 
-  .ant-input {
-    border: none;
-    background-color: rgba(255, 255, 255, 0) !important;
-    color: #fff;
+  .addBtn {
+    height: 30px;
+    position: absolute;
+    background-size: 100% 100%;
+    background-position: center;
+    padding: 2px;
+    right: 10px;
+    bottom: 40px;
+    left: 10px;
+    align-items: center;
+    border-radius: 3px;
+    cursor: pointer;
   }
-  .ant-input:focus {
-    border: none; /* 聚焦时无边框 */
-    outline: none; /* 聚焦时无轮廓 */
-    box-shadow: none; /* 移除可能存在的阴影效果 */
+  .custom-list {
+    height: 650px;
+    overflow-y: auto;
   }
-  .ctrl-btn {
+  .text-container {
     display: flex;
-    flex-direction: row;
     justify-content: space-between;
+    width: 100%;
+    overflow: hidden;
+  }
+  .btn-container {
+    display: flex;
   }
-  .question-input {
-    background-color: #1e293b !important;
-    border-color: #334155 !important;
-    color: #e2e8f0 !important;
-    border-radius: 8px !important;
-    padding: 12px 16px !important;
-    font-size: 14px !important;
+  .jeecg-layout-header-action span[role='img'] {
+    padding: 0;
   }
-
-  .question-input::placeholder {
-    color: #64748b !important;
+  .text-ellipsis {
+    flex: 1;
   }
-
-  .control-btn {
-    height: 25px;
-    background-color: #043256;
-    border: 1px solid #2cb6ff;
+  .edit-text {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    width: 90px;
     color: #fff;
-    font-size: 10px;
-    margin-right: 10px;
+    font-size: 12px;
     cursor: pointer;
-    transition: background-color 0.2s ease; /* 平滑过渡效果 */
   }
-  /* 激活状态样式(点击后) */
-  .control-btn.active {
-    background-color: #2cb6ff; /* 蓝色背景(Ant Design 主色) */
-    color: white; /* 白色文字 */
+  .edit-icon {
+    flex-shrink: 0;
+    margin-left: auto;
+    line-height: 23px;
   }
-  .control-btn1 {
-    height: 20px;
-    background-color: #234a6b;
-    border: 1px solid #234a6b;
-    color: #fff;
-    font-size: 10px;
-    margin-right: 10px;
+  .delete-icon {
+    flex-shrink: 0;
+    margin-left: auto;
+    line-height: 23px;
+  }
+  .edit-icon:hover {
+    color: #1890ff !important;
     cursor: pointer;
-    transition: all 0.2s;
   }
-  .control-btn2 {
-    height: 20px;
-    background-color: #2cb6ff;
-    border: 1px solid #2cb6ff;
-    color: #fff;
-    font-size: 10px;
-    margin-right: 10px;
+  .delete-icon:hover {
+    color: #1890ff !important;
     cursor: pointer;
-    transition: all 0.2s;
   }
-  /* 文件上传区 */
-  .file-upload {
+  .edit-input {
+    font-size: 10px;
+  }
+  .btn-text-bg {
+    width: 14px;
+    height: 14px;
     position: absolute;
-    right: 20px;
-    bottom: 70px;
-    width: 180px;
-    display: flex;
-    flex-direction: column;
-    gap: 10px;
-    border: 1px solid #2cb6ff;
-    background-color: #234a6b;
-    border-radius: 6px;
-    padding: 10px;
+    background-size: 100% 100%;
+    right: 10px;
+    top: 10px;
+    left: 10px;
+    bottom: 10px;
   }
-
-  .input-container {
-    position: relative;
-    display: flex;
-    align-items: center;
-    width: 100%;
+  .btn-text {
+    margin-left: 3px;
+    font-size: 12px;
+    color: #fff;
+    white-space: nowrap;
+    margin-left: 30px;
+    line-height: 29px;
   }
-
-  .file-input {
-    flex: 1;
-    background-color: #234a6b;
-    border-color: #2cb6ff !important;
-    color: #e2e8f0 !important;
-    border-radius: 6px !important;
-    font-size: 10px !important;
-    padding-right: 70px !important;
-    height: 36px !important;
-    width: 100% !important;
+  .historyBtn {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    background-size: 100% 100%;
+    background-position: center;
+    padding: 2px;
+    right: 10px;
+    top: 10px;
   }
-
-  .confirm-btn {
+  .historyBtn1 {
+    width: 20px;
+    height: 20px;
     position: absolute;
-    right: 5px;
-    background-color: #2cb6ff;
-    border: none;
-    color: #fff;
-    border-radius: 4px;
-    font-size: 12px;
-    padding: 4px 10px;
+    background-size: 100% 100%;
+    background-position: center;
+    left: 3px;
+  }
+  .divider0 {
+    border-bottom: 1px solid #1074c1;
+    width: auto;
+    margin: 0 10px;
+    height: 13%;
+    display: block;
+    background: transparent;
+  }
+  .foldBtn {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    background-size: 100% 100%;
+    background-position: center;
+    padding: 2px;
+    right: 10px;
+    bottom: 10px;
     cursor: pointer;
-    transition: all 0.2s;
-    height: 28px;
   }
 
-  .confirm-btn:hover {
-    background-color: #2cb6ff;
-  }
+  .right-side {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    width: calc(100% - 134px) !important;
+    .title {
+      text-align: center;
+      font-size: 14px;
+      padding: 5px;
+    }
+    .dialog-area {
+      flex: 1;
+      gap: 30px;
+      overflow-y: auto;
+      padding: 5px;
+      display: flex;
+      flex-direction: column;
+      color: #fff;
 
-  .custom-upload {
-    width: 100%;
-    padding: 0 !important;
-  }
+      .ask-message {
+        padding: 10px;
+        border-radius: 5px;
+        background: #0c2842;
+        max-width: 300px;
+        min-width: 50px;
+        white-space: pre-wrap;
+        word-wrap: break-word;
+        overflow-wrap: break-word;
+        overflow: auto;
+        line-height: 1.5;
+      }
+      .answer-message {
+        padding: 10px;
+        border-radius: 5px;
+        background: #0c2842;
+        max-width: 90%;
+      }
+    }
 
-  .upload-btn {
-    background-color: #234a6b !important;
-    border: 1px solid #2188c3 !important;
-    color: #dbeafe !important;
-    border-radius: 6px !important;
-    font-size: 12px !important;
-    cursor: pointer;
-    transition: all 0.2s;
-    padding: 8px 0 !important;
-    width: 190% !important;
-    height: 36px !important;
-    box-sizing: border-box !important;
-  }
-  .upload-btn:hover {
-    background-color: #1f84bd !important;
-    color: #fff !important;
+    .input-area {
+      padding: 5px;
+      background-color: #043256;
+      border: 1px solid #2cb6ff;
+      border-radius: 5px;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-around;
+      gap: 5px;
+      min-height: 170px;
+      height: auto;
+      margin: 5px;
+      position: relative;
+    }
+    /* 文件展示区域 */
+    .img-preview {
+      position: relative;
+      width: 50px;
+      height: 50px;
+    }
+    .img-preview img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+      display: block;
+    }
+    .file-preview {
+      position: relative;
+      margin-bottom: 10px;
+      padding: 8px;
+      border: 1px solid #e5e7eb;
+      border-radius: 4px;
+      background: #f9fafb;
+      box-sizing: border-box;
+    }
+    .file-info {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      font-size: 14px;
+      color: #333;
+    }
+    .clear-btn {
+      border: none;
+      background: #ff4d4f;
+      color: white;
+      border-radius: 50%;
+      width: 20px;
+      height: 20px;
+      cursor: pointer;
+      font-size: 12px;
+    }
+    .file-content {
+      margin-top: 6px;
+      font-size: 13px;
+      color: #666;
+      line-height: 1.4;
+    }
+    /* 文件列表容器 */
+    .uploaded-files {
+      padding: 8px;
+      background-color: #f5f5f5;
+      border-radius: 4px;
+      min-height: 40px;
+    }
+
+    /* 单个文件项 */
+    .file-item {
+      display: inline-flex;
+      align-items: center;
+      padding: 4px 8px;
+      margin-right: 8px;
+      margin-bottom: 8px;
+      background-color: #fff;
+      border: 1px solid #e9e9e9;
+      border-radius: 4px;
+    }
+
+    /* 文件名 */
+    .file-name {
+      margin-left: 8px;
+      margin-right: 8px;
+      max-width: 150px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
+    .ant-input {
+      border: none;
+      background-color: rgba(255, 255, 255, 0) !important;
+      color: #fff;
+    }
+    .ant-input:focus {
+      border: none; /* 聚焦时无边框 */
+      outline: none; /* 聚焦时无轮廓 */
+      box-shadow: none; /* 移除可能存在的阴影效果 */
+    }
+    .ctrl-btn {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+    }
+    .question-input {
+      background-color: #1e293b !important;
+      border-color: #334155 !important;
+      color: #e2e8f0 !important;
+      border-radius: 8px !important;
+      padding: 12px 16px !important;
+      font-size: 14px !important;
+    }
+
+    .question-input::placeholder {
+      color: #64748b !important;
+    }
+
+    .control-btn {
+      height: 25px;
+      background-color: #043256;
+      border: 1px solid #2cb6ff;
+      color: #fff;
+      font-size: 10px;
+      margin-right: 10px;
+      cursor: pointer;
+      transition: background-color 0.2s ease; /* 平滑过渡效果 */
+    }
+    /* 激活状态样式(点击后) */
+    .control-btn.active {
+      background-color: #2cb6ff; /* 蓝色背景(Ant Design 主色) */
+      color: white; /* 白色文字 */
+    }
+    .control-btn1 {
+      height: 20px;
+      background-color: #234a6b;
+      border: 1px solid #234a6b;
+      color: #fff;
+      font-size: 10px;
+      margin-right: 10px;
+      cursor: pointer;
+      transition: all 0.2s;
+    }
+    .control-btn2 {
+      height: 20px;
+      background-color: #2cb6ff;
+      border: 1px solid #2cb6ff;
+      color: #fff;
+      font-size: 10px;
+      margin-right: 10px;
+      cursor: pointer;
+      transition: all 0.2s;
+    }
+    /* 文件上传区 */
+    .file-upload {
+      position: absolute;
+      right: 20px;
+      bottom: 70px;
+      width: 180px;
+      display: flex;
+      flex-direction: column;
+      gap: 10px;
+      border: 1px solid #2cb6ff;
+      background-color: #234a6b;
+      border-radius: 6px;
+      padding: 10px;
+    }
+
+    .input-container {
+      position: relative;
+      display: flex;
+      align-items: center;
+      width: 100%;
+    }
+
+    .file-input {
+      flex: 1;
+      background-color: #234a6b;
+      border-color: #2cb6ff !important;
+      color: #e2e8f0 !important;
+      border-radius: 6px !important;
+      font-size: 10px !important;
+      padding-right: 70px !important;
+      height: 36px !important;
+      width: 100% !important;
+    }
+
+    .confirm-btn {
+      position: absolute;
+      right: 5px;
+      background-color: #2cb6ff;
+      border: none;
+      color: #fff;
+      border-radius: 4px;
+      font-size: 12px;
+      padding: 4px 10px;
+      cursor: pointer;
+      transition: all 0.2s;
+      height: 28px;
+    }
+
+    .confirm-btn:hover {
+      background-color: #2cb6ff;
+    }
+
+    .custom-upload {
+      width: 100%;
+      padding: 0 !important;
+    }
+
+    .upload-btn {
+      background-color: #234a6b !important;
+      border: 1px solid #2188c3 !important;
+      color: #dbeafe !important;
+      border-radius: 6px !important;
+      font-size: 12px !important;
+      cursor: pointer;
+      transition: all 0.2s;
+      padding: 8px 0 !important;
+      width: 190% !important;
+      height: 36px !important;
+      box-sizing: border-box !important;
+    }
+    .upload-btn:hover {
+      background-color: #1f84bd !important;
+      color: #fff !important;
+    }
+    .custom-upload .ant-upload-select:hover .ant-btn {
+      border-color: #1f84bd !important;
+    }
+    .message-wrapper.ai-message-wrapper {
+      display: flex;
+      align-items: flex-start;
+    }
+    .answerIcon {
+      flex: 0 0 45px;
+    }
+
+    .suggestion-item {
+      height: 30px;
+      margin-left: 45px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 10px 16px;
+      border: 1px solid #1890ff;
+      color: white;
+      border-radius: 4px;
+      cursor: pointer;
+      width: 33%;
+      font-size: 12px;
+    }
+    .thinking-section {
+      border-left: 3px solid #e5e7eb;
+      padding-left: 12px;
+      margin-bottom: 16px;
+    }
+
+    .thinking-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 8px 0;
+      cursor: pointer;
+      user-select: none;
+    }
+
+    .thinking-title {
+      font-size: 14px;
+      font-weight: 500;
+      color: #6b7280;
+    }
   }
-  .custom-upload .ant-upload-select:hover .ant-btn {
-    border-color: #1f84bd !important;
+</style>
+<style scoped>
+  .zxm-popover-inner-content {
+    padding: 1px;
   }
-  .message-wrapper.ai-message-wrapper {
+  .message-wrapper {
     display: flex;
     align-items: flex-start;
+    position: relative;
   }
-  .answerIcon {
-    flex: 0 0 45px;
+  .user-message-wrapper {
+    flex-direction: row-reverse;
   }
-
-  .suggestion-item {
-    height: 30px;
-    margin-left: 45px;
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 10px 16px;
-    border: 1px solid #1890ff;
-    color: white;
-    border-radius: 4px;
-    cursor: pointer;
-    width: 33%;
-    font-size: 12px;
+  .ai-message-wrapper {
+    flex-direction: row;
   }
-  .thinking-section {
-    border-left: 3px solid #e5e7eb;
-    padding-left: 12px;
-    margin-bottom: 16px;
+  /* 鼠标滑过 .message-wrapper 时,显示图标 */
+  .ai-message-wrapper:hover .copy-icon-container {
+    opacity: 1;
+    visibility: visible;
   }
-
-  .thinking-header {
+  .user-message-wrapper:hover .copy-icon-container {
+    opacity: 1;
+    visibility: visible;
+  }
+  .copy-icon {
+    font-size: 16px;
+    color: #666;
+    cursor: pointer;
+  }
+  /* 默认隐藏,hover 时显示 */
+  .copy-icon-container {
+    position: absolute;
     display: flex;
-    justify-content: space-between;
-    align-items: center;
-    padding: 8px 0;
+    flex-direction: row;
+    bottom: -20px;
+    right: 15%;
+    opacity: 0;
+    visibility: hidden;
+    transition: all 0.3s ease;
+    z-index: 10;
+  }
+  /* 复制图标样式 */
+  .copy-icon {
+    font-size: 16px;
     cursor: pointer;
-    user-select: none;
+    margin-right: 20%;
+    float: right;
+    color: #fff;
   }
-
-  .thinking-title {
-    font-size: 14px;
-    font-weight: 500;
-    color: #6b7280;
+  .message-wrapper:hover .copy-icon {
+    opacity: 1;
+  }
+  .copy-icon:hover {
+    color: #1890ff;
+  }
+  ::v-deep table {
+    border-collapse: collapse;
+    width: 100%;
+    margin: 10px 0;
+    border: 1px solid #333;
+  }
+  ::v-deep th {
+    border: 1px solid #333;
+    background-color: #234a6b;
+    padding: 5px;
+    text-align: center;
+  }
+  ::v-deep td {
+    border: 1px solid #ddd;
+    padding: 8px 12px;
+    text-align: center;
   }
-}
-</style>
-<style scoped>
-.zxm-popover-inner-content {
-  padding: 1px;
-}
-.message-wrapper {
-  display: flex;
-  align-items: flex-start;
-  position: relative;
-}
-.user-message-wrapper {
-  flex-direction: row-reverse;
-}
-.ai-message-wrapper {
-  flex-direction: row;
-}
-/* 鼠标滑过 .message-wrapper 时,显示图标 */
-.ai-message-wrapper:hover .copy-icon-container {
-  opacity: 1;
-  visibility: visible;
-}
-.user-message-wrapper:hover .copy-icon-container {
-  opacity: 1;
-  visibility: visible;
-}
-.copy-icon {
-  font-size: 16px;
-  color: #666;
-  cursor: pointer;
-}
-/* 默认隐藏,hover 时显示 */
-.copy-icon-container {
-  position: absolute;
-  display: flex;
-  flex-direction: row;
-  bottom: -20px;
-  right: 15%;
-  opacity: 0;
-  visibility: hidden;
-  transition: all 0.3s ease;
-  z-index: 10;
-}
-/* 复制图标样式 */
-.copy-icon {
-  font-size: 16px;
-  cursor: pointer;
-  margin-right: 20%;
-  float: right;
-  color: #fff;
-}
-.message-wrapper:hover .copy-icon {
-  opacity: 1;
-}
-.copy-icon:hover {
-  color: #1890ff;
-}
-::v-deep table {
-  border-collapse: collapse;
-  width: 100%;
-  margin: 10px 0;
-  border: 1px solid #333;
-}
-::v-deep th {
-  border: 1px solid #333;
-  background-color: #234a6b;
-  padding: 5px;
-  text-align: center;
-}
-::v-deep td {
-  border: 1px solid #ddd;
-  padding: 8px 12px;
-  text-align: center;
-}
 </style>
 <style scoped>
-/* 已上传文件列表 */
-.file-list {
-  margin-top: 20px;
-}
-.pre-container {
-  flex: 1;
-  width: 100%;
-  height: 100%;
-  overflow: auto;
-}
-.img-container {
-}
-.vue-office-excel {
-  background: #fff !important;
-}
+  /* 已上传文件列表 */
+  .file-list {
+    margin-top: 20px;
+  }
+  .pre-container {
+    flex: 1;
+    width: 100%;
+    height: 100%;
+    overflow: auto;
+  }
+  .img-container {
+  }
+  .vue-office-excel {
+    background: #fff !important;
+  }
 
-.file-item {
-  display: flex;
-  align-items: center;
-  padding: 12px 15px;
-  background-color: #ddd;
-  border-radius: 6px;
-  margin-bottom: 10px;
-  transition: background-color 0.2s ease;
-}
+  .file-item {
+    display: flex;
+    align-items: center;
+    padding: 12px 15px;
+    background-color: #ddd;
+    border-radius: 6px;
+    margin-bottom: 10px;
+    transition: background-color 0.2s ease;
+  }
 
-.file-item:hover {
-  background-color: #f0f2f5;
-}
+  .file-item:hover {
+    background-color: #f0f2f5;
+  }
 
-.file-info {
-  flex: 1;
-  overflow: hidden;
-}
+  .file-info {
+    flex: 1;
+    overflow: hidden;
+  }
 
-.file-name {
-  font-size: 15px;
-  color: #1d2129;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  margin-bottom: 3px;
-}
+  .file-name {
+    font-size: 15px;
+    color: #1d2129;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    margin-bottom: 3px;
+  }
 
-.file-actions {
-  display: flex;
-  gap: 10px;
-}
+  .file-actions {
+    display: flex;
+    gap: 10px;
+  }
 
-.btn {
-  padding: 0px 15px;
-  margin-left: 10px;
-  border-radius: 4px;
-  border: none;
-  font-size: 14px;
-  cursor: pointer;
-  transition: all 0.2s ease;
-}
+  .btn {
+    padding: 0px 15px;
+    margin-left: 10px;
+    border-radius: 4px;
+    border: none;
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.2s ease;
+  }
 
-.btn-preview {
-  background-color: #165dff;
-  color: white;
-}
+  .btn-preview {
+    background-color: #165dff;
+    color: white;
+  }
 
-.btn-preview:hover {
-  background-color: #0d47a1;
-}
+  .btn-preview:hover {
+    background-color: #0d47a1;
+  }
 
-.btn-delete {
-  background-color: #f2f3f5;
-  color: #4e5969;
-}
+  .btn-delete {
+    background-color: #f2f3f5;
+    color: #4e5969;
+  }
 
-.btn-delete:hover {
-  background-color: #e5e6eb;
-  color: #1d2129;
-}
+  .btn-delete:hover {
+    background-color: #e5e6eb;
+    color: #1d2129;
+  }
 </style>

+ 1 - 0
src/components/Application/src/AppProvider.vue

@@ -68,6 +68,7 @@
                 split: menuSplit,
               },
             });
+            // appStore.setModalType();
           }
         }
       }

+ 3 - 3
src/components/Container/src/Adaptive.vue

@@ -125,7 +125,7 @@
         observer = new MutationObserver(onResize);
         observer.observe(dom, {
           attributes: true,
-          attributeFilter: ['style'],
+          // attributeFilter: ['style'],
           attributeOldValue: true,
         });
       };
@@ -146,13 +146,13 @@
         setRem();
         cssSize();
         window.addEventListener('resize', debounce(100, onResize));
-        initMutationObserver();
+        // initMutationObserver();
         ready.value = true;
       });
 
       onUnmounted(() => {
         window.removeEventListener('resize', onResize);
-        removeMutationObserver();
+        // removeMutationObserver();
       });
 
       return {

+ 3 - 5
src/components/vent/micro/needAir.vue

@@ -8,21 +8,19 @@
   import { onMounted, onBeforeUnmount, defineComponent, ref, unref } from 'vue';
   import { unmountMicroApps, mountMicroApp } from '/@/qiankun';
   import { resetMicroContentWH } from '/@/utils/domUtils';
-  import { useRouter } from 'vue-router';
   export default defineComponent({
     name: 'NeedAir',
     setup() {
       const loading = ref(true);
-      const { currentRoute } = useRouter();
       onMounted(() => {
-        mountMicroApp(unref(currentRoute).fullPath);
+        mountMicroApp('micro-need-air');
         resetMicroContentWH('micro-need-air', () => {
           loading.value = false;
         });
       });
 
-      onBeforeUnmount(() => {
-        unmountMicroApps(currentRoute);
+      onBeforeUnmount(async () => {
+        await unmountMicroApps(['micro-need-air']);
       });
 
       return { loading };

+ 4 - 6
src/components/vent/micro/ventDoc.vue

@@ -8,23 +8,21 @@
   import { ref, onMounted, onBeforeUnmount, defineComponent, unref } from 'vue';
   import { unmountMicroApps, mountMicroApp, activeApps } from '/@/qiankun';
   import { resetMicroContentWH } from '/@/utils/domUtils';
-  import { useRouter } from 'vue-router';
 
   export default defineComponent({
-    name: 'VentModel',
+    name: 'VentDoc',
     setup() {
-      const { currentRoute } = useRouter();
       const loading = ref(true);
       onMounted(() => {
         // 判断子应用是否存在,不存在注册
-        mountMicroApp(unref(currentRoute).fullPath);
+        mountMicroApp('micro-vent-doc');
         resetMicroContentWH('micro-vent-doc', () => {
           loading.value = false;
         });
       });
 
-      onBeforeUnmount(() => {
-        unmountMicroApps(['/micro-vent-doc']);
+      onBeforeUnmount(async () => {
+        await unmountMicroApps(['micro-vent-doc']);
       });
 
       return { loading };

+ 5 - 7
src/components/vent/micro/ventModal.vue

@@ -5,26 +5,24 @@
   <div id="micro-vent-3dModal"></div>
 </template>
 <script lang="ts">
-  import { ref, onMounted, onBeforeUnmount, defineComponent, unref } from 'vue';
-  import { unmountMicroApps, mountMicroApp, activeApps } from '/@/qiankun';
+  import { ref, onMounted, onBeforeUnmount, defineComponent } from 'vue';
+  import { unmountMicroApps, mountMicroApp } from '/@/qiankun';
   import { resetMicroContentWH } from '/@/utils/domUtils';
-  import { useRouter } from 'vue-router';
 
   export default defineComponent({
     name: 'VentModel',
     setup() {
-      const { currentRoute } = useRouter();
       const loading = ref(true);
       onMounted(() => {
         // 判断子应用是否存在,不存在注册
-        mountMicroApp(unref(currentRoute).fullPath);
+        mountMicroApp('micro-vent-3dModal', true);
         resetMicroContentWH('micro-vent-3dModal', () => {
           loading.value = false;
         });
       });
 
-      onBeforeUnmount(() => {
-        unmountMicroApps(['/micro-vent-3dModal']);
+      onBeforeUnmount(async () => {
+        await unmountMicroApps(['micro-vent-3dModal']);
       });
 
       return { loading };

+ 7 - 8
src/components/vent/micro/ventModal2D.vue

@@ -5,24 +5,22 @@
   <div id="micro-vent-2dModal"></div>
 </template>
 <script lang="ts">
-  import { onMounted, onBeforeUnmount, defineComponent, ref, unref } from 'vue';
+  import { onMounted, onBeforeUnmount, defineComponent, ref, unref, nextTick } from 'vue';
   import { unmountMicroApps, mountMicroApp } from '/@/qiankun';
   import { resetMicroContentWH } from '/@/utils/domUtils';
-  import { useRouter } from 'vue-router';
   export default defineComponent({
     name: 'Vent2dModal',
     setup() {
       const loading = ref(true);
-      const { currentRoute } = useRouter();
       onMounted(() => {
-        mountMicroApp(unref(currentRoute).fullPath);
+        mountMicroApp('micro-vent-2dModal');
         resetMicroContentWH('micro-vent-2dModal', () => {
           loading.value = false;
         });
       });
 
-      onBeforeUnmount(() => {
-        unmountMicroApps(currentRoute);
+      onBeforeUnmount(async () => {
+        await unmountMicroApps(['micro-vent-2dModal']);
       });
 
       return { loading };
@@ -39,7 +37,8 @@
     height: 100%;
   }
   #micro-vent-2dModal {
-    width: 100vw;
-    height: 100vh;
+    width: 100%;
+    height: 100%;
+    pointer-events: auto;
   }
 </style>

+ 2 - 0
src/enums/cacheEnum.ts

@@ -43,3 +43,5 @@ export enum CacheTypeEnum {
   SESSION,
   LOCAL,
 }
+
+export const MODAL_TYPE = 'MODAL__TYPE';

+ 5 - 5
src/layouts/default/header/components/VoiceBroadcast.vue

@@ -123,11 +123,11 @@
         // let wsClientId = md5(token);
         // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
         let userId = unref(userStore.getUserInfo).id + '?token=' + token;
-        console.log(userStore.getUserInfo,'userId---')
+        console.log(userStore.getUserInfo, 'userId---');
         // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
         // let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
         let url = 'http://' + window.location.hostname + ':9999'?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        console.log(url,'url------')
+        console.log(url, 'url------');
         connectWebSocket(url);
         onWebSocket(onWebSocketMessage);
       }
@@ -183,7 +183,7 @@
 <style lang="less" scoped>
   .btn {
     line-height: 30px;
-    margin-right: 20px;
+    margin-right: 10px;
     cursor: pointer;
     display: flex;
   }
@@ -213,8 +213,8 @@
     height: 350px;
     border-radius: 4px;
     position: fixed;
-    top: 50px;
-    right: 20px;
+    top: 57px;
+    right: 2px;
     background-color: rgb(255, 255, 255);
     background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
     background-size: 100% 100%;

+ 1 - 1
src/layouts/default/header/components/VoiceBroadcastGsd.vue

@@ -153,7 +153,7 @@
 <style lang="less" scoped>
   .btn {
     line-height: 30px;
-    margin-right: 20px;
+    margin-right: 10px;
     cursor: pointer;
     display: flex;
   }

+ 19 - 1
src/layouts/default/header/index.vue

@@ -58,9 +58,13 @@
   <div :class="`${prefixCls}-action`" style="position: fixed; top: 30px; right: 20px; z-index: 999999">
     <div class="right-position">
       <!-- 公司端不显示语音播报功能 weatherBroadcast.vue-->
+      <a-radio-group v-if="hasPermission('show:modalChange')" v-model:value="programModalType" @change="changeModalType" style="display: flex">
+        <a-radio :value="true">2.5D</a-radio>
+        <a-radio :value="false">3D</a-radio>
+      </a-radio-group>
       <WeatherBroadcast v-if="sysOrgCode != 'sdmtjtgsd' && isShowQy && portValue != '8062'" />
       <VoiceBroadcast v-if="sysOrgCode != 'sdmtjtgsd' && portValue != '8062'" />
-      <AIChat v-if="hasPermission('show:AIChat')"></AIChat>
+      <AIChat v-if="hasPermission('show:AIChat')" />
       <VoiceBroadcastGsd v-if="sysOrgCode == 'sdmtjtgsd'" />
       <UserDropDown v-if="showUserDropdown" :theme="getHeaderTheme" />
       <LoginSelect ref="loginSelectRef" @success="loginSelectOk" />
@@ -93,6 +97,7 @@
 
   import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
   import { useLocale } from '/@/locales/useLocale';
+  import { Persistent } from '/@/utils/cache/persistent';
 
   import WeatherBroadcast from './components/weatherBroadcast.vue';
   import VoiceBroadcast from './components/VoiceBroadcast.vue';
@@ -105,6 +110,8 @@
 
   import { noHeadeLink } from '../layout.data';
   import { usePermission } from '/@/hooks/web/usePermission';
+  import { useAppStore } from '/@/store/modules/app';
+  import { router } from '/@/router';
 
   export default defineComponent({
     name: 'LayoutHeader',
@@ -206,6 +213,9 @@
         return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null;
       });
 
+      const appStore = useAppStore();
+      const programModalType = ref(appStore.getProgramModalType);
+
       // /**
       //  * 首页多租户部门弹窗逻辑
       //  */
@@ -232,6 +242,12 @@
         return window.self === window.top;
       });
 
+      const changeModalType = (e) => {
+        appStore.setModalType(e.target['value']);
+        programModalType.value = e.target['value'];
+        window.location.reload();
+      };
+
       onMounted(() => {
         showLoginSelect();
       });
@@ -272,6 +288,8 @@
         homePath,
         hasPermission,
         isShowQy,
+        programModalType,
+        changeModalType,
       };
     },
   });

+ 1 - 1
src/layouts/default/setting/handler.ts

@@ -21,7 +21,7 @@ export function baseHandler(event: HandlerEnum, value: any) {
 
 export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
   const appStore = useAppStore();
-
+  // appStore.setModalType();
   const { getThemeColor, getDarkMode } = useRootSetting();
   switch (event) {
     case HandlerEnum.CHANGE_LAYOUT:

+ 5 - 16
src/layouts/default/sider/bottomSideder.vue

@@ -70,6 +70,7 @@
   import { unmountMicroApps } from '/@/qiankun';
   import { useUserStoreWithOut } from '/@/store/modules/user';
   import { useAppStore } from '/@/store/modules/app';
+  import { router } from '/@/router';
 
   export default defineComponent({
     name: 'BottomSider',
@@ -86,7 +87,7 @@
       const userStore = useUserStoreWithOut();
       // const appStore = useAppStore();
       // const themeIcon = appStore.getDarkMode;
-        const themeIcon=ref('styleTwo')
+      const themeIcon = ref('styleTwo');
 
       function selectMenu(e: Event, programMenu) {
         e.stopPropagation();
@@ -115,8 +116,9 @@
           return;
         }
         // if (currentRoute.value.path.startsWith('/micro')) {
-        //   go(path.path);
-        //   // window.history.pushState({}, '', path.path);
+        //   router.replace(path.path);
+        //   // go(path.path);
+        //   window.history.pushState({}, '', path.path);
         // } else {
         //   go(path.path);
         // }
@@ -130,19 +132,6 @@
           go(userStore.getUserInfo.homePath);
         } else if (currentRoute.value.path.startsWith('/micro-need-air')) {
           window.history.pushState({}, '', glob.homePath || PageEnum.BASE_HOME);
-          // if (currentRoute.value.path.startsWith('/micro-vent-3dModal/dashboard/analysis')) {
-          //   if (glob.homePath == '/micro-vent-3dModal/dashboard/analysis' || PageEnum.BASE_HOME == '/micro-vent-3dModal/dashboard/analysis') {
-          //     actions.setGlobalState({ pageObj: { pageType: 'home' } });
-          //     go(glob.homePath || PageEnum.BASE_HOME);
-          //   }
-          // } else {
-          //   if (glob.homePath == '/model3D/home' || PageEnum.BASE_HOME == '/model3D/home') {
-          //     go(glob.homePath || PageEnum.BASE_HOME);
-          //     // location.reload()
-          //   }
-
-          //   go(glob.homePath || PageEnum.BASE_HOME);
-          // }
         } else {
           go(glob.homePath || PageEnum.BASE_HOME);
         }

+ 1 - 0
src/logics/theme/updateBackground.ts

@@ -25,6 +25,7 @@ export function updateHeaderBgColor(color?: string) {
       theme: appStore.getDarkMode as ThemeEnum,
     },
   });
+  appStore.setModalType();
 
   // if theme is not default, set the colors in /design/colors or /design/themify/
   if (!color) {

+ 4 - 2
src/main.ts

@@ -1,9 +1,9 @@
 import 'uno.css';
 import '/@/design/index.less';
-import animate from 'animate.css';
 //lxh
 import './assets/iconfong/iconfont.css';
 import './assets/iconfong/iconfont.js';
+import animate from 'animate.css';
 
 // 注册图标
 import 'virtual:svg-icons-register';
@@ -23,6 +23,7 @@ import { registerThirdComp } from '/@/settings/registerThirdComp';
 // import { registerPackages } from '/@/utils/monorepo/registerPackages';
 import { initModalWorker, initTHREE } from '/@/utils/threejs/main.worker';
 import GlobalConfig from './components/config/GlobalConfig.vue';
+import { MODAL_TYPE } from '/@/enums/cacheEnum';
 
 // 在本地开发中引入的,以提高浏览器响应速度
 if (import.meta.env.DEV) {
@@ -74,13 +75,14 @@ async function bootstrap() {
   initTHREE();
 
   app.component('GlobalConfig', GlobalConfig);
+  debugger;
   app.provide('globalConfig', {
     // 你的全局配置
     simulatedPassword: VENT_PARAM['simulatedPassword'],
     History_Type: History_Type['type'],
     pageType: '',
     showReport: VENT_PARAM['showReport'],
-    is2DModel: VENT_PARAM['is2DModel'],
+    is2DModel: localStorage.getItem(MODAL_TYPE) == 'false' ? false : true,
   });
 
   // 挂载应用

+ 1 - 0
src/qiankun/apps.ts

@@ -30,6 +30,7 @@ for (const key in import.meta.env) {
         container: `#${app[0]}`,
         activeRule: app[0],
       };
+      // debugger;
 
       _apps.push(obj);
     });

+ 14 - 42
src/qiankun/index.ts

@@ -1,7 +1,7 @@
 /**
  * qiankun配置
  */
-import { loadMicroApp } from 'qiankun';
+import { loadMicroApp, start } from 'qiankun';
 import { apps } from './apps';
 import { getProps } from './state';
 
@@ -13,7 +13,6 @@ function filterApps() {
   apps.forEach((item) => {
     //主应用需要传递给微应用的数据。
     item['props'] = getProps();
-    console.log('主应用给子应用传的数据', item.props);
 
     //微应用触发的路由规则
     // @ts-ignore
@@ -22,56 +21,29 @@ function filterApps() {
   return apps;
 }
 
-const mountMicroApp = (path, toPath?) => {
+const mountMicroApp = (name, isReFresh = false) => {
   const microApps = filterApps();
-  const app = microApps.find((item) => path.startsWith(item['activeRule']));
+  const app = microApps.find((item) => item.name === name);
   if (app) {
-    if (activeApps[app['activeRule']]) {
-      // return;
-      activeApps[app['activeRule']].unmount();
-      activeApps[app['activeRule']] = null;
-      delete activeApps[app['activeRule']];
-    }
-    // debugger;
-    const instance = activeApps[app['activeRule']];
-    console.log('子应用实例--------------->', instance);
-    if (instance) {
-      instance.update();
+    const instance = activeApps[app.name];
+    if (instance && instance.getStatus() === 'NOT_MOUNTED' && !isReFresh) {
+      instance.mount(app);
     } else {
-      if (toPath) {
-        app['props']['data']['publicPath'] = toPath;
-      }
-      activeApps[app['activeRule']] = loadMicroApp(app, {
-        fetch(url, ...args) {
-          // 给指定的微应用 entry 开启跨域请求
-          if (url === 'http://1.1.1.3:89/cookie/flash.js') {
-            return window.fetch(url, {
-              ...args,
-              headers: {
-                'Access-Control-Allow-Origin': '*',
-                'Content-Type': 'text/plain',
-              },
-              mode: 'cors',
-              credentials: 'include',
-            });
-          }
-          return window.fetch(url, ...args);
-        },
-      }); // 手动加载子应用
+      delete activeApps[app.name];
+      activeApps[app.name] = loadMicroApp(app, { autoStart: false, sandbox: { strictStyleIsolation: false } }); // 手动加载子应用'
     }
   }
 };
 
 // 卸载app的方法
-const unmountMicroApps = (multipleApp) => {
+const unmountMicroApps = async (multipleApp) => {
   if (JSON.stringify(activeApps) !== '{}' && multipleApp.some) {
     for (const key in activeApps) {
-      const isExist = multipleApp.some((name) => name == key);
-      if (isExist) {
-        activeApps[key].unmount();
-        activeApps[key] = null;
-        delete activeApps[key];
-      }
+      multipleApp.filter(async (name) => {
+        if (name.includes(key)) {
+          await activeApps[key].unmount();
+        }
+      });
     }
   }
 };

+ 1 - 0
src/qiankun/state.ts

@@ -18,6 +18,7 @@ export function getProps() {
       router,
       isMounted: false,
     },
+    actions: getActions(),
   };
 }
 

+ 10 - 6
src/router/guard/index.ts

@@ -39,20 +39,24 @@ RootRoute.redirect = glob.homePath || PageEnum.BASE_HOME;
 function createPageGuard(router: Router) {
   const loadedPageMap = new Map<string, boolean>();
   router.beforeEach(async (to, from) => {
-    if (from.path.startsWith('/micro-') && !to.path.startsWith('/micro-')) {
-      unmountMicroApps(['/' + from.path.split('/')[1]]);
-    } else if (from.path.startsWith('/micro-') && to.path.startsWith('/micro-') && from.path.split('/')[1] != to.path.split('/')[1]) {
-      unmountMicroApps(['/' + from.path.split('/')[1]]);
-    }
+    // if (from.path.startsWith('/micro-') && !to.path.startsWith('/micro-')) {
+    //   await unmountMicroApps([from.path.split('/')[1]]);
+    // } else if (from.path.startsWith('/micro-') && to.path.startsWith('/micro-') && from.path.split('/')[1] != to.path.split('/')[1]) {
+    //   await unmountMicroApps([from.path.split('/')[1]]);
+    // }
     // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
     to.meta.loaded = !!loadedPageMap.get(to.path);
+
     // Notify routing changes
     setRouteChange(to);
 
     return true;
   });
 
-  router.afterEach((to) => {
+  router.afterEach(async (to, from) => {
+    // debugger;
+    // history.replaceState({ ...history.state, current: to.path }, '', '');
+
     loadedPageMap.set(to.path, true);
   });
 }

+ 19 - 0
src/router/guard/permissionGuard.ts

@@ -19,6 +19,7 @@ import { MOCK_LOGIN_URL_QUERY, SKIP_SSO_URL_QUERY } from '../constant';
 import { useSso } from '/@/hooks/web/useSso';
 import { useAutoLogin } from '/@/hooks/vent/useAutoLogin';
 import { addBrowseLog } from '@/router/helper/menuHelper';
+import { string } from 'vue-types';
 
 const LOGIN_PATH = PageEnum.BASE_LOGIN;
 //auth2登录路由
@@ -45,6 +46,21 @@ export function createPermissionGuard(router: Router) {
   const { doAutoLogin, doTokenLogin, validateRoute, tokenValidateRoute } = useAutoLogin();
   router.beforeEach(async (to, from, next) => {
     RootRoute.redirect = glob.homePath || PageEnum.BASE_HOME;
+    if (to.query['isNoReverse'] != '1') {
+      if (VENT_PARAM['is2DModel']) {
+        for (const key in to) {
+          if (typeof to[key] == 'string' && to[key].includes('micro-vent-3dModal')) {
+            to[key] = to[key].replace('micro-vent-3dModal', 'micro-vent-2dModal');
+          }
+        }
+      } else {
+        for (const key in to) {
+          if (typeof to[key] == 'string' && to[key].includes('micro-vent-2dModal')) {
+            to[key] = to[key].replace('micro-vent-2dModal', 'micro-vent-3dModal');
+          }
+        }
+      }
+    }
 
     if (_.isEmpty(history.state.current)) {
       _.assign(history.state, { current: from.fullPath });
@@ -278,6 +294,9 @@ export function createPermissionGuard(router: Router) {
 
   router.afterEach((to, from) => {
     addBrowseLog(to, from, [...whitePathList, PAGE_NOT_FOUND_ROUTE.path]);
+    if (to.path.startsWith('micro-')) {
+      window.history.pushState({}, '', to.fullPath);
+    }
   });
 
   window.addEventListener(

+ 33 - 0
src/router/routes/basic.ts

@@ -75,6 +75,17 @@ export const QIANKUN_ROUTE: AppRouteRecordRaw = {
       },
       ver: '1',
     },
+    {
+      path: '/micro-vent-2dModal/gas/home',
+      name: '2dModal-gas-home',
+      component: () => import('/@/views/vent/gas/gasHome/index.vue'),
+      meta: {
+        title: '抽采综合管控',
+        hideBreadcrumb: true,
+        hideMenu: true,
+      },
+      ver: '1',
+    },
     {
       path: '/micro-vent-3dModal/modelchannel/model3D/home',
       name: 'micro-vent-3dModal-modelchannel-model3D-home',
@@ -97,6 +108,17 @@ export const QIANKUN_ROUTE: AppRouteRecordRaw = {
       },
       ver: '1',
     },
+    {
+      path: '/micro-vent-2dModal/gas-pipe-net/home',
+      name: '2dModal-gas-pipe-net-home',
+      component: () => import('/@/views/vent/gas/gasPipeNet/index.vue'),
+      meta: {
+        title: '瓦斯管网监测',
+        hideBreadcrumb: true,
+        hideMenu: true,
+      },
+      ver: '1',
+    },
     {
       path: '/micro-vent-3dModal/dashboard/analysis',
       name: 'micro-vent-3dModal-dashboard-analysis',
@@ -108,6 +130,17 @@ export const QIANKUN_ROUTE: AppRouteRecordRaw = {
       },
       ver: '1',
     },
+    {
+      path: '/micro-vent-2dModal/dashboard/analysis',
+      name: 'micro-vent-2dModal-dashboard-analysis',
+      component: () => import('/@/views/vent/monitorManager/deviceMonitor/index.vue'),
+      meta: {
+        title: '通防综合管控',
+        hideBreadcrumb: true,
+        hideMenu: true,
+      },
+      ver: '1',
+    },
     {
       path: '/micro-need-air/:path(.*)*',
       name: 'micro-need-air',

+ 17 - 1
src/store/modules/app.ts

@@ -5,7 +5,7 @@ import { defineStore } from 'pinia';
 import { store } from '/@/store';
 
 import { ThemeEnum } from '/@/enums/appEnum';
-import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum';
+import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY, MODAL_TYPE } from '/@/enums/cacheEnum';
 import { Persistent } from '/@/utils/cache/persistent';
 import { darkMode } from '/@/settings/designSetting';
 import { resetRouter } from '/@/router';
@@ -75,6 +75,10 @@ export const useAppStore = defineStore({
     getHeightScale(): number {
       return this.heightScale;
     },
+    getProgramModalType(): boolean | null {
+      VENT_PARAM['is2DModel'] = localStorage.getItem(MODAL_TYPE) == 'false' ? false : true;
+      return VENT_PARAM['is2DModel'];
+    },
   },
   actions: {
     setPageLoading(loading: boolean): void {
@@ -95,6 +99,18 @@ export const useAppStore = defineStore({
       Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig);
     },
 
+    setModalType(is2DModel?): void {
+      if (is2DModel === undefined) {
+        if (localStorage.getItem(MODAL_TYPE)) {
+          VENT_PARAM['is2DModel'] = localStorage.getItem(MODAL_TYPE) == 'false' ? false : true;
+        } else {
+          localStorage.setItem(MODAL_TYPE, VENT_PARAM['is2DModel']);
+        }
+      } else {
+        localStorage.setItem(MODAL_TYPE, is2DModel);
+      }
+    },
+
     async resetAllState() {
       resetRouter();
       Persistent.clearAll();

+ 2 - 0
src/utils/cache/persistent.ts

@@ -18,6 +18,7 @@ import {
   LOGIN_INFO_KEY,
   OAUTH2_THIRD_LOGIN_TENANT_ID,
   PWD_KEY,
+  MODAL_TYPE,
 } from '/@/enums/cacheEnum';
 import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting';
 import { toRaw } from 'vue';
@@ -35,6 +36,7 @@ interface BasicStore {
   [TENANT_ID]: string;
   [LOGIN_INFO_KEY]: LoginInfo;
   [OAUTH2_THIRD_LOGIN_TENANT_ID]: string;
+  [MODAL_TYPE]: string;
 }
 
 type LocalStore = BasicStore;

+ 2 - 2
src/views/vent/gas/gasHome/index.vue

@@ -89,8 +89,8 @@
     dataSource.value = await gasSystem();
   });
   onMounted(() => {});
-  onBeforeUnmount(() => {
-    unmountMicroApps(['/micro-vent-3dModal']);
+  onBeforeUnmount(async () => {
+    await unmountMicroApps(['/micro-vent-3dModal']);
   });
 </script>
 

+ 241 - 235
src/views/vent/home/clique/components/icon-light.vue

@@ -1,178 +1,194 @@
 <template>
   <div class="icon-light">
     <template v-for="(item, index) in pointList" :key="index">
-      <div class="icon-point" @click="openModal(item.code, item.label, item.leftV, item.topV)"
-        :style="{ left: item.leftV, top: item.topV }">
+      <div class="icon-point" @click="openModal(item.code, item.label, item.leftV, item.topV)" :style="{ left: item.leftV, top: item.topV }">
         <img :src="item.imgSrc" alt="" />
         <span
-          :class="{ 'icon-text-c': item.align == 'center', 'icon-text-l': item.align == 'left', 'icon-text-r': item.align == 'right', 'icon-text-b': item.align == 'bottom' }"
-          :style="{ color: item.textColor }">{{ item.label }}</span>
+          :class="{
+            'icon-text-c': item.align == 'center',
+            'icon-text-l': item.align == 'left',
+            'icon-text-r': item.align == 'right',
+            'icon-text-b': item.align == 'bottom',
+          }"
+          :style="{ color: item.textColor }"
+          >{{ item.label }}</span
+        >
       </div>
     </template>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, defineEmits, inject, watch, nextTick } from 'vue';
-import { getAssetURL } from '/@/utils/ui';
+  import { ref, defineEmits, inject, watch, nextTick } from 'vue';
+  import { getAssetURL } from '/@/utils/ui';
 
-const emit = defineEmits(['showDetail']);
-const globalConfig = inject('globalConfig');
-let props = defineProps({
-  warningList: {
-    type: Array,
-    default: () => {
-      return [];
-    },
-  },
-});
-// const iconWarningList = ref([]);
-const warningLevel1 = getAssetURL('company/home/point1.png'); // 低风险
-const warningLevel2 = getAssetURL('company/home/point2.png'); // 中风险
-const warningLevel3 = getAssetURL('company/home/point3.png'); // 高风险
-const warningLevel4 = getAssetURL('company/home/point4.png'); // 报警
-let pointList = ref<any[]>(
-  globalConfig.History_Type == ''
-    ? [
-      { code: 'sdmtjtltmk', imgSrc: warningLevel1, label: 'lt', leftV: '327px', topV: '40px', textColor: '#fff', align: 'left' },
-      { code: 'sdmtjtcctrk', imgSrc: warningLevel1, label: 'cce', leftV: '291px', topV: '69px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtbetmk',
-        imgSrc: warningLevel1,
-        label: 'bet',
-        leftV: '286px',
-        topV: '97px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtwlmlmk', imgSrc: warningLevel1, label: 'wlml', leftV: '327px', topV: '115px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtcctmk',
-        imgSrc: warningLevel1,
-        label: 'cc',
-        leftV: '346px',
-        topV: '132px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtsgtmk', imgSrc: warningLevel1, label: 'skt', leftV: '373px', topV: '149px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtbltmk',
-        imgSrc: warningLevel1,
-        label: 'blt',
-        leftV: '408px',
-        topV: '184px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjthlgmk', imgSrc: warningLevel1, label: 'hlg', leftV: '445px', topV: '214px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtswmk',
-        imgSrc: warningLevel1,
-        label: 'sw',
-        leftV: '439px',
-        topV: '244px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtdltmkhjtj', imgSrc: warningLevel1, label: 'hjt', leftV: '398px', topV: '265px', textColor: '#fff', align: 'left' },
-      { code: 'sdmtjtdltmk', imgSrc: warningLevel1, label: 'dlt', leftV: '492px', topV: '260px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtjjmk',
-        imgSrc: warningLevel1,
-        label: 'jj',
-        leftV: '565px',
-        topV: '413px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtyjlmk', imgSrc: warningLevel1, label: 'yjl', leftV: '669px', topV: '308px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtbdmk',
-        imgSrc: warningLevel1,
-        label: 'bd',
-        leftV: '862px',
-        topV: '340px',
-        textColor: '#fff',
-        align: 'left',
-      },
-    ]
-    : [
-      { code: 'sdmtjtltmk', imgSrc: warningLevel1, label: '柳塔矿', leftV: '405px', topV: '165px', textColor: '#fff', align: 'right' },
-      { code: 'sdmtjtcctrk', imgSrc: warningLevel1, label: '寸草塔二矿', leftV: '269px', topV: '116px', textColor: '#fff', align: 'left' },
-      {
-        code: 'sdmtjtbetmk',
-        imgSrc: warningLevel1,
-        label: '布尔台矿',
-        leftV: '329px',
-        topV: '177px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtwlmlmk', imgSrc: warningLevel4, label: '乌兰木伦矿', leftV: '462px', topV: '210px', textColor: '#fff', align: 'right' },
-      {
-        code: 'sdmtjtcctmk',
-        imgSrc: warningLevel1,
-        label: '寸草塔矿',
-        leftV: '396px',
-        topV: '224px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtsgtmk', imgSrc: warningLevel1, label: '石圪台矿', leftV: '514px', topV: '250px', textColor: '#fff', align: 'bottom' },
-      {
-        code: 'sdmtjtbltmk',
-        imgSrc: warningLevel1,
-        label: '补连塔矿',
-        leftV: '432px',
-        topV: '282px',
-        textColor: '#fff',
-        align: 'left',
+  const emit = defineEmits(['showDetail']);
+  const globalConfig = inject('globalConfig');
+  let props = defineProps({
+    warningList: {
+      type: Array,
+      default: () => {
+        return [];
       },
-      { code: 'sdmtjthlgmk', imgSrc: warningLevel1, label: '哈拉沟矿', leftV: '641px', topV: '258px', textColor: '#fff', align: 'bottom' },
-      {
-        code: 'sdmtjtswmk',
-        imgSrc: warningLevel3,
-        label: '上湾矿',
-        leftV: '381px',
-        topV: '334px',
-        textColor: '#fff',
-        align: 'left',
-      },
-      { code: 'sdmtjtdltmkhjtj', imgSrc: warningLevel1, label: '活鸡兔井', leftV: '598px', topV: '368px', textColor: '#fff', align: 'bottom' },
-      { code: 'sdmtjtdltmk', imgSrc: warningLevel2, label: '大柳塔井', leftV: '598px', topV: '308px', textColor: '#fff', align: 'bottom' },
-      {
-        code: 'sdmtjtjjmk',
-        imgSrc: warningLevel1,
-        label: '锦界矿',
-        leftV: '575px',
-        topV: '460px',
-        textColor: '#fff',
-        align: 'bottom',
-      },
-      { code: 'sdmtjtyjlmk', imgSrc: warningLevel1, label: '榆家梁矿', leftV: '748px', topV: '370px', textColor: '#fff', align: 'center' },
-      {
-        code: 'sdmtjtbdmk',
-        imgSrc: warningLevel1,
-        label: '保德矿',
-        leftV: '892px',
-        topV: '200px',
-        textColor: '#fff',
-        align: 'center',
-      },
-    ]
-);
-function openModal(code, label, leftV, topV) {
-  emit('showDetail', code, label, leftV, topV);
-}
-watch(
-  () => props.warningList,
-  (newVal: any, oldVal: any) => {
-    let newPointList;
-    if (newVal && oldVal && newVal.length == oldVal.length) {
-      for (let i = 0; i < newVal.length; i++) {
-        if (newVal[i].isWarning !== oldVal[i].isWarning) {
-          if (!newPointList) newPointList = [...pointList.value];
+    },
+  });
+  // const iconWarningList = ref([]);
+  const warningLevel1 = getAssetURL('company/home/point1.png'); // 低风险
+  const warningLevel2 = getAssetURL('company/home/point2.png'); // 中风险
+  const warningLevel3 = getAssetURL('company/home/point3.png'); // 高风险
+  const warningLevel4 = getAssetURL('company/home/point4.png'); // 报警
+  let pointList = ref<any[]>(
+    globalConfig.History_Type == ''
+      ? [
+          { code: 'sdmtjtltmk', imgSrc: warningLevel1, label: 'lt', leftV: '327px', topV: '40px', textColor: '#fff', align: 'left' },
+          { code: 'sdmtjtcctrk', imgSrc: warningLevel1, label: 'cce', leftV: '291px', topV: '69px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtbetmk',
+            imgSrc: warningLevel1,
+            label: 'bet',
+            leftV: '286px',
+            topV: '97px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtwlmlmk', imgSrc: warningLevel1, label: 'wlml', leftV: '327px', topV: '115px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtcctmk',
+            imgSrc: warningLevel1,
+            label: 'cc',
+            leftV: '346px',
+            topV: '132px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtsgtmk', imgSrc: warningLevel1, label: 'skt', leftV: '373px', topV: '149px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtbltmk',
+            imgSrc: warningLevel1,
+            label: 'blt',
+            leftV: '408px',
+            topV: '184px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjthlgmk', imgSrc: warningLevel1, label: 'hlg', leftV: '445px', topV: '214px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtswmk',
+            imgSrc: warningLevel1,
+            label: 'sw',
+            leftV: '439px',
+            topV: '244px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtdltmkhjtj', imgSrc: warningLevel1, label: 'hjt', leftV: '398px', topV: '265px', textColor: '#fff', align: 'left' },
+          { code: 'sdmtjtdltmk', imgSrc: warningLevel1, label: 'dlt', leftV: '492px', topV: '260px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtjjmk',
+            imgSrc: warningLevel1,
+            label: 'jj',
+            leftV: '565px',
+            topV: '413px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtyjlmk', imgSrc: warningLevel1, label: 'yjl', leftV: '669px', topV: '308px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtbdmk',
+            imgSrc: warningLevel1,
+            label: 'bd',
+            leftV: '862px',
+            topV: '340px',
+            textColor: '#fff',
+            align: 'left',
+          },
+        ]
+      : [
+          { code: 'sdmtjtltmk', imgSrc: warningLevel1, label: '柳塔矿', leftV: '405px', topV: '165px', textColor: '#fff', align: 'right' },
+          { code: 'sdmtjtcctrk', imgSrc: warningLevel1, label: '寸草塔二矿', leftV: '269px', topV: '116px', textColor: '#fff', align: 'left' },
+          {
+            code: 'sdmtjtbetmk',
+            imgSrc: warningLevel1,
+            label: '布尔台矿',
+            leftV: '329px',
+            topV: '177px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtwlmlmk', imgSrc: warningLevel4, label: '乌兰木伦矿', leftV: '462px', topV: '210px', textColor: '#fff', align: 'right' },
+          {
+            code: 'sdmtjtcctmk',
+            imgSrc: warningLevel1,
+            label: '寸草塔矿',
+            leftV: '396px',
+            topV: '224px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtsgtmk', imgSrc: warningLevel1, label: '石圪台矿', leftV: '514px', topV: '250px', textColor: '#fff', align: 'bottom' },
+          {
+            code: 'sdmtjtbltmk',
+            imgSrc: warningLevel1,
+            label: '补连塔矿',
+            leftV: '432px',
+            topV: '282px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjthlgmk', imgSrc: warningLevel1, label: '哈拉沟矿', leftV: '641px', topV: '258px', textColor: '#fff', align: 'bottom' },
+          {
+            code: 'sdmtjtswmk',
+            imgSrc: warningLevel3,
+            label: '上湾矿',
+            leftV: '381px',
+            topV: '334px',
+            textColor: '#fff',
+            align: 'left',
+          },
+          { code: 'sdmtjtdltmkhjtj', imgSrc: warningLevel1, label: '活鸡兔井', leftV: '598px', topV: '368px', textColor: '#fff', align: 'bottom' },
+          { code: 'sdmtjtdltmk', imgSrc: warningLevel2, label: '大柳塔井', leftV: '598px', topV: '308px', textColor: '#fff', align: 'bottom' },
+          {
+            code: 'sdmtjtjjmk',
+            imgSrc: warningLevel1,
+            label: '锦界矿',
+            leftV: '575px',
+            topV: '460px',
+            textColor: '#fff',
+            align: 'bottom',
+          },
+          { code: 'sdmtjtyjlmk', imgSrc: warningLevel1, label: '榆家梁矿', leftV: '748px', topV: '370px', textColor: '#fff', align: 'center' },
+          {
+            code: 'sdmtjtbdmk',
+            imgSrc: warningLevel1,
+            label: '保德矿',
+            leftV: '892px',
+            topV: '200px',
+            textColor: '#fff',
+            align: 'center',
+          },
+        ]
+  );
+  function openModal(code, label, leftV, topV) {
+    emit('showDetail', code, label, leftV, topV);
+  }
+  watch(
+    () => props.warningList,
+    (newVal: any, oldVal: any) => {
+      let newPointList;
+      if (newVal && oldVal && newVal.length == oldVal.length) {
+        for (let i = 0; i < newVal.length; i++) {
+          if (newVal[i].isWarning !== oldVal[i].isWarning) {
+            if (!newPointList) newPointList = [...pointList.value];
+            const index = (newPointList as []).findIndex((item) => item['code'] === newVal[i]['orgcode']);
+            // newPointList[index]['imgSrc'] = newVal[i].isWarning ? warningLevel4 : warningLevel1;
+            newPointList[index]['imgSrc'] = warningLevel1;
+            // newPointList[index]['textColor'] = newVal[i].isWarning ? '#ff5e00' : '#fff';
+            newPointList[index]['textColor'] = '#fff';
+          }
+        }
+      } else {
+        newPointList = [...pointList.value];
+        for (let i = 0; i < newVal.length; i++) {
           const index = (newPointList as []).findIndex((item) => item['code'] === newVal[i]['orgcode']);
           // newPointList[index]['imgSrc'] = newVal[i].isWarning ? warningLevel4 : warningLevel1;
           newPointList[index]['imgSrc'] = warningLevel1;
@@ -180,91 +196,81 @@ watch(
           newPointList[index]['textColor'] = '#fff';
         }
       }
-    } else {
-      newPointList = [...pointList.value];
-      for (let i = 0; i < newVal.length; i++) {
-        const index = (newPointList as []).findIndex((item) => item['code'] === newVal[i]['orgcode']);
-        // newPointList[index]['imgSrc'] = newVal[i].isWarning ? warningLevel4 : warningLevel1;
-        newPointList[index]['imgSrc'] = warningLevel1;
-        // newPointList[index]['textColor'] = newVal[i].isWarning ? '#ff5e00' : '#fff';
-        newPointList[index]['textColor'] = '#fff';
+      if (newPointList) {
+        pointList.value = newPointList;
       }
     }
-    if (newPointList) {
-      pointList.value = newPointList;
-    }
-  }
-);
+  );
 </script>
 
 <style lang="less" scoped>
-.icon-light {
-  position: relative;
-  width: 100%;
-  height: 100%;
+  .icon-light {
+    position: relative;
+    width: 100%;
+    height: 100%;
 
-  .icon-point {
-    display: flex;
-    align-items: center;
-    position: absolute;
+    .icon-point {
+      display: flex;
+      align-items: center;
+      position: absolute;
 
-    img {
-      width: 35px;
-      height: 35px;
-      cursor: pointer;
-    }
+      img {
+        width: 35px;
+        height: 35px;
+        cursor: pointer;
+      }
 
-    span {
-      font-size: 12px;
-      padding: 0px 5px;
-      color: #ffffff;
-      // background-color: rgba(12, 13, 13);
-    }
+      span {
+        font-size: 12px;
+        padding: 0px 5px;
+        color: #ffffff;
+        // background-color: rgba(12, 13, 13);
+      }
 
-    .icon-text-l {
-      position: absolute;
-      font-size: 12px;
-      padding: 0px 5px;
-      // background-color: rgba(12, 13, 13);
-      display: block;
-      width: 100px;
-      text-align: center;
-      // top: -20px;
-      left: -75px;
-    }
+      .icon-text-l {
+        position: absolute;
+        font-size: 12px;
+        padding: 0px 5px;
+        // background-color: rgba(12, 13, 13);
+        display: block;
+        width: 100px;
+        text-align: center;
+        // top: -20px;
+        left: -75px;
+      }
 
-    .icon-text-r {
-      position: absolute;
-      font-size: 12px;
-      padding: 0px 5px;
-      display: block;
-      width: 100px;
-      text-align: center;
-      // top: -20px;
-      left: 12px;
-    }
+      .icon-text-r {
+        position: absolute;
+        font-size: 12px;
+        padding: 0px 5px;
+        display: block;
+        width: 100px;
+        text-align: center;
+        // top: -20px;
+        left: 12px;
+      }
 
-    .icon-text-c {
-      position: absolute;
-      font-size: 12px;
-      padding: 0px 5px;
-      display: block;
-      width: 60px;
-      text-align: center;
-      top: -20px;
-      left: -12px;
-    }
+      .icon-text-c {
+        position: absolute;
+        font-size: 12px;
+        padding: 0px 5px;
+        display: block;
+        width: 60px;
+        text-align: center;
+        top: -20px;
+        left: -12px;
+      }
 
-    .icon-text-b {
-      position: absolute;
-      font-size: 12px;
-      padding: 0px 5px;
-      display: block;
-      width: 100px;
-      text-align: center;
-      left: -28px;
-      bottom: -20px;
+      .icon-text-b {
+        position: absolute;
+        font-size: 12px;
+        padding: 0px 5px;
+        display: block;
+        width: 100px;
+        text-align: center;
+        left: -28px;
+        bottom: -20px;
+      }
     }
   }
-}
 </style>

+ 3 - 5
src/views/vent/home/colliery/index.vue

@@ -49,10 +49,7 @@
               <!-- <div class="btn-icon" @click="goModalDetail"></div> -->
               <!-- 展会不显示按钮 -->
               <div v-if="sysOrgCode !== 'mkyzhpt'" class="btn-icon" @click="goModalDetail"></div>
-              <VentModal
-                ref="centerModalRef"
-                style="width: calc(100% - 30px); height: calc(100% - 30px); position: absolute; background-color: #fff"
-              />
+              <SubApp ref="centerModalRef" style="width: calc(100% - 30px); height: calc(100% - 40px); position: absolute; background-color: #fff" />
             </div>
           </div>
           <!-- 风量监测 -->
@@ -110,7 +107,7 @@
   import { getActions } from '/@/qiankun/state';
   import { unmountMicroApps, mountMicroApp } from '/@/qiankun';
   import { getDate } from './clique.data';
-  import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import SubApp from '/@/components/vent/micro/createSubApp.vue';
   import { usePermission } from '/@/hooks/web/usePermission';
 
   const { currentRoute } = useRouter();
@@ -290,6 +287,7 @@
   }
 
   const changePageType = (pageType) => {
+    debugger;
     actions.setGlobalState({ pageObj: { pageType: pageType } });
   };
 

+ 3 - 0
src/views/vent/home/configurable/components/MonitorBar.vue

@@ -123,6 +123,9 @@
   });
 </script>
 <style lang="less" scoped>
+  .midback-info {
+    pointer-events: none;
+  }
   .middata {
     // margin-top: 7px;
     padding: 5px 0px 5px 60px;

+ 81 - 21
src/views/vent/home/configurable/vent182.vue

@@ -2,7 +2,7 @@
 <template>
   <div class="company-home">
     <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
-      <VentModal />
+      <SubApp />
     </div>
     <!-- 如果是有 deviceType、type 等 query,认为是详情页,不需要展示普通模块,只需要模型 -->
     <template v-if="!route.query.deviceType">
@@ -71,7 +71,8 @@
         class="switch-button report-mode right-525px"
         @click="switchDataMode"
       ></div>
-      <div class="switch-button icon-goto right-475px" @click="goMicroApp()"></div>
+      <div class="switch-button icon-goto2D right-455px" @click="goMicroApp('2.5')"></div>
+      <div class="switch-button icon-goto3D right-515px" @click="goMicroApp('3')"></div>
     </template>
   </div>
 </template>
@@ -86,7 +87,7 @@
   import ModuleOriginal from './components/ModuleOriginal.vue';
   import ModuleCommon from './components/ModuleCommon.vue';
   // import { useRoute } from 'vue-router';
-  import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import SubApp from '/@/components/vent/micro/createSubApp.vue';
   import { list } from './configurable.api';
   import { useRoute, useRouter } from 'vue-router';
   import { useGlobSetting } from '/@/hooks/setting';
@@ -123,15 +124,28 @@
     }, 60000);
   }
 
-  function goMicroApp() {
-    router.push({
-      path: route.path,
-      query: {
-        ...route.query,
-        type: 'model3D',
-        deviceType: 'model3D',
-      },
-    });
+  function goMicroApp(flag: string) {
+    if (flag === '3') {
+      router.push({
+        path: route.path.includes('micro-vent-3dModal') ? route.path : route.path.replace('micro-vent-2dModal', 'micro-vent-3dModal'),
+        query: {
+          ...route.query,
+          type: 'model3D',
+          deviceType: 'model3D',
+          isNoReverse: '1',
+        },
+      });
+    } else {
+      router.push({
+        path: route.path.includes('micro-vent-2dModal') ? route.path : route.path.replace('micro-vent-3dModal', 'micro-vent-2dModal'),
+        query: {
+          ...route.query,
+          type: 'model3D',
+          deviceType: 'model3D',
+          isNoReverse: '1',
+        },
+      });
+    }
   }
 
   watch(
@@ -175,7 +189,8 @@
     --image-modal-top: url('/@/assets/images/vent/home/modal-top.png');
     --image-monitor-realtime: url('/@/assets/images/company/monitor-realtime.png');
     --image-monitor-doc: url('/@/assets/images/company/monitor-doc.png');
-    --image-monitor-goto: url('/@/assets/images/company/monitor-goto.png');
+    --image-monitor-goto2: url('/@/assets/images/vent/home/2.5D.png');
+    --image-monitor-goto3: url('/@/assets/images/vent/home/3D.png');
 
     width: 100%;
     height: 100%;
@@ -243,23 +258,68 @@
     }
 
     .switch-button {
-      width: 34px;
-      height: 34px;
+      width: 50px;
+      height: 50px;
+      border-radius: 15%;
+      padding: 8px;
+      backdrop-filter: blur(10px);
+      background-color: rgba(30, 58, 117, 0.418);
       position: absolute;
       // right: 5px;
       bottom: 300px;
       z-index: 5;
-      background-repeat: no-repeat;
-      background-size: 100% 100%;
     }
     .report-mode {
-      background-image: var(--image-monitor-doc);
+      &::after {
+        width: 34px;
+        height: 34px;
+        content: '';
+        position: absolute;
+        top: 8px;
+        left: 8px;
+        background-image: var(--image-monitor-doc);
+        background-repeat: no-repeat;
+        background-size: 100% 100%;
+      }
     }
     .realtime-mode {
-      background-image: var(--image-monitor-realtime);
+      &::after {
+        width: 34px;
+        height: 34px;
+        content: '';
+        position: absolute;
+        top: 8px;
+        left: 8px;
+        background-image: var(--image-monitor-realtime);
+        background-repeat: no-repeat;
+        background-size: 100% 100%;
+      }
     }
-    .icon-goto {
-      background-image: var(--image-monitor-goto);
+    .icon-goto2D {
+      &::after {
+        width: 34px;
+        height: 34px;
+        content: '';
+        position: absolute;
+        top: 8px;
+        left: 8px;
+        background-image: var(--image-monitor-goto2);
+        background-repeat: no-repeat;
+        background-size: 100% 100%;
+      }
+    }
+    .icon-goto3D {
+      &::after {
+        width: 34px;
+        height: 34px;
+        content: '';
+        position: absolute;
+        top: 8px;
+        left: 8px;
+        background-image: var(--image-monitor-goto3);
+        background-repeat: no-repeat;
+        background-size: 100% 100%;
+      }
     }
 
     .module-monitor-bar {

+ 6 - 4
src/views/vent/home/configurable/ventV5.vue

@@ -2,7 +2,8 @@
 <template>
   <div class="company-home">
     <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
-      <VentModal />
+      <SubApp />
+      <!-- <VentModel /> -->
     </div>
     <!-- 如果是有 deviceType、type 等 query,认为是详情页,不需要展示普通模块,只需要模型 -->
     <template v-if="!route.query.deviceType">
@@ -76,7 +77,7 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { onMounted, onUnmounted, ref, watch } from 'vue';
+  import { onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue';
   // import { CaretDownOutlined } from '@ant-design/icons-vue';
   import MonitorBar from './components/MonitorBar.vue';
   import { useInitConfigs, useInitPage } from './hooks/useInit';
@@ -84,12 +85,13 @@
   import ModuleOriginal from './components/ModuleOriginal.vue';
   import ModuleCommon from './components/ModuleCommon.vue';
   // import { useRoute } from 'vue-router';
-  import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import SubApp from '/@/components/vent/micro/createSubApp.vue';
+  // import VentModel from '/@/components/vent/micro/ventModal.vue';
   import { list } from './configurable.api';
   import { useRoute, useRouter } from 'vue-router';
   import { useGlobSetting } from '/@/hooks/setting';
   // import { testConfigVent, testConfigVentRealtime } from './configurable.data';
-
+  const sunAppType = ref('');
   const { sysDataType = 'monitor', title = '智能通风管控系统' } = useGlobSetting();
   const { configs, isOriginal, isCommon, fetchConfigs } = useInitConfigs();
   const { mainTitle, enhancedConfigs, hiddenList, data, updateData, updateEnhancedConfigs } = useInitPage(title);

+ 68 - 68
src/views/vent/monitorManager/alarmMonitor/warn/waterLevel.vue

@@ -21,89 +21,89 @@
         class="tableW"
         @change="pageChange"
         :scroll="{ y: 700 }"
-      ></a-table>
+      />
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted, onUnmounted, computed } from 'vue';
-import CustomHeader from '/@/components/vent/customHeader.vue';
-import { getHydrology } from '../common.api';
-import { usePermission } from '/@/hooks/web/usePermission';
-import { useRouter } from 'vue-router';
-import { columns } from '../common.data';
-const { hasPermission } = usePermission();
-const router = useRouter();
-const tableData = ref([]);
+  import { ref, reactive, onMounted, onUnmounted, computed } from 'vue';
+  import CustomHeader from '/@/components/vent/customHeader.vue';
+  import { getHydrology } from '../common.api';
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { useRouter } from 'vue-router';
+  import { columns } from '../common.data';
+  const { hasPermission } = usePermission();
+  const router = useRouter();
+  const tableData = ref([]);
 
-//分页切换
-const pageChange = (val) => {
-  console.log(val, 'val');
-  pagination.current = val.current;
-  pagination.pageSize = val.pageSize;
-  getListData();
-};
-const pagination = reactive({
-  current: 1, // 当前页码
-  pageSize: 20, // 每页显示条数
-  total: 0, // 总条目数,后端返回
-  showTotal: (total) => `共 ${total} 条`, // 分页右下角显示信息
-});
-//返回首页
-function getBack() {
-  router.push('/monitorChannel/monitor-alarm-home');
-}
-async function getListData() {
-  var params = {
-    pageIndex: pagination.current,
-    pageSize: pagination.pageSize,
+  //分页切换
+  const pageChange = (val) => {
+    console.log(val, 'val');
+    pagination.current = val.current;
+    pagination.pageSize = val.pageSize;
+    getListData();
   };
-  const res = await getHydrology({ ...params });
-  tableData.value = res.data;
-  pagination.total = res.count;
-}
-onMounted(() => {
-  getListData();
-});
-onUnmounted(() => {});
+  const pagination = reactive({
+    current: 1, // 当前页码
+    pageSize: 20, // 每页显示条数
+    total: 0, // 总条目数,后端返回
+    showTotal: (total) => `共 ${total} 条`, // 分页右下角显示信息
+  });
+  //返回首页
+  function getBack() {
+    router.push('/monitorChannel/monitor-alarm-home');
+  }
+  async function getListData() {
+    var params = {
+      pageIndex: pagination.current,
+      pageSize: pagination.pageSize,
+    };
+    const res = await getHydrology({ ...params });
+    tableData.value = res.data;
+    pagination.total = res.count;
+  }
+  onMounted(() => {
+    getListData();
+  });
+  onUnmounted(() => {});
 </script>
 
 <style lang="less" scoped>
-@import '/@/design/theme.less';
+  @import '/@/design/theme.less';
 
-@{theme-deepblue} {
-  .gasWarn {
-    --image-no-choice: url('/@/assets/images/themify/deepblue/fire/no-choice.png');
-    --image-choice: url('/@/assets/images/themify/deepblue/fire/choice.png');
-    --image-border: url('/@/assets/images/themify/deepblue/fire/border.png');
-    --image-bj1: url('/@/assets/images/themify/deepblue/fire/bj1.png');
-    --image-top-area: url('/@/assets/images/themify/deepblue/fire/top-area.png');
+  @{theme-deepblue} {
+    .gasWarn {
+      --image-no-choice: url('/@/assets/images/themify/deepblue/fire/no-choice.png');
+      --image-choice: url('/@/assets/images/themify/deepblue/fire/choice.png');
+      --image-border: url('/@/assets/images/themify/deepblue/fire/border.png');
+      --image-bj1: url('/@/assets/images/themify/deepblue/fire/bj1.png');
+      --image-top-area: url('/@/assets/images/themify/deepblue/fire/top-area.png');
+    }
   }
-}
 
-.gasWarn {
-  --image-no-choice: url('/@/assets/images/fire/no-choice.png');
-  --image-choice: url('/@/assets/images/fire/choice.png');
-  --image-border: url('/@/assets/images/fire/border.png');
-  --image-bj1: url('/@/assets/images/fire/bj1.png');
-  --image-top-area: url('/@/assets/images/fire/top-area.png');
-  width: 100%;
-  height: 100%;
-  padding: 80px 10px 15px 10px;
-  box-sizing: border-box;
-  display: flex;
-  justify-content: space-between;
-
-  .gas-content {
-    position: relative;
+  .gasWarn {
+    --image-no-choice: url('/@/assets/images/fire/no-choice.png');
+    --image-choice: url('/@/assets/images/fire/choice.png');
+    --image-border: url('/@/assets/images/fire/border.png');
+    --image-bj1: url('/@/assets/images/fire/bj1.png');
+    --image-top-area: url('/@/assets/images/fire/top-area.png');
     width: 100%;
     height: 100%;
-    margin-left: 10px;
-    padding: 15px;
-    background: var(--image-border) no-repeat;
-    background-size: 100% 100%;
+    padding: 80px 10px 15px 10px;
     box-sizing: border-box;
+    display: flex;
+    justify-content: space-between;
+
+    .gas-content {
+      position: relative;
+      width: 100%;
+      height: 100%;
+      margin-left: 10px;
+      padding: 15px;
+      background: var(--image-border) no-repeat;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+    }
   }
-}
 </style>

+ 2 - 2
src/views/vent/monitorManager/balancePressMonitor/index1.vue

@@ -171,8 +171,8 @@
   });
 
   onUnmounted(() => {});
-  onBeforeUnmount(() => {
-    unmountMicroApps(['/micro-vent-2dModal']);
+  onBeforeUnmount(async () => {
+    await unmountMicroApps(['micro-vent-2dModal']);
   });
 </script>
 <style lang="less" scoped>

+ 121 - 31
src/views/vent/monitorManager/deviceMonitor/components/device/index.vue

@@ -56,7 +56,7 @@
       </div>
     </div>
     <div
-      class="tabs-box bottom-tabs-box"
+      class="bottom-tabs-box"
       :class="{ 'table-hide': !tableShow, 'table-show': tableShow }"
       style="height: 290px"
       @mousedown="setDivHeight($event, 230, scroll, 0)"
@@ -64,7 +64,9 @@
     >
       <div :style="`padding: 5px; height: ${scroll.y + 100}px`">
         <div class="to-small">
-          <div class="to-home" @click="toHome"></div>
+          <div class="to-home" @click="toHome()"></div>
+          <div class="to-2D" @click="toHome('2D')"></div>
+          <div class="to-3D" @click="toHome('3D')"></div>
           <FullscreenOutlined v-if="!tableShow" class="table-show-icon" @click="toHide" />
         </div>
         <div class="device-button-group" v-if="deviceList.length > 0">
@@ -164,7 +166,7 @@
             <Input style="width: 200px" v-model:value="locationForm.stationname" />
           </div>
         </div>
-        <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange" id="tabsBox">
+        <a-tabs v-model:activeKey="activeKey" @change="tabChange" id="tabsBox">
           <a-tab-pane
             key="monitor"
             :tab="
@@ -689,6 +691,8 @@
   import { useGo } from '/@/hooks/web/usePage';
   import { useGlobSetting } from '/@/hooks/setting';
   import { usePermission } from '/@/hooks/web/usePermission';
+  import { PageEnum } from '/@/enums/pageEnum';
+  import { useUserStore } from '/@/store/modules/user';
 
   type DeviceType = { deviceType: string; deviceName: string; datalist: any[] };
   const glob = useGlobSetting();
@@ -773,6 +777,7 @@
     insType: '2',
     class: 'night',
   });
+
   //树形菜单选择事件
   const onSelect: TreeProps['onSelect'] = (keys, e) => {
     deviceType.value = '';
@@ -784,11 +789,11 @@
       if (deviceType.value != e.node.parent.node.type) deviceType.value = e.node.parent.node.type;
       systemID.value = e.node.type;
       // 传递工作面id信息,用于定位
-      go(`/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=${deviceType.value}&deviceid=${systemID.value}`);
+      go(`${route.path}?type=tunMonitor&deviceType=${deviceType.value}&deviceid=${systemID.value}`);
     } else {
       systemType.value = e.node.type;
       if (deviceType.value != e.node.type) deviceType.value = e.node.type;
-      go(`/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=${deviceType.value}&deviceid=`);
+      go(`${route.path}?type=tunMonitor&deviceType=${deviceType.value}&deviceid=`);
     }
     clearTimeout(timer);
     timer = undefined;
@@ -1115,24 +1120,23 @@
   }
 
   function goLocation(record) {
-    // debugger;
     if (record['deviceType'] == 'person_bd' || record['deviceType'] == 'car_bd') {
-      actions.setGlobalState({ locationId: record.devNum, locationObj: null, pageObj: null, type: record['deviceType'].split('_')[0] });
+      actions.setGlobalState({ locationId: record.devNum, locationObj: record, pageObj: null, type: record['deviceType'].split('_')[0] });
     } else if (deviceType.value == 'bundleSpyDayReport' || deviceType.value == 'dustDayReport' || deviceType.value == 'bundleDayReport') {
-      actions.setGlobalState({ locationName: record.jcdd, locationObj: null, pageObj: null, type: record['deviceType'] });
+      actions.setGlobalState({ locationName: record.jcdd, locationObj: record, pageObj: null, type: record['deviceType'] });
     } else if (deviceType.value.startsWith('gasDay')) {
-      actions.setGlobalState({ locationName: record.strInstallPos, locationObj: null, pageObj: null, type: record['deviceType'] });
+      actions.setGlobalState({ locationName: record.strInstallPos, locationObj: record, pageObj: null, type: record['deviceType'] });
     } else if (deviceType.value == 'gasDayReport') {
-      actions.setGlobalState({ locationName: record.jcdd, locationObj: null, pageObj: null, type: record['deviceType'] });
+      actions.setGlobalState({ locationName: record.jcdd, locationObj: record, pageObj: null, type: record['deviceType'] });
     } else if (deviceType.value.startsWith('substation')) {
-      actions.setGlobalState({ locationId: record.id, locationObj: null, pageObj: null, type: record['deviceType'] });
+      actions.setGlobalState({ locationId: record.id, locationObj: record, pageObj: null, type: record['deviceType'] });
     } else {
       if (deviceType.value.startsWith('location')) {
-        actions.setGlobalState({ locationId: record.deviceID, locationObj: null, pageObj: null, type: 'person' });
+        actions.setGlobalState({ locationId: record.deviceID, locationObj: record, pageObj: null, type: 'person' });
       } else if (deviceType.value.startsWith('vehicle')) {
-        actions.setGlobalState({ locationId: record.deviceID, locationObj: null, pageObj: null, type: 'car' });
+        actions.setGlobalState({ locationId: record.deviceID, locationObj: record, pageObj: null, type: 'car' });
       } else {
-        actions.setGlobalState({ locationId: record.deviceID, locationObj: null, pageObj: null });
+        actions.setGlobalState({ locationId: record.deviceID, locationObj: record, pageObj: null });
       }
     }
   }
@@ -1274,12 +1278,31 @@
     handleExportXls('瓦斯巡检记录', getExportUrl, { devicetype: deviceType.value });
   }
 
-  function toHome() {
-    deviceList.value = [];
-    if (timer) clearTimeout(timer);
-    timer = undefined;
-    deviceType.value = '';
-    go(glob.homePath);
+  function toHome(flag?: string) {
+    if (flag == '2D') {
+      router.push({
+        path: route.path.includes('micro-vent-2dModal') ? route.path : route.path.replace('micro-vent-3dModal', 'micro-vent-2dModal'),
+        query: {
+          ...route.query,
+          isNoReverse: '1',
+        },
+      });
+    } else if (flag == '3D') {
+      router.push({
+        path: route.path.includes('micro-vent-3dModal') ? route.path : route.path.replace('micro-vent-2dModal', 'micro-vent-3dModal'),
+        query: {
+          ...route.query,
+          isNoReverse: '1',
+        },
+      });
+    } else {
+      deviceList.value = [];
+      if (timer) clearTimeout(timer);
+      timer = undefined;
+      deviceType.value = '';
+      const { userInfo } = useUserStore();
+      go((userInfo && userInfo.homePath) || glob.homePath || PageEnum.BASE_HOME);
+    }
   }
 
   function toHide() {
@@ -1491,11 +1514,16 @@
     --image-tree-icon-cover-bg: url('/@/assets/images/vent/home/tree-icon-cover-bg.png');
     --image-tree-icon-cover-hover-bg: url('/@/assets/images/vent/home/tree-icon-cover-hover-bg.png');
     --image-tohome: url('/@/assets/images/vent/home/tohome.png');
+    --image-to2D: url('/@/assets/images/vent/home/2.5D.png');
+    --image-to3D: url('/@/assets/images/vent/home/3D.png');
     --tree-node-select: #00b1c8;
     --tree-node-hover: #00b1c855;
     --location-bottom-bg: #00709955;
     --location-bottom-border: #aef3ff4d;
   }
+  .scene-box {
+    pointer-events: none;
+  }
 
   .top-header {
     position: fixed;
@@ -1833,12 +1861,14 @@
 
   .bottom-tabs-box {
     position: relative;
-
-    .tabs-box {
-      width: calc(100% - 12px) !important;
-      bottom: 3px !important;
-      background-color: red;
-    }
+    background-color: var(--vent-configurable-module-border-bd);
+    backdrop-filter: blur(18px);
+    border: 1px solid #ffffff55;
+    border-radius: 8px;
+    // .tabs-box {
+    //   width: calc(100% - 12px) !important;
+    //   bottom: 3px !important;
+    // }
 
     .to-small {
       position: absolute;
@@ -1849,12 +1879,72 @@
       justify-content: center;
 
       .to-home {
-        width: 60px;
-        height: 60px;
-        background: var(--image-tohome) no-repeat center;
-        background-size: auto;
+        width: 50px;
+        height: 50px;
+        border-radius: 15%;
         padding: 8px;
-
+        backdrop-filter: blur(10px);
+        background-color: rgba(30, 58, 117, 0.418);
+        margin-right: 10px;
+        cursor: pointer;
+        &::after {
+          width: 34px;
+          height: 34px;
+          content: '';
+          position: absolute;
+          top: 8px;
+          left: 8px;
+          background: var(--image-tohome) no-repeat center;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+        }
+        &:hover {
+          background-color: rgba(79, 104, 134, 0.418);
+        }
+      }
+      .to-2D {
+        width: 50px;
+        height: 50px;
+        border-radius: 15%;
+        padding: 8px;
+        backdrop-filter: blur(10px);
+        background-color: rgba(30, 58, 117, 0.418);
+        margin-right: 10px;
+        cursor: pointer;
+        &::after {
+          width: 34px;
+          height: 34px;
+          content: '';
+          position: absolute;
+          top: 8px;
+          left: 8px;
+          background: var(--image-to2D) no-repeat center;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+        }
+        &:hover {
+          background-color: rgba(79, 104, 134, 0.418);
+        }
+      }
+      .to-3D {
+        width: 50px;
+        height: 50px;
+        border-radius: 15%;
+        padding: 8px;
+        backdrop-filter: blur(10px);
+        background-color: rgba(30, 58, 117, 0.418);
+        cursor: pointer;
+        &::after {
+          width: 34px;
+          height: 34px;
+          content: '';
+          position: absolute;
+          top: 8px;
+          left: 8px;
+          background: var(--image-to3D) no-repeat center;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+        }
         &:hover {
           background-color: rgba(79, 104, 134, 0.418);
         }

+ 6 - 6
src/views/vent/monitorManager/deviceMonitor/index.vue

@@ -5,8 +5,9 @@
       <DeviceVue ref="DeviceRef" v-else :pageData="pageData" /> -->
       <DeviceVue ref="DeviceRef" :pageData="pageData" />
     </template>
-    <Network ref="NetworkRef" v-if="routerParam === 'timesolution'" :pageResult="pageResult" @changePageType="changePageType" />
-    <VentModal style="width: 100%; height: 100%; position: absolute" />
+    <Network ref="NetworkRef" v-if="routerParam === 'timesolution'" :pageResult="pageResult" @change-page-type="changePageType" />
+    <!-- <VentModal style="width: 100%; height: 100%; position: absolute" /> -->
+    <SubApp style="width: 100%; height: 100%; position: absolute" />
   </div>
 </template>
 
@@ -18,7 +19,8 @@
   import { unmountMicroApps } from '/@/qiankun';
   import { getActions } from '/@/qiankun/state';
   import { useRoute } from 'vue-router';
-  import VentModal from '/@/components/vent/micro/ventModal.vue';
+  // import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import SubApp from '/@/components/vent/micro/createSubApp.vue';
 
   const route = useRoute();
   const actions = getActions();
@@ -91,9 +93,7 @@
       }
     });
   });
-  onBeforeUnmount(() => {
-    unmountMicroApps(['/micro-vent-3dModal']);
-  });
+  onBeforeUnmount(() => {});
   onUnmounted(() => {
     isShow.value = false;
   });

+ 0 - 2
src/views/vent/monitorManager/fireDoorMonitor/fireDoor.threejs.fire.redGate.ts

@@ -1,5 +1,4 @@
 import * as THREE from 'three';
-import { useAppStore } from '/@/store/modules/app';
 
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
@@ -20,7 +19,6 @@ class FireDoor {
 
   fmClock = new THREE.Clock();
   mixers: THREE.AnimationMixer | undefined;
-  appStore = useAppStore();
   damperOpenMesh;
   damperClosedMesh;
 

+ 2 - 3
src/views/vent/monitorManager/footageMonitor/index.vue

@@ -58,9 +58,8 @@
   onMounted(async () => {
     await getSysDataSource();
   });
-  onBeforeUnmount(() => {
-    unmountMicroApps(['/micro-vent-3dModal']);
-  });
+  // onBeforeUnmount(async () => {
+  // });
 </script>
 <style lang="less" scoped>
   @import '/@/design/theme.less';

+ 81 - 49
src/views/vent/monitorManager/mainFanMonitor/index.vue

@@ -76,22 +76,22 @@
                     selectData['Fan1StartStatus'] == '0' && globalConfig?.simulatedPassword
                       ? '-'
                       : selectData[data.dataIndex.replace('Fan', 'Fan1')]
-                      ? selectData[data.dataIndex.replace('Fan', 'Fan1')]
-                      : '-'
+                        ? selectData[data.dataIndex.replace('Fan', 'Fan1')]
+                        : '-'
                   }}</div>
                   <div class="item-value" v-if="dataMonitorRowIndex == 1">{{
                     selectData['Fan2StartStatus'] == '0' && globalConfig?.simulatedPassword
                       ? '-'
                       : selectData[data.dataIndex.replace('Fan', 'Fan2')]
-                      ? selectData[data.dataIndex.replace('Fan', 'Fan2')]
-                      : '-'
+                        ? selectData[data.dataIndex.replace('Fan', 'Fan2')]
+                        : '-'
                   }}</div>
                   <div class="item-value" v-if="dataMonitorRowIndex == 2">{{
                     selectData['Fan3StartStatus'] == '0' && globalConfig?.simulatedPassword
                       ? '-'
                       : selectData[data.dataIndex.replace('Fan', 'Fan3')]
-                      ? selectData[data.dataIndex.replace('Fan', 'Fan3')]
-                      : '-'
+                        ? selectData[data.dataIndex.replace('Fan', 'Fan3')]
+                        : '-'
                   }}</div>
                 </div>
                 <div v-else>
@@ -150,8 +150,8 @@
                           selectData[state.dataIndex.replace('Fan', 'Fan1')] === undefined
                             ? '无状态'
                             : selectData[state.dataIndex.replace('Fan', 'Fan1')] == '0'
-                            ? '正常'
-                            : '异常'
+                              ? '正常'
+                              : '异常'
                         }}</div>
                       </template>
                     </div>
@@ -175,8 +175,8 @@
                           selectData[state.dataIndex.replace('Fan', 'Fan2')] == undefined
                             ? '无状态'
                             : selectData[state.dataIndex.replace('Fan', 'Fan2')] == '0'
-                            ? '正常'
-                            : '异常'
+                              ? '正常'
+                              : '异常'
                         }}</div>
                       </template>
                     </div>
@@ -200,8 +200,8 @@
                           selectData[state.dataIndex.replace('Fan', 'Fan3')] == undefined
                             ? '无状态'
                             : selectData[state.dataIndex.replace('Fan', 'Fan3')] == '0'
-                            ? '正常'
-                            : '异常'
+                              ? '正常'
+                              : '异常'
                         }}</div>
                       </template>
                     </div>
@@ -423,9 +423,7 @@
       </dv-border-box8>
     </div>
   </div>
-  <div style="z-index: -1; position: absolute; top: -100px; right: 10px; width: 300px; height: 280px; margin: auto" class="palyer">
-    <LivePlayer id="main-player1" ref="player1" :videoUrl="flvURL1()" muted loop loading controls />
-  </div>
+
   <div
     v-if="renderPlayer"
     ref="playerRef"
@@ -579,6 +577,10 @@
           > -->
         </div>
       </div>
+      <div class="vent-flex-row input-box" v-if="modalType == 'setVal' && setValPoint">
+        <div class="label">{{ setValPoint['valuename'] }}:</div>
+        <a-input-number v-model:value="setValPoint['value']" style="width: 150px" />
+      </div>
     </div>
   </a-modal>
   <a-modal
@@ -617,16 +619,21 @@
   </div>
 
   <!-- 摄像头显示隐藏图标 -->
-  <VideoCameraOutlined class="video-icon" :class="{ 'no-play': !showPlay }" @click="changePlay" />
-  <!-- 主风机故障诊断显示隐藏图标 -->
-  <div v-if="hasPermission('mainFan:isOpenAlarm') && sysOrgCode !== 'wljttlbl'" class="warn-icon" @click="showModalWarn"></div>
+  <div class="icon-box">
+    <VideoCameraOutlined class="video-icon" :class="{ 'no-play': !showPlay }" @click="changePlay" />
+    <FormOutlined @click="openModalDeviceSet" />
+    <!-- 主风机故障诊断显示隐藏图标 -->
+    <div v-if="hasPermission('mainFan:isOpenAlarm') && sysOrgCode !== 'wljttlbl'" class="warn-icon" @click="showModalWarn"></div>
+  </div>
+
   <!-- 工况辅助决策 -->
   <ConditionAssistance @register="registerModal" :deviceType="deviceType" :selectData="currentData" />
   <DeviceBaseInfo @register="registerModalDeviceEdit" :device-type="selectData['deviceType']" />
+  <setValueSetting @register="registerModalDeviceSet" :deviceType="deviceType" @show-set-modal="showSetModal" />
 </template>
 
 <script setup lang="ts">
-  import { ExclamationCircleFilled, VideoCameraOutlined } from '@ant-design/icons-vue';
+  import { ExclamationCircleFilled, VideoCameraOutlined, FormOutlined } from '@ant-design/icons-vue';
   import FanDeviceEcharts from '../comment/FanDeviceEcharts.vue';
   import BarAndLine from '../../../../components/chart/BarAndLine.vue';
   import FanEchrats from '/@/views/vent/monitorManager/mainFanMonitor/fanEchrats.vue';
@@ -653,7 +660,6 @@
   import { modalTypeArr, fbmControlData, faultDeviceHeader, PointMonitorType, getModelComponent } from './main.data';
   import { deviceControlApi } from '/@/api/vent/index';
   import { mountedThree, destroy, addText, setModelType, playAnimate, resetEcharts } from './main.threejs';
-  import LivePlayer from '@liveqing/liveplayer-v3';
   import { SvgIcon } from '/@/components/Icon';
   import { list, pointMonitor, getFaultDiagnosis } from './main.api';
   import { list as baseList } from '../../deviceManager/fanTabel/fan.api';
@@ -664,6 +670,7 @@
   import { BorderBox8 as DvBorderBox8 } from '@kjgl77/datav-vue3';
   import { useRouter } from 'vue-router';
   import ConditionAssistance from './components/conditionAssistance.vue';
+  import setValueSetting from './components/setValueSetting.vue';
   import AnalysisTable from './components/AnalysisTable.vue';
   import { useModal } from '/@/components/Modal';
   import type { BasicColumn } from '/@/components/Table/src/types/table';
@@ -673,8 +680,6 @@
   import { usePermission } from '/@/hooks/web/usePermission';
   import { cloneDeep } from 'lodash-es';
   import { getDictItems } from '/@/api/common/api';
-  import { warn } from 'node:console';
-  import { merge } from 'lodash';
 
   const globalConfig = inject('globalConfig');
   const HistoryTable =
@@ -686,6 +691,7 @@
 
   const [registerModal, { openModal, closeModal }] = useModal();
   const [registerModalDeviceEdit, { openModal: openModalDeviceEdit }] = useModal();
+  const [registerModalDeviceSet, { openModal: openModalDeviceSet }] = useModal();
   const { currentRoute } = useRouter();
   const { createMessage, createConfirm } = useMessage();
   const { sysOrgCode } = useGlobSetting();
@@ -705,7 +711,6 @@
   const MonitorDataTable = ref();
   const showPlay = ref(hasPermission('mainFan:showCamera') ? true : false);
   const player1 = ref(null);
-  const player2 = ref(null);
   const activeKey = ref('1');
   const loading = ref(false);
   const renderPlayer = ref(true);
@@ -728,6 +733,7 @@
   const warningMonitorRowIndex = ref(0);
   const faultData = ref<PointMonitorType[]>([]); // 存放故障点位监测数据(查的点表)
   const explosionDoorData = ref<PointMonitorType[]>([]); // 存放防爆门点位监测数据(查的点表)
+  const setValPoint = ref(null);
   const faultShow = ref(false);
   const IdList = ref<any[]>([]); // 存放风机设备id
   let headElHeight = ref(0);
@@ -807,6 +813,8 @@
   const echartsDataList = ref<any[]>([]);
   const requestLock = ref(hasPermission('mainFan:isOpenAlarm')); // 是否允许请求数据
   const warnList = ref<any[]>([]); // 存放故障诊断数据
+
+  /*** 获取图表列 */
   const remoteChartsColumns = getTableHeaderColumns('fanmain_chart');
   const chartsColumns = remoteChartsColumns && remoteChartsColumns.length > 0 ? remoteChartsColumns : [];
   let chartsColumnsFan1 = [],
@@ -820,7 +828,6 @@
 
       if (itemColumn['dataIndex']) {
         const dataIndex = itemColumn['dataIndex'] as string;
-
         dataIndexFan1 = dataIndex.startsWith('Fan') ? dataIndex.replace('Fan', 'Fan1') : dataIndex.replace('fan', 'fan1');
         dataIndexFan2 = dataIndex.startsWith('Fan') ? dataIndex.replace('Fan', 'Fan2') : dataIndex.replace('fan', 'fan2');
         chartsColumnsFan1.push({ ...itemColumn, dataIndex: dataIndexFan1, legend: '主机' + itemColumn['legend'] });
@@ -828,6 +835,11 @@
       }
     }
   }
+
+  /*** 获取设置列 */
+  let setValueColumnsFan1 = [],
+    setValueColumnsFan2 = [];
+
   const echatsOption = {
     legend: {
       top: 8,
@@ -874,15 +886,6 @@
     }
   });
 
-  const flvURL1 = () => {
-    // return `https://muiplayer.js.org/media/media.m3u8`;
-    return `/video/mainWind.mp4`;
-  };
-  const flvURL2 = () => {
-    return `/video/mainWind.mp4`;
-    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
-  };
-
   const dataSource = ref([]);
 
   const propTypeArr = new Map([
@@ -902,6 +905,12 @@
     // MonitorDataTable.value.setSelectedRowKeys(selectData.deviceID);
   };
 
+  const showSetModal = (point) => {
+    modalIsShow.value = true;
+    modalType.value = 'setVal';
+    setValPoint.value = point;
+  };
+
   // 设备数据
   const controlType = ref(1);
 
@@ -1042,6 +1051,7 @@
       deviceBaseList.value = res.records;
     });
   };
+
   // 切换检测数据
   const getSelectRow = async (id) => {
     removeCamera(playerRef);
@@ -1077,12 +1087,12 @@
         selectData['modalTyoe'] === 'xiejing'
           ? 'mainXjWindRect'
           : selectData['modalTyoe'] === 'lijing1'
-          ? 'mainLjWindRect'
-          : selectData['modalTyoe'] === 'lijing_3'
-          ? 'mainWindRect3'
-          : selectData['modalTyoe'] === 'lijing_1'
-          ? 'mainLjDtWindRect'
-          : 'mainWindRect';
+            ? 'mainLjWindRect'
+            : selectData['modalTyoe'] === 'lijing_3'
+              ? 'mainWindRect3'
+              : selectData['modalTyoe'] === 'lijing_1'
+                ? 'mainLjDtWindRect'
+                : 'mainWindRect';
 
       frontMonitorIsShow.value = false;
       centerMonitorIsShow.value = false;
@@ -1140,6 +1150,7 @@
   const changePlay = () => {
     showPlay.value = !showPlay.value;
   };
+
   // 打开并设置modal的标题
   const showModal = (obj) => {
     // 神东要求主扇的控制功能改回跳转至生产管控平台
@@ -1574,6 +1585,15 @@
           .catch((err) => {
             createMessage.error(err.message);
           });
+      } else if (modalType.value == 'setVal' && setValPoint.value) {
+        start(setValPoint.value['valuecode'], setValPoint.value['value'])
+          .then(() => {
+            createMessage.success('指令下发成功');
+            setValPoint.value = null;
+          })
+          .catch((err) => {
+            createMessage.error(err.message);
+          });
       }
       modalIsShow.value = false;
     };
@@ -1592,13 +1612,17 @@
       }
     }
     modalIsShow.value = false;
+    setValPoint.value = null;
   };
+
   const handlefaultCancel = () => {
     modalWarnIsShow.value = false;
   };
+
   const handlefaultOk = () => {
     modalWarnIsShow.value = false;
   };
+
   function showModalWarn() {
     if (warnList.value.length > 0) {
       modalWarnIsShow.value = true;
@@ -1606,6 +1630,7 @@
       createMessage.info('当前无告警信息');
     }
   }
+
   function deviceEdit(e: Event, type: string, record) {
     e.stopPropagation();
     openModalDeviceEdit(true, {
@@ -2180,8 +2205,8 @@
     }
   }
 
-  .video-icon {
-    width: 30px;
+  .icon-box {
+    width: 140px;
     height: 38px;
     position: absolute;
     top: 600px;
@@ -2189,17 +2214,13 @@
     color: var(--vent-font-color);
     z-index: 1;
     font-size: 28px;
+    display: flex;
+    justify-content: space-between;
   }
-  .warn-icon {
+  .video-icon {
     width: 30px;
     height: 38px;
-    position: absolute;
-    top: 600px;
-    right: 460px;
-    background: url('/@/assets/images/vent/normal-mainfan.png') no-repeat;
-    background-size: contain;
-    z-index: 1;
-    font-size: 28px;
+    position: relative;
   }
   .no-play {
     &::after {
@@ -2219,6 +2240,17 @@
       );
     }
   }
+  .warn-icon {
+    width: 30px;
+    height: 38px;
+    // position: absolute;
+    // top: 600px;
+    // right: 460px;
+    background: url('/@/assets/images/vent/normal-mainfan.png') no-repeat;
+    background-size: contain;
+    z-index: 1;
+    font-size: 28px;
+  }
 
   .threejs-Object-CSS {
     .elementTag {