|
@@ -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>
|