update:仿真执行界面修改

This commit is contained in:
2026-03-24 15:01:30 +08:00
parent 6e9c9f946b
commit eb5f749a58
7 changed files with 427 additions and 151 deletions

View File

@@ -155,44 +155,51 @@ export const getNodeList = async (noload?: any) => {
current: 1,
size: 999,
};
const res: any = await queryAllApplicationApi(param);
if (res.code === 200) {
appList = [];
const apps: any = res.data.data || [];
for (let i = 0; i < apps.length; i++) {
const paths = isJSONFun(apps[i].appPath)
? JSON.parse(apps[i].appPath as string)
: apps[i].appPath;
if (paths && paths instanceof Object) {
const keys = Object.keys(paths);
if (keys.includes(getUserId())) {
apps[i].appPath = paths[getUserId()];
} else {
apps[i].appPath = '';
}
}
if (apps[i].appStatus === 1) {
// if (!noload) {
// apps[i].nodeParamConfigName = await getAppConfigListFun(apps[i].uuid);
// }
if (typeKeyArray[apps[i].appType]) {
typeKeyArray[apps[i].appType].nodes.push(apps[i]);
appList.push(apps[i]);
}
}
if (appList.length) {
for (let i = 0; i < appList.length; i++) {
typeKeyArray[appList[i].appType].nodes.push(appList[i]);
}
} else {
const res: any = await queryAllApplicationApi(param);
if (res.code === 200) {
appList = [];
// res.data.data.forEach((item: any) => {
// // 启用的app才能在流程中使用
// if (item.appStatus === 1) {
// typeKeyArray[item.appType].nodes.push(item);
// appList.push(item);
// }
// });
const apps: any = res.data.data || [];
for (let i = 0; i < apps.length; i++) {
const paths = isJSONFun(apps[i].appPath)
? JSON.parse(apps[i].appPath as string)
: apps[i].appPath;
if (paths && paths instanceof Object) {
const keys = Object.keys(paths);
if (keys.includes(getUserId())) {
apps[i].appPath = paths[getUserId()];
} else {
apps[i].appPath = '';
}
}
if (apps[i].appStatus === 1) {
// if (!noload) {
// apps[i].nodeParamConfigName = await getAppConfigListFun(apps[i].uuid);
// }
if (typeKeyArray[apps[i].appType]) {
typeKeyArray[apps[i].appType].nodes.push(apps[i]);
appList.push(apps[i]);
}
}
}
// res.data.data.forEach((item: any) => {
// // 启用的app才能在流程中使用
// if (item.appStatus === 1) {
// typeKeyArray[item.appType].nodes.push(item);
// appList.push(item);
// }
// });
}
}
return typeKeyArray;

View File

@@ -164,14 +164,17 @@
@flowclick="flowclickFun"
></flowNodeParamTable>
<runDataPage
v-show="nodeActiveName === 'input' || nodeActiveName === 'output'"
:file-id="
nodeActiveName === 'input' ? flowNodeData?.inputDirId : flowNodeData?.outputDirId
"
v-if="nodeActiveName === 'output'"
:file-id="flowNodeData?.outputDirId"
:node-info="flowNodeData"
:run-info="runInfo"
></runDataPage>
<runDataPage
v-if="nodeActiveName === 'input'"
:file-id="flowNodeData?.inputDirId"
:node-info="flowNodeData"
:run-info="runInfo"
></runDataPage>
<div class="bottom-info-content-tab" v-show="nodeActiveName === 'param'">
<div class="node-img">
<img :src="flowNodeParamData.iconUrl" alt="" />
@@ -279,10 +282,11 @@
<el-tabs v-model="taskActiveName" class="demo-tabs" @tab-click="handleRightClickFun">
<el-tab-pane label="作业列表" name="job-list"></el-tab-pane>
<el-tab-pane label="标准规范" name="standard"></el-tab-pane>
<!-- <el-tab-pane label="仿真参数" name="param"></el-tab-pane> -->
<el-tab-pane label="仿真参数" name="param"></el-tab-pane>
<el-tab-pane label="关键结果" name="result"></el-tab-pane>
<el-tab-pane label="仿真报告" name="report"></el-tab-pane>
<el-tab-pane label="关联任务" name="associated-run"></el-tab-pane>
<el-tab-pane label="数据归档" name="data-archive"></el-tab-pane>
<!-- <el-tab-pane label="日志输出" name="job-log"></el-tab-pane> -->
<!-- <el-tab-pane label="性能指标" name="performance"></el-tab-pane> -->
@@ -313,6 +317,8 @@
v-if="taskActiveName === 'report'"
:current-run-ifno="runInfo"
></reportResult>
<simulationParam v-if="taskActiveName === 'param'"></simulationParam>
<dataAchieve v-if="taskActiveName === 'data-archive'" :run-info="runInfo"></dataAchieve>
</div>
</div>
</div>
@@ -361,6 +367,8 @@ import { getUserData, getUserId, getUserTenantId } from '@/utils/user';
import reportResult from './runPagecomponent/reportResult.vue';
import dayjs from 'dayjs';
import { base64ToStrFun, isJSONFun } from '@/utils/file';
import simulationParam from './runPagecomponent/simulationParam.vue';
import dataAchieve from './runPagecomponent/dataAchieve.vue';
const props = defineProps({
runInfo: {
@@ -1233,12 +1241,12 @@ onMounted(async () => {
await getDictionaryDataFun();
emitter.on('UPLOAD_FINISHED', uploadFinishedFun);
// 5分钟自动刷新一次流程信息
timer.value = setInterval(
() => {
refreshFun();
},
5 * 60 * 1000
);
// timer.value = setInterval(
// () => {
// refreshFun();
// },
// 5 * 60 * 1000
// );
});
onBeforeUnmount(() => {

View File

@@ -0,0 +1,89 @@
<template>
<Dialog
v-model="showSyncFileTypeSelectFlag"
diaTitle="交付文件类型"
:width="'20%'"
:height="'20%'"
:confirm-closable="cancalFun"
>
<div class="form-content">
<el-form :model="formData">
<el-form-item label="文件类型">
<el-select v-model="formData.fileType">
<el-option
v-for="item in fileTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<el-button @click="cancalFun">取消</el-button>
<el-button @click="submitFun" type="primary">确定</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import Dialog from '@/components/common/dialog/index.vue';
import { FILE_TYPE } from '@/utils/enum/file';
import { useDict } from '@/utils/useDict';
import { ElMessage } from 'element-plus';
import { syncKeyResultToTaskApi } from '@/api/project/run';
const props = defineProps({
nodeInfo: {
type: Object,
default: () => {},
},
fileList: {
type: Array,
default: () => [],
},
});
const emits = defineEmits(['close', 'finished']);
const { ALL_FILE_TYPE }: any = useDict('ALL_FILE_TYPE');
const fileTypeList = ref<any>(ALL_FILE_TYPE.value['A']);
const showSyncFileTypeSelectFlag = ref(true);
const formData = reactive<any>({
fileType: '',
fileTypeDictValue: [FILE_TYPE.CALCULATION_FILE],
files: [],
disciplineDictValue: '',
});
const cancalFun = () => {
emits('close');
};
const submitFun = async () => {
if (!formData.fileType) {
ElMessage.warning('请选择归档文件类型');
return;
}
const fileIds = props.fileList.map((item: any) => {
return item.id;
});
const param = {
fileIds,
fileType: formData.fileType,
runId: props.nodeInfo.runId,
};
try {
const res: any = await syncKeyResultToTaskApi(param);
if (res && res.code == 200) {
ElMessage.success('归档成功');
emits('finished');
}
} catch {}
};
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,246 @@
<template>
<div class="achieve-page">
<BaseTable
ref="baseTableRef"
:table-name="tableName"
:full-height="true"
:hide-pagination="true"
:data="treeData"
:show-overflow="true"
:show-node-name="'originalName'"
:tree-config="{
expandAll: true,
lazy: true,
rowField: 'originalName',
childrenField: 'children',
hasChild: 'hasChild',
loadMethod({ row }: any) {
return getChildFun(row);
},
}"
>
<template #leftOptions>
<el-button type="primary" @click="asyncFileFun">归档</el-button>
</template>
<template #achieveType="{ row }">
<el-select
v-if="row.dataType != 1"
v-model="row.achieveType"
@change="changeFileTypeFun($event, row)"
clearable
>
<el-option
v-for="item in typeList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
</BaseTable>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import {
listSimulationFlowNodeApi,
queryRunDirApi,
syncKeyResultToTaskApi,
} from '@/api/project/run';
import BaseTable from '@/components/common/table/baseTable.vue';
import { useDict } from '@/utils/useDict';
import { ElMessage } from 'element-plus';
import { objectTypeArrayRemovesDuplicates } from '@/utils/common';
const props = defineProps({
runInfo: {
type: Object,
default: () => {},
},
tableName: {
type: String,
default: 'ACHIEVE_DATA_TABLE',
},
});
const baseTableRef = ref();
const treeData = ref<any>([]);
const { ALL_FILE_TYPE }: any = useDict('ALL_FILE_TYPE');
const typeList = ref<any>(ALL_FILE_TYPE.value['A']);
const getSimulationFlowNodeInfoFun = async (info: any) => {
const param = {
runId: info.uuid,
};
try {
const res: any = await listSimulationFlowNodeApi(param);
if (res && res.code === 200) {
const list = res.data.flowNodeDtoList.filter((item: any) => {
return item.nodeName != '起始节点' && item.nodeName != '结束节点';
});
treeData.value = list.map((item: any) => {
const listChild = [
{
originalName: '输入数据',
id: item.inputDirId,
children: [],
dataType: 1,
hasChild: 'hasChild',
},
{
originalName: '输出数据',
id: item.outputDirId,
children: [],
dataType: 1,
hasChild: 'hasChild',
},
];
const obj: any = {
...item,
originalName: item.nodeName,
children: listChild,
dataType: 1,
hasChild: 'hasChild',
};
return obj;
});
}
} catch {}
};
const currentRunInfo = ref<any>({});
const getChildFun = async (row: any) => {
const listChild = [
{
originalName: '输入数据',
id: row.inputDirId,
children: [],
dataType: 1,
hasChild: 'hasChild',
},
{
originalName: '输出数据',
id: row.outputDirId,
children: [],
dataType: 1,
hasChild: 'hasChild',
},
];
if (row?.outputDirId && row?.inputDirId) {
return listChild;
} else {
return queryRunDirFun(row.id);
}
};
const queryRunDirFun = async (id: any) => {
const param = {
current: 1,
fileId: id,
size: 9999,
};
try {
const res: any = await queryRunDirApi(param);
if (res && res.code === 200) {
return res.data.data.map((item: any) => {
return {
...item,
achieveType: null,
};
});
} else {
return [];
}
} catch {
return [];
}
};
watch(
() => props.runInfo,
async (newVal) => {
currentRunInfo.value = newVal;
await getSimulationFlowNodeInfoFun(currentRunInfo.value);
},
{
immediate: true,
deep: true,
}
);
const asyncFiles = ref<any>([]);
const changeFileTypeFun = (event: any, row: any) => {
if (row.achieveType) {
const data: any =
asyncFiles.value.find((item: any) => {
return item.id === row.id;
}) || null;
if (data) {
for (let i = 0; i < asyncFiles.value.length; i++) {
if (asyncFiles.value[i].id === row.id) {
asyncFiles.value[i].achieveType = row.achieveType;
}
}
} else {
// 没有存在就push
asyncFiles.value.push(row);
}
} else {
asyncFiles.value = asyncFiles.value.filter((item: any) => {
return item.id != row.id;
});
}
};
const asyncFileFun = async () => {
console.log(asyncFiles.value, 'asyncFiles.value');
if (asyncFiles.value.length) {
const list: any = [];
let types = asyncFiles.value.map((item: any) => {
return item.achieveType;
});
types = objectTypeArrayRemovesDuplicates(types, 1);
for (let i = 0; i < types.length; i++) {
const obj: any = {
fileIds: [],
runId: props.runInfo.uuid,
fileType: types[i],
};
for (let j = 0; j < asyncFiles.value.length; j++) {
if (asyncFiles.value[j].achieveType === types[i]) {
obj.fileIds.push(asyncFiles.value[j].id);
}
}
list.push(obj);
}
for (let i = 0; i < list.length; i++) {
await syncKeyResultToTaskApi(list[i]);
}
ElMessage.success('归档完成');
} else {
ElMessage.warning('没有文件选择归档类型,无需归档');
}
};
</script>
<style lang="scss" scoped>
.achieve-page {
width: 100%;
height: 100%;
}
</style>

View File

@@ -293,13 +293,13 @@ watch(
);
onMounted(async () => {
setTimeout(async () => {
if (props.runInfo) {
await initGraph();
await querLlistSimulationFlowNode(props.runInfo.uuid);
await getFlowDetail(props.runInfo.flowTemplate);
}
});
// setTimeout(async () => {
if (props.runInfo) {
await initGraph();
await querLlistSimulationFlowNode(props.runInfo.uuid);
await getFlowDetail(props.runInfo.flowTemplate);
}
// });
});
</script>

View File

@@ -9,20 +9,15 @@
ref="baseTableRef"
tableName="RUN_RESULT_FILE_TABLE"
:api="queryRunDirFun"
:params="{
fileId: fileId,
// uuid:nodeInfo.uuid
}"
:row-config="{
height: '34',
}"
:show-checkbox="true"
:action-list="actionList"
:full-height="true"
:show-setting="false"
>
<template #leftOptions v-if="!readonly">
<el-button type="" @click="asyncFileFun">归档</el-button>
<el-button type="" @click="asyncFileFun">交付</el-button>
<el-button class="ml10" type="primary" @click="openUploadFileFun">上传</el-button>
@@ -52,7 +47,7 @@
</div> -->
<FilePreview v-model="previewVisible" :fileId="currentRow?.id" />
<Dialog
<!-- <Dialog
v-model="showSyncFileTypeSelectFlag"
diaTitle="文件归档"
:width="'20%'"
@@ -77,7 +72,15 @@
<el-button @click="cancalFun">取消</el-button>
<el-button @click="submitFun" type="primary">确定</el-button>
</template>
</Dialog>
</Dialog> -->
<asyncRunFile
v-if="showSyncFileTypeSelectFlag"
:file-list="syncFiles"
:node-info="nodeInfo"
@close="showSyncFileTypeSelectFlag = false"
@finished="finishAsyncFun"
></asyncRunFile>
<Dialog
v-model="showUploadFileVisible"
@@ -92,7 +95,7 @@
ref="tableFormRef"
:tableName="'TASK_DETAIL_UPLOAD_FILE'"
:itemNum="3"
v-model:data="formData"
:data="formData"
/>
</el-form>
</div>
@@ -105,7 +108,7 @@
</template>
<script setup lang="ts">
import { nextTick, reactive, ref, watch } from 'vue';
import { nextTick, reactive, ref } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue';
import { queryRunDirApi, syncKeyResultToTaskApi, uploadRunFilesApi } from '@/api/project/run';
import { downloadFileById, downloadFileByStream, fileUploadAllocationTypeFun } from '@/utils/file';
@@ -115,9 +118,9 @@ import emitter from '@/utils/eventBus';
import { dataDelFileApi } from '@/api/data/data';
import { ElMessage } from 'element-plus';
import Dialog from '@/components/common/dialog/index.vue';
import { useDict } from '@/utils/useDict';
import { FILE_TYPE } from '@/utils/enum/file';
import TableForm from '@/components/common/table/tableForm.vue';
import asyncRunFile from './asyncRunFile.vue';
const props = defineProps({
nodeInfo: {
@@ -147,58 +150,14 @@ const formData = reactive<any>({
files: [],
disciplineDictValue: '',
});
const { ALL_FILE_TYPE }: any = useDict('ALL_FILE_TYPE');
const fileTypeList = ref<any>(ALL_FILE_TYPE.value['A']);
const beforeUploadFun = async (file: any) => {
if (!props.fileId) {
return;
}
const list = [file];
const sourceFiles = [
{
fileName: file.name,
size: file.size,
fileType: fileUploadAllocationTypeFun(file.name),
},
];
const param = {
sourceFiles,
uploadTaskId: new Date().getTime(),
dirId: props.fileId,
isConverSameNameFile: true,
};
const res: any = await uploadRunFilesApi(param);
if (res && res.code === 200) {
res.data.forEach((item: any, index: any) => {
item.isSaveLocal = 'Y';
emitter.emit('ADD_UPLOAD_FILE', {
file: list[index],
data: {
// 接口返回的文件目录信息,包括配置信息
...item,
isApprove: 0, // 0否 1是
taskType: 4, // 4交付物
},
});
});
}
if (res.code === 200) {
reloadFun();
}
};
const queryRunDirFun = async (param: any) => {
if (param.fileId) {
const res: any = await queryRunDirApi(param);
return res;
} else {
return {};
}
const params = {
...param,
fileId: props.fileId,
};
const res: any = await queryRunDirApi(params);
return res;
};
const downLoadFileFun = async () => {
@@ -299,28 +258,8 @@ const openUploadFileFun = () => {
});
};
const submitFun = async () => {
if (!formData.fileType) {
ElMessage.warning('请选择归档文件类型');
return;
}
const fileIds = syncFiles.value.map((item: any) => {
return item.id;
});
const param = {
fileIds,
fileType: formData.fileType,
runId: props.nodeInfo.runId,
};
try {
const res: any = await syncKeyResultToTaskApi(param);
if (res && res.code == 200) {
ElMessage.success('归档成功');
showSyncFileTypeSelectFlag.value = false;
}
} catch {}
const finishAsyncFun = () => {
showSyncFileTypeSelectFlag.value = false;
};
const submitFun2 = async () => {
@@ -382,19 +321,6 @@ const submitFun2 = async () => {
}
}
};
watch(
() => props.nodeInfo,
(newVal) => {
if (newVal) {
console.log(newVal, 'newVal');
}
},
{
immediate: true,
deep: true,
}
);
</script>
<style lang="scss" scoped>

View File

@@ -22,7 +22,7 @@
}"
:colNum="1"
:hideKeys="hideKeys"
v-model:data="sendForm"
:data="sendForm"
@change="changeFun"
@load="formLoad"
>