update:任务执行,算例的流程节点相关

This commit is contained in:
2025-12-01 19:13:11 +08:00
parent ef82bb9016
commit 86d2f11dc7
9 changed files with 713 additions and 57 deletions

View File

@@ -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);
};

View File

@@ -1,7 +1,7 @@
<template> <template>
<!-- <el-button @click="exportJson">导出json</el-button> <!-- <el-button @click="exportJson">导出json</el-button>
<el-button @click="importJson">导入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"> <div class="left-box">
<span class="name">{{ flowName }}</span> <span class="name">{{ flowName }}</span>
<!-- <span class="line">|</span> <!-- <span class="line">|</span>
@@ -22,12 +22,12 @@
</el-select> </el-select>
</div> </div>
</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 id="flow-view-content">
</div> </div>
</div> </div>
<TeleportContainer /> <TeleportContainer />
<FlowConfig v-model="drawerVisible" :nodeAttribute="nodeAttribute" @update:drawer-visible="drawerVisible = false"></FlowConfig> <FlowConfig v-model="drawerVisible" :nodeAttribute="nodeAttribute"></FlowConfig>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -58,14 +58,8 @@ const props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
showConfigPage: {
type: Boolean,
default: true,
},
}); });
const emits = defineEmits(['detail']);
const flowName = ref(''); const flowName = ref('');
const currentVersion = ref<any>(); const currentVersion = ref<any>();
@@ -161,12 +155,7 @@ const initGraph = async() => {
console.log('click node', node); console.log('click node', node);
if (node.data.isApp) { if (node.data.isApp) {
nodeAttribute.value = node.data; nodeAttribute.value = node.data;
if (props.showConfigPage) { drawerVisible.value = true;
drawerVisible.value = true;
} else {
emits('detail', node);
}
;
} }
}); });
}; };
@@ -203,10 +192,6 @@ onMounted(async() => {
.flow-view-box { .flow-view-box {
height: calc(100% - 40px); height: calc(100% - 40px);
}
.flow-view-box-all{
height:100%
} }
#header-box { #header-box {
padding: 0; padding: 0;

View File

@@ -6,7 +6,7 @@
<div <div
class="numInput flex-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 <div
class="input-grid" class="input-grid"
@@ -32,7 +32,7 @@
</div> </div>
<!-- 2下拉框--> <!-- 2下拉框-->
<el-select <el-select
v-if="row.type === WIDGET_TYPE.SELECT" v-if="row.tagType === WIDGET_TYPE.SELECT"
:multiple="row.isMultiple === '1'" :multiple="row.isMultiple === '1'"
:title="row.value" :title="row.value"
v-model="row.value" v-model="row.value"
@@ -50,9 +50,9 @@
/> />
</el-select> </el-select>
<!-- 4单选框 --> <!-- 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 <div
class="input-grid" class="input-grid"
:style="{ :style="{
@@ -75,7 +75,7 @@
<div <div
class="numInput flex-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" <!-- <el-input-number :precision="row.decimals" controls-position="right"
v-model="row.value"></el-input-number> --> v-model="row.value"></el-input-number> -->
@@ -120,14 +120,14 @@
<span class="ml10" v-else>{{ row.unit }}</span> <span class="ml10" v-else>{{ row.unit }}</span>
</div> </div>
<!-- 6单纯显示内容无法编辑 --> <!-- 6单纯显示内容无法编辑 -->
<div v-if="row.type === WIDGET_TYPE.VIEW"> <div v-if="row.tagType === WIDGET_TYPE.VIEW">
<el-icon class="colorIcon" v-if="isLoadingBaseInfo"> <el-icon class="colorIcon" v-if="isLoadingBaseInfo">
<Loading /> <Loading />
</el-icon> </el-icon>
{{ row.value }} {{ row.value }}
</div> </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> <span class="value">{{ row.value }}</span>
<input <input
class="slider-input" class="slider-input"
@@ -143,7 +143,7 @@
</div> </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 v-model="row.isAllChecked" @change="changeBatchLoadcase($event, row)">全选</el-checkbox>
<el-checkbox-group v-model="row.checkedList" @change="changeBatchLoadcaseNum(row)"> <el-checkbox-group v-model="row.checkedList" @change="changeBatchLoadcaseNum(row)">
<el-checkbox <el-checkbox
@@ -161,7 +161,7 @@
<div <div
class="localServer" class="localServer"
v-if=" 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 <!-- <server-local-file
@@ -268,6 +268,9 @@ const changeBatchLoadcaseNum = (record: any) => {
watch(() => props.nodeParams, (newVal) => { watch(() => props.nodeParams, (newVal) => {
if (newVal) { if (newVal) {
tableData.value = newVal; tableData.value = newVal;
console.log(tableData.value, 'tableData.value');
nextTick(() => { nextTick(() => {
baseTableRef.value.setDataFun(tableData.value); baseTableRef.value.setDataFun(tableData.value);
}); });

View File

@@ -35,7 +35,8 @@
<InfoFilled /> <InfoFilled />
</el-icon> </el-icon>
<span class="status-title">{{ currentRunNodeInfo?.status? statusList[currentRunNodeInfo?.status]:'未开始' }}</span> <span class="status-title">{{ currentRunNodeInfo?.status ? statusList[currentRunNodeInfo?.status] : '未开始'
}}</span>
</div> </div>
</div> </div>
@@ -59,7 +60,7 @@
</div> </div>
<div class="run-flow-box"> <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>
<div class="run-info-box"> <div class="run-info-box">
@@ -80,8 +81,16 @@
</el-tabs> </el-tabs>
</div> </div>
<div class="tabs-info-content"> <div class="tabs-info-content">
<paramSetting v-if="nodeActiveName === 'param'"></paramSetting> <paramSetting
<runDataPage v-else></runDataPage> 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>
</div> </div>
@@ -106,7 +115,12 @@
<div class="tabs-info-content"> <div class="tabs-info-content">
<resultData v-if="taskActiveName === 'result'" :current-run-ifno="runInfo"></resultData> <resultData v-if="taskActiveName === 'result'" :current-run-ifno="runInfo"></resultData>
<jobList v-if="taskActiveName === 'job-list'"></jobList> <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> <runLogs v-if="taskActiveName === 'job-log'"></runLogs>
<ModelReview v-if="taskActiveName === '3D-model'"></ModelReview> <ModelReview v-if="taskActiveName === '3D-model'"></ModelReview>
<runVersionTree v-if="taskActiveName === 'associated-run'" :current-task-info="runInfo"></runVersionTree> <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 runLogs from './runPagecomponent/runLogs.vue';
import ModelReview from './runPagecomponent/3DModelReview.vue'; import ModelReview from './runPagecomponent/3DModelReview.vue';
import runVersionTree from './runPagecomponent/runVersionTree.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({ const props = defineProps({
runInfo: { runInfo: {
type: Object, 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(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; align-items: center;
justify-content: space-between; justify-content: space-between;
.info-box-left,.info-box-right { .info-box-left,
.info-box-right {
width: calc(50% - 5px); width: calc(50% - 5px);
height: 100%; height: 100%;
background-color: #fff; background-color: #fff;
border-radius: 2px; border-radius: 2px;
overflow: hidden; overflow: hidden;
.bottom-title{ .bottom-title {
width: 100%; width: 100%;
height: 40px; height: 40px;
display: flex; display: flex;
@@ -276,34 +300,34 @@ watch(() => props.runInfo, (newVal) => {
justify-content: space-between; justify-content: space-between;
padding-left: 10px; padding-left: 10px;
.title-name{ .title-name {
padding-left: 10px; padding-left: 10px;
border-left: 3px solid var(--el-color-primary); border-left: 3px solid var(--el-color-primary);
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
} }
.title-operate{ .title-operate {
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
} }
} }
.bottom-info-content{ .bottom-info-content {
width: 100%; width: 100%;
height: calc(100% - 40px); height: calc(100% - 40px);
padding: 0 10px; padding: 0 10px;
.tabs-box{ .tabs-box {
width: 100%; width: 100%;
height: 40px; height: 40px;
} }
.tabs-info-content{ .tabs-info-content {
width: 100%; width: 100%;
height: calc(100% - 40px); height: calc(100% - 40px);
padding: 10px; padding: 10px;
@@ -327,7 +351,7 @@ watch(() => props.runInfo, (newVal) => {
border-radius: 50%; border-radius: 50%;
} }
.status-title{ .status-title {
padding-left: 8px; padding-left: 8px;
} }

View File

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

View File

@@ -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
);
};

View File

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

View File

@@ -1,6 +1,7 @@
<template> <template>
<div class="param-set-page"> <div class="param-set-page">
<flowNodeParamTable></flowNodeParamTable> {{ nodeParamData }}
<flowNodeParamTable :node-params="nodeParamData"></flowNodeParamTable>
</div> </div>
</template> </template>
@@ -9,21 +10,24 @@ import { ref, watch } from 'vue';
import flowNodeParamTable from '@/components/flow/flowNodeParamTable.vue'; import flowNodeParamTable from '@/components/flow/flowNodeParamTable.vue';
const props = defineProps({ const props = defineProps({
currentNodeInfo: { currentRunFlowNode: {
type: Object, type: Object,
default: () => { default: () => {
}, },
}, },
nodeParamData: {
type: Array,
default: () => [],
},
}); });
const nodeParamInfo = ref<any>({}); watch(() => props.currentRunFlowNode, (newVal) => {
watch(() => props.currentNodeInfo, (newVal) => {
if (newVal) { if (newVal) {
nodeParamInfo.value = newVal;
} }
}, {
immediate: true,
deep: true,
}); });
</script> </script>

View File

@@ -7,12 +7,18 @@
showIndex showIndex
ref="baseTableRef" ref="baseTableRef"
tableName="RUN_RESULT_FILE_TABLE" tableName="RUN_RESULT_FILE_TABLE"
:api="queryRunDirFun"
:params="{
fileId:fileId,
// uuid:nodeInfo.uuid
}"
:show-checkbox="true"
> >
<template #leftOptions> <template #leftOptions>
<el-upload :show-file-list="false" :before-upload="beforeUploadFun"> <el-upload :show-file-list="false" :before-upload="beforeUploadFun">
<el-button>上传文件</el-button> <el-button>上传文件</el-button>
</el-upload> </el-upload>
<el-button type="primary" class="ml10">下载文件</el-button> <el-button type="primary" class="ml10" @click="downLoadFileFun">下载文件</el-button>
</template> </template>
</BaseTable> </BaseTable>
</div> </div>
@@ -21,23 +27,85 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import BaseTable from '@/components/common/table/baseTable.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({ const props = defineProps({
currentNodeInfo: { nodeInfo: {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
fileId: {
type: String,
default: '',
},
}); });
const baseTableRef = ref(); const baseTableRef = ref();
<<<<<<< Updated upstream
const nodeInfo = ref<any>({}); const nodeInfo = ref<any>({});
const beforeUploadFun = () => { 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(() => {
});
>>>>>>> Stashed changes
}; };
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) { if (newVal) {
nodeInfo.value = newVal;
} }
}, { }, {