add 添加模型接口

This commit is contained in:
gssong 2024-02-03 14:09:45 +08:00
parent 0423e28250
commit c61d1b2850
6 changed files with 170 additions and 79 deletions

View File

@ -15,6 +15,18 @@ export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => {
}); });
}; };
/**
*
* @param query
* @returns {*}
*/
export const getInfo = (id: string): AxiosPromise<ModelForm> => {
return request({
url: '/workflow/model/getInfo/'+id,
method: 'get'
});
};
/** /**
* *
* @param data * @param data
@ -22,12 +34,38 @@ export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => {
*/ */
export const addModel = (data: ModelForm): AxiosPromise<void> => { export const addModel = (data: ModelForm): AxiosPromise<void> => {
return request({ return request({
url: '/workflow/model/rest/models', url: '/workflow/model/save',
method: 'post', method: 'post',
data: data data: data
}); });
}; };
/**
*
* @param data
* @returns {*}
*/
export function update(data: ModelForm): AxiosPromise<void> {
return request({
url: '/workflow/model/update',
method: 'put',
data: data
});
}
/**
*
* @param data
* @returns {*}
*/
export function editModelXml(data: ModelForm): AxiosPromise<void> {
return request({
url: '/workflow/model/editModelXml',
method: 'put',
data: data
});
}
/** /**
* id删除模型 * id删除模型
* @returns {*} * @returns {*}

View File

@ -1,7 +1,10 @@
export interface ModelForm { export interface ModelForm {
id: string,
name: string; name: string;
key: string; key: string;
categoryCode: string; categoryCode: string;
xml:string,
svg:string,
description: string; description: string;
} }

View File

@ -7,7 +7,7 @@
<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" type="primary"> </el-button> <el-button size="small" @click="saveXml" type="primary"> </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>
@ -27,10 +27,6 @@
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
<el-upload ref="xmlUploadRef" action="" style="display: none" />
<el-tooltip effect="dark" content="加载xml" placement="bottom">
<el-button size="small" icon="FolderOpened" @click="loadXML" />
</el-tooltip>
<el-tooltip effect="dark" content="新建" placement="bottom"> <el-tooltip effect="dark" content="新建" placement="bottom">
<el-button size="small" icon="CirclePlus" @click="newDiagram" /> <el-button size="small" icon="CirclePlus" @click="newDiagram" />
</el-tooltip> </el-tooltip>
@ -99,15 +95,13 @@ const modelerStore = useModelerStore();
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const dialog = reactive({ const dialog = reactive({
visible: true, visible: false,
title: '编辑流程' title: '编辑流程'
}); });
const panelFlag = ref(false); const panelFlag = ref(false);
const showPanel = ref(true); const showPanel = ref(true);
const xmlUploadRef = ref<ElUploadInstance>();
const canvas = ref<HTMLDivElement>(); const canvas = ref<HTMLDivElement>();
const panel = ref<HTMLDivElement>(); const panel = ref<HTMLDivElement>();
@ -122,7 +116,7 @@ const svgData = ref('');
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
initCanvas(); initCanvas();
initDiagram(); //initDiagram(null);
initModel(); initModel();
}); });
}); });
@ -135,13 +129,6 @@ const panelBarClick = () => {
}, 100); }, 100);
}; };
/**
* 从文件加载xml
*/
const loadXML = () => {
xmlUploadRef.value.$el.querySelector('input').click();
};
/** /**
* 初始化Canvas * 初始化Canvas
*/ */
@ -179,13 +166,26 @@ const initModel = () => {
*/ */
const newDiagram = async () => { const newDiagram = async () => {
await proxy?.$modal.confirm('是否确认新建'); await proxy?.$modal.confirm('是否确认新建');
initDiagram(); initDiagram(null);
}; };
/** /**
* 初始化 * 初始化
*/ */
const initDiagram = () => { const initDiagram = (xml) => {
bpmnModeler.value.importXML(diagramXML); if(xml){
nextTick(async () => {
console.log("xml")
dialog.visible = true
bpmnModeler.value.importXML(xml);
})
}else{
nextTick(async () => {
console.log("diagramXML")
bpmnModeler.value.importXML(diagramXML);
})
}
}; };
/** /**
@ -288,6 +288,31 @@ const getProcessElement = () => {
if (rootElements[i].$type === 'bpmn:Process') return rootElements[i]; if (rootElements[i].$type === 'bpmn:Process') return rootElements[i];
} }
}; };
const getProcess = () => {
const element = getProcessElement()
return {
id: element.id,
name: element.name
}
};
const saveXml = async () => {
const { xml } = await bpmnModeler.value.saveXML({ format: true });
const { svg } = await bpmnModeler.value.saveSVG();
const process = getProcess()
console.log(xml)
console.log(svg)
console.log(process)
};
/**
* 对外暴露子组件方法
*/
defineExpose({
initDiagram,
saveXml
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -340,7 +340,7 @@ const handleExport = () => {
// //
const handleStartWorkFlow = async (data: LeaveVO) => { const handleStartWorkFlow = async (data: LeaveVO) => {
submitFormData.value.processKey = 'leave1'; submitFormData.value.processKey = 'test';
submitFormData.value.businessKey = data.id; submitFormData.value.businessKey = data.id;
// //
taskVariables.value = { taskVariables.value = {

View File

@ -1,59 +1,35 @@
<template> <template>
<el-dialog v-if="visible" v-model="visible" title="Flowable工作流在线流程设计器" width="90%" height="100%" :before-close="handleClose"> <el-dialog v-if="dialog.visible" v-model="dialog.visible" :title="dialog.title" width="90%" height="100%">
<div class="modeler"> <div class="modeler">
<iframe class="iframe" :src="src"></iframe> <bpmn-design ref="bpmnDesign"></bpmn-design>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts"> <script lang="ts" setup name="Design">
import { propTypes } from '@/utils/propTypes'; import { getInfo } from '@/api/workflow/model';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const baseURL = import.meta.env.VITE_APP_BASE_API; import { ModelForm } from '@/api/workflow/model/types';
import { getToken } from '@/utils/auth'; import BpmnDesign from '@/components/BpmnDesign';
export default { const bpmnDesign = ref<InstanceType<typeof BpmnDesign>>();
props: { const dialog = reactive<DialogOption>({
modelId: propTypes.string.isRequired visible: false,
}, title: 'Flowable工作流在线流程设计器'
emits: ['handleClose'], });
const modelForm = ref<ModelForm>();
data() { const openDialog = (id) => {
return { dialog.visible = true
visible: false getInfo(id).then(res=>{
}; if (bpmnDesign.value) {
}, Object.assign(modelForm.value, res.data);
computed: { bpmnDesign.value.initDiagram(modelForm.value.xml);
src() { }
return `/static/flowable-modeler/index.html#/editor/${this.modelId}`; });
},
apiUrl() {
return baseURL;
},
token() {
return getToken();
},
clientid() {
return import.meta.env.VITE_APP_CLIENT_ID;
}
},
mounted() {
//vue
(window as any).this = this;
},
methods: {
async handleClose() {
await this.$modal.confirm('请记得点击左上角保存按钮,确定关闭设计窗口?').finally(() => ((this as any).loading = false));
this.visible = false;
//
this.$emit('handleClose');
}
}
}; };
/**
* 对外暴露子组件方法
*/
defineExpose({
openDialog
});
</script> </script>
<style scoped>
.iframe {
width: 100%;
height: calc(100vh - 120px);
border: 0;
}
</style>

View File

@ -44,6 +44,9 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button> <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="multiple" @click="handleUpdate()">修改</el-button>
</el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button> <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button>
</el-col> </el-col>
@ -102,10 +105,10 @@
<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 v-model="form.name" maxlength="20" show-word-limit /> <el-input :disabled="ids && ids.length > 0" v-model="form.name" 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 v-model="form.key" maxlength="20" show-word-limit /> <el-input :disabled="ids && ids.length > 0" v-model="form.key" 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
@ -118,7 +121,7 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="备注:" prop="description"> <el-form-item label="备注:" prop="description">
<el-input v-model="form.description" type="textarea" maxlength="30" show-word-limit></el-input> <el-input v-model="form.description" type="textarea" maxlength="200" show-word-limit></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -133,7 +136,7 @@
<script lang="ts" setup name="Model"> <script lang="ts" setup name="Model">
import Design from './design.vue'; import Design from './design.vue';
import { listModel, addModel, delModel, modelDeploy } 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';
@ -167,9 +170,12 @@ const dialog = reactive<DialogOption>({
}); });
const initFormData: ModelForm = { const initFormData: ModelForm = {
id:'',
name: '', name: '',
key: '', key: '',
categoryCode: '', categoryCode: '',
xml:'',
svg:'',
description: '' description: ''
}; };
const data = reactive<PageData<ModelForm, ModelQuery>>({ const data = reactive<PageData<ModelForm, ModelQuery>>({
@ -264,18 +270,38 @@ const clickDeploy = async (id: string, key: string) => {
proxy?.$modal.msgSuccess('部署成功'); proxy?.$modal.msgSuccess('部署成功');
}; };
const handleAdd = () => { const handleAdd = () => {
ids.value = []
getTreeselect(); getTreeselect();
form.value = { ...initFormData }; form.value = { ...initFormData };
dialog.visible = true; dialog.visible = true;
dialog.title = '新增模型'; dialog.title = '新增模型';
}; };
const handleUpdate = () => {
dialog.title = '修改模型';
nextTick(async () => {
getTreeselect();
const _id = ids.value[0];
const res = await getInfo(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
})
};
/** 提交按钮 */ /** 提交按钮 */
const submitForm = () => { const submitForm = () => {
formRef.value.validate(async (valid: boolean) => { formRef.value.validate(async (valid: boolean) => {
if (valid) { if (valid) {
buttonLoading.value = true; buttonLoading.value = true;
await addModel(form.value); if(ids.value && ids.value.length > 0){
proxy?.$modal.msgSuccess('新增成功'); form.value.id = ids.value[0]
await update(form.value);
proxy?.$modal.msgSuccess('新增成功');
}else{
initXml(form.value.key,form.value.name)
form.value.xml = xml.value
await addModel(form.value);
proxy?.$modal.msgSuccess('新增成功');
}
dialog.visible = false; dialog.visible = false;
await getList(); await getList();
} }
@ -298,7 +324,7 @@ const reset = () => {
const clickDesign = (id: string) => { const clickDesign = (id: string) => {
modelId.value = id; modelId.value = id;
if (designModel.value) { if (designModel.value) {
designModel.value.visible = true; designModel.value.openDialog(id);
} }
}; };
// //
@ -313,4 +339,27 @@ const getTreeselect = async () => {
data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId');
categoryOptions.value.push(data); categoryOptions.value.push(data);
}; };
const xml = ref<string>('');
const initXml = async ( key:string,name:string) => {
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">
<process id="${key}" name="${name}">
<startEvent id="startNode1" name="开始" />
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_flow">
<bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c">
<bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke="">
<omgdc:Bounds x="240" y="200" width="30" height="30" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="242" y="237" width="23" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>`;
return xml;
}
</script> </script>