This commit is contained in:
2026-01-27 20:19:29 +08:00
10 changed files with 413 additions and 309 deletions

View File

@@ -58,7 +58,7 @@ export const dataExportKnowledgeListApi = (params: any, filename: string) => {
return download(`${PREFIX}data/exportKnowledgeList`, params, filename); return download(`${PREFIX}data/exportKnowledgeList`, params, filename);
}; };
export const dataDownloadFileApi = (params: any) => { export const dataDownloadFileApi = (params: any) => {
return get(`${PREFIX}data/downloadFile`, params); return post(`${PREFIX}data/downloadFile`, params);
}; };
export const getFileBaseInfoApi = (params: any) => { export const getFileBaseInfoApi = (params: any) => {

View File

@@ -267,3 +267,12 @@ export const syncKeyResultToTaskApi = (params: any) => {
export const generateNewReportApi = (params: any) => { export const generateNewReportApi = (params: any) => {
return download(`${PREFIX}run/generateNewReport`, params, params.fileName); return download(`${PREFIX}run/generateNewReport`, params, params.fileName);
}; };
/**
* 流程失败节点重试
* @param params processInstanceId failNodeId
* @returns
*/
export const retryFailedNodeApi = (params: any) => {
return post(`${PREFIX}run/retryFailedNode`, params);
};

View File

@@ -238,10 +238,12 @@ const formatDataFun = (list: any, parentId: any) => {
} }
} }
}; };
const uploadFileFlag = ref(false);
const checkParamRequired = ref(false); const checkParamRequired = ref(false);
// 保存参数 // 保存参数
const saveNodeParamFun = async () => { const saveNodeParamFun = async (flag?: any) => {
uploadFileFlag.value = false;
const runNodeInfo = props.currentNode?.store?.data?.data?.flowNodeInfo; const runNodeInfo = props.currentNode?.store?.data?.data?.flowNodeInfo;
const runNodeData = props.currentNode?.store?.data?.data; const runNodeData = props.currentNode?.store?.data?.data;
const newParams: any = cloneDeep(tableData.value); const newParams: any = cloneDeep(tableData.value);
@@ -251,7 +253,7 @@ const saveNodeParamFun = async () => {
checkParamRequiredFun(newParams); checkParamRequiredFun(newParams);
if (checkParamRequired.value) { if (checkParamRequired.value) {
ElMessage.warning('存在必填项没有填写!'); // ElMessage.warning('存在必填项没有填写!');
checkParamRequired.value = false; checkParamRequired.value = false;
// return; // return;
inputParams.executeMode = 'MANUAL'; inputParams.executeMode = 'MANUAL';
@@ -259,7 +261,7 @@ const saveNodeParamFun = async () => {
inputParams.executeMode = 'AUTO'; inputParams.executeMode = 'AUTO';
} }
await setDataToParam(newParams, inputParams, true); await setDataToParam(newParams, inputParams, true, flag);
if (runNodeData.nodeType === 'HPC') { if (runNodeData.nodeType === 'HPC') {
setSpecialParamData(inputParams, runNodeData); setSpecialParamData(inputParams, runNodeData);
@@ -276,7 +278,7 @@ const saveNodeParamFun = async () => {
const res: any = await saveNodeParamsApi(params); const res: any = await saveNodeParamsApi(params);
if (res && res.code === 200) { if (res && res.code === 200) {
ElMessage.success('保存成功'); ElMessage.success('保存成功');
emits('confirm'); emits('confirm', { flag: uploadFileFlag.value });
} }
}; };
@@ -301,15 +303,16 @@ const checkParamRequiredFun = (list: any) => {
} }
}; };
const setDataToParam = async (list: any, obj: any, isUpload?: any) => { const setDataToParam = async (list: any, obj: any, isUpload?: any, flag?: any) => {
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
if (list[i]?.englishLabel) { if (list[i]?.englishLabel) {
if (list[i].tagType === WIDGET_TYPE.FILE && list[i]?.fileList?.length) { if (list[i].tagType === WIDGET_TYPE.FILE && list[i]?.fileList?.length) {
const fileList = list[i]?.fileList || []; const fileList = list[i]?.fileList || [];
let arrs: any = []; let arrs: any = [];
if (fileList.length) { if (fileList.length) {
const fileData = await runUploadRunFilesFun(fileList); const fileData = await runUploadRunFilesFun(fileList, flag);
arrs = fileData; arrs = fileData;
uploadFileFlag.value = true;
// for (let j = 0; j < fileList.length; j++) { // for (let j = 0; j < fileList.length; j++) {
// if (isUpload) { // if (isUpload) {
// await uploadRunFilesFun(fileList[j].raw); // await uploadRunFilesFun(fileList[j].raw);
@@ -326,14 +329,14 @@ const setDataToParam = async (list: any, obj: any, isUpload?: any) => {
if (list[i].tagType === WIDGET_TYPE.VIEW && list[i].tagIcon === 'row') { if (list[i].tagType === WIDGET_TYPE.VIEW && list[i].tagIcon === 'row') {
if (list[i]?.children?.length) { if (list[i]?.children?.length) {
obj[list[i].vModel] = {}; obj[list[i].vModel] = {};
setDataToParam(list[i]?.children, obj[list[i].vModel], isUpload); setDataToParam(list[i]?.children, obj[list[i].vModel], isUpload, flag);
} }
} }
} }
} }
}; };
const runUploadRunFilesFun = async (list: any) => { const runUploadRunFilesFun = async (list: any, flag: any) => {
const sourceFiles = []; const sourceFiles = [];
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
@@ -370,6 +373,7 @@ const runUploadRunFilesFun = async (list: any) => {
...item, ...item,
isApprove: 0, // 0否 1是 isApprove: 0, // 0否 1是
taskType: 4, // 4交付物 taskType: 4, // 4交付物
callbackFlag: flag,
}, },
}); });
}); });
@@ -468,7 +472,9 @@ const setReportSpecialParamDataFun = (param: any) => {
localStorage.getItem('CURRENT_FILTER_RUN_TASK_TREE_PARAM') as string localStorage.getItem('CURRENT_FILTER_RUN_TASK_TREE_PARAM') as string
); );
param.reportName = '算例报告_' + dayjs().format('YYYY_MM_DD_HH_mm'); if (!param.reportName) {
param.reportName = '算例报告_' + dayjs().format('YYYY_MM_DD_HH_mm');
}
param.applicants = getUserData().nickname; param.applicants = getUserData().nickname;
param.date = dayjs().format('YYYY-MM-DD HH:mm:ss'); param.date = dayjs().format('YYYY-MM-DD HH:mm:ss');
param.loadcaseName = props.runInfo.parentName; param.loadcaseName = props.runInfo.parentName;

View File

@@ -12,17 +12,26 @@
fullHeight fullHeight
> >
<template #totalElapsedTime="{ row }"> <template #totalElapsedTime="{ row }">
<span>{{ row.totalElapsedTime || '--' }}h</span> <span>{{ row.totalElapsedTime ? row.totalElapsedTime + 'h' : '--' }}</span>
</template> </template>
<template #jobStatus="{ row }"> <template #jobStatus="{ row }">
<span>{{ WORK_STATUS.O[row.jobStatus] }}</span> <el-tag v-if="row.jobStatus === 'Finished'" type="success">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag type="info" v-else-if="row.jobStatus === 'Canceled'">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag v-else-if="row.jobStatus === 'Failed'" type="danger">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag v-else type="primary">{{ WORK_STATUS.O[row.jobStatus] }}</el-tag>
</template> </template>
</BaseTable> </BaseTable>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="本地作业执行列表" name="local"> <!-- <el-tab-pane label="本地作业执行列表" name="local">
<div class="table"></div> <div class="table"></div>
</el-tab-pane> </el-tab-pane> -->
</el-tabs> </el-tabs>
</div> </div>
</Dialog> </Dialog>

View File

@@ -159,7 +159,7 @@ export const getNodeList = async (noload?: any) => {
if (!noload) { if (!noload) {
apps[i].nodeParamConfigName = await getAppConfigListFun(apps[i].uuid); apps[i].nodeParamConfigName = await getAppConfigListFun(apps[i].uuid);
} }
typeKeyArray[apps[i].appType].nodes.push(apps[i]); typeKeyArray[apps[i].appType]?.nodes?.push(apps[i]);
appList.push(apps[i]); appList.push(apps[i]);
} }
} }

View File

@@ -610,6 +610,7 @@ const createRunFun = async (data: any) => {
currentNodeInfo.value = runInfo; currentNodeInfo.value = runInfo;
defaultExpandKeys.value = [runInfo.id]; defaultExpandKeys.value = [runInfo.id];
taskTreeRef.value.setCurrentKey(runInfo.id); taskTreeRef.value.setCurrentKey(runInfo.id);
emits('nodeClickFn', { node: currentNodeInfo.value });
} }
} else { } else {
info.label = info.runNames; info.label = info.runNames;

View File

@@ -3,21 +3,9 @@
<div class="run-title-box" v-show="!leftFullScreen && !rightFullScreen"> <div class="run-title-box" v-show="!leftFullScreen && !rightFullScreen">
<div class="task-info"> <div class="task-info">
<div class="task-name">{{ currentRunNodeInfo?.runName }}</div> <div class="task-name">{{ currentRunNodeInfo?.runName }}</div>
<!-- <div class="task-executor">
执行人
<el-icon class="blue">
<UserFilled />
</el-icon>
<span class="name">
{{ '执行人' }}</span>
</div> -->
<div class="task-status"> <div class="task-status">
任务状态 任务状态
<div class="status"> <div class="status">
<!-- <el-icon class="info" title="未开始" v-if="!runFlowPocesInfo?.status">
<InfoFilled />
</el-icon> -->
<el-icon class="upload" title="运行中" v-if="runFlowPocesInfo?.status === 'running'"> <el-icon class="upload" title="运行中" v-if="runFlowPocesInfo?.status === 'running'">
<HelpFilled /> <HelpFilled />
</el-icon> </el-icon>
@@ -62,37 +50,14 @@
</div> </div>
</div> </div>
<div class="task-operate"> <div class="task-operate">
<!-- <el-dropdown placement="bottom-end">
<el-button type="primary">
操作 <el-icon class="el-icon--right"><ArrowDown /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-if="runInfo.status === RUN_STATUS.UNSTART"
@click="startTaskRunJobFun"
>开始</el-dropdown-item
>
<el-dropdown-item v-if="runInfo.status === RUN_STATUS.RUNNING">暂停</el-dropdown-item>
<el-dropdown-item @click="refreshFun">刷新</el-dropdown-item>
<el-dropdown-item @click="visible = true">查看所有活动</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown> -->
<el-button <el-button
type="primary" type="primary"
v-if="runInfo.status === RUN_STATUS.UNSTART" v-if="runInfo.status === RUN_STATUS.UNSTART"
:disabled="uploadFileFlag"
@click="startTaskRunJobFun" @click="startTaskRunJobFun"
>开始</el-button >开始</el-button
> >
<!-- <el-button size="small" type="danger" v-if="runInfo.status === RUN_STATUS.RUNNING"
>暂停</el-button
> -->
<!-- <el-button size="small" type="primary">完成</el-button> -->
<el-button @click="refreshFun">刷新</el-button> <el-button @click="refreshFun">刷新</el-button>
<el-button @click="visible = true">作业列表</el-button> <el-button @click="visible = true">作业列表</el-button>
</div> </div>
</div> </div>
@@ -110,47 +75,36 @@
</div> </div>
<div :class="leftFullScreen || rightFullScreen ? 'run-info-box is-all-page' : 'run-info-box'"> <div :class="leftFullScreen || rightFullScreen ? 'run-info-box is-all-page' : 'run-info-box'">
<!-- <div class="run-flow-info-box"> <div
v-if="!rightFullScreen"
:class="leftFullScreen ? 'info-box-left allpage ' : 'info-box-left'"
>
<div class="bottom-title"> <div class="bottom-title">
<div class="title-name">节点信息</div> <div class="title-name">节点详情</div>
<div class="title-operate">
<el-icon
v-if="!leftFullScreen"
@click="leftFullScreen = !leftFullScreen"
class="icon-style"
><FullScreen
/></el-icon>
<el-icon v-else @click="leftFullScreen = !leftFullScreen" class="icon-style"
><Close
/></el-icon>
</div>
</div> </div>
</div> -->
<!-- <DragSplit :left-content-width="'50%'">
<template #left> -->
<div
v-if="!rightFullScreen"
:class="leftFullScreen ? 'info-box-left allpage ' : 'info-box-left'"
>
<div class="bottom-title">
<div class="title-name">节点详情</div>
<div class="title-operate">
<el-icon
v-if="!leftFullScreen"
@click="leftFullScreen = !leftFullScreen"
class="icon-style"
><FullScreen
/></el-icon>
<el-icon v-else @click="leftFullScreen = !leftFullScreen" class="icon-style"
><Close
/></el-icon>
</div>
</div>
<div class="bottom-info-content"> <div class="bottom-info-content">
<div class="tabs-box left-tab"> <div class="tabs-box left-tab">
<el-tabs <el-tabs v-model="nodeActiveName" class="demo-tabs" @tab-change="handleLeftClickFun">
v-model="nodeActiveName" <el-tab-pane label="节点信息" name="info"></el-tab-pane>
class="demo-tabs" <el-tab-pane label="参数设置" name="param"></el-tab-pane>
@tab-change="handleLeftClickFun" <el-tab-pane label="数据输入" name="input"></el-tab-pane>
> <el-tab-pane label="数据输出" name="output"></el-tab-pane>
<el-tab-pane label="节点信息" name="info"></el-tab-pane> </el-tabs>
<el-tab-pane label="参数设置" name="param"></el-tab-pane> </div>
<el-tab-pane label="数据输入" name="input"></el-tab-pane> <div class="operate-box">
<el-tab-pane label="数据输出" name="output"></el-tab-pane> <!-- <el-switch
</el-tabs>
</div>
<div class="operate-box">
<!-- <el-switch
v-model="executeMode" v-model="executeMode"
class="mr10" class="mr10"
active-value="AUTO" active-value="AUTO"
@@ -159,28 +113,28 @@
inactive-text="手动执行" inactive-text="手动执行"
@change="FlowNodeExecuteModeChangeFun" @change="FlowNodeExecuteModeChangeFun"
/> --> /> -->
<!-- <el-button <!-- <el-button
type="" type=""
v-if="flowNodeParamData?.nodeTypeValue === '1'" v-if="flowNodeParamData?.nodeTypeValue === '1'"
@click="startLocalAppFun" @click="startLocalAppFun"
>启动</el-button >启动</el-button
> --> > -->
<!-- <el-button type="primary" @click="startLocalAppFun">执行</el-button> --> <!-- <el-button type="primary" @click="startLocalAppFun">执行</el-button> -->
<!-- <el-button <!-- <el-button
type="primary" type="primary"
v-if="flowNodeData.nodeStatus === RUN_NODE_STATUS.WAITING_FOR_USER" v-if="flowNodeData.nodeStatus === RUN_NODE_STATUS.WAITING_FOR_USER"
@click="continueStartRunJobFun" @click="continueStartRunJobFun"
>执行手动节点</el-button >执行手动节点</el-button
> --> > -->
<!-- <el-button <!-- <el-button
type="primary" type="primary"
@click="skipCurrentNodeFlowFun" @click="skipCurrentNodeFlowFun"
v-if="flowNodeParamData?.nodeTypeValue === '1'" v-if="flowNodeParamData?.nodeTypeValue === '1'"
>跳过当前本地节点</el-button >跳过当前本地节点</el-button
> --> > -->
</div> </div>
<div class="tabs-info-content"> <div class="tabs-info-content">
<!-- <paramSetting <!-- <paramSetting
:current-run-flow-node="flowNode" :current-run-flow-node="flowNode"
:node-param-data="nodeParamDataList" :node-param-data="nodeParamDataList"
:node-data="flowNodeParamData" :node-data="flowNodeParamData"
@@ -191,161 +145,149 @@
@update="refreshFlowNodeParamFun" @update="refreshFlowNodeParamFun"
> >
</paramSetting> --> </paramSetting> -->
<!-- v-if="nodeActiveName === 'param' && showPage" --> <!-- v-if="nodeActiveName === 'param' && showPage" -->
<flowNodeParamTable <flowNodeParamTable
v-show="nodeActiveName === 'param' && showPage" ref="flowNodeParamTableRef"
:node-params="nodeParamDataList" v-show="nodeActiveName === 'param' && showPage"
:current-node="flowNode" :node-params="nodeParamDataList"
:page-info="flowNodeData" :current-node="flowNode"
:run-info="runInfo" :page-info="flowNodeData"
:online-file-param="onlineFileParam" :run-info="runInfo"
@confirm="refreshFlowNodeParamFun" :online-file-param="onlineFileParam"
@update="updateFlowNodeParamFun" @confirm="refreshFlowNodeParamFun"
></flowNodeParamTable> @update="updateFlowNodeParamFun"
<runDataPage ></flowNodeParamTable>
v-show="nodeActiveName === 'input' || nodeActiveName === 'output'" <runDataPage
:file-id=" v-show="nodeActiveName === 'input' || nodeActiveName === 'output'"
nodeActiveName === 'input' :file-id="
? flowNodeData?.inputDirId nodeActiveName === 'input' ? flowNodeData?.inputDirId : flowNodeData?.outputDirId
: flowNodeData?.outputDirId "
" :node-info="flowNodeData"
:node-info="flowNodeData" ></runDataPage>
></runDataPage>
<div class="bottom-info-content-tab" v-show="nodeActiveName === 'info'"> <div class="bottom-info-content-tab" v-show="nodeActiveName === 'info'">
<div class="node-img"> <div class="node-img">
<img :src="flowNodeParamData.iconUrl" alt="" /> <img :src="flowNodeParamData.iconUrl" alt="" />
</div> </div>
<div class="node-content"> <div class="node-content">
<el-form> <el-form>
<el-form-item label="节点名称"> <el-form-item label="节点名称">
<span>{{ flowNodeData.nodeName }}</span> <span>{{ flowNodeData.nodeName }}</span>
</el-form-item> </el-form-item>
<el-form-item label="节点类型"> <el-form-item label="节点类型">
<el-tag v-if="flowNodeParamData.nodeTypeValue === '3'" type="primary">{{ <el-tag v-if="flowNodeParamData.nodeTypeValue === '3'" type="primary">{{
getTypeNameFun(flowNodeParamData.nodeTypeValue) getTypeNameFun(flowNodeParamData.nodeTypeValue)
}}</el-tag> }}</el-tag>
<el-tag <el-tag v-else-if="flowNodeParamData.nodeTypeValue === '2'" type="success">{{
v-else-if="flowNodeParamData.nodeTypeValue === '2'" getTypeNameFun(flowNodeParamData.nodeTypeValue)
type="success" }}</el-tag>
>{{ getTypeNameFun(flowNodeParamData.nodeTypeValue) }}</el-tag <el-tag v-else-if="flowNodeParamData.nodeTypeValue === '1'" type="warning">{{
> getTypeNameFun(flowNodeParamData.nodeTypeValue)
<el-tag }}</el-tag>
v-else-if="flowNodeParamData.nodeTypeValue === '1'" <el-tag v-else type="primary">{{
type="warning" getTypeNameFun(flowNodeParamData.nodeTypeValue)
>{{ getTypeNameFun(flowNodeParamData.nodeTypeValue) }}</el-tag }}</el-tag>
>
<el-tag v-else type="primary">{{
getTypeNameFun(flowNodeParamData.nodeTypeValue)
}}</el-tag>
<!-- {{ flowNodeParamData?.nodeTypeValue }} --> <!-- {{ flowNodeParamData?.nodeTypeValue }} -->
</el-form-item> </el-form-item>
<el-form-item label="节点状态"> <el-form-item label="节点状态">
<div class="app-status"> <div class="app-status">
<div <div
class="round" class="round"
:style="{ :style="{
background: getStyleFun(flowNodeData?.nodeStatus).color, background: getStyleFun(flowNodeData?.nodeStatus).color,
}" }"
></div> ></div>
<div class="text"> <div class="text">
{{ getStyleFun(flowNodeData?.nodeStatus).title }} {{ getStyleFun(flowNodeData?.nodeStatus).title }}
</div> </div>
</div> </div>
<!-- {{ flowNodeData?.nodeDetailInfo?.status }} --> <!-- {{ flowNodeData?.nodeDetailInfo?.status }} -->
</el-form-item> </el-form-item>
<el-form-item label="执行时间"> <el-form-item label="执行时间">
<el-icon class="icon-style mr5"><Timer /></el-icon> <el-icon class="icon-style mr5"><Timer /></el-icon>
<span class="gl-text-ellipsis"> <span class="gl-text-ellipsis">
{{ flowNodeData?.nodeDetailInfo?.durationFormatted || '--' }} {{ flowNodeData?.nodeDetailInfo?.durationFormatted || '--' }}
</span> </span>
</el-form-item> </el-form-item>
<el-form-item label="开始时间"> <el-form-item label="开始时间">
<el-icon class="icon-style mr5"><Calendar /></el-icon> <el-icon class="icon-style mr5"><Calendar /></el-icon>
<span class="gl-text-ellipsis"> <span class="gl-text-ellipsis">
{{ flowNodeData?.nodeDetailInfo?.startTime || '--' }} {{ flowNodeData?.nodeDetailInfo?.startTime || '--' }}
</span> </span>
</el-form-item> </el-form-item>
<el-form-item label="完成时间"> <el-form-item label="完成时间">
<el-icon class="icon-style mr5"><Calendar /></el-icon> <el-icon class="icon-style mr5"><Calendar /></el-icon>
<span class="gl-text-ellipsis"> <span class="gl-text-ellipsis">
{{ flowNodeData?.nodeDetailInfo?.endTime || '--' }} {{ flowNodeData?.nodeDetailInfo?.endTime || '--' }}
</span> </span>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- </template> --> </div>
<!-- <template #right> --> </div>
<div <!-- </template> -->
v-if="!leftFullScreen" <!-- <template #right> -->
:class="rightFullScreen ? 'info-box-right allpage ' : 'info-box-right'" <div
> v-if="!leftFullScreen"
<div class="bottom-title"> :class="rightFullScreen ? 'info-box-right allpage ' : 'info-box-right'"
<div class="title-name">作业相关</div> >
<div class="title-operate"> <div class="bottom-title">
<el-icon <div class="title-name">作业相关</div>
v-if="!rightFullScreen" <div class="title-operate">
class="icon-style" <el-icon
@click="rightFullScreen = !rightFullScreen" v-if="!rightFullScreen"
><FullScreen class="icon-style"
/></el-icon> @click="rightFullScreen = !rightFullScreen"
<el-icon v-else class="icon-style" @click="rightFullScreen = !rightFullScreen" ><FullScreen
><Close /></el-icon>
/></el-icon> <el-icon v-else class="icon-style" @click="rightFullScreen = !rightFullScreen"
</div> ><Close
</div> /></el-icon>
<div class="bottom-info-content">
<div class="tabs-box">
<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="job-log"></el-tab-pane> -->
<el-tab-pane label="关联任务" name="associated-run"></el-tab-pane>
<el-tab-pane label="仿真结果" name="result"></el-tab-pane>
<!-- <el-tab-pane label="性能指标" name="performance"></el-tab-pane> -->
<el-tab-pane label="报告结果" name="report"></el-tab-pane>
<el-tab-pane label="标准规范" name="standard"></el-tab-pane>
<!-- <el-tab-pane label="3D模型预览" name="3D-model"></el-tab-pane> -->
</el-tabs>
</div>
<div class="tabs-info-content">
<resultData
v-if="taskActiveName === 'result'"
:current-run-ifno="runInfo"
></resultData>
<jobList v-if="taskActiveName === 'job-list'" :current-run-info="runInfo"></jobList>
<taskPerformance
v-if="taskActiveName === 'performance'"
:param-type="'run'"
:run-info="runInfo"
:show-save-button="true"
:full-height="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>
<runStandard v-if="taskActiveName === 'standard'" :run-info="runInfo"></runStandard>
<reportResult
v-if="taskActiveName === 'report'"
:current-run-ifno="runInfo"
></reportResult>
</div>
</div>
</div> </div>
<!-- </template> </div>
<div class="bottom-info-content">
<div class="tabs-box">
<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="job-log"></el-tab-pane> -->
<el-tab-pane label="关联任务" name="associated-run"></el-tab-pane>
<el-tab-pane label="仿真结果" name="result"></el-tab-pane>
<!-- <el-tab-pane label="性能指标" name="performance"></el-tab-pane> -->
<el-tab-pane label="报告结果" name="report"></el-tab-pane>
<el-tab-pane label="标准规范" name="standard"></el-tab-pane>
<!-- <el-tab-pane label="3D模型预览" name="3D-model"></el-tab-pane> -->
</el-tabs>
</div>
<div class="tabs-info-content">
<resultData v-if="taskActiveName === 'result'" :current-run-ifno="runInfo"></resultData>
<jobList v-if="taskActiveName === 'job-list'" :current-run-info="runInfo"></jobList>
<taskPerformance
v-if="taskActiveName === 'performance'"
:param-type="'run'"
:run-info="runInfo"
:show-save-button="true"
:full-height="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>
<runStandard v-if="taskActiveName === 'standard'" :run-info="runInfo"></runStandard>
<reportResult
v-if="taskActiveName === 'report'"
:current-run-ifno="runInfo"
></reportResult>
</div>
</div>
</div>
<!-- </template>
</DragSplit> --> </DragSplit> -->
</div> </div>
<HpcList v-model="visible" /> <HpcList v-model="visible" />
@@ -353,7 +295,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, watch } from 'vue'; import { onActivated, onBeforeUnmount, onDeactivated, onMounted, ref, watch } from 'vue';
import resultData from './runPagecomponent/resultData.vue'; import resultData from './runPagecomponent/resultData.vue';
import runDataPage from './runPagecomponent/runDataPage.vue'; import runDataPage from './runPagecomponent/runDataPage.vue';
import jobList from './runPagecomponent/jobList.vue'; import jobList from './runPagecomponent/jobList.vue';
@@ -365,6 +307,7 @@ import runFlowPage from './runPagecomponent/flow/runFlowPage.vue';
import HpcList from '@/components/task/hpcList.vue'; import HpcList from '@/components/task/hpcList.vue';
import { import {
queryRunDirApi, queryRunDirApi,
retryFailedNodeApi,
saveNodeParamsApi, saveNodeParamsApi,
startProcessInstanceApi, startProcessInstanceApi,
uploadRunFilesApi, uploadRunFilesApi,
@@ -388,7 +331,6 @@ import { getDictionaryDataApi } from '@/api/system/systemData';
import { getUserData, getUserId, getUserTenantId } from '@/utils/user'; import { getUserData, getUserId, getUserTenantId } from '@/utils/user';
import reportResult from './runPagecomponent/reportResult.vue'; import reportResult from './runPagecomponent/reportResult.vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import DragSplit from '@/components/common/dragSplit/index.vue';
const props = defineProps({ const props = defineProps({
runInfo: { runInfo: {
@@ -406,7 +348,7 @@ const statusList = ref<any>({
error: '异常', error: '异常',
waiting_for_user: '待操作', waiting_for_user: '待操作',
}); });
const flowNodeParamTableRef = ref();
const executeMode = ref('MANUAL'); const executeMode = ref('MANUAL');
const visible = ref(false); const visible = ref(false);
const nodeActiveName = ref('info'); const nodeActiveName = ref('info');
@@ -430,6 +372,9 @@ const onlineFileParam = ref<any>({});
const changeCurrentFlowNodeFun = (info: any) => { const changeCurrentFlowNodeFun = (info: any) => {
refreshPage.value = false; refreshPage.value = false;
const { node, data, process }: any = info; const { node, data, process }: any = info;
console.log(info, 'info');
flowNode.value = node; flowNode.value = node;
flowNodeData.value = data; flowNodeData.value = data;
// nodeParamDataList.value = flowNode.value?.store?.data?.data?.pageConfigList || []; // nodeParamDataList.value = flowNode.value?.store?.data?.data?.pageConfigList || [];
@@ -494,6 +439,7 @@ const startTaskRunJobFun = async () => {
// 在开始执行任务之前,保存每个节点的参数后再调用执行任务的接口 // 在开始执行任务之前,保存每个节点的参数后再调用执行任务的接口
// 检查每个节点的参数 // 检查每个节点的参数
uploadFileFlag.value = false;
for (const key in pageParamInfo.value) { for (const key in pageParamInfo.value) {
const params = pageUserParam.value[key]; const params = pageUserParam.value[key];
@@ -507,14 +453,18 @@ const startTaskRunJobFun = async () => {
await saveParamsFun(params, list, data, node); await saveParamsFun(params, list, data, node);
} }
const res: any = await startProcessInstanceApi({ if (!uploadFileFlag.value) {
runId: props.runInfo.uuid, const res: any = await startProcessInstanceApi({
}); runId: props.runInfo.uuid,
if (res && res.code === 200) { });
ElMessage.success(res.message); if (res && res.code === 200) {
showPage.value = false; ElMessage.success(res.message);
refreshRunFlowInfo(); showPage.value = false;
emits('update', { status: RUN_STATUS.RUNNING }); refreshRunFlowInfo();
emits('update', { status: RUN_STATUS.RUNNING });
}
} else {
ElMessage.success('文件正在上传中,请勿进行其他操作!');
} }
}; };
@@ -552,6 +502,7 @@ const saveParamsFun = async (params: any, list: any, data: any, node: any) => {
} }
}; };
const uploadFileFlag = ref(false);
const setDataToParam = async (list: any, obj: any, isUpload?: any, inputDirId?: any) => { const setDataToParam = async (list: any, obj: any, isUpload?: any, inputDirId?: any) => {
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
if (list[i]?.englishLabel) { if (list[i]?.englishLabel) {
@@ -561,13 +512,7 @@ const setDataToParam = async (list: any, obj: any, isUpload?: any, inputDirId?:
if (fileList.length) { if (fileList.length) {
const fileData = await runUploadRunFilesFun(fileList, inputDirId); const fileData = await runUploadRunFilesFun(fileList, inputDirId);
arrs = fileData; arrs = fileData;
// for (let j = 0; j < fileList.length; j++) { uploadFileFlag.value = true;
// if (isUpload) {
// await uploadRunFilesFun(fileList[j].raw);
// }
// arrs.push({ fileName: fileList[j].name });
// }
} }
list[i].defaultValue = arrs; list[i].defaultValue = arrs;
@@ -603,6 +548,7 @@ const runUploadRunFilesFun = async (list: any, inputDirId: any) => {
if (res && res.code === 200) { if (res && res.code === 200) {
res.data.forEach((item: any, index: any) => { res.data.forEach((item: any, index: any) => {
item.isSaveLocal = 'Y';
emitter.emit('ADD_UPLOAD_FILE', { emitter.emit('ADD_UPLOAD_FILE', {
file: list[index].raw, file: list[index].raw,
data: { data: {
@@ -610,6 +556,7 @@ const runUploadRunFilesFun = async (list: any, inputDirId: any) => {
...item, ...item,
isApprove: 0, // 0否 1是 isApprove: 0, // 0否 1是
taskType: 4, // 4交付物 taskType: 4, // 4交付物
callbackFlag: 'START_FLOW',
}, },
}); });
}); });
@@ -701,6 +648,11 @@ const continueStartRunJobFun = async () => {
const startLocalAppFun = async () => { const startLocalAppFun = async () => {
if (flowNodeData.value?.nodeStatus === RUN_NODE_STATUS.WAITING_FOR_USER) { if (flowNodeData.value?.nodeStatus === RUN_NODE_STATUS.WAITING_FOR_USER) {
continueStartRunJobFun(); continueStartRunJobFun();
} else if (flowNodeData.value?.nodeStatus === RUN_NODE_STATUS.ERROR) {
// 重新执行失败的流程节点
// 重新保存该流程节点的参数
await flowNodeParamTableRef.value.saveNodeParamFun('RESTART_FLOW_NODE');
// 调用重新执行的接口
} else { } else {
// 本地节点拉起应用 // 本地节点拉起应用
if (flowNodeParamData.value?.nodeTypeValue === '1') { if (flowNodeParamData.value?.nodeTypeValue === '1') {
@@ -732,6 +684,25 @@ const startLocalAppFun = async () => {
} }
}; };
// 重新执行节点按钮
const retryFailedNodeFun = async () => {
const param = {
processInstanceId: flowNodeData.value.processInstanceId,
failNodeId: flowNodeData.value.nodeId,
};
try {
const res: any = await retryFailedNodeApi(param);
if (res && res.code === 200) {
ElMessage.success('节点已重新执行!');
showPage.value = false;
refreshRunFlowInfo();
}
} catch (error) {
console.log(error);
}
};
// 获取插件提交计算的参数信息 // 获取插件提交计算的参数信息
const getSubmitParamFun = async () => { const getSubmitParamFun = async () => {
const taskName = props.runInfo?.parentName; const taskName = props.runInfo?.parentName;
@@ -790,6 +761,22 @@ const getNodeFileIdAndNames = async () => {
const fileIds: any = []; const fileIds: any = [];
const fileNames: any = []; const fileNames: any = [];
let taskCmdParam: any = {}; let taskCmdParam: any = {};
// 本地应用执行的脚本也需要下载下来
if (flowNodeParamData.value?.postScripts?.length) {
for (let i = 0; i < flowNodeParamData.value?.postScripts?.length; i++) {
fileIds.push(flowNodeParamData.value?.postScripts[i].fileId);
fileNames.push(flowNodeParamData.value?.postScripts[i].name);
}
}
if (flowNodeParamData.value?.preScripts?.length) {
for (let i = 0; i < flowNodeParamData.value?.preScripts?.length; i++) {
fileIds.push(flowNodeParamData.value?.preScripts[i].fileId);
fileNames.push(flowNodeParamData.value?.preScripts[i].name);
}
}
try { try {
const res: any = await queryRunDirApi({ const res: any = await queryRunDirApi({
current: 1, current: 1,
@@ -916,9 +903,17 @@ const refreshFun = () => {
// } catch {} // } catch {}
// }; // };
const refreshFlowNodeParamFun = () => { const refreshFlowNodeParamFun = async (data: any) => {
showPage.value = false; const { flag }: any = data;
refreshRunFlowInfo(); if (flag === false) {
await retryFailedNodeFun();
showPage.value = false;
refreshRunFlowInfo();
}
if (flag === true) {
ElMessage.success('文件正在上传中,请等待文件上传完成后再操作');
}
}; };
const newNodeData = ref<any>({}); const newNodeData = ref<any>({});
const updateFlowNodeParamFun = (data: any) => { const updateFlowNodeParamFun = (data: any) => {
@@ -1002,6 +997,27 @@ const executeFun = () => {
startLocalAppFun(); startLocalAppFun();
}; };
// 文件上传完成后的回调事件
const uploadFinishedFun = async (data: any) => {
// 开始任务执行
if (data.callbackFlag === 'START_FLOW') {
const res: any = await startProcessInstanceApi({
runId: props.runInfo.uuid,
});
if (res && res.code === 200) {
ElMessage.success(res.message);
showPage.value = false;
refreshRunFlowInfo();
emits('update', { status: RUN_STATUS.RUNNING });
}
}
// 重复执行失败节点
if (data.callbackFlag === 'RESTART_FLOW_NODE') {
await retryFailedNodeFun();
}
};
watch( watch(
() => props.runInfo, () => props.runInfo,
(newVal) => { (newVal) => {
@@ -1017,6 +1033,19 @@ watch(
onMounted(async () => { onMounted(async () => {
await getDictionaryDataFun(); await getDictionaryDataFun();
emitter.on('UPLOAD_FINISHED', uploadFinishedFun);
});
onBeforeUnmount(() => {
emitter.off('UPLOAD_FINISHED', uploadFinishedFun);
});
onActivated(() => {
emitter.on('UPLOAD_FINISHED', uploadFinishedFun);
});
onDeactivated(() => {
emitter.off('UPLOAD_FINISHED', uploadFinishedFun);
}); });
</script> </script>

View File

@@ -8,8 +8,24 @@
:params="{ :params="{
runId: currentRunInfo?.uuid, runId: currentRunInfo?.uuid,
}" }"
:actionList="actionList"
:fullHeight="true" :fullHeight="true"
> >
<template #totalElapsedTime="{ row }">
<span>{{ row.totalElapsedTime ? row.totalElapsedTime + 'h' : '--' }}</span>
</template>
<template #jobStatus="{ row }">
<el-tag v-if="row.jobStatus === 'Finished'" type="success">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag type="info" v-else-if="row.jobStatus === 'Canceled'">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag v-else-if="row.jobStatus === 'Failed'" type="danger">{{
WORK_STATUS.O[row.jobStatus]
}}</el-tag>
<el-tag v-else type="primary">{{ WORK_STATUS.O[row.jobStatus] }}</el-tag>
</template>
</BaseTable> </BaseTable>
</div> </div>
</template> </template>
@@ -18,6 +34,7 @@
import { ref } from 'vue'; import { ref } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue'; import BaseTable from '@/components/common/table/baseTable.vue';
import { queryJobsApi } from '@/api/pbs/pbs'; import { queryJobsApi } from '@/api/pbs/pbs';
import { useDict } from '@/utils/useDict';
defineProps({ defineProps({
currentRunInfo: { currentRunInfo: {
@@ -25,8 +42,20 @@ defineProps({
default: () => {}, default: () => {},
}, },
}); });
const { WORK_STATUS } = useDict('WORK_STATUS');
const baseTableRef = ref(); const baseTableRef = ref();
const actionList = ref([
{
title: '暂停',
type: 'danger',
click: (row: any) => {},
hide: (row: any) => {
return !['Canceled', 'Finished', 'Failed'].includes(row.jobStatus);
},
},
]);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -18,7 +18,7 @@
:show-task-info="false" :show-task-info="false"
></taskDetailPage> ></taskDetailPage>
<runDetailPage <runDetailPage
v-else-if="treeCurrentNodeInfo?.nodeType === NODE_TYPE.RUN" v-else-if="treeCurrentNodeInfo?.nodeType === NODE_TYPE.RUN && showPage"
:run-info="treeCurrentNodeInfo" :run-info="treeCurrentNodeInfo"
@update="updateLeftTreeNodeInfoFun" @update="updateLeftTreeNodeInfoFun"
></runDetailPage> ></runDetailPage>
@@ -29,7 +29,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { nextTick, ref } from 'vue';
import { NODE_TYPE } from '@/utils/enum/node'; import { NODE_TYPE } from '@/utils/enum/node';
import leftTaskTree from './components/leftTaskTree/index.vue'; import leftTaskTree from './components/leftTaskTree/index.vue';
import taskDetailPage from './components/taskDetailPage/index.vue'; import taskDetailPage from './components/taskDetailPage/index.vue';
@@ -40,15 +40,21 @@ const toggleFun = () => {
isToggleShow.value = !isToggleShow.value; isToggleShow.value = !isToggleShow.value;
}; };
const leftTreeRef = ref(); const leftTreeRef = ref();
const showPage = ref(true);
const treeCurrentNodeInfo = ref<any>(null); const treeCurrentNodeInfo = ref<any>(null);
const getTreeCurrentNodeFun = (data: any) => { const getTreeCurrentNodeFun = (data: any) => {
showPage.value = false;
treeCurrentNodeInfo.value = {}; treeCurrentNodeInfo.value = {};
setTimeout(() => { // setTimeout(() => {
// }, 1000);
nextTick(() => {
const { node }: any = data; const { node }: any = data;
treeCurrentNodeInfo.value = node; treeCurrentNodeInfo.value = node;
}, 1000); showPage.value = true;
});
}; };
// 作业启动更新左侧树的算例的状态 // 作业启动更新左侧树的算例的状态

View File

@@ -86,46 +86,35 @@
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="项目详情" name="projectDetail"> <el-tab-pane label="项目详情" name="projectDetail">
<baseInfo <div
ref="basePageRef" class="project-detail-content"
@update:projectInfo="updateProjectInfo" v-if="displayedTabs.includes('projectDetail') && projectUuid"
@loaded="projectInfoLoadCompleteFun" >
v-if="projectUuid" <!-- 基本信息 -->
:nodeId="projectUuid" <div class="section-block">
/> <div class="section-title">基本信息</div>
</el-tab-pane> <baseInfo
<el-tab-pane ref="basePageRef"
v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" @update:projectInfo="updateProjectInfo"
label="方案维护" @loaded="projectInfoLoadCompleteFun"
name="schemeMaintain" :nodeId="projectUuid"
> />
<SchemeMaintain </div>
ref="schemeMaintainRef" <template v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])">
v-if="displayedTabs.includes('schemeMaintain') && projectUuid" <div class="section-block">
:nodeId="projectUuid" <div class="section-title">方案维护</div>
/> <SchemeMaintain ref="schemeMaintainRef" :nodeId="projectUuid" />
</el-tab-pane> </div>
<el-tab-pane <div class="section-block">
v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" <div class="section-title">批次信息</div>
label="批次信息" <BatchInfo ref="batchInfoRef" :nodeId="projectUuid" />
name="batchInfo" </div>
> <div class="section-block">
<BatchInfo <div class="section-title">产线信息</div>
ref="batchInfoRef" <productionLine ref="productionLineRef" :nodeCode="currentProjectInfo.nodeCode" />
v-if="displayedTabs.includes('batchInfo') && projectUuid" </div>
:nodeId="projectUuid" </template>
/> </div>
</el-tab-pane>
<el-tab-pane
v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])"
label="产线信息"
name="productionLine"
>
<productionLine
ref="productionLineRef"
v-if="displayedTabs.includes('productionLine') && projectUuid"
:nodeCode="currentProjectInfo.nodeCode"
/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" label="项目PDT" name="PDT"> <el-tab-pane v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" label="项目PDT" name="PDT">
<PDT <PDT
@@ -418,4 +407,30 @@ const projectInfoLoadCompleteFun = () => {
height: 100%; height: 100%;
} }
} }
.project-detail-content {
height: 100%;
overflow-y: auto;
padding-right: 10px;
}
.section-block {
margin-bottom: 24px;
padding-bottom: 20px;
border-bottom: 1px solid var(--el-border-color-lighter);
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
}
.section-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 12px;
padding-left: 10px;
border-left: 3px solid var(--el-color-primary);
}
</style> </style>