This commit is contained in:
2025-12-02 19:32:34 +08:00
18 changed files with 328 additions and 97 deletions

View File

@@ -0,0 +1,15 @@
<template>
<div class="upload-page"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
</script>
<style lang="scss" scoped>
.upload-page{
width: 100%;
height: 100%;
}
</style>

View File

@@ -14,8 +14,8 @@
>
<template #leftOptions>
<el-button type="primary">参数入库</el-button>
<el-button type="primary">保存参数</el-button>
<el-button type="primary" >参数入库</el-button>
<el-button type="primary" @click="saveNodeParamFun">保存参数</el-button>
<el-button type="">引用参数</el-button>
</template>
@@ -131,9 +131,11 @@
</template>
<script setup lang="ts">
import { ref, watch, nextTick } from 'vue';
import { ref, watch, nextTick, onMounted } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue';
import { NODE_TYPE, WIDGET_TYPE } from '@/utils/enum/flow';
import { saveNodeParamsApi } from '@/api/project/run';
import { cloneDeep } from 'lodash-es';
const props = defineProps({
nodeParams: {
@@ -146,6 +148,10 @@ const props = defineProps({
currentNode: {
type: Object,
},
nodeInfo: {
type: Object,
default: () => {},
},
});
const baseTableRef = ref();
@@ -162,12 +168,102 @@ const formatDataFun = (list:any, parentId:any) => {
};
watch(() => props.nodeParams, (newVal) => {
if (newVal) {
tableData.value = newVal;
formatDataFun(tableData.value, 0);
console.log(tableData.value, 'tableData.value');
// 保存参数
const saveNodeParamFun = async () => {
console.log(props.nodeInfo, 'nodeInfo');
const runNodeInfo = props.currentNode?.store?.data?.data?.flowNodeInfo;
const newParams:any = cloneDeep(tableData.value);
const inputParams:any = {};
setDataToParam(newParams, inputParams);
console.log(newParams, 'newParams');
const params:any = {
nodeUuid: runNodeInfo.uuid,
runId: runNodeInfo.runId,
inputParams,
};
const res:any = await saveNodeParamsApi(params);
if (res && res.code === 200) {
}
};
const setDataToParam = (list:any, obj:any) => {
for (let i = 0;i < list.length;i++) {
if (list[i].englishLabel) {
obj[list[i].englishLabel] = list[i].defaultValue || '';
}
}
};
const nodeParamData = ref<any>([]);
const paramNames = ['exeMethod', 'inputFormat', 'nodeCondition', 'outputFormat', 'postExeCommand', 'postScripts', 'preExeCommand', 'preScripts'];
watch(() => props.pageInfo, (newVal) => {
if (newVal) {
console.log(newVal, 'newVal');
nodeParamData.value = cloneDeep(newVal) ;
const paramData = nodeParamData.value?.pageConfigList || [];
const arr:any = [];
for (const key in nodeParamData.value) {
if (paramNames.includes(key)) {
const obj = {
'id': key,
'label': key,
'englishLabel': key,
'tag': 'el-input',
'tagType': 'INPUT',
'tagIcon': 'input',
'placeholder': '请输入单行文本',
'defaultValue': nodeParamData.value[key],
'span': 24,
'labelWidth': null,
'style': {
'width': '100%',
},
'clearable': true,
'prepend': '',
'append': '',
'prefix-icon': '',
'suffix-icon': '',
'maxlength': null,
'show-word-limit': false,
'readonly': false,
'disabled': false,
'required': true,
'regList': [],
'changeTag': true,
'document': 'https://element.eleme.cn/#/zh-CN/component/input',
'needLabel': false,
'total': 1,
'column': 1,
'englishLabelReadOnly': false,
'widgetViewType': '',
'specialWidget': false,
'formId': 101 + key,
'renderKey': 1764593613403 + key,
'layout': 'colFormItem',
'vModel': 'field101',
'oldLabel': '单行文本1',
};
arr.push(obj);
}
}
tableData.value = paramData;
tableData.value = arr.concat(paramData);
formatDataFun(tableData.value, 0);
nextTick(() => {
baseTableRef.value.setDataFun(tableData.value);
});

View File

@@ -35,7 +35,7 @@ const props = withDefaults(defineProps<Props>(), {
});
const emit = defineEmits(['update:modelValue']);
const visible = ref(true);
const visible = ref(false);
watch(() => props.modelValue, (val: boolean) => {
visible.value = val;

View File

@@ -59,7 +59,7 @@ const handleChangeLineFun = () => {
const getTaskResultImageDataFun = async () => {
const res: any = await getSimulationTaskFilesApi({
taskId: props.taskId,
uuid: props.taskId,
fileBizType: 1,
fileName: '',
startTime: '',

View File

@@ -120,7 +120,7 @@ const getCheckedNodesCurveFun = async () => {
];
const res: any = await getSimulationTaskFilesApi({
taskId: props.taskId,
uuid: props.taskId,
fileBizType: 5,
fileName: '',
startTime: '',

View File

@@ -6,7 +6,7 @@
:api="getSimulationTaskFilesApi"
showCheckbox
:params="{
taskId: taskId,
uuid: taskId,
fileBizType: 8,
fileName: '',
startTime: '',

View File

@@ -7,7 +7,7 @@
:api="getSimulationTaskFilesApi"
showCheckbox
:params="{
taskId: taskId,
uuid: taskId,
fileBizType: 1,
fileName: '',
startTime: '',

View File

@@ -4,7 +4,7 @@
tableName="TASK_REPORT"
:api="getSimulationTaskFilesApi"
:params="{
taskId: currentId,
uuid: currentId,
fileBizType: 2,
fileName: '',
startTime: '',

View File

@@ -188,6 +188,7 @@ export const nodeAttribute = reactive<any>({
uuid: '',
type: '',
iconUrl: '',
appPath: '',
preScripts: [],
postScripts: [],
postExeCommand: '', // 执行命令

View File

@@ -38,12 +38,12 @@ export const stencilRegister = async (graph: any) => {
],
};
console.log('nodeList2', nodeListObj);
const groups:any = [];
const groups: any = [];
for (const key in nodeListObj) {
groups.push({ name: 'group' + key, title: nodeListObj[key].label });
}
const stencil:Stencil = new Stencil({
const stencil: Stencil = new Stencil({
title: 'Stencil',
target: graph,
// search(cell, keyword) {
@@ -68,7 +68,7 @@ export const stencilRegister = async (graph: any) => {
containerHtml.appendChild(stencilContainer);
console.log('containerHtml', containerHtml);
nextTick( () => {
nextTick(() => {
const stencilHtml = document.getElementById('stencil') as HTMLElement;
console.log('stencilHtml', stencilHtml);
stencilHtml.appendChild(stencil.container);
@@ -91,9 +91,9 @@ export const stencilRegister = async (graph: any) => {
};
export const createNode = (nodeListObj:any, graph:any, stencil?:any) => {
export const createNode = (nodeListObj: any, graph: any, stencil?: any) => {
for (const key in nodeListObj) {
const imageNodes = nodeListObj[key].nodes.map((item:any) =>
const imageNodes = nodeListObj[key].nodes.map((item: any) =>
graph.createNode({
shape: 'custom-stencil-node',
label: item.appName,
@@ -114,6 +114,7 @@ export const createNode = (nodeListObj:any, graph:any, stencil?:any) => {
nodeType: item.isLocal ? item.nodeType : nodeListObj[key].label,
nodeTypeValue: nodeListObj[key].type,
iconUrl: item.isLocal ? item.appImage : FileUtil.getFilePreviewImgPathUrl(item.appImage),
appPath: item.appPath ? item.appPath : '',
preScripts: [],
postScripts: [],
pageConfigList: [],
@@ -135,11 +136,11 @@ export const createNode = (nodeListObj:any, graph:any, stencil?:any) => {
export const getNodeList = async () => {
const typeList: any = (await commonStore.getDictData('APP_TYPE') as any).A;
const typeKeyArray:any = {};
const typeKeyArray: any = {};
typeList.forEach((item: any) => {
typeKeyArray[item.value] = { label: item.label, type: item.value, nodes: [] };
});
const res:any = await queryAllApplicationApi();
const res: any = await queryAllApplicationApi();
if (res.code === 200) {
res.data.forEach((item: any) => {
typeKeyArray[item.appType].nodes.push(item);

View File

@@ -159,7 +159,7 @@ const getProjectListFun = async (val?: any) => {
if (val) {
filterFormData.projectName = val;
} else {
filterFormData.projectName = projectList.value[0].id;
filterFormData.projectName = projectList.value[0].uuid;
}
}
} else {

View File

@@ -105,11 +105,11 @@
<DocumentCopy />
</el-icon>复制算例
</p>
<p class="menuButton" v-if="rightClickNodeInfo?.nodeType === NODE_TYPE.RUN" @click="showDiaFun('editRun')">
<!-- <p class="menuButton" v-if="rightClickNodeInfo?.nodeType === NODE_TYPE.RUN" @click="showDiaFun('editRun')">
<el-icon>
<Edit />
</el-icon>编辑说明
</p>
</p> -->
<!-- <p class="menuButton" v-if="rightClickNodeInfo?.nodeType === NODE_TYPE.RUN" @click="showDiaFun('shareRun')">
<el-icon>
<CopyDocument />
@@ -171,6 +171,7 @@ import { addTaskRunApi, createRunDirApi, deleteTaskRunApi, getTaskRunTreeApi, qu
import runVersionTreeDiv from './operateComponent/runVersionTreeDiv.vue';
import taskRunPerformance from './operateComponent/taskRunPerformance.vue';
import createRunReport from './operateComponent/createRunReport.vue';
import { ElMessage, ElMessageBox } from 'element-plus';
const emits = defineEmits(['nodeClickFn']);
const tableId = ref(new Date().getTime());
@@ -202,7 +203,7 @@ const setExpandElementFun = (list:any, flag:any = 'all') => {
}
if (flag === 'node') {
if (list[i].nodeType === NODE_TYPE.WORKSPACE) {
if (list[i].nodeType === 'workspace') {
defaultExpandKeys.value.push(list[i].id);
}
}
@@ -471,7 +472,23 @@ const showDiaFun = (flag: string) => {
// 删除算例
case 'delRun':
deleteTaskRunFun();
ElMessageBox.confirm(
'是否删除这个算例?',
'Warning',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteTaskRunFun();
})
.catch(() => {
});
break;
// 生成报告
case 'createReport':

View File

@@ -60,7 +60,7 @@
</template>
<script setup lang="ts">
import { ref, watch, reactive, onMounted } from 'vue';
import { ref, watch, reactive, onMounted, nextTick } from 'vue';
import Dialog from '@/components/common/dialog/index.vue';
import { NODE_TYPE } from '@/utils/enum/node';
import { ElMessage } from 'element-plus';
@@ -135,11 +135,12 @@ const createSuccessFun = () => {
};
// 拼接改变
const changeJoinFun = () => {
const changeJoinFun = async () => {
const version = await getRunDetailInfoFun(props.divInfo.uuid, operateType.value);
if (runInfoFormData.isJointProjectInfo) {
runInfoFormData.runNames = props.divInfo.nodeName || props.divInfo.runName + '_V1' ;
runInfoFormData.runNames = (props.divInfo.nodeName || props.divInfo.runName) + '_V' + version ;
} else {
runInfoFormData.runNames = '算例_' + 'V1';
runInfoFormData.runNames = '算例_' + 'V' + version;
}
};
@@ -159,7 +160,7 @@ const getRunDetailInfoFun = async (id: any, flag:any) => {
taskId: id,
});
if (res && res.code === 200) {
const length = res.data.length || 1;
const length = res.data.length + 1 || 1;
return length;
}
};
@@ -170,6 +171,7 @@ watch(() => props.operateFlag, async (newVal) => {
operateType.value = newVal;
if (newVal === 'createRun') {
pageTitle.value = '创建算例';
}
if (newVal === 'createChildRun') {
@@ -239,8 +241,8 @@ const geTemplateListFun = async () => {
onMounted(async () => {
await geTemplateListFun();
console.log(props.divInfo);
console.log(props.divInfo, 'props.divInfo');
runInfoFormData.templateName = props.divInfo.flowTemplate;
});
</script>

View File

@@ -36,7 +36,7 @@
</el-icon>
<span class="status-title">{{ currentRunNodeInfo?.status ? statusList[currentRunNodeInfo?.status] : '未开始'
}}</span>
}}</span>
</div>
</div>
@@ -51,16 +51,18 @@
</div>
<div class="task-operate">
<el-button size="small" type="primary">一键执行</el-button>
<el-button size="small" type="primary" @click="startTaskRunJobFun">一键执行</el-button>
<el-button size="small" type="danger">停止</el-button>
<el-button size="small">刷新</el-button>
<el-button size="small">查看所有计算</el-button>
<el-button size="small" type="primary" @click="startLocalAppFun">启动应用</el-button>
<el-button size="small" type="primary">继续执行</el-button>
<el-button size="small" @click="visible = true">查看所有计算</el-button>
</div>
</div>
<div class="run-flow-box">
<runFlowPage v-if="runInfo.flowTemplate" :run-info="runInfo" @change="changeCurrentFlowNodeFun"></runFlowPage>
<runFlowPage v-if="runInfo.flowTemplate && showPage" :run-info="runInfo" @change="changeCurrentFlowNodeFun"></runFlowPage>
</div>
<div class="run-info-box">
@@ -82,15 +84,13 @@
</div>
<div class="tabs-info-content">
<paramSetting
v-if="nodeActiveName === 'param'"
:current-run-flow-node="flowNode"
:node-param-data="nodeParamDataList"
></paramSetting>
v-if="nodeActiveName === 'param' && showPage" :current-run-flow-node="flowNode"
:node-param-data="nodeParamDataList" :node-data="flowNodeParamData" :node-info="flowNodeData">
</paramSetting>
<runDataPage
v-else
v-else
:file-id="nodeActiveName === 'input' ? flowNodeData?.inputDirId : flowNodeData?.outputDirId"
:node-info="flowNodeData"
></runDataPage>
:node-info="flowNodeData"></runDataPage>
</div>
</div>
@@ -116,11 +116,8 @@
<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>
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,7 +128,7 @@
</div>
</div>
<HpcList v-model="visible" />
</div>
</template>
@@ -146,6 +143,10 @@ import runLogs from './runPagecomponent/runLogs.vue';
import ModelReview from './runPagecomponent/3DModelReview.vue';
import runVersionTree from './runPagecomponent/runVersionTree.vue';
import runFlowPage from './runPagecomponent/flow/runFlowPage.vue';
import HpcList from '@/components/task/hpcList.vue';
import { startProcessInstanceApi } from '@/api/project/run';
import { execApi, getdeviceuuidApi, startupPlugin } from '@/api/application/application';
import { ElMessage } from 'element-plus';
const props = defineProps({
runInfo: {
@@ -157,10 +158,10 @@ const props = defineProps({
const statusList = ref([
'未开始', '进行中', '已完成', '回传中', '异常',
]);
const visible = ref(false);
const nodeActiveName = ref('param');
const taskActiveName = ref('job-list');
const showPage = ref(true);
const handleLeftClickFun = () => {
};
@@ -173,18 +174,89 @@ const nodeParamDataList = ref<any>([]);
const flowNode = ref<any>({});
const flowNodeData = ref<any>({});
const flowNodeParamData = 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 || [];
flowNodeParamData.value = flowNode.value?.store?.data?.data || {};
};
const currentRunNodeInfo = ref<any>({});
// 开始执行任务
const startTaskRunJobFun = async () => {
const res: any = await startProcessInstanceApi({
runId: props.runInfo.uuid,
});
if (res && res.code === 200) {
ElMessage.success(res.message);
showPage.value = false;
refreshRunFlowInfo();
}
};
// 启动应用
const startLocalAppFun = async () => {
if (flowNodeParamData.value?.nodeTypeValue != '1') {
ElMessage.warning('只有本地应用才能手动启动');
return;
}
const appPath = flowNodeParamData.value.appPath || '';
await getdeviceuuidFun();
const uuid = localStorage.getItem('USER_UUID');
if (uuid) {
const res = await execApi({
path: appPath,
param: '',
});
if (res) {
ElMessage.success('应用正在启动中,请等待');
} else {
}
} else {
return;
}
};
const getdeviceuuidFun = async () => {
try {
const res: any = await getdeviceuuidApi();
if (res) {
const uuid = res
.replace('UUID', '')
.replace(/\ +/g, '')
.replace(/[\r\n]/g, '');
localStorage.setItem('USER_UUID', uuid);
}
} catch (error) {
console.log(error);
startupPlugin();
}
};
// 刷新节点页面信息
const refreshRunFlowInfo = () => {
setTimeout(() => {
showPage.value = true;
});
};
watch(() => props.runInfo, (newVal) => {
if (newVal) {

View File

@@ -1,5 +1,6 @@
import { register } from '@antv/x6-vue-shape';
import AppNode from './registerAppNode.vue';
import LocalNode from '@/views/simulation/creation/components/localVueNode.vue';
import { Graph } from '@antv/x6';
export const registerCustomNode = () => {
@@ -93,6 +94,16 @@ export const registerCustomNode = () => {
ports: ports,
});
// 自定义的画布中的显示节点
register({
shape: 'custom-local-vue-node',
type: 'local',
width: 56,
height: 56,
component: LocalNode,
ports: ports,
});
// 自定义的左侧拖拽的节点
Graph.registerNode(
'custom-stencil-node',

View File

@@ -5,7 +5,7 @@
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from 'vue';
import { ref, watch, onMounted, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import { Graph } from '@antv/x6';
import { queryFlowTemplateDetailApi } from '@/api/capability/flow';
@@ -45,6 +45,7 @@ const getFlowDetail = async(uuid:string) => {
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 === '结束节点';
});
@@ -57,6 +58,8 @@ const getFlowDetail = async(uuid:string) => {
const nodes = dataJson.cells.filter((item:any) => {
return item?.type;
});
// 改变各个节点之间的距离
let position = nodes.map((item:any) => {
return item?.position?.x;
});
@@ -83,9 +86,6 @@ const getFlowDetail = async(uuid:string) => {
}
}
// console.log(dataJson, 'dataJson');
// console.log(nodeDataList.value, 'nodeDataList');
setTimeout(() => {
graph.value.fromJSON(dataJson);
graph.value.centerContent();
@@ -155,6 +155,9 @@ const initGraph = async() => {
return item.nodeId === node.id;
});
console.log(node, 'node');
console.log(data, 'data');
emits('change', {
node,
data,
@@ -167,45 +170,35 @@ const initGraph = async() => {
const setCurrentNodeFun = () => {
const allNodes = graph.value.getNodes();
const currentId = localStorage.getItem('CURRENT_RUN_FLOW_NODE_INFO') || '';
let currentNodes:any = {};
if (currentId) {
const currentNodes = allNodes.find((item:any) => {
currentNodes = allNodes.find((item:any) => {
return item.id === currentId;
}) || allNodes[0];
currentNodes.addTools({
name: 'boundary',
args: {
padding: 0,
attrs: {
// fill: '#7c68fc',
stroke: '#0366FF ',
'stroke-width': 2,
'stroke-dasharray': '',
rx: 4,
ry: 4,
},
},
});
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({
currentNodes = allNodes[0];
currentNodes.addTools({
name: 'boundary',
args: {
padding: 0,
@@ -221,6 +214,15 @@ const setCurrentNodeFun = () => {
});
}
const data = nodeDataList.value.find((item:any) => {
return item.nodeId === currentNodes.id;
});
emits('change', {
node: currentNodes,
data: data,
});
};
watch(() => props.runInfo, async (newVal) => {
@@ -247,6 +249,10 @@ onMounted( async() => {
}
});
setTimeout(() => {
setCurrentNodeFun();
}, 3000);
});
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="param-set-page">
<flowNodeParamTable :node-params="nodeParamData" :current-node="currentRunFlowNode"></flowNodeParamTable>
<flowNodeParamTable :node-params="nodeParamData" :current-node="currentRunFlowNode" :page-info="nodeData" :node-info="nodeInfo"></flowNodeParamTable>
</div>
</template>
@@ -18,6 +18,16 @@ const props = defineProps({
type: Array,
default: () => [],
},
nodeData: {
type: Object,
default: () => {
},
},
nodeInfo: {
type: Object,
default: () => {
},
},
});
watch(() => props.currentRunFlowNode, (newVal) => {

View File

@@ -17,23 +17,23 @@
<taskPerformance :task-id="currentTaskInfo?.id" :show-save-button="true" :task-info="currentTaskInfo" ></taskPerformance>
</div>
<div class="tabs-component" v-if="activeName === 'picture'">
<resultImage :task-id="currentTaskInfo?.id"></resultImage>
<resultImage :task-id="currentTaskInfo?.uuid"></resultImage>
</div>
<div class="tabs-component" v-if="activeName === 'canvas'">
<taskCurve :task-id="currentTaskInfo?.id"></taskCurve>
<taskCurve :task-id="currentTaskInfo?.uuid"></taskCurve>
</div>
<div class="tabs-component" v-if="activeName === 'deliverable'">
<taskDeliverable :task-info="currentTaskInfo" :task-id="currentTaskInfo?.id"></taskDeliverable>
<taskDeliverable :task-info="currentTaskInfo" :task-id="currentTaskInfo?.uuid"></taskDeliverable>
</div>
<div class="tabs-component" v-if="activeName === 'model'">
<taskModel :task-id="currentTaskInfo?.id"></taskModel>
<taskModel :task-id="currentTaskInfo?.uuid"></taskModel>
</div>
<div class="tabs-component" v-if="activeName === 'report'">
<taskReport :task-id="currentTaskInfo?.id"></taskReport>
<taskReport :task-id="currentTaskInfo?.uuid"></taskReport>
</div>