Jelajahi Sumber

拓扑工具栏

lichunyang 5 hari lalu
induk
melakukan
00b6f42d96

+ 340 - 0
src/components/layout/TopoButtonBar.vue

@@ -0,0 +1,340 @@
+<template>
+  <div class="header-button-bar" style="position: relative">
+    <el-tabs v-model="activeTab" type="border-card" @tab-click="handleTabClick">
+      <!-- 特殊按钮 tab 退出 保存 -->
+      <el-tab-pane v-for="btn in fakeTabs" :key="btn.name" :name="btn.name">
+        <template #label>
+          <span @click.stop>
+            <el-tooltip :content="btn.label" placement="top">
+              <el-button
+                :type="btn.type"
+                :size="btn.size || 'small'"
+                @click="btn.onClick"
+                class="icon-only-button"
+              >
+                <img :src="btn.icon" alt="icon" class="button-icon" />
+              </el-button>
+            </el-tooltip>
+          </span>
+        </template>
+        <template #default></template>
+      </el-tab-pane>
+      <!-- 普通标签页 -->
+      <el-tab-pane v-for="tab in tabs" :key="tab.name" :name="tab.name">
+        <template #label>
+            <span class="tab-label">
+              <!-- <img :src="tab.icon" alt="icon" class="tab-icon" /> -->
+              {{ tab.label }}
+            </span>
+        </template>
+        <div class="button-group">
+          <el-tooltip
+            v-for="button in tab.buttons"
+            :key="button.action"
+            :content="button.label"
+            placement="top"
+          >
+            <el-button
+              type=""
+              @click="emitButtonClick(button.action)"
+              class="icon-text-button"
+            >
+              <img :src="button.icon" alt="icon" class="button-icon" />
+              <!-- {{ button.label }} -->
+            </el-button>
+          </el-tooltip>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from "vue"
+import { useI18n } from "vue-i18n"
+const { t } = useI18n()
+
+import libraryIcon from "@/assets/icons/library.png" // 图层
+import addLayerIcon from "@/assets/icons/addLayer.png" // 新建图层
+import editIcon from "@/assets/icons/edit.png" // 编辑
+import importProIcon from "@/assets/icons/importPro.png" // 导入
+import tutorialIcon from "@/assets/icons/tutorial.png" // 配置
+import copyIcon from "@/assets/icons/copy.png" // 复制
+import cutIcon from "@/assets/icons/cut.png" // 剪切
+import pasteIcon from "@/assets/icons/paste.png" // 粘贴
+import alignLeftIcon from "@/assets/icons/alignLeft.png" // 左对齐
+import alignRightIcon from "@/assets/icons/alignRight.png" // 右对齐
+import topToItIcon from "@/assets/icons/topToIt.png" // 顶部对齐
+import bottomToItIcon from "@/assets/icons/bottomToIt.png" // 底部
+import horizontalDistributionIcon from "@/assets/icons/horizontalDistribution.png" // 水平分布
+import verticalDistributionIcon from "@/assets/icons/vertical.png" // 垂直分布
+import rotateRightIcon from "@/assets/icons/rotateRight.png" // 右旋转
+import rotateLeftIcon from "@/assets/icons/rotateLeft.png" // 左旋转
+import horizontalFlipIcon from "@/assets/icons/horizontalFlip.png" // 水平翻转
+import verticalFlipIcon from "@/assets/icons вертикReverse.png" // 垂直翻转
+import imageIcon from "@/assets/icons/image.png" // 图片
+import graphicIcon from "@/assets/icons/graphic.png" // 图形
+import documentIcon from "@/assets/icons/document.png" // 文档
+import commentIcon from "@/assets/icons/comment.png" // 注释
+import toolIcon from "@/assets/icons/tool.png" // 工具
+import undoIcon from "@/assets/icons/withDrawing.png" // 撤销
+import redoIcon from "@/assets/icons/redo.png" // 重做
+import configIcon from "@/assets/icons/tutorial.png" // 配置
+import navigationIcon from "@/assets/icons/navigation.png" // 导航
+import parameterAssistantIcon from "@/assets/icons/parameterAssistant.png" // 参数助手
+
+const emit = defineEmits(["button-click"])
+
+const fakeTabs = [
+  {
+    name: "layer",
+    label: "图层",
+    type: "",
+    icon: libraryIcon,
+    onClick: () => {
+      console.log("点击了 图层")
+    }
+  },
+  {
+    name: "addLayer",
+    label: "新增图层",
+    type: "",
+    icon: addLayerIcon,
+    onClick: () => {
+      console.log("点击了 导入文件")
+    }
+  }
+]
+
+const tabs = [
+  {
+    name: "show",
+    label: t("tabs.show"),
+    icon: "",
+    buttons: [
+      { action: "cut", label: t("buttons.cut"), icon: cutIcon },
+      { action: "copy", label: t("buttons.copy"), icon: copyIcon },
+      { action: "paste", label: t("buttons.paste"), icon: pasteIcon },
+      { action: "undo", label: t("buttons.undo"), icon: undoIcon },
+      { action: "redo", label: t("buttons.redo"), icon: redoIcon }
+    ]
+  },
+  {
+    name: "view",
+    label: t("tabs.view"),
+    icon: "",
+    buttons: [
+      { action: "importProject", label: t("buttons.importProject"), icon: "" },
+      {action: "importFMU",label: t("buttons.importFMU"),icon: ""},
+      {action: "importCAD",label: t("buttons.importCAD"),icon: ""},
+      {action: "exportXML",label: t("buttons.exportXML"),icon: ""},
+      {action: "exportFMU",label: t("buttons.exportFMU"),icon: ""}
+    ]
+  },
+  {
+    name: "arrange",
+    label: t("tabs.arrange"),
+    icon: configIcon,
+    buttons: [
+      {action: "unitManagement",label: t("buttons.unitManagement"),icon: ""},
+      {action: "preference",label: t("buttons.preference"),icon: ""}
+    ]
+  },
+  {
+    name: "insert",
+    label: t("tabs.insert"),
+    icon: configIcon,
+    buttons: [
+      {action: "unitManagement",label: t("buttons.unitManagement"),icon: ""},
+      {action: "preference",label: t("buttons.preference"),icon: ""}
+    ]
+  },
+  {
+    name: "simulation",
+    label: t("tabs.simulation"),
+    icon: configIcon,
+    buttons: [
+      {action: "unitManagement",label: t("buttons.unitManagement"),icon: ""},
+      {action: "preference",label: t("buttons.preference"),icon: ""}
+    ]
+  },
+  {
+    name: "result",
+    label: t("tabs.result"),
+    icon: configIcon,
+    buttons: [
+      {action: "unitManagement",label: t("buttons.unitManagement"),icon: ""},
+      {action: "preference",label: t("buttons.preference"),icon: ""}
+    ]
+  },
+  {
+    name: "tools",
+    label: t("tabs.tools"),
+    icon: toolIcon,
+    buttons: [
+      { action: "wizard", label: t("buttons.wizard"), icon: navigationIcon },
+      {action: "parameterAssisant",label: t("buttons.parameterAssistant"),icon: parameterAssistantIcon}
+    ]
+  }
+]
+
+const activeTab = ref(tabs[0].name)
+
+const emitButtonClick = (action) => {
+  emit("button-click", action)
+}
+
+const handleTabClick = (tab) => {
+  console.log("Tab switched to:", tab.name)
+}
+</script>
+
+<style scoped>
+.header-button-bar {
+  position: relative; /* 作为绝对定位的参照 */
+  display: flex;
+  align-items: center;
+  width: 100%;
+  background: #ffffff;
+  margin: -1px 0 -3px -1px;
+}
+
+:deep(.el-tabs) {
+  width: 100%;
+}
+
+:deep(.el-tabs__nav-wrap) {
+  width: 100%;
+  position: relative; /* 备用定位参照 */
+}
+
+:deep(.el-tabs__nav) {
+  display: flex;
+  gap: 4px;
+  width: calc(100% - 100px); /* 为 #tab-user 预留空间 */
+}
+.el-button+.el-button{
+    margin-left: 4px;
+}
+
+.custom-tab-nav {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.left-buttons {
+  display: flex;
+  gap: 8px;
+}
+
+.tab-like-button {
+  padding: 8px 16px;
+  font-size: 14px;
+  border: none;
+  background: #fff;
+  transition: all 0.3s;
+}
+
+.tab-like-button:hover {
+  background-color: #f0f0f0;
+  color: #075679;
+}
+
+.tabs-nav {
+  flex: 1;
+}
+
+.button-group {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 4px;
+  padding: 2px;
+}
+
+.button-group .el-button {
+  min-width: 30px;
+  padding: 4px 8px;
+  font-size: 14px;
+  border: none;
+  transition: all 0.3s;
+}
+
+.button-group .el-button:hover {
+  background-color: #f0f0f0;
+  color: #075679;
+}
+
+:deep(.el-tabs__header) {
+  margin: 0;
+  border-bottom: 1px solid #e4e7ed;
+  background-color: #edf2fa;
+}
+
+:deep(.el-tabs--border-card>.el-tabs__content) {
+  padding: 0 !important;
+  background: #ffffff;
+}
+
+.icon-only-button {
+  padding: 0;
+  min-width: 32px;
+  height: 44px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background-color: #edf2fa;
+  border: none;
+}
+
+:deep(.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active) {
+  border-top: none;
+}
+
+.icon-text-button {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.button-icon {
+  width: 16px;
+  height: 16px;
+}
+
+.tab-label {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.tab-icon {
+  width: 16px;
+  height: 16px;
+}
+
+:deep(#tab-layer) {
+  padding: 0 !important;
+}
+
+:deep(#tab-addLayer) {
+  padding: 0 !important;
+}
+
+:deep(#tab-help) {
+  padding: 0 !important;
+}
+
+.open-page-header-icons {
+  width: 150px;
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+}
+
+.open-page-header-icons .el-button {
+  padding: 0;
+  border: none;
+  margin: 0;
+}
+</style>

+ 8 - 2
src/locales/en.json

@@ -163,7 +163,13 @@
     "edit":"Edit",
     "importExport":"Import/Export",
     "config":"Config",
-    "tools":"Tools",
-    "help":"Help"
+    "help":"Help",
+    "show": "Show",
+    "view": "View",
+    "arrange": "Arrange",
+    "insert": "Insert",
+    "simulation": "Simulation",
+    "result": "Result",
+    "tools":"Tools"
   }
 }

+ 8 - 2
src/locales/zh-CN.json

@@ -163,7 +163,13 @@
     "edit":"编辑",
     "importExport":"导入/导出",
     "config":"配置",
-    "tools":"工具",
-    "help":"帮助"
+    "help":"帮助",
+    "show": "显示",
+    "view": "视图",
+    "arrange": "排列",
+    "insert": "插入",
+    "simulation": "仿真",
+    "result": "结果",
+    "tools":"工具"
   }
 }

+ 141 - 87
src/views/model/index.vue

@@ -25,7 +25,7 @@
           class="full-height-tabs"
           @tab-click="handleTabclick"
         >
-        <!-- 组件区域 -->
+          <!-- 组件区域 -->
           <el-tab-pane label="Library" name="Liberal">
             <el-collapse v-model="colactiveNames">
               <el-collapse-item
@@ -62,7 +62,11 @@
               :nodeIcon="systemIcon"
               :expandIcon="expandIcon"
               :collapseIcon="collapseIcon"
-              :treeProps="{ label: 'label', children: 'children', isLeaf: 'isLeaf' }"
+              :treeProps="{
+                label: 'label',
+                children: 'children',
+                isLeaf: 'isLeaf'
+              }"
               @node-click="handleNodeClick"
             />
             <!-- 使用 Element Plus 默认箭头(无前置图标和虚线) -->
@@ -91,10 +95,21 @@
         <splitpanes class="default-theme" horizontal>
           <pane min-size="50" size="75" max-size="100" class="flow-pane">
             <div class="main-header">
-              <el-tabs type="border-card">
+              <div class="header-content">
+                <div class="image-container">
+                  <img :src="expandIcon" alt="Topology Image" />
+                </div>
+                <div class="text-container">
+                  <h2>Topology</h2>
+                </div>
+              </div>
+              <TopoButtonBar @button-click="btnfunc" />
+            </div>
+            <!-- <div class="main-header">
+              <div class="topologyStyle">Topology</div> -->
+              <!-- <el-tabs type="border-card">
                 <el-tab-pane label="Topology">
                   <el-space :size="spacesize" class="spaceclass">
-                    <!-- 放大 -->
                     <el-button
                       title="放大"
                       @click="zoomIn"
@@ -102,8 +117,6 @@
                     >
                       <el-icon><ZoomIn /></el-icon>
                     </el-button>
-
-                    <!-- 缩小 -->
                     <el-button
                       title="缩小"
                       @click="zoomOut"
@@ -111,8 +124,6 @@
                     >
                       <el-icon><ZoomOut /></el-icon>
                     </el-button>
-
-                    <!-- 自适应 -->
                     <el-button
                       title="自适应"
                       @click="fitView"
@@ -181,8 +192,8 @@
                     </el-tooltip>
                   </el-space>
                 </el-tab-pane>
-              </el-tabs>
-            </div>
+              </el-tabs> -->
+            <!-- </div> -->
             <div class="flow-content">
               <vueflow ref="vueflowref" :jobId="jobId" />
             </div>
@@ -195,7 +206,7 @@
                   type="textarea"
                   id="textarea_id"
                   spellcheck="false"
-                  style="height: 100%;font-size: 12px;"
+                  style="height: 100%; font-size: 12px"
                   :autosize="false"
                   resize="none"
                 />
@@ -209,7 +220,7 @@
     <!-- 模拟数据弹窗 -->
     <SLDataDialog ref="SLdatadialogref" @selectRunType="handleSelectRunType" />
     <!-- 运行弹窗 -->
-    <RunDialog ref="RunDialogRef" :runData="arrobj"/>
+    <RunDialog ref="RunDialogRef" :runData="arrobj" />
 
     <!-- 单位系统弹窗 -->
     <SystemUnitDialog
@@ -223,7 +234,6 @@
       @update:visible="showPersonUnitDialog = $event"
       @confirm="handlePersonUnitConfirm"
     />
-
   </el-container>
 </template>
 
@@ -236,7 +246,8 @@ import { useProjectStore } from "@/store/project"
 import { useI18n } from "vue-i18n"
 import vueflow from "./vueflow/index.vue"
 import useDragAndDrop from "./vueflow/useDnD"
-import { ProjectTree } from '@/components/ProjectTree';
+import { ProjectTree } from "@/components/ProjectTree"
+import TopoButtonBar from "@/components/layout/TopoButtonBar.vue"
 import {
   ZoomIn,
   ZoomOut,
@@ -255,11 +266,11 @@ import changebak from "./vueflow/changebak.vue"
 import SLDataDialog from "./dialog/SLDataDialog.vue"
 import RunDialog from "./dialog/RunDialog.vue"
 import { useVueFlow } from "@vue-flow/core"
-import SystemUnitDialog from '@/components/SystemUnitDialog.vue';
-import PersonUnitDialog from '@/components/PersonUnitDialog.vue';
-import systemIcon from '@/assets/img/treeSystemIcon.png';
-import expandIcon from '@/assets/img/treeExpand.png';
-import collapseIcon from '@/assets/img/treeCollapse.png';
+import SystemUnitDialog from "@/components/SystemUnitDialog.vue"
+import PersonUnitDialog from "@/components/PersonUnitDialog.vue"
+import systemIcon from "@/assets/img/treeSystemIcon.png"
+import expandIcon from "@/assets/img/treeExpand.png"
+import collapseIcon from "@/assets/img/treeCollapse.png"
 
 const { zoomIn, zoomOut, fitView } = useVueFlow()
 
@@ -270,43 +281,57 @@ const projectStore = useProjectStore()
 const { onDragStart, onDragLeave, treeobj, onDrop } = useDragAndDrop()
 
 // 树中单元系统的弹窗显示控制
-const showSystemUnitDialog = ref(false);
-const showPersonUnitDialog = ref(false);
+const showSystemUnitDialog = ref(false)
+const showPersonUnitDialog = ref(false)
 // 存储 SystemUnitDialog 的 tableData
-const systemUnitData = ref([]);
+const systemUnitData = ref([])
 
 // 项目树数据
 const treeData = ref([
   {
     id: "root",
-    label: t('treeData.system'),
+    label: t("treeData.system"),
     children: [
-      { id: "systemSetup", label: t('treeData.systemSetup'),children: [{ id: "systemUnit", label: t('treeData.systemUnitView'), children: [] }, { id: "personUnit", label: t('treeData.personUnitSetting'), children: [] }]}
-    ],
-  },
-]);
+      {
+        id: "systemSetup",
+        label: t("treeData.systemSetup"),
+        children: [
+          {
+            id: "systemUnit",
+            label: t("treeData.systemUnitView"),
+            children: []
+          },
+          {
+            id: "personUnit",
+            label: t("treeData.personUnitSetting"),
+            children: []
+          }
+        ]
+      }
+    ]
+  }
+])
 
 // 项目树节点点击事件
 const handleNodeClick = ({ node, data, event }) => {
-  console.log("Node clicked:", node, data, event);
-  if (node.id === 'systemUnit') {
-    console.log("System Unit clicked");
-    showSystemUnitDialog.value = true;
-  } else if (node.id === 'personUnit') {
-    showPersonUnitDialog.value = true;
+  console.log("Node clicked:", node, data, event)
+  if (node.id === "systemUnit") {
+    console.log("System Unit clicked")
+    showSystemUnitDialog.value = true
+  } else if (node.id === "personUnit") {
+    showPersonUnitDialog.value = true
   }
-};
-
+}
 
 // 单元系统弹窗确认事件
 const handleSystemUnitConfirm = () => {
-  showSystemUnitDialog.value = false;
-};
+  showSystemUnitDialog.value = false
+}
 
 // 个人单元弹窗确认事件
 const handlePersonUnitConfirm = () => {
-  showPersonUnitDialog.value = false;
-};
+  showPersonUnitDialog.value = false
+}
 
 const getImgPath = (url) => {
   return new URL(`../../assets/img/${url}`, import.meta.url).href
@@ -373,17 +398,17 @@ let mainbuttons = ref([
 
 const logContent = ref("")
 const arrobj = ref([])
-let websock = ref(null);
+let websock = ref(null)
 let times = ref({
   lockReconnect: false, //是否真正建立连接
   timeout: 28 * 1000, //30秒一次心跳
   timeoutObj: null, //心跳倒计时
   serverTimeoutObj: null, //
-  timeoutnum: null, //断开重连倒计时
+  timeoutnum: null //断开重连倒计时
 })
 
 // 用于分开不同求解运行
-const runtype = ref('');
+const runtype = ref("")
 
 // 获取组件数据
 const getComponent = () => {
@@ -438,25 +463,24 @@ const confirmDelete = () => {
 
 const btnfunc = (name) => {
   if (name === "run") {
-    if(runtype.value === '') {
+    if (runtype.value === "") {
       ElMessage.error("请先设置模拟类型")
       return
-    }else if(runtype.value === 'Incompressible Transient'){
+    } else if (runtype.value === "Incompressible Transient") {
       // 处理不可压缩瞬态的逻辑
       RunDialogRef.value?.openDialog?.()
-    }else if(runtype.value === 'Incompressible Steady State'){
+    } else if (runtype.value === "Incompressible Steady State") {
       // 处理不可压缩稳态的逻辑
-      runProject();
-    }else if(runtype.value === 'Compressible Transient'){
+      runProject()
+    } else if (runtype.value === "Compressible Transient") {
       // 处理可压缩瞬态的逻辑
-    }else if(runtype.value === 'Compressible Steady State'){
+    } else if (runtype.value === "Compressible Steady State") {
       // 处理可压缩稳态的逻辑
-      runProject();
-    }else{
+      runProject()
+    } else {
       ElMessage.error("未知的模拟类型")
       return
     }
-    
   } else if (name === "SLdata") {
     nextTick(() => {
       SLdatadialogref.value?.openDialog?.(pid.value)
@@ -495,8 +519,8 @@ const getresultlist = () => {
       // 处理结果列表数据
       activities.value = res.rows.map((item) => ({
         jobId: item.jobId,
-        content: "结果"+item.ser,
-        timestamp: item.startTime.split(' +')[0]
+        content: "结果" + item.ser,
+        timestamp: item.startTime.split(" +")[0]
       }))
     })
     .catch((err) => {
@@ -519,7 +543,6 @@ const handleTimelineItemClick = (index) => {
   vueflowref.value?.asideDataref?.getresultData(jobId.value)
 }
 
-
 //websockct的连接
 function initWebSocket() {
   //初始化weosocket
@@ -539,15 +562,14 @@ const websocketonopen = (res) => {
 
 // Websoket接收消息事件
 const websocketonmessage = (res) => {
-  console.log('websocket接受消息:',res.data)
+  console.log("websocket接受消息:", res.data)
   if (res.data.indexOf("{") !== -1) {
-    
   } else {
     if (res.data.indexOf("——开始") !== -1) {
       arrobj.value = [] // 清空数据点数组
     }
     if (res.data.indexOf("——成功") !== -1) {
-      getresultlist();//刷新结果列表
+      getresultlist() //刷新结果列表
       const timer = setTimeout(function () {
         console.log("关闭定时器")
       }, 10000)
@@ -580,51 +602,51 @@ const websocketonmessage = (res) => {
 
 // Websoket连接错误事件
 const websocketonerror = (res) => {
-  console.log("连接错误", res);
-  websock.close();
-  reconnect();
-};
+  console.log("连接错误", res)
+  websock.close()
+  reconnect()
+}
 // Websoket断开事件
 const websocketclose = (res) => {
-  console.log("断开连接", res);
-};
+  console.log("断开连接", res)
+}
 
 // 心跳包
 const reconnect = () => {
-  if (times.value.lockReconnect) return;
-  times.value.lockReconnect = true;
+  if (times.value.lockReconnect) return
+  times.value.lockReconnect = true
   //没连接上会一直重连,设置延迟避免请求过多
-  times.value.timeoutnum && clearTimeout(times.value.timeoutnum);
+  times.value.timeoutnum && clearTimeout(times.value.timeoutnum)
   times.value.timeoutnum = setTimeout(function () {
     //新连接
-    initWebSocket();
-    times.value.lockReconnect = false;
-  }, 10000);
+    initWebSocket()
+    times.value.lockReconnect = false
+  }, 10000)
 }
 const reset = () => {
   //重置心跳
-  clearTimeout(times.value.timeoutObj);
-  clearTimeout(times.value.serverTimeoutObj);
-  start();
+  clearTimeout(times.value.timeoutObj)
+  clearTimeout(times.value.serverTimeoutObj)
+  start()
 }
 const start = () => {
   //开启心跳
-  times.value.timeoutObj && clearTimeout(times.value.timeoutObj);
-  times.value.serverTimeoutObj && clearTimeout(times.value.serverTimeoutObj);
+  times.value.timeoutObj && clearTimeout(times.value.timeoutObj)
+  times.value.serverTimeoutObj && clearTimeout(times.value.serverTimeoutObj)
   times.value.timeoutObj = setTimeout(function () {
     //这里发送一个心跳,后端收到后,返回一个心跳消息
     if (websock.readyState == 1) {
       //如果连接正常
-      websock.send("heartCheck");
+      websock.send("heartCheck")
     } else {
       //否则重连
-      reconnect();
+      reconnect()
     }
     times.value.serverTimeoutObj = setTimeout(function () {
       // 超时关闭
-      websock.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
-    }, times.value.timeout);
-  }, times.value.timeout);
+      websock.close() //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
+    }, times.value.timeout)
+  }, times.value.timeout)
 }
 
 const getlogs = () => {
@@ -635,7 +657,10 @@ const getlogs = () => {
   request(params)
     .then((res) => {
       // console.log("获取日志成功", res)
-      logContent.value = res.logs.split('\n').filter(line => line.trim() !== '').join('\n');
+      logContent.value = res.logs
+        .split("\n")
+        .filter((line) => line.trim() !== "")
+        .join("\n")
       // 自动滚动日志到底部
       let textarea = document.getElementById("textarea_id")
       textarea.scrollTop = textarea.scrollHeight
@@ -647,14 +672,14 @@ const getlogs = () => {
 }
 
 onMounted(() => {
-  runtype.value = projectStore.runtype || '';
+  runtype.value = projectStore.runtype || ""
 
   getComponent()
 
   setTimeout(function () {
-    initWebSocket();
-    getlogs();
-  }, 1500);
+    initWebSocket()
+    getlogs()
+  }, 1500)
 })
 
 // onBeforeUnmount(() => {
@@ -662,8 +687,6 @@ onMounted(() => {
 //   clearTimeout(times.value.timeoutObj)
 //   clearTimeout(times.value.serverTimeoutObj)
 // })
-
-
 </script>
 
 <style scoped>
@@ -676,7 +699,30 @@ onMounted(() => {
 .main-header {
   background: #eeeeee;
   border-radius: 0px 0px 0px 0px;
-  border: 4px solid #eeeeee;
+  border: 2px solid #eeeeee;
+}
+
+.header-content {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  max-width: 140px;
+  background-color: #ffffff;
+  padding: 0;
+  margin: 0;
+  border-top: #77c5e6 3px solid;
+}
+
+.image-container {
+  flex: 1;
+  max-width: 50%;
+  padding-right: 10px;
+}
+
+.image-container img {
+  width: 100%;
+  height: auto;
+  object-fit: cover;
 }
 
 .diysplitpanes {
@@ -722,4 +768,12 @@ onMounted(() => {
 .btn-icon {
   font-size: 16px;
 }
+
+.topologyStyle {
+  width: 80px;
+  height: 30px;
+  font-size: 18px;
+  border-top: 3px solid #77c5e6;
+  background-color: #ffffff;
+}
 </style>