因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。
1、需要做一个界面保存与显示仿钉钉的流程,先建一个表,用online建
2、通过上面生成代码,放入到相应的前后端工程里
3、修改前端仿钉钉流程的设计功能,在原来list页面上增加一个对话框,如下:
<el-dialog :title="designerData.name" class="ddDialog" v-model="designerOpen" append-to-body fullscreen>
<ding-designer
ref="ddDesigner"
v-loading="designerLoading"
:process = "flowJsonData"
@save="onSaveDesigner"
/>
</el-dialog>
4、增加一个上面的仿钉钉流程组件
<template>
<div class="formDesign">
<FlowDesign :process="process" :fields="fields" :readOnly="readOnly">
<el-switch
inline-prompt
size="large"
active-text="正常模式"
inactive-text="暗黑模式"
@change="handleToggleDark"
v-model="isDark"
/>
<el-switch
v-model="readOnly"
size="large"
active-text="只读模式"
inactive-text="编辑模式"
inline-prompt
:active-value="true"
:inactive-value="false"
/>
<el-button-group>
<el-button @click="viewJson" size="small" type="primary" round icon="View"> 查看Json</el-button>
</el-button-group>
<el-button-group>
<el-button @click="viewXmlBpmn" size="small" type="primary" round icon="View"> 查看XML </el-button>
</el-button-group>
<el-button-group>
<el-button @click="converterBpmn" size="small" type="primary" round icon="View"> 预览bpmn </el-button>
</el-button-group>
<el-button-group>
<el-button @click="save" size="small" type="primary" round icon="View"> 保存 </el-button>
</el-button-group>
</FlowDesign>
<el-dialog title="预览" width="60%" v-model="previewModelVisible" append-to-body destroy-on-close>
<highlightjs :language="previewType" :code="previewResult" style="height: 80vh" />
</el-dialog>
<!-- Bpmn流程图 -->
<el-dialog :title="processView.title" v-model="processView.open" width="70%" append-to-body>
<process-viewer :key="`designer-${processView.title}`" :xml="processView.xmlData" :style="{height: '500px'}" />
</el-dialog>
</div>
</template>
<script setup lang="ts" name="DingDesigner">
import { ref, reactive, toRaw, onMounted } from 'vue';
import '@/views/lowflow/styles/index.scss'
// If you want to use ElMessage, import it.
import 'element-plus/dist/index.css';
import 'element-plus/theme-chalk/display.css';
import FlowDesign from '@/views/lowflow/flowDesign/index.vue'
import type { Field } from '@/views/lowflow/components/Render/type'
import type { EndNode, FlowNode, StartNode } from '@/views/lowflow/flowDesign/nodes/type'
import { viewXml, ddToBpmnXml } from '@/views/lowflow/api/modules/model'
import ProcessViewer from '@/components/ProcessViewer/index.vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps({
process: {
type: Object,
required: true
},
});
const emit = defineEmits([
'save'
])
const previewModelVisible = ref(false)
const previewResult = ref('')
const previewType = ref('xml')
const processView = reactive<any>({
title: '',
open: false,
xmlData:'',
})
// 流程节点
/*const process = ref<FlowNode>({
id: 'root',
pid: undefined,
type: 'start',
name: '流程开始',
executionListeners: [],
formProperties: [],
child: {
id: 'end',
pid: 'root',
type: 'end',
name: '流程结束',
executionListeners: [],
child: undefined
} as EndNode
} as StartNode)*/
// 表单字段
const fields = ref<Field[]>([
{
id: 'field_da2w55',
type: 'formItem',
label: '请假人',
name: 'UserSelector',
value: null,
readonly: false,
required: true,
hidden: false,
props: {
multiple: false,
disabled: false,
placeholder: '请选择用户',
style: {
width: '100%'
}
}
},
{
id: 'field_fa2w40',
type: 'formItem',
label: '请假天数',
name: 'ElInputNumber',
value: null,
readonly: false,
required: true,
hidden: false,
props: {
disabled: false,
placeholder: '请假天数',
style: {
width: '100%'
},
min: 0,
max: 100,
step: 1,
precision: 0
}
},
{
id: 'field_d42t45',
type: 'formItem',
label: '请假事由',
name: 'ElSelect',
value: null,
readonly: false,
required: true,
hidden: false,
props: {
disabled: false,
multiple: false,
placeholder: '请选择请假事由',
options: [
{
label: '事假',
value: '事假'
},
{
label: '病假',
value: '病假'
},
{
label: '婚假',
value: '婚假'
},
{
label: '产假',
value: '产假'
},
{
label: '丧假',
value: '丧假'
},
{
label: '其他',
value: '其他'
}
],
style: {
width: '100%'
}
}
},
{
id: 'field_522g58',
type: 'formItem',
label: '请假原因',
name: 'ElInput',
value: null,
readonly: false,
required: true,
hidden: false,
props: {
type: 'textarea',
placeholder: '请输入请假原因',
autosize: {
minRows: 3,
maxRows: 3
},
disabled: false,
style: {
width: '100%'
}
}
}
])
// 是否只读
const readOnly = ref(false)
// 是否暗黑模式
const isDark = ref(false)
const viewJson = () => {
const processJson = JSON.stringify(props.process,undefined, 2);
previewResult.value = processJson;
previewType.value = 'json'
previewModelVisible.value = true
}
const viewXmlBpmn = () => {
const processModel = {
code: 'test',
name: '测试',
icon: {
name: 'el:HomeFilled',
color: '#409EFF'
},
process: props.process,
enable: true,
version: 1,
sort: 0,
groupId: '',
remark: ''
}
const xmlData = viewXml(processModel)
xmlData.then((result) => {
previewResult.value = result
previewType.value = 'xml'
previewModelVisible.value = true
})
}
const converterBpmn = () => {
const processModel = {
code: 'test',
name: '测试',
icon: {
name: 'el:HomeFilled',
color: '#409EFF'
},
process: props.process,
enable: true,
version: 1,
sort: 0,
groupId: '',
remark: ''
}
ddToBpmnXml(processModel).then(res => {
console.log("ddToBpmnXml res",res)
processView.xmlData = res.result
processView.title = "Bpmn流程图预览"
processView.open = true
})
}
const save = () => {
const flowData = props.process
emit('save', flowData);
}
const handleToggleDark = () => {
if (isDark.value) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}
onMounted(() => {
});
</script>
<style scoped lang="scss">
.formDesign {
z-index: 999;
top: 120px;
height: 100%;
}
</style>
5、效果图如下:
点设计如下: