仿真流程库功能优化

This commit is contained in:
weibl
2025-11-14 17:58:17 +08:00
parent ddff25c648
commit 5dbb6a7a40
15 changed files with 246 additions and 69 deletions

View File

@@ -3,10 +3,24 @@ import { get, post } from '@/api/request';
const env = import.meta.env;
const PREFIX = env.VITE_API_PREFIX_FLOW;
/**
* 创建流程草稿模板
* @param
* @returns
*/
export const addFlowTemplateDraftApi = (params: any) => {
return post(`${PREFIX}flow/createFlowTemplateDraft`, params);
};
/**
* 升版流程草稿模板
* @param
* @returns
*/
export const upgradeFlowTemplateDraftApi = (params: any) => {
return post(`${PREFIX}flow/upgradeFlowTemplateDraft`, params);
};
/**
*
* @param params

View File

@@ -79,6 +79,6 @@ defineExpose({
<style lang="scss" scoped>
.monaco-editor-box {
height: 800px;
height: 100%;
}
</style>

View File

@@ -82,15 +82,10 @@ const saveFile = async () => {
if (isChange.value) {
const currentValue = toRaw(editor.value).getValue();
const baseRes:any = await getFileBaseInfoApi({ fileId: props.fileId });
if (baseRes.code === 200) {
fileTitle.value = '';
}
const form = new FormData();
// form.append('fileType', String(FILE_TYPE.FLOW_PYTHON));
form.append('scriptFileId ', props.fileId);
form.append('fileName ', 'hello_world.py');
form.append('fileName ', fileTitle.value);
form.append('updateFile ', new Blob([currentValue], { type: 'text/txt' }));
const res = await upload(`${PREFIX}data/updateScriptFile`, form);
@@ -125,7 +120,10 @@ const fileTitle = ref<string>('');
const getFile = async () => {
loading.value = true;
const baseRes:any = await getFileBaseInfoApi({ fileId: props.fileId });
if (baseRes.code === 200) {
fileTitle.value = baseRes.data.originalName;
}
const res:any = await dataDownloadFileApi({ fileId: props.fileId });
if (res) {
// 设置语言

View File

@@ -178,7 +178,7 @@ const validateFun = () => {
const getFormDataFun = () => {
const objData: any = formData.value || {};
const hasExtras = !!formData.value.extras;
objData.extras = hasExtras ? formData.value.extras : null;
objData.extras = hasExtras ? formData.value.extras : [];
tableData.value.forEach((item: any) => {
const { key, type } = item;
if (type === 1) {

View File

@@ -150,20 +150,27 @@ export default [
icon: Icons['Cpu'],
children: [
{
title: '仿真流程库',
path: '/simulation/process',
name: 'SimulationProcess',
component: () => import('@/views/simulation/process/index.vue'),
title: '通用仿真流程库',
path: '/simulation/publicProcess',
name: 'SimulationPublicProcess',
component: () => import('@/views/simulation/publicProcess/index.vue'),
// component: () => import('@/views/error/developing.vue'),
},
{
title: '仿真流程创建',
path: '/simulation/creation',
name: 'SimulationCreation',
// component: () => import('@/views/simulation/creation/index.vue'),
component: () => import('@/views/error/developing.vue'),
title: '我的仿真流程',
path: '/simulation/myProcess',
name: 'SimulationMyProcess',
component: () => import('@/views/simulation/myProcess/index.vue'),
// component: () => import('@/views/error/developing.vue'),
},
// {
// title: '仿真流程创建',
// path: '/simulation/creation',
// name: 'SimulationCreation',
// // component: () => import('@/views/simulation/creation/index.vue'),
// component: () => import('@/views/error/developing.vue'),
// },
// {
// title: '仿真工具',
// path: '/simulation/tool',
// name: 'SimulationTool',

View File

@@ -8,3 +8,40 @@ export enum FLOW_USE_STATUS {
*/
USED = 1,
}
export enum FLOW_APPROVE_STATUS {
/**
* 未审核
*/
NOT_APPROVED = 0,
/**
* 审核中
*/
APPROVING = 1,
/**
* 审核通过
*/
APPROVED = 2,
/**
* 审核不通过
*/
NOT_APPROVED_REJECT = 3,
}
export enum FLOW_TEMPLATE_PUBLIC_STATUS {
/**
* 私有
*/
PRIVATE = 2,
/**
* 公共
*/
PUBLIC = 1,
}
export const FLOW_APPROVE_MAP = new Map([
[FLOW_APPROVE_STATUS.NOT_APPROVED, '未审核'],
[FLOW_APPROVE_STATUS.NOT_APPROVED_REJECT, '审核不通过'],
[FLOW_APPROVE_STATUS.APPROVED, '审核通过'],
[FLOW_APPROVE_STATUS.APPROVING, '评审中']])
;

View File

@@ -9,6 +9,8 @@ const lang = {
'流程管理': 'Simulation Workflow',
'仿真参数库': 'Parameter Library',
'仿真流程库': 'Process Library',
'通用仿真流程库': 'Public Process',
'我的仿真流程库': 'My Process',
'仿真流程创建': 'Process Creation',
'仿真工具': 'Point Tool',
'任务管理': 'Simulation Task',

View File

@@ -10,6 +10,8 @@ const lang = {
'仿真参数库': '仿真参数库',
'仿真流程库': '仿真流程库',
'仿真流程创建': '仿真流程创建',
'通用仿真流程库': '通用仿真流程库',
'我的仿真流程库': '我的仿真流程库',
'仿真工具': '仿真工具',
'任务管理': '任务管理',
'我的任务': '我的任务',

View File

@@ -21,6 +21,12 @@
<el-radio value="upgrade" size="large">升版草稿</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="升级方式:">
<el-radio-group v-model="approveForm.versionType">
<el-radio value="1" size="large">大版本</el-radio>
<el-radio value="0" size="large">小版本</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div>
@@ -34,18 +40,20 @@
<script lang='ts' setup>
import Dialog from '@/components/common/dialog/index.vue';
// import { ElMessage } from 'element-plus';
import { computed, reactive, ref } from 'vue';
import { computed, inject, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import ApproveList from '@/components/common/approveList/index.vue';
import { releaseFlowTemplateApi } from '@/api/flow/flow';
import { releaseFlowTemplateApi, upgradeFlowTemplateDraftApi } from '@/api/flow/flow';
const props = defineProps<{
showDialog: boolean;
uuid: string;
versionType:string;
graphJson: string;
graph: any;
}>();
const flowDetail:any = inject('flowDetail');
const loadingInterface = ref(false);
const dialogVisible = computed({
@@ -61,6 +69,7 @@ const emits = defineEmits(['update:showDialog', 'confirm', 'saveDraft' ]);
const approveForm = reactive<any>({
approve: '',
updateMode: 'update',
versionType: '1',
});
const approveFormRef = ref();
@@ -72,30 +81,54 @@ const approveFormRules = reactive<any>({
});
const confirmFun = async () => {
approveFormRef.value.validate(async(valid: boolean) => {
if (valid) {
console.log('approveForm', approveForm);
loadingInterface.value = true;
if (approveForm.updateMode === 'update') {
emits('saveDraft', async () => {
const res:any = await releaseFlowTemplateApi({
uuid: props.uuid,
versionType: props.versionType,
approveFlowId: approveForm.approve,
});
if (res.code === 200) {
ElMessage.success('提交成功');
} else {
ElMessage.error(res.message);
}
loadingInterface.value = false;
await submitApproveFun();
});
} else {
const upgradeRes:any = await upgradeDraftFun({
'templateName': flowDetail.templateName,
'templateContent': '',
'viewContent': JSON.stringify(props.graph.toJSON()),
'templateType': flowDetail.templateType,
'comment': flowDetail.comment,
versionType: approveForm.versionType,
});
await submitApproveFun(upgradeRes.data);
}
loadingInterface.value = false;
emits('update:showDialog', false);
}
});
};
const upgradeDraftFun = async (params:any) => {
const res:any = await upgradeFlowTemplateDraftApi(params);
if (res.code === 200) {
return res;
} else {
ElMessage.error(res.message);
}
};
const submitApproveFun = async (uuid:string = props.uuid) => {
const res:any = await releaseFlowTemplateApi({
uuid: uuid,
// versionType: props.versionType,
approveTemplateId: approveForm.approve,
});
if (res.code === 200) {
ElMessage.success('提交成功');
} else {
ElMessage.error(res.message);
}
};
const closeFun = () => {
console.log('关闭弹窗');
emits('update:showDialog', false);

View File

@@ -51,6 +51,45 @@
</div>
</div>
</div>
<div class="item-box">
<div class="title">
<span>节点后脚本</span>
<el-upload
class="upload-btn"
:multiple="true"
:auto-upload="false"
:show-file-list="false"
@change="(val: any) => changeFileFun('post', val)"
>
<img src="@/assets/imgs/dragFlow/add-script.svg" alt="">
</el-upload>
</div>
<div class="script-box" v-for="(item,index) in nodeAttribute.postScripts" :key="item.id">
<div class="s-name">脚本名称</div>
<div class="operation">
<el-input v-model="item.name" class="el-input"></el-input>
<span class="code-view-btn">
<img src="@/assets/imgs/dragFlow/open-code.svg" v-if="!item.isPreview" @click="changeReviewFun('post',index)" alt="">
<img class="select-ing" src="@/assets/imgs/dragFlow/close-code.png" v-else @click="changeReviewFun('post',index)" alt="">
</span>
<el-popconfirm title="确认删除?" @confirm="removeFileFun('post', index)">
<template #reference>
<img src="@/assets/imgs/dragFlow/lessen.svg" alt="">
</template>
</el-popconfirm>
</div>
<div class="code-box" v-if="item.isPreview">
<div class="code-header">
<span class="s-name">脚本代码</span>
<div class="edit-code" @click="openCodeDialogFun(item.fileId)">在IDE中编辑</div>
</div>
<div class="code-text">
<MonacoEditor :idIndex="item.fileId + item.name" readonly :file-id="item.fileId"></MonacoEditor>
<!-- <img src="@/assets/imgs/dragFlow/code.png" alt=""> -->
</div>
</div>
</div>
</div>
</div>
<FleEdit v-model:showDialog="showCodeEdit" :file-id="editFileId" :idIndex="editFileId+'dialog'"></FleEdit>
</template>
@@ -91,12 +130,6 @@ const versions = ref([
{ label: '版本 3.0.0', value: '3.0.0' },
]);
// const nodeAttribute = reactive<any>({
// version: '',
// preScripts: [],
// postScripts: [],
// });
const changeFileFun = async (type:string, file:any) => {
console.log('file', file);
const isRepeat = props.nodeAttribute[type === 'pre' ? 'preScripts' : 'postScripts'].some((item:any) => item.name === file.name);
@@ -110,7 +143,7 @@ const changeFileFun = async (type:string, file:any) => {
const res = await upload(`${PREFIX}data/uploadScriptFile`, form);
const preScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.postScripts;
if (type === 'pre') {
preScripts.push({
name: file.name,
@@ -136,7 +169,7 @@ const changeFileFun = async (type:string, file:any) => {
const changeReviewFun = (type:string, index:number) => {
const preScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.postScripts;
if (type === 'pre') {
preScripts[index].isPreview = !preScripts[index].isPreview;
}
@@ -148,7 +181,7 @@ const changeReviewFun = (type:string, index:number) => {
const removeFileFun = (type:string, index:number) => {
const preScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.preScripts;
const postScripts = props.nodeAttribute.postScripts;
if (type === 'pre') {
preScripts.splice(index, 1);
}
@@ -175,6 +208,8 @@ onMounted(() => {
.script-manager {
padding: 0 var(--padding-medium);
padding-top: var(--padding-medium);
height: 100%;
overflow-y: auto;
}
.item-box {
padding-bottom: var(--padding-medium);

View File

@@ -3,6 +3,7 @@ import { nextTick } from 'vue';
import { registerCustomNode } from './registerNode';
import { queryAllApplicationApi } from '@/api/system/application';
import { CommonStore } from '@/stores/common';
import { FileUtil } from '@/utils/file';
const commonStore = CommonStore();
@@ -52,10 +53,10 @@ export const stencilRegister = async (graph: any) => {
const imageNodes = nodeList[key].nodes.map((item:any) =>
graph.createNode({
shape: 'custom-image',
label: item.label,
label: item.appName,
attrs: {
image: {
'xlink:href': 'https://zcloud.paratera.com/images/app_icons/icon-abaqus.png?_=2018060401',
'xlink:href': FileUtil.getFilePreviewImgPathUrl(item.appImage),
},
// body: {
// fill: '#EBEBEB',
@@ -64,7 +65,7 @@ export const stencilRegister = async (graph: any) => {
data: {
label: item.appName,
type: nodeList[key].label,
iconUrl: item.appImage,
iconUrl: FileUtil.getFilePreviewImgPathUrl(item.appImage),
preScripts: [],
postScripts: [],
appVersion: '',

View File

@@ -8,7 +8,19 @@
<span class="name">{{ flowName }}</span>
<span class="line">|</span>
<span class="version">版本</span>
<el-select @change="changeVersionFun" class="select-box" value-key="uuid" v-model="currentVersion" :options="flowVersionOptions"></el-select>
<el-select
@change="changeVersionFun"
class="select-box"
value-key="uuid"
v-model="currentVersion"
>
<el-option
v-for="item in flowVersionOptions"
:key="item.uuid"
:label="item.templateVersion + '' + FLOW_APPROVE_MAP.get(item.approveType) + ''"
:value="item"
/>
</el-select>
</div>
<div class="center-box">
<img @click="undoFun(graph)" src="@/assets/imgs/dragFlow/undo.svg" alt="">
@@ -29,16 +41,16 @@
<ConfigPage v-if="drawerVisible" v-model:drawerVisible="drawerVisible" :nodeAttribute="nodeAttribute" />
<ApproveDialog
v-model:showDialog="showApproveDia"
:uuid="currentVersion.uuid"
:versionType="currentVersion.templateVersion"
:graphJson="JSON.stringify(graph?.toJSON())"
:uuid="currentVersion?.uuid"
:versionType="currentVersion?.templateVersion"
:graph="graph"
@saveDraft="saveDraftFun"
></ApproveDialog>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import { onMounted, ref } from 'vue';
import { getTeleport } from '@antv/x6-vue-shape';
import { useNodeAttribute, useNodeEvents } from './components/nodeEvents';
import { registerCustomConnector } from './components/registerConnector';
@@ -47,6 +59,7 @@ import { queryFlowTemplateDetailApi, queryFlowTemplateVersionApi, updateFlowTemp
import { ElMessage } from 'element-plus';
import { initGraph } from './components/initGraph';
import ApproveDialog from './components/approveDialog.vue';
import { FLOW_APPROVE_MAP } from '@/utils/enum/flow';
const props = defineProps({
flowUuid: {
@@ -63,11 +76,7 @@ const emits = defineEmits(['goBack']);
const flowName = ref('');
const currentVersion = reactive<any>({
uuid: '',
templateVersion: '',
approveType: 0,
});
const currentVersion = ref<any>();
const flowVersionOptions = ref<any[]>([]);
@@ -87,14 +96,13 @@ const getFlowVersionOptions = async() => {
if (res.code === 200) {
flowVersionOptions.value = res.data.map((item: any) => {
return {
label: item.templateVersion,
value: item,
templateVersion: item.templateVersion,
approveType: item.approveType,
uuid: item.uuid,
};
});
if (flowVersionOptions.value.length > 0) {
for (const key in currentVersion) {
currentVersion[key] = flowVersionOptions.value[0].value[key];
}
currentVersion.value = flowVersionOptions.value[flowVersionOptions.value.length - 1];
getFlowDetail();
}
} else {
@@ -103,11 +111,12 @@ const getFlowVersionOptions = async() => {
};
const changeVersionFun = () => {
drawerVisible.value = false;
getFlowDetail();
};
const getFlowDetail = async() => {
const res:any = await queryFlowTemplateDetailApi({ uuid: currentVersion.uuid, status: 1 });
const res:any = await queryFlowTemplateDetailApi({ uuid: currentVersion.value.uuid, status: 1 });
if (res.code === 200) {
const dataJson = JSON.parse(res.data.viewContent);
graph.value.fromJSON(dataJson);
@@ -133,6 +142,7 @@ const saveDraftFun = async(callback: () => void) => {
}
}
if (callback) {
console.log('callback', 111);
callback();
}
};

View File

@@ -0,0 +1,11 @@
<template>
<Process
:apiParams="{
creator: getUserId()
}"
></Process>
</template>
<script lang='ts' setup>
import { getUserId } from '@/utils/user';
import Process from '@/views/simulation/process/index.vue';
</script>

View File

@@ -12,7 +12,7 @@
showIndex
ref="tableRef"
tableName="SIMULATION_FLOW_LIB_LIST"
:params="{type:2}"
:params="{...apiParams}"
:api="queryFlowTemplateApi"
:searchLimitNum="3"
:listMode="viewType === 'list' ? 'default' : 'card'"
@@ -36,7 +36,7 @@
<span class="info-label">状态</span>
<span class="info-value">
<span :class="['status-badge', 'status-' + (project.exeStatus ? '' : 'no-start')]">
{{ PROJECT_EXE_STATUS.O[project.exeStatus] }}
{{ FLOW_USE_TYPE.O[project.exeStatus] }}
</span>
</span>
</div>
@@ -66,9 +66,12 @@
{{ $t('项目列表.新增') }}
</el-button>
</template>
<!-- <template #approveType="{ row }">
{{ PROJECT_EXE_STATUS.O[row.exeStatus] }}
</template> -->
<template #templateStatus="{ row }">
{{ FLOW_USE_TYPE.O[row.templateStatus] }}
</template>
<template #approveType="{ row }">
{{ FLOW_APPROVE_STATUS.O[row.approveType] }}
</template>
<template #tableActions="{ row }">
<div class="gl-table-actions">
<el-link type="primary" @click="goProjectDetailFun(row.uuid, row.nodeName)">预览</el-link>
@@ -101,7 +104,7 @@
</template>
<script setup lang="ts">
import { nextTick, reactive, ref } from 'vue';
import { nextTick, provide, reactive, ref } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue';
import { useDict } from '@/utils/useDict';
import addDialog from './components/addDialog.vue';
@@ -110,9 +113,13 @@ import { deleteFlowTemplateDraftApi, queryFlowTemplateApi, updateFlowTemplateDra
import { ElMessage } from 'element-plus';
import { FLOW_USE_STATUS } from '@/utils/enum/flow';
defineProps({
apiParams: Object,
});
const showFlowDetailVisible = ref(false);
const { PROJECT_TYPE, PROJECT_EXE_STATUS } = useDict('PROJECT_TYPE', 'PROJECT_EXE_STATUS');
const { FLOW_APPROVE_STATUS, FLOW_USE_TYPE } = useDict('FLOW_APPROVE_STATUS', 'FLOW_USE_TYPE');
const showDialog = ref(false);
@@ -184,12 +191,21 @@ const goProjectDetailFun = (uuid: string, nodeName: string) => {
const flowDetail = reactive({
uuid: '',
version: '',
comment: '',
templateName: '',
templateType: '',
});
provide('flowDetail', flowDetail);
const goFlowDetailFun = (row: any) => {
console.log('row', row);
showFlowDetailVisible.value = true;
flowDetail.uuid = row.uuid;
flowDetail.version = row.templateVersion;
flowDetail.templateName = row.templateName;
flowDetail.comment = row.comment;
flowDetail.templateType = row.templateType;
};
// NODE_LIST_LEVEL1

View File

@@ -0,0 +1,11 @@
<template>
<Process
:apiParams="{
type: FLOW_TEMPLATE_PUBLIC_STATUS.PUBLIC
}"
></Process>
</template>
<script lang='ts' setup>
import { FLOW_TEMPLATE_PUBLIC_STATUS } from '@/utils/enum/flow';
import Process from '@/views/simulation/process/index.vue';
</script>