merge
This commit is contained in:
@@ -140,3 +140,11 @@ export const queryKeyResultAndTaskInfoApi = (params: any) => {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询流程节点列表
|
||||
* @param params runId 算例的uuid
|
||||
* @returns
|
||||
*/
|
||||
export const listSimulationFlowNodeApi = (params: any) => {
|
||||
return post(`${PREFIX}run/listFlowNodes`, params);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<!-- <el-button @click="exportJson">导出json</el-button>
|
||||
<el-button @click="importJson">导入json</el-button> -->
|
||||
<div class="header-box" id="header-box" v-if="showConfigPage">
|
||||
<div class="header-box" id="header-box">
|
||||
<div class="left-box">
|
||||
<span class="name">{{ flowName }}</span>
|
||||
<!-- <span class="line">|</span>
|
||||
@@ -22,12 +22,12 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="showConfigPage? 'flow-view-box' : 'flow-view-box-all'" v-loading="contentLoading">
|
||||
<div class="flow-view-box" v-loading="contentLoading">
|
||||
<div id="flow-view-content">
|
||||
</div>
|
||||
</div>
|
||||
<TeleportContainer />
|
||||
<FlowConfig v-model="drawerVisible" :nodeAttribute="nodeAttribute" @update:drawer-visible="drawerVisible = false"></FlowConfig>
|
||||
<FlowConfig v-model="drawerVisible" :nodeAttribute="nodeAttribute"></FlowConfig>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -58,14 +58,8 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
showConfigPage: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['detail']);
|
||||
|
||||
const flowName = ref('');
|
||||
|
||||
const currentVersion = ref<any>();
|
||||
@@ -161,12 +155,7 @@ const initGraph = async() => {
|
||||
console.log('click node', node);
|
||||
if (node.data.isApp) {
|
||||
nodeAttribute.value = node.data;
|
||||
if (props.showConfigPage) {
|
||||
drawerVisible.value = true;
|
||||
} else {
|
||||
emits('detail', node);
|
||||
}
|
||||
;
|
||||
drawerVisible.value = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -203,10 +192,6 @@ onMounted(async() => {
|
||||
.flow-view-box {
|
||||
height: calc(100% - 40px);
|
||||
|
||||
}
|
||||
|
||||
.flow-view-box-all{
|
||||
height:100%
|
||||
}
|
||||
#header-box {
|
||||
padding: 0;
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
<template>
|
||||
<div class="flow-node-param-page">
|
||||
<BaseTable ref="baseTableRef" hide-pagination tableName="FLOW_NODE_PARAM">
|
||||
<template #value="{ row }">
|
||||
<BaseTable
|
||||
ref="baseTableRef"
|
||||
hide-pagination
|
||||
tableName="FLOW_NODE_PARAM"
|
||||
>
|
||||
|
||||
<template #leftOptions>
|
||||
<el-button type="primary">参数入库</el-button>
|
||||
<el-button type="primary">保存参数</el-button>
|
||||
<el-button type="">引用参数</el-button>
|
||||
</template>
|
||||
|
||||
<template #value="{ row, column }">
|
||||
<div class="pr10 tableCellContent">
|
||||
|
||||
<div
|
||||
class="numInput flex-div"
|
||||
v-if="(row.type === WIDGET_TYPE.INPUTS || row.type === WIDGET_TYPE.INPUT) && row.englishLabel"
|
||||
v-if="(row.tagType === WIDGET_TYPE.INPUTS || row.tagType === WIDGET_TYPE.INPUT) && row.englishLabel"
|
||||
>
|
||||
<div
|
||||
class="input-grid"
|
||||
@@ -32,7 +43,7 @@
|
||||
</div>
|
||||
<!-- 2下拉框-->
|
||||
<el-select
|
||||
v-if="row.type === WIDGET_TYPE.SELECT"
|
||||
v-if="row.tagType === WIDGET_TYPE.SELECT"
|
||||
:multiple="row.isMultiple === '1'"
|
||||
:title="row.value"
|
||||
v-model="row.value"
|
||||
@@ -50,9 +61,9 @@
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 4单选框 -->
|
||||
<el-checkbox v-if="row.type === WIDGET_TYPE.CHECKBOX" v-model="row.value" true-value="1" false-value="0" />
|
||||
<el-checkbox v-if="row.tagType === WIDGET_TYPE.CHECKBOX" v-model="row.value" true-value="1" false-value="0" />
|
||||
<!-- 多选框 -->
|
||||
<div v-if="row.type === WIDGET_TYPE.CHECKBOXS">
|
||||
<div v-if="row.tagType === WIDGET_TYPE.CHECKBOXS">
|
||||
<div
|
||||
class="input-grid"
|
||||
:style="{
|
||||
@@ -75,7 +86,7 @@
|
||||
|
||||
<div
|
||||
class="numInput flex-div"
|
||||
v-if="row.type === WIDGET_TYPE.NUMBER_INPUTS || row.type === WIDGET_TYPE.NUMBER_INPUT"
|
||||
v-if="row.tagType === WIDGET_TYPE.NUMBER_INPUTS || row.tagType === WIDGET_TYPE.NUMBER_INPUT"
|
||||
>
|
||||
<!-- <el-input-number :precision="row.decimals" controls-position="right"
|
||||
v-model="row.value"></el-input-number> -->
|
||||
@@ -120,14 +131,14 @@
|
||||
<span class="ml10" v-else>{{ row.unit }}</span>
|
||||
</div>
|
||||
<!-- 6单纯显示内容,无法编辑 -->
|
||||
<div v-if="row.type === WIDGET_TYPE.VIEW">
|
||||
<div v-if="row.tagType === WIDGET_TYPE.VIEW">
|
||||
<el-icon class="colorIcon" v-if="isLoadingBaseInfo">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
{{ row.value }}
|
||||
</div>
|
||||
<!-- 滑块 -->
|
||||
<div v-if="row.type === WIDGET_TYPE.SLIDER" class="slider">
|
||||
<div v-if="row.tagType === WIDGET_TYPE.SLIDER" class="slider">
|
||||
<span class="value">{{ row.value }}</span>
|
||||
<input
|
||||
class="slider-input"
|
||||
@@ -143,7 +154,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 批量选择框控件 -->
|
||||
<div v-if="row.type === WIDGET_TYPE.BATCH_LOADCASE" class="INCLFileList loadcaseList">
|
||||
<div v-if="row.tagType === WIDGET_TYPE.BATCH_LOADCASE" class="INCLFileList loadcaseList">
|
||||
<el-checkbox v-model="row.isAllChecked" @change="changeBatchLoadcase($event, row)">全选</el-checkbox>
|
||||
<el-checkbox-group v-model="row.checkedList" @change="changeBatchLoadcaseNum(row)">
|
||||
<el-checkbox
|
||||
@@ -161,7 +172,7 @@
|
||||
<div
|
||||
class="localServer"
|
||||
v-if="
|
||||
row.type === WIDGET_TYPE.FILE || row.type === NODE_TYPE.SCRIPT || row.type === NODE_TYPE.PPT
|
||||
row.tagType === WIDGET_TYPE.FILE || row.tagType === NODE_TYPE.SCRIPT || row.tagType === NODE_TYPE.PPT
|
||||
"
|
||||
>
|
||||
<!-- <server-local-file
|
||||
@@ -268,6 +279,9 @@ const changeBatchLoadcaseNum = (record: any) => {
|
||||
watch(() => props.nodeParams, (newVal) => {
|
||||
if (newVal) {
|
||||
tableData.value = newVal;
|
||||
|
||||
console.log(tableData.value, 'tableData.value');
|
||||
|
||||
nextTick(() => {
|
||||
baseTableRef.value.setDataFun(tableData.value);
|
||||
});
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
|
||||
<span class="status-title">{{ currentRunNodeInfo?.status? statusList[currentRunNodeInfo?.status]:'未开始' }}</span>
|
||||
<span class="status-title">{{ currentRunNodeInfo?.status ? statusList[currentRunNodeInfo?.status] : '未开始'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -59,7 +60,7 @@
|
||||
</div>
|
||||
|
||||
<div class="run-flow-box">
|
||||
<FlowView v-if="runInfo.flowTemplate" :show-config-page="false" :flow-uuid="runInfo.flowTemplate" @detail="getNodeTailFun"></FlowView>
|
||||
<runFlowPage v-if="runInfo.flowTemplate" :run-info="runInfo" @change="changeCurrentFlowNodeFun"></runFlowPage>
|
||||
</div>
|
||||
|
||||
<div class="run-info-box">
|
||||
@@ -80,8 +81,16 @@
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="tabs-info-content">
|
||||
<paramSetting v-if="nodeActiveName === 'param'"></paramSetting>
|
||||
<runDataPage v-else></runDataPage>
|
||||
<paramSetting
|
||||
v-if="nodeActiveName === 'param'"
|
||||
:current-run-flow-node="flowNode"
|
||||
:node-param-data="nodeParamDataList"
|
||||
></paramSetting>
|
||||
<runDataPage
|
||||
v-else
|
||||
:file-id="nodeActiveName === 'input' ? flowNodeData?.inputDirId : flowNodeData?.outputDirId"
|
||||
:node-info="flowNodeData"
|
||||
></runDataPage>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -106,7 +115,12 @@
|
||||
<div class="tabs-info-content">
|
||||
<resultData v-if="taskActiveName === 'result'" :current-run-ifno="runInfo"></resultData>
|
||||
<jobList v-if="taskActiveName === 'job-list'"></jobList>
|
||||
<taskPerformance v-if="taskActiveName === 'performance'" :param-type="'run'" :run-info="runInfo" :show-save-button="true"></taskPerformance>
|
||||
<taskPerformance
|
||||
v-if="taskActiveName === 'performance'"
|
||||
:param-type="'run'"
|
||||
:run-info="runInfo"
|
||||
:show-save-button="true"
|
||||
></taskPerformance>
|
||||
<runLogs v-if="taskActiveName === 'job-log'"></runLogs>
|
||||
<ModelReview v-if="taskActiveName === '3D-model'"></ModelReview>
|
||||
<runVersionTree v-if="taskActiveName === 'associated-run'" :current-task-info="runInfo"></runVersionTree>
|
||||
@@ -131,12 +145,12 @@ import taskPerformance from '@/components/taskDetail/taskPerformance.vue';
|
||||
import runLogs from './runPagecomponent/runLogs.vue';
|
||||
import ModelReview from './runPagecomponent/3DModelReview.vue';
|
||||
import runVersionTree from './runPagecomponent/runVersionTree.vue';
|
||||
import FlowView from '@/components/common/flow/flowView.vue';
|
||||
import runFlowPage from './runPagecomponent/flow/runFlowPage.vue';
|
||||
|
||||
const props = defineProps({
|
||||
runInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
default: () => { },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -155,8 +169,17 @@ const handleRightClickFun = () => {
|
||||
|
||||
};
|
||||
|
||||
const getNodeTailFun = (node:any) => {
|
||||
const nodeParamDataList = ref<any>([]);
|
||||
|
||||
const flowNode = ref<any>({});
|
||||
const flowNodeData = ref<any>({});
|
||||
const changeCurrentFlowNodeFun = (info: any) => {
|
||||
const { node, data }: any = info;
|
||||
console.log(node, 'node');
|
||||
console.log(data, 'data');
|
||||
flowNode.value = node;
|
||||
flowNodeData.value = data;
|
||||
nodeParamDataList.value = flowNode.value?.store?.data?.data?.pageConfigList || [];
|
||||
|
||||
};
|
||||
|
||||
@@ -261,14 +284,15 @@ watch(() => props.runInfo, (newVal) => {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.info-box-left,.info-box-right {
|
||||
.info-box-left,
|
||||
.info-box-right {
|
||||
width: calc(50% - 5px);
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
|
||||
.bottom-title{
|
||||
.bottom-title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
@@ -276,34 +300,34 @@ watch(() => props.runInfo, (newVal) => {
|
||||
justify-content: space-between;
|
||||
padding-left: 10px;
|
||||
|
||||
.title-name{
|
||||
.title-name {
|
||||
padding-left: 10px;
|
||||
border-left: 3px solid var(--el-color-primary);
|
||||
border-left: 3px solid var(--el-color-primary);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
|
||||
}
|
||||
|
||||
.title-operate{
|
||||
.title-operate {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-info-content{
|
||||
.bottom-info-content {
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding: 0 10px;
|
||||
|
||||
.tabs-box{
|
||||
.tabs-box {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.tabs-info-content{
|
||||
.tabs-info-content {
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding: 10px;
|
||||
@@ -327,7 +351,7 @@ watch(() => props.runInfo, (newVal) => {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.status-title{
|
||||
.status-title {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="custom-node">
|
||||
<img class="app-icon" v-if="appProperty.iconUrl" :src="appProperty.iconUrl" alt="">
|
||||
<div class="app-icon app-text" v-else>{{ appProperty?.name.split('')[0] }}</div>
|
||||
<div class="app-info">
|
||||
<div class="app-name" :title="appProperty.name">{{ appProperty.name }}</div>
|
||||
<div class="app-tag">{{ appProperty.type }}</div>
|
||||
</div>
|
||||
<div class="app-status">
|
||||
|
||||
<div class="round" :style="{ background:getStyleFun(appProperty.status).color}"></div>
|
||||
<div class="text" >{{ getStyleFun(appProperty.status).title }}</div>
|
||||
|
||||
</div>
|
||||
<!-- <div>
|
||||
<span @click="attributeFun">属性</span>
|
||||
<span @click="paramFun">参数</span>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject, onMounted, reactive } from 'vue';
|
||||
// import { setNodeAttribute } from './nodeEvents';
|
||||
|
||||
// const emits = defineEmits(['attribute', 'param']);
|
||||
|
||||
const appProperty = reactive({
|
||||
name: '',
|
||||
iconUrl: '',
|
||||
type: '',
|
||||
status: '',
|
||||
});
|
||||
|
||||
const getNode:any = inject('getNode');
|
||||
|
||||
// const attributeFun = () => {
|
||||
// console.log('click attributeFun');
|
||||
// setNodeAttribute(appProperty);
|
||||
// };
|
||||
|
||||
// const paramFun = () => {
|
||||
// emits('param', appProperty);
|
||||
// };
|
||||
|
||||
const getStyleFun = (flag:any) => {
|
||||
const styles:any = {
|
||||
active: {
|
||||
color: '#409eff',
|
||||
title: '进行中',
|
||||
},
|
||||
finished: {
|
||||
color: '#67c23a',
|
||||
title: '已完成',
|
||||
},
|
||||
pending: {
|
||||
color: '#909399',
|
||||
title: '未开始',
|
||||
},
|
||||
};
|
||||
|
||||
if (styles[flag]) {
|
||||
return styles[flag];
|
||||
} else {
|
||||
return {
|
||||
color: '#f56c6c',
|
||||
title: '异常',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (getNode) {
|
||||
|
||||
const node = getNode();
|
||||
console.log('getNode()', node, node.getData());
|
||||
const data = node.getData();
|
||||
if (data?.label) {
|
||||
appProperty.name = data.label;
|
||||
appProperty.iconUrl = data.iconUrl;
|
||||
appProperty.type = data.type;
|
||||
appProperty.status = data.flowNodeInfo.nodeStatus || 'pending';
|
||||
// console.log('data', data, appProperty);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.custom-node {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
.app-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin-right: 8px;
|
||||
background-color: #F2F2F2;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.app-text {
|
||||
|
||||
}
|
||||
.app-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100px;
|
||||
}
|
||||
.app-status{
|
||||
width: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.round{
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background-color: #191919;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.text{
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.app-name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #191919;
|
||||
width: 83px;
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出的内容 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
}
|
||||
.app-tag {
|
||||
font-size: 12px;
|
||||
color: #595959;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,146 @@
|
||||
import { register } from '@antv/x6-vue-shape';
|
||||
import AppNode from './registerAppNode.vue';
|
||||
import { Graph } from '@antv/x6';
|
||||
|
||||
export const registerCustomNode = () => {
|
||||
|
||||
const ports = {
|
||||
groups: {
|
||||
top: {
|
||||
position: 'top',
|
||||
attrs: {
|
||||
circle: {
|
||||
r: 4,
|
||||
magnet: true,
|
||||
stroke: '#5F95FF',
|
||||
strokeWidth: 1,
|
||||
fill: '#fff',
|
||||
style: {
|
||||
visibility: 'hidden',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
right: {
|
||||
position: 'right',
|
||||
attrs: {
|
||||
circle: {
|
||||
r: 4,
|
||||
magnet: true,
|
||||
stroke: '#5F95FF',
|
||||
strokeWidth: 1,
|
||||
fill: '#fff',
|
||||
style: {
|
||||
visibility: 'hidden',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
bottom: {
|
||||
position: 'bottom',
|
||||
attrs: {
|
||||
circle: {
|
||||
r: 4,
|
||||
magnet: true,
|
||||
stroke: '#5F95FF',
|
||||
strokeWidth: 1,
|
||||
fill: '#fff',
|
||||
style: {
|
||||
visibility: 'hidden',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
left: {
|
||||
position: 'left',
|
||||
attrs: {
|
||||
circle: {
|
||||
r: 4,
|
||||
magnet: true,
|
||||
stroke: '#5F95FF',
|
||||
strokeWidth: 1,
|
||||
fill: '#fff',
|
||||
style: {
|
||||
visibility: 'hidden',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
items: [
|
||||
{
|
||||
group: 'top',
|
||||
},
|
||||
{
|
||||
group: 'right',
|
||||
},
|
||||
{
|
||||
group: 'bottom',
|
||||
},
|
||||
{
|
||||
group: 'left',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 自定义的画布中的显示节点
|
||||
register({
|
||||
shape: 'custom-app-vue-node',
|
||||
type: 'app',
|
||||
width: 220,
|
||||
height: 56,
|
||||
component: AppNode,
|
||||
ports: ports,
|
||||
});
|
||||
|
||||
// 自定义的左侧拖拽的节点
|
||||
Graph.registerNode(
|
||||
'custom-stencil-node',
|
||||
{
|
||||
inherit: 'rect',
|
||||
width: 50,
|
||||
height: 70,
|
||||
markup: [
|
||||
{
|
||||
tagName: 'rect',
|
||||
selector: 'body',
|
||||
attrs: {
|
||||
fill: '#333',
|
||||
textAnchor: 'middle',
|
||||
textVerticalAnchor: 'middle',
|
||||
},
|
||||
},
|
||||
{
|
||||
tagName: 'image',
|
||||
},
|
||||
{
|
||||
tagName: 'text',
|
||||
selector: 'label',
|
||||
},
|
||||
],
|
||||
attrs: {
|
||||
body: {
|
||||
stroke: '#fff',
|
||||
fill: '#fff',
|
||||
},
|
||||
image: { // 图片布局设置
|
||||
width: 50,
|
||||
height: 50,
|
||||
fill: '#F0F0F0',
|
||||
// refX: 5,
|
||||
// refY: 5,
|
||||
},
|
||||
label: { // 文本布局设置
|
||||
dominantBaseline: 'middle',
|
||||
y: 20,
|
||||
// textAnchor: 'center',
|
||||
// textVerticalAnchor: 'bottom',
|
||||
fontSize: 10,
|
||||
// fill: '#1F1F1F',
|
||||
},
|
||||
},
|
||||
// ports: { ...ports },
|
||||
},
|
||||
true
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,266 @@
|
||||
<template>
|
||||
<div class="run-flow-page" >
|
||||
<div class="flow-content" id="flow-view-content" v-loading="contentLoading"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineProps, defineEmits, watch, onMounted, nextTick } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Graph } from '@antv/x6';
|
||||
import { queryFlowTemplateDetailApi } from '@/api/capability/flow';
|
||||
import { createNode, getNodeList } from '@/views/simulation/creation/components/stencil';
|
||||
import { objectTypeArrayRemovesDuplicates } from '@/utils/common';
|
||||
import { registerCustomNode } from './registerNode';
|
||||
import { listSimulationFlowNodeApi } from '@/api/project/run';
|
||||
|
||||
const props = defineProps({
|
||||
runInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['change']);
|
||||
|
||||
const contentLoading = ref(false);
|
||||
|
||||
const graph = ref<any>();
|
||||
const flowName = ref<any>();
|
||||
|
||||
const nodeDataList = ref<any>([]);
|
||||
const querLlistSimulationFlowNode = async (id:any) => {
|
||||
const res:any = await listSimulationFlowNodeApi({
|
||||
runId: id,
|
||||
});
|
||||
if (res && res.code === 200) {
|
||||
nodeDataList.value = res.data;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const getFlowDetail = async(uuid:string) => {
|
||||
contentLoading.value = true;
|
||||
const res:any = await queryFlowTemplateDetailApi({ uuid: uuid, status: 1 });
|
||||
if (res.code === 200) {
|
||||
if (res.data.viewContent.length > 50) {
|
||||
const dataJson = JSON.parse(res.data.viewContent);
|
||||
const beginandend = dataJson.cells.filter((item:any) => {
|
||||
return item.type === 'local' || item?.data?.label === '起始节点' || item?.data?.label === '结束节点';
|
||||
});
|
||||
const ids = beginandend.map((item:any) => {
|
||||
return item.id;
|
||||
});
|
||||
dataJson.cells = dataJson.cells.filter((item:any) => {
|
||||
return !ids.includes(item.id) && !ids.includes(item?.source?.cell) && !ids.includes(item?.target?.cell);
|
||||
});
|
||||
const nodes = dataJson.cells.filter((item:any) => {
|
||||
return item?.type;
|
||||
});
|
||||
let position = nodes.map((item:any) => {
|
||||
return item?.position?.x;
|
||||
});
|
||||
position = objectTypeArrayRemovesDuplicates(position, 2);
|
||||
for (let i = 0;i < position.length;i++) {
|
||||
|
||||
for (let j = 0;j < dataJson.cells.length;j++) {
|
||||
if (dataJson.cells[j]?.position?.x === position[i]) {
|
||||
dataJson.cells[j].rank = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0;i < dataJson.cells.length;i++) {
|
||||
if (dataJson.cells[i].type ) {
|
||||
dataJson.cells[i].size.width = 220;
|
||||
dataJson.cells[i].position.x = dataJson.cells[i].position.x + dataJson.cells[i].rank * 70;
|
||||
|
||||
for (let j = 0;j < nodeDataList.value.length;j++) {
|
||||
if (dataJson.cells[i].id === nodeDataList.value[j].nodeId) {
|
||||
dataJson.cells[i].data.flowNodeInfo = nodeDataList.value[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(dataJson, 'dataJson');
|
||||
// console.log(nodeDataList.value, 'nodeDataList');
|
||||
|
||||
setTimeout(() => {
|
||||
graph.value.fromJSON(dataJson);
|
||||
graph.value.centerContent();
|
||||
contentLoading.value = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
contentLoading.value = false;
|
||||
}
|
||||
flowName.value = res.data.templateName;
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
};
|
||||
|
||||
const selectNode = ref<any>({});
|
||||
const initGraph = async() => {
|
||||
graph.value = new Graph({
|
||||
panning: {
|
||||
enabled: true,
|
||||
},
|
||||
interacting: {
|
||||
// 禁用画布拖拽
|
||||
nodeMovable: false,
|
||||
},
|
||||
container: document.getElementById('flow-view-content') as HTMLElement,
|
||||
autoResize: true,
|
||||
// 画布的最小最大缩放级别
|
||||
scaling: { min: 0.5, max: 3 },
|
||||
grid: true,
|
||||
// width: 800,
|
||||
// height: 800,
|
||||
background: {
|
||||
color: '#F2F7FA',
|
||||
},
|
||||
});
|
||||
registerCustomNode();
|
||||
const nodeList = await getNodeList();
|
||||
createNode(nodeList, graph.value);
|
||||
|
||||
graph.value.on('node:click', ({ node }:any) => {
|
||||
selectNode.value = node;
|
||||
const allNodes = graph.value.getNodes();
|
||||
for (let i = 0;i < allNodes.length;i++) {
|
||||
if (selectNode.value.id === allNodes[i].id) {
|
||||
allNodes[i].addTools({
|
||||
name: 'boundary',
|
||||
args: {
|
||||
padding: 0,
|
||||
attrs: {
|
||||
// fill: '#7c68fc',
|
||||
stroke: '#0366FF ',
|
||||
'stroke-width': 2,
|
||||
'stroke-dasharray': '',
|
||||
rx: 4,
|
||||
ry: 4,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
localStorage.setItem('CURRENT_RUN_FLOW_NODE_INFO', allNodes[i].id);
|
||||
} else {
|
||||
allNodes[i].removeTools();
|
||||
}
|
||||
}
|
||||
|
||||
const data = nodeDataList.value.find((item:any) => {
|
||||
return item.nodeId === node.id;
|
||||
});
|
||||
|
||||
emits('change', {
|
||||
node,
|
||||
data,
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// 设置默认点击节点
|
||||
const setCurrentNodeFun = () => {
|
||||
|
||||
const allNodes = graph.value.getNodes();
|
||||
const currentId = localStorage.getItem('CURRENT_RUN_FLOW_NODE_INFO') || '';
|
||||
if (currentId) {
|
||||
const currentNodes = allNodes.find((item:any) => {
|
||||
return item.id === currentId;
|
||||
});
|
||||
if (currentNodes) {
|
||||
currentNodes.addTools({
|
||||
name: 'boundary',
|
||||
args: {
|
||||
padding: 0,
|
||||
attrs: {
|
||||
// fill: '#7c68fc',
|
||||
stroke: '#0366FF ',
|
||||
'stroke-width': 2,
|
||||
'stroke-dasharray': '',
|
||||
rx: 4,
|
||||
ry: 4,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
allNodes[0].addTools({
|
||||
name: 'boundary',
|
||||
args: {
|
||||
padding: 0,
|
||||
attrs: {
|
||||
// fill: '#7c68fc',
|
||||
stroke: '#0366FF ',
|
||||
'stroke-width': 2,
|
||||
'stroke-dasharray': '',
|
||||
rx: 4,
|
||||
ry: 4,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
allNodes[0].addTools({
|
||||
name: 'boundary',
|
||||
args: {
|
||||
padding: 0,
|
||||
attrs: {
|
||||
// fill: '#7c68fc',
|
||||
stroke: '#0366FF ',
|
||||
'stroke-width': 2,
|
||||
'stroke-dasharray': '',
|
||||
rx: 4,
|
||||
ry: 4,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
watch(() => props.runInfo, async (newVal) => {
|
||||
|
||||
if (newVal) {
|
||||
|
||||
// currentRunNodeInfo.value = newVal;
|
||||
// await initGraph();
|
||||
// await getFlowDetail(currentRunNodeInfo.value.flowTemplate);
|
||||
// await querLlistSimulationFlowNode(currentRunNodeInfo.value.uuid);
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
});
|
||||
|
||||
onMounted( async() => {
|
||||
setTimeout( async() => {
|
||||
if (props.runInfo) {
|
||||
await initGraph();
|
||||
await querLlistSimulationFlowNode(props.runInfo.uuid);
|
||||
await getFlowDetail(props.runInfo.flowTemplate);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.run-flow-page{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.flow-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="param-set-page">
|
||||
<flowNodeParamTable></flowNodeParamTable>
|
||||
<flowNodeParamTable :node-params="nodeParamData"></flowNodeParamTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -9,21 +9,24 @@ import { ref, watch } from 'vue';
|
||||
import flowNodeParamTable from '@/components/flow/flowNodeParamTable.vue';
|
||||
|
||||
const props = defineProps({
|
||||
currentNodeInfo: {
|
||||
currentRunFlowNode: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
|
||||
},
|
||||
},
|
||||
nodeParamData: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const nodeParamInfo = ref<any>({});
|
||||
|
||||
watch(() => props.currentNodeInfo, (newVal) => {
|
||||
watch(() => props.currentRunFlowNode, (newVal) => {
|
||||
|
||||
if (newVal) {
|
||||
nodeParamInfo.value = newVal;
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -7,12 +7,18 @@
|
||||
showIndex
|
||||
ref="baseTableRef"
|
||||
tableName="RUN_RESULT_FILE_TABLE"
|
||||
:api="queryRunDirFun"
|
||||
:params="{
|
||||
fileId:fileId,
|
||||
// uuid:nodeInfo.uuid
|
||||
}"
|
||||
:show-checkbox="true"
|
||||
>
|
||||
<template #leftOptions>
|
||||
<el-upload :show-file-list="false" :before-upload="beforeUploadFun">
|
||||
<el-button>上传文件</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" class="ml10">下载文件</el-button>
|
||||
<el-button type="primary" class="ml10" @click="downLoadFileFun">下载文件</el-button>
|
||||
</template>
|
||||
</BaseTable>
|
||||
</div>
|
||||
@@ -21,23 +27,80 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import BaseTable from '@/components/common/table/baseTable.vue';
|
||||
import { queryRunDirApi, uploadRunFilesApi } from '@/api/project/run';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const env = import.meta.env;
|
||||
|
||||
const props = defineProps({
|
||||
currentNodeInfo: {
|
||||
nodeInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
fileId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const baseTableRef = ref();
|
||||
const nodeInfo = ref<any>({});
|
||||
const beforeUploadFun = () => {
|
||||
const beforeUploadFun = async (file:any) => {
|
||||
|
||||
if (!props.fileId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { name } = file;
|
||||
|
||||
const param = {
|
||||
file,
|
||||
dirId: props.fileId,
|
||||
fileName: name,
|
||||
fileType: 1,
|
||||
};
|
||||
|
||||
await uploadRunFilesApi(param).then(async (res:any) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('上传成功');
|
||||
await reloadFun();
|
||||
}
|
||||
}).finally(() => {
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
watch(() => props.currentNodeInfo, (newVal) => {
|
||||
const queryRunDirFun = async (param:any) => {
|
||||
if (param.fileId) {
|
||||
const res:any = await queryRunDirApi(param);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
const downLoadFileFun = async () => {
|
||||
|
||||
const ckeckData = baseTableRef.value.tableRef.getCheckboxRecords();
|
||||
|
||||
for (let i = 0;i < ckeckData.length;i++) {
|
||||
|
||||
const downloadUrl = `${env.VITE_API_FILE_URL}/data/downloadFile?fileId=${ckeckData[i].id}`;
|
||||
window.open(downloadUrl, '_blank');
|
||||
|
||||
}
|
||||
|
||||
console.log(ckeckData, 'ckeckData');
|
||||
|
||||
};
|
||||
|
||||
const reloadFun = async () => {
|
||||
if (baseTableRef.value) {
|
||||
await baseTableRef.value.resetFun();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => props.nodeInfo, (newVal) => {
|
||||
if (newVal) {
|
||||
nodeInfo.value = newVal;
|
||||
}
|
||||
|
||||
}, {
|
||||
|
||||
Reference in New Issue
Block a user