update 优化设计器

This commit is contained in:
LiuHao 2024-02-03 23:09:22 +08:00
parent b102f2eb60
commit c4e69956a3
3 changed files with 77 additions and 73 deletions

View File

@ -1,13 +1,13 @@
<template> <template>
<div class="containers"> <div class="containers">
<el-dialog ref="flowDialogRef" v-model="dialog.visible" width="100%" fullscreen :title="dialog.title"> <el-dialog v-model="visible" width="100%" fullscreen :title="title" @close="closeCallBack" @opened="designOpened">
<div class="app-containers"> <div class="app-containers">
<el-container class="h-full"> <el-container class="h-full">
<el-container style="align-items: stretch"> <el-container style="align-items: stretch">
<el-header> <el-header>
<div class="process-toolbar"> <div class="process-toolbar">
<el-space wrap :size="10"> <el-space wrap :size="10">
<el-button size="small" @click="saveXml" type="primary"> </el-button> <el-button size="small" type="primary" @click="saveXml"> </el-button>
<el-dropdown size="small"> <el-dropdown size="small">
<el-button size="small" type="primary"> </el-button> <el-button size="small" type="primary"> </el-button>
<template #dropdown> <template #dropdown>
@ -82,44 +82,47 @@ import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'; import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'; import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'; import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
import { Canvas, ElementRegistry, Modeler } from 'bpmn'; import { Canvas, Modeler } from 'bpmn';
import PropertyPanel from './PropertyPanel.vue'; import PropertyPanel from './PropertyPanel.vue';
import BpmnModeler from 'bpmn-js/lib/Modeler.js'; import BpmnModeler from 'bpmn-js/lib/Modeler.js';
import diagramXML from '@/components/BpmnDesign/assets/defaultXML'; import defaultXML from '@/components/BpmnDesign/assets/defaultXML';
import flowableModdle from '@/components/BpmnDesign/assets/moddle/flowable'; import flowableModdle from '@/components/BpmnDesign/assets/moddle/flowable';
import Modules from './assets/module/index'; import Modules from './assets/module/index';
import useModelerStore from '@/store/modules/modeler'; import useModelerStore from '@/store/modules/modeler';
import useDialog from '@/hooks/useDialog';
interface PropType {
closeCallBack?: () => void;
xml?: string;
}
const prop = withDefaults(defineProps<PropType>(), {
closeCallBack: () => {},
xml: defaultXML
});
const { visible, title, openDialog, closeDialog } = useDialog({
title: '编辑流程'
});
const modelerStore = useModelerStore(); const modelerStore = useModelerStore();
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const dialog = reactive({
visible: false,
title: '编辑流程'
});
const panelFlag = ref(false); const panelFlag = ref(false);
const showPanel = ref(true); const showPanel = ref(true);
const canvas = ref<HTMLDivElement>(); const canvas = ref<HTMLDivElement>();
const panel = ref<HTMLDivElement>(); const panel = ref<HTMLDivElement>();
const bpmnModeler = ref<Modeler>(); const bpmnModeler = ref<Modeler>();
const zoom = ref(1); const zoom = ref(1);
const perviewXMLShow = ref(false); const perviewXMLShow = ref(false);
const perviewSVGShow = ref(false); const perviewSVGShow = ref(false);
const xmlStr = ref(''); const xmlStr = ref('');
const svgData = ref(''); const svgData = ref('');
onMounted(() => { const designOpened = () => {
nextTick(() => { // initCanvas();
initCanvas(); // initModel();
//initDiagram(null); // initDiagram();
initModel(); };
});
});
const panelBarClick = () => { const panelBarClick = () => {
// //
@ -154,7 +157,6 @@ const initCanvas = () => {
*/ */
const initModel = () => { const initModel = () => {
if (modelerStore.getModeler()) { if (modelerStore.getModeler()) {
// modeler
modelerStore.getModeler().destroy(); modelerStore.getModeler().destroy();
modelerStore.setModeler(undefined); modelerStore.setModeler(undefined);
} }
@ -166,26 +168,15 @@ const initModel = () => {
*/ */
const newDiagram = async () => { const newDiagram = async () => {
await proxy?.$modal.confirm('是否确认新建'); await proxy?.$modal.confirm('是否确认新建');
initDiagram(null); initDiagram();
}; };
/** /**
* 初始化 * 初始化
*/ */
const initDiagram = (xml) => { const initDiagram = (xml?: string) => {
if(xml){ if (!xml) xml = defaultXML;
nextTick(async () => { bpmnModeler.value.importXML(xml);
console.log("xml")
dialog.visible = true
bpmnModeler.value.importXML(xml);
})
}else{
nextTick(async () => {
console.log("diagramXML")
bpmnModeler.value.importXML(diagramXML);
})
}
}; };
/** /**
@ -290,28 +281,42 @@ const getProcessElement = () => {
}; };
const getProcess = () => { const getProcess = () => {
const element = getProcessElement() const element = getProcessElement();
return { return {
id: element.id, id: element.id,
name: element.name name: element.name
} };
}; };
const saveXml = async () => { const saveXml = async () => {
const { xml } = await bpmnModeler.value.saveXML({ format: true }); const { xml } = await bpmnModeler.value.saveXML({ format: true });
const { svg } = await bpmnModeler.value.saveSVG(); const { svg } = await bpmnModeler.value.saveSVG();
const process = getProcess() const process = getProcess();
console.log(xml) console.log(xml);
console.log(svg) console.log(svg);
console.log(process) console.log(process);
};
const open = (xml?: string) => {
openDialog();
nextTick(() => {
initCanvas();
initModel();
initDiagram(xml);
});
};
const close = () => {
closeDialog();
}; };
/** /**
* 对外暴露子组件方法 * 对外暴露子组件方法
*/ */
defineExpose({ defineExpose({
initDiagram, initDiagram,
saveXml saveXml,
open,
close
}); });
</script> </script>

View File

@ -2,6 +2,7 @@ import { Ref } from 'vue';
interface Options { interface Options {
title?: string; title?: string;
visible?: boolean;
} }
interface Return { interface Return {
@ -12,7 +13,7 @@ interface Return {
closeDialog: () => void; closeDialog: () => void;
} }
export default (ops?: Options): Return => { export default (ops?: Options): Return => {
const visible = ref(false); const visible = ref(ops.visible !== undefined ? ops.visible : false);
const title = ref(ops.title || ''); const title = ref(ops.title || '');
const openDialog = () => { const openDialog = () => {

View File

@ -99,16 +99,16 @@
</el-col> </el-col>
</el-row> </el-row>
<!-- 设计流程开始 --> <!-- 设计流程开始 -->
<design ref="designModel" :model-id="modelId" @handle-close="getList" /> <BpmnDesign ref="bpmnDesignRef" :xml="xmlStr"></BpmnDesign>
<!-- 设计流程结束 --> <!-- 设计流程结束 -->
<!-- 添加模型对话框 --> <!-- 添加模型对话框 -->
<el-dialog v-model="dialog.visible" :title="dialog.title" width="650px" append-to-body :close-on-click-modal="false"> <el-dialog v-model="dialog.visible" :title="dialog.title" width="650px" append-to-body :close-on-click-modal="false">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="模型名称:" prop="name"> <el-form-item label="模型名称:" prop="name">
<el-input :disabled="ids && ids.length > 0" v-model="form.name" maxlength="20" show-word-limit /> <el-input v-model="form.name" :disabled="ids && ids.length > 0" maxlength="20" show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="模型KEY" prop="key"> <el-form-item label="模型KEY" prop="key">
<el-input :disabled="ids && ids.length > 0" v-model="form.key" maxlength="20" show-word-limit /> <el-input v-model="form.key" :disabled="ids && ids.length > 0" maxlength="20" show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="流程分类" prop="categoryCode"> <el-form-item label="流程分类" prop="categoryCode">
<el-tree-select <el-tree-select
@ -135,17 +135,17 @@
</template> </template>
<script lang="ts" setup name="Model"> <script lang="ts" setup name="Model">
import Design from './design.vue'; import BpmnDesign from '@/components/BpmnDesign/index.vue';
import { listModel, addModel, delModel, modelDeploy ,getInfo,update} from '@/api/workflow/model'; import { listModel, addModel, delModel, modelDeploy, getInfo, update } from '@/api/workflow/model';
import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types'; import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types';
import { listCategory } from '@/api/workflow/category'; import { listCategory } from '@/api/workflow/category';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const designModel = ref<InstanceType<typeof Design>>();
const formRef = ref<ElFormInstance>(); const formRef = ref<ElFormInstance>();
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<ElFormInstance>();
const categoryTreeRef = ref<ElTreeInstance>(); const categoryTreeRef = ref<ElTreeInstance>();
const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>();
type CategoryOption = { type CategoryOption = {
categoryCode: string; categoryCode: string;
@ -163,6 +163,8 @@ const total = ref(0);
const modelList = ref<ModelVO[]>([]); const modelList = ref<ModelVO[]>([]);
const categoryOptions = ref<CategoryOption[]>([]); const categoryOptions = ref<CategoryOption[]>([]);
const categoryName = ref(''); const categoryName = ref('');
const modelId = ref<string>('');
const xmlStr = ref('');
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
@ -170,12 +172,12 @@ const dialog = reactive<DialogOption>({
}); });
const initFormData: ModelForm = { const initFormData: ModelForm = {
id:'', id: '',
name: '', name: '',
key: '', key: '',
categoryCode: '', categoryCode: '',
xml:'', xml: '',
svg:'', svg: '',
description: '' description: ''
}; };
const data = reactive<PageData<ModelForm, ModelQuery>>({ const data = reactive<PageData<ModelForm, ModelQuery>>({
@ -195,8 +197,6 @@ const data = reactive<PageData<ModelForm, ModelQuery>>({
}); });
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data);
const modelId = ref<string>('');
onMounted(() => { onMounted(() => {
getList(); getList();
getTreeselect(); getTreeselect();
@ -270,7 +270,7 @@ const clickDeploy = async (id: string, key: string) => {
proxy?.$modal.msgSuccess('部署成功'); proxy?.$modal.msgSuccess('部署成功');
}; };
const handleAdd = () => { const handleAdd = () => {
ids.value = [] ids.value = [];
getTreeselect(); getTreeselect();
form.value = { ...initFormData }; form.value = { ...initFormData };
dialog.visible = true; dialog.visible = true;
@ -279,12 +279,12 @@ const handleAdd = () => {
const handleUpdate = () => { const handleUpdate = () => {
dialog.title = '修改模型'; dialog.title = '修改模型';
nextTick(async () => { nextTick(async () => {
getTreeselect(); await getTreeselect();
const _id = ids.value[0]; const _id = ids.value[0];
const res = await getInfo(_id); const res = await getInfo(_id);
Object.assign(form.value, res.data); Object.assign(form.value, res.data);
dialog.visible = true; dialog.visible = true;
}) });
}; };
/** 提交按钮 */ /** 提交按钮 */
@ -292,13 +292,13 @@ const submitForm = () => {
formRef.value.validate(async (valid: boolean) => { formRef.value.validate(async (valid: boolean) => {
if (valid) { if (valid) {
buttonLoading.value = true; buttonLoading.value = true;
if(ids.value && ids.value.length > 0){ if (ids.value && ids.value.length > 0) {
form.value.id = ids.value[0] form.value.id = ids.value[0];
await update(form.value); await update(form.value);
proxy?.$modal.msgSuccess('新增成功'); proxy?.$modal.msgSuccess('新增成功');
}else{ } else {
initXml(form.value.key,form.value.name) initXml(form.value.key, form.value.name);
form.value.xml = xml.value form.value.xml = xml.value;
await addModel(form.value); await addModel(form.value);
proxy?.$modal.msgSuccess('新增成功'); proxy?.$modal.msgSuccess('新增成功');
} }
@ -321,11 +321,10 @@ const reset = () => {
}; };
// //
const clickDesign = (id: string) => { const clickDesign = async (id: string) => {
modelId.value = id; const res = await getInfo(id);
if (designModel.value) { xml.value = res.data.xml;
designModel.value.openDialog(id); bpmnDesignRef.value?.open(res.data.xml);
}
}; };
// //
const clickExportZip = (data: any) => { const clickExportZip = (data: any) => {
@ -342,8 +341,7 @@ const getTreeselect = async () => {
const xml = ref<string>(''); const xml = ref<string>('');
const initXml = async ( key:string,name:string) => { const initXml = async (key: string, name: string) => {
xml.value = `<?xml version="1.0" encoding="UTF-8"?> xml.value = `<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef"> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef">
<process id="${key}" name="${name}"> <process id="${key}" name="${name}">
@ -360,6 +358,6 @@ const initXml = async ( key:string,name:string) => {
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>
</definitions>`; </definitions>`;
return xml; return xml;
} };
</script> </script>