|
@@ -3,8 +3,44 @@
|
|
|
<div id="container"></div>
|
|
|
<div id="stencil"></div>
|
|
|
<div id="graph-container"></div>
|
|
|
-
|
|
|
</div>
|
|
|
+ <el-button @click="submitAll" type="primary">保存</el-button>
|
|
|
+ <el-dialog
|
|
|
+ :title="modalType == 'add' ? '新增' : '编辑'"
|
|
|
+ v-model="dialogVisible"
|
|
|
+ width="500"
|
|
|
+ v-loading="loading"
|
|
|
+ >
|
|
|
+ <byForm
|
|
|
+ :formConfig="formConfig"
|
|
|
+ :formOption="formOption"
|
|
|
+ v-model="formData.data"
|
|
|
+ :rules="rules"
|
|
|
+ ref="byform"
|
|
|
+ >
|
|
|
+ </byForm>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="dialogVisible = false" size="large"
|
|
|
+ >取 消</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ @click="deleteFlowDefinitionNodeObj()"
|
|
|
+ size="large"
|
|
|
+ :loading="submitLoading"
|
|
|
+ >
|
|
|
+ 删 除
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="submitForm('byform')"
|
|
|
+ size="large"
|
|
|
+ :loading="submitLoading"
|
|
|
+ >
|
|
|
+ 确 定
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
import {
|
|
@@ -17,7 +53,9 @@ import {
|
|
|
toRefs,
|
|
|
computed,
|
|
|
nextTick,
|
|
|
+ getCurrentInstance,
|
|
|
} from 'vue'
|
|
|
+import byForm from '@/components/byForm/index'
|
|
|
import { Graph, Shape } from '@antv/x6'
|
|
|
import { Stencil } from '@antv/x6-plugin-stencil'
|
|
|
import { Transform } from '@antv/x6-plugin-transform'
|
|
@@ -26,15 +64,390 @@ import { Snapline } from '@antv/x6-plugin-snapline'
|
|
|
import { Keyboard } from '@antv/x6-plugin-keyboard'
|
|
|
import { Clipboard } from '@antv/x6-plugin-clipboard'
|
|
|
import { History } from '@antv/x6-plugin-history'
|
|
|
-const aaa = (port: any) => {
|
|
|
+import Cookies from 'js-cookie'
|
|
|
+import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
+defineProps({
|
|
|
+ title: {
|
|
|
+ type: Object,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+
|
|
|
+});
|
|
|
+const { proxy } = getCurrentInstance()
|
|
|
+const internalInstance = getCurrentInstance()
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const modalType = ref('add')
|
|
|
+const loading = ref(false)
|
|
|
+const submitLoading = ref(false)
|
|
|
+const formData = reactive({
|
|
|
+ data: {
|
|
|
+ userName: '',
|
|
|
+ password: '',
|
|
|
+ },
|
|
|
+})
|
|
|
+const byform = ref(null)
|
|
|
+const flowDefinitionNodeObj = ref({})
|
|
|
+const rules = reactive({
|
|
|
+ nodeName: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入节点名称',
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ handleObjectType: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '办理人类型不能为空',
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ handleObjectId: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '办理人不能为空',
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+})
|
|
|
+const formConfig = computed(() => {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ type: 'input',
|
|
|
+ prop: 'nodeName',
|
|
|
+ label: '节点名称',
|
|
|
+ required: true,
|
|
|
+ itemType: 'text',
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ type: 'select',
|
|
|
+ prop: 'handleObjectType',
|
|
|
+ label: '办理人',
|
|
|
+ placeholder: '请选择办理人类型',
|
|
|
+ required: true,
|
|
|
+ itemWidth: 30,
|
|
|
+ fn: (e) => {
|
|
|
+ console.log(e)
|
|
|
+ gethandleObjectList(e)
|
|
|
+ },
|
|
|
+ //1用户 2部门负责人 3部门总监 4岗位 5角色
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ label: '用户',
|
|
|
+ value: 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '部门负责人',
|
|
|
+ value: 2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '部门总监',
|
|
|
+ value: 3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '岗位',
|
|
|
+ value: 4,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '角色',
|
|
|
+ value: 5,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // type: "treeSelect",
|
|
|
+ // prop: "handleObjectId",
|
|
|
+ // label: "请选择办理人",
|
|
|
+ // itemWidth: 30,
|
|
|
+ // data: [],
|
|
|
+ // },
|
|
|
+ {
|
|
|
+ type: 'select',
|
|
|
+
|
|
|
+ label: ' ',
|
|
|
+ itemWidth: 30,
|
|
|
+ prop: 'handleObjectId',
|
|
|
+ placeholder: '请选择办理人',
|
|
|
+ data: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'input',
|
|
|
+ prop: 'handlingMethod',
|
|
|
+ label: '节点后置执行方法',
|
|
|
+ required: true,
|
|
|
+ itemType: 'text',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'input',
|
|
|
+ prop: 'jumpCondition',
|
|
|
+ label: '条件表达式',
|
|
|
+ required: true,
|
|
|
+ itemType: 'text',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'checkbox',
|
|
|
+ prop: 'nodeButtonSet',
|
|
|
+ label: '节点按钮',
|
|
|
+ //1通过 2驳回 3返回上一步 4退回到发起人
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ label: '通过',
|
|
|
+ value: 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '驳回',
|
|
|
+ value: 2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '返回上一步',
|
|
|
+ value: 3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '退回到发起人',
|
|
|
+ value: 4,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'radio',
|
|
|
+ prop: 'jobNumber11',
|
|
|
+ label: '审批意见必填',
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ label: '是',
|
|
|
+ value: 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '否',
|
|
|
+ value: 0,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ]
|
|
|
+})
|
|
|
+const formOption = reactive({
|
|
|
+ inline: true,
|
|
|
+ labelWidth: 100,
|
|
|
+ itemWidth: 100,
|
|
|
+})
|
|
|
+let graph
|
|
|
+const submitForm = () => {
|
|
|
+ byform.value.handleSubmit((valid) => {
|
|
|
+ flowDefinitionNodeObj.value[formData.data.id] = formData.data
|
|
|
+ console.log(flowDefinitionNodeObj.value)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const submitFormData = {
|
|
|
+ flowInfoId:null,
|
|
|
+ titleTemplate:null,
|
|
|
+ tenantId:Cookies.get('tenantId'),
|
|
|
+ nodeObject:'',
|
|
|
+ lineObject:'',
|
|
|
+ flowDefinitionNodeList:[],
|
|
|
+}
|
|
|
+const submitAll = () => {
|
|
|
+ if(proxy.title == '') {
|
|
|
+ ElMessage({
|
|
|
+ message: '请输入流程标题',
|
|
|
+ type: 'warning',
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ submitFormData.titleTemplate = proxy.title
|
|
|
+ const nodeList = graph.toJSON().cells
|
|
|
+ console.log(nodeList)
|
|
|
+ const isStart = false
|
|
|
+ for (let i = 0; i < nodeList.length; i++) {
|
|
|
+ const element = nodeList[i];
|
|
|
+ //是办理节点
|
|
|
+ if(element.id != 1 && element.shape != "edge") {
|
|
|
+ console.log(element)
|
|
|
+ if(!flowDefinitionNodeObj.value[element.id]) {
|
|
|
+ ElMessage({
|
|
|
+ message: '有节点未配置,请检查节点123123123',
|
|
|
+ type: 'warning',
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ submitFormData.flowDefinitionNodeList.push({...flowDefinitionNodeObj.value[element.id],nodeType:2})
|
|
|
+ }
|
|
|
+ if(element.id == "1") {
|
|
|
+ submitFormData.flowDefinitionNodeList.push({
|
|
|
+ nodeName:'开始',
|
|
|
+ nodeType:1,
|
|
|
+ id:1,
|
|
|
+ nodeButtonSet:'',
|
|
|
+ parentId:0,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ //说明是线
|
|
|
+ if(element.shape == "edge") {
|
|
|
+ console.log(flowDefinitionNodeObj)
|
|
|
+ if(!flowDefinitionNodeObj.value[element.target.cell]) {
|
|
|
+ ElMessage({
|
|
|
+ message: '有节点未配置,请检查节点',
|
|
|
+ type: 'warning',
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ flowDefinitionNodeObj.value[element.target.cell].id = element.target.cell
|
|
|
+ flowDefinitionNodeObj.value[element.target.cell].parentId = element.source.cell
|
|
|
+ submitFormData.flowDefinitionNodeList = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+ addVersion()
|
|
|
+ console.log(flowDefinitionNodeObj.value)
|
|
|
+}
|
|
|
+
|
|
|
+//选取一个随机不重复的正整数id
|
|
|
+const randomId = () => {
|
|
|
+ const id = Math.floor(Math.random() * 100000000000000000)
|
|
|
+ if(flowDefinitionNodeObj.value[id]) {
|
|
|
+ randomId()
|
|
|
+ } else {
|
|
|
+ return id
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const addVersion = () => {
|
|
|
+ const idObg = {}
|
|
|
+ for (let i = 0; i < submitFormData.flowDefinitionNodeList.length; i++) {
|
|
|
+ const element = submitFormData.flowDefinitionNodeList[i];
|
|
|
+ if(isNaN(element.id)) {
|
|
|
+ if(idObg[element.id]) {
|
|
|
+ element.id = idObg[element.id]
|
|
|
+ } else {
|
|
|
+ const id = randomId()
|
|
|
+ idObg[element.id] = id
|
|
|
+ element.id = id
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(isNaN(element.parentId) && element.nodeName != '开始') {
|
|
|
+ if(idObg[element.parentId]) {
|
|
|
+ element.parentId = idObg[element.parentId]
|
|
|
+ } else {
|
|
|
+ const id = randomId()
|
|
|
+ idObg[element.parentId] = id
|
|
|
+ element.parentId = id
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //nodeButtonSet转成字符串类型,用逗号隔开
|
|
|
+ if(element.nodeButtonSet) {
|
|
|
+ element.nodeButtonSet = element.nodeButtonSet.join(',')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(submitFormData)
|
|
|
+
|
|
|
+ proxy.post('/flowDefinition/addVersion',submitFormData)
|
|
|
+ .then((res) => {
|
|
|
+ console.log(res)
|
|
|
+ ElMessage({
|
|
|
+ message: '保存成功',
|
|
|
+ type: 'success',
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+//将组数里的id和parentId转换成整正整数类型
|
|
|
+const changeId = (arr) => {
|
|
|
+ for (let i = 0; i < arr.length; i++) {
|
|
|
+ const element = arr[i];
|
|
|
+ element.id = parseInt(element.id)
|
|
|
+ element.parentId = parseInt(element.parentId)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const deleteFlowDefinitionNodeObj = (id) => {
|
|
|
+ graph.removeNode(formData.data.id)
|
|
|
+ delete flowDefinitionNodeObj.value[id]
|
|
|
+ dialogVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const gethandleObjectList = (e) => {
|
|
|
+ formData.data.handleObjectId = ''
|
|
|
+ if(e === 1) {
|
|
|
+ proxy.get('/tenantUser/list?pageNum=1&pageSize=1000&tenantId=' + Cookies.get('tenantId'),{})
|
|
|
+ .then((res) => {
|
|
|
+ formConfig.value[2].data = res.rows.map((item) => {
|
|
|
+ return {
|
|
|
+ label: item.nickName,
|
|
|
+ value: item.userId,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if(e === 3 || e === 2) {
|
|
|
+ proxy.get('/tenantDept/list?pageNum=1&pageSize=1000&tenantId=' + Cookies.get('tenantId'),{})
|
|
|
+ .then((res) => {
|
|
|
+ formConfig.value[2].data =res.data.map(item=> {
|
|
|
+ return {
|
|
|
+ label: item.deptName,
|
|
|
+ value: item.deptId,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if(e === 4) {
|
|
|
+
|
|
|
+ }
|
|
|
+ if(e === 5) {
|
|
|
+ proxy.get('/tenantRole/list?pageNum=1&pageSize=1000&tenantId=' + Cookies.get('tenantId'),{})
|
|
|
+ .then((res) => {
|
|
|
+ formConfig.value[2].data = res.rows.map((item) => {
|
|
|
+ return {
|
|
|
+ label: item.roleName,
|
|
|
+ value: item.roleId,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+const getTenantDept = () => {
|
|
|
+
|
|
|
+}
|
|
|
+getTenantDept()
|
|
|
+
|
|
|
+const recursive = (data) => {
|
|
|
+ data.map((item) => {
|
|
|
+ item.label = item.deptName;
|
|
|
+ item.id = item.deptId;
|
|
|
+ if (item.children) {
|
|
|
+ recursive(item.children);
|
|
|
+ } else {
|
|
|
+ item.children = [];
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const pushRoom = (port: any) => {
|
|
|
console.log(port)
|
|
|
+ if(port.node.label == '结束') {
|
|
|
+ flowDefinitionNodeObj.value[port.node.id] = {
|
|
|
+ nodeName:'结束',
|
|
|
+ nodeType:99,
|
|
|
+ id:port.id,
|
|
|
+ nodeButtonSet:'',
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(flowDefinitionNodeObj.value)
|
|
|
}
|
|
|
+//用于存储流程定义节点数据
|
|
|
+
|
|
|
const antvInit = () => {
|
|
|
- const graph = new Graph({
|
|
|
- height:700,
|
|
|
+ graph = new Graph({
|
|
|
+ height: 600,
|
|
|
container: document.getElementById('graph-container')!,
|
|
|
grid: true,
|
|
|
- onPortRendered:aaa,
|
|
|
+ onPortRendered: pushRoom,
|
|
|
mousewheel: {
|
|
|
enabled: true,
|
|
|
zoomAtMousePosition: true,
|
|
@@ -99,7 +512,6 @@ const antvInit = () => {
|
|
|
title: '基础流程图',
|
|
|
name: 'group1',
|
|
|
},
|
|
|
-
|
|
|
],
|
|
|
layoutOptions: {
|
|
|
columns: 2,
|
|
@@ -144,7 +556,6 @@ const antvInit = () => {
|
|
|
})
|
|
|
)
|
|
|
|
|
|
-
|
|
|
// 控制连接桩显示/隐藏
|
|
|
const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
|
|
|
for (let i = 0, len = ports.length; i < len; i += 1) {
|
|
@@ -166,7 +577,22 @@ const antvInit = () => {
|
|
|
showPorts(ports, false)
|
|
|
})
|
|
|
// #endregion
|
|
|
+ graph.on('cell:click', ({ e, x, y, cell, view }) => {
|
|
|
+ console.log(cell)
|
|
|
+ if (cell.label === '开始' || cell.label === '结束' || cell.shape === 'edge') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (flowDefinitionNodeObj.value[cell.id]) {
|
|
|
+ formData.data = flowDefinitionNodeObj.value[cell.id]
|
|
|
+ } else {
|
|
|
+ formData.data = {
|
|
|
+ id: cell.id,
|
|
|
+ cell: cell,
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ dialogVisible.value = true
|
|
|
+ })
|
|
|
// #region 初始化图形
|
|
|
const ports = {
|
|
|
groups: {
|
|
@@ -365,15 +791,27 @@ const antvInit = () => {
|
|
|
},
|
|
|
true
|
|
|
)
|
|
|
+ let firstLi = document.createElement('li')
|
|
|
+ firstLi.innerText = '指标详情'
|
|
|
+ console.log(firstLi)
|
|
|
const r1 = graph.createNode({
|
|
|
shape: 'custom-rect',
|
|
|
label: '开始',
|
|
|
+ zIndex: 100,
|
|
|
attrs: {
|
|
|
body: {
|
|
|
rx: 20,
|
|
|
ry: 26,
|
|
|
},
|
|
|
},
|
|
|
+ tools: [
|
|
|
+ {
|
|
|
+ name: 'button',
|
|
|
+ args: {
|
|
|
+ firstLi,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
})
|
|
|
const r2 = graph.createNode({
|
|
|
shape: 'custom-rect',
|
|
@@ -398,20 +836,35 @@ const antvInit = () => {
|
|
|
},
|
|
|
label: '结束',
|
|
|
})
|
|
|
- stencil.load([r1, r2, r3, r4], 'group1')
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ stencil.load([ r2, r4], 'group1')
|
|
|
+ graph.addNode({
|
|
|
+ shape: 'custom-rect',
|
|
|
+ label: '开始',
|
|
|
+ id: 1,
|
|
|
+ x: 500,
|
|
|
+ y: 100,
|
|
|
+ })
|
|
|
}
|
|
|
onMounted(() => {
|
|
|
antvInit()
|
|
|
+ //获取url router参数
|
|
|
+ const router = useRouter();
|
|
|
+ submitFormData.flowInfoId = router.currentRoute.value.query.id
|
|
|
})
|
|
|
</script>
|
|
|
<style lang="scss">
|
|
|
+.x6-widget-stencil-title {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+.x6-widget-stencil-content {
|
|
|
+ top: 0 !important;
|
|
|
+}
|
|
|
.vueFlow {
|
|
|
position: relative;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
+ overflow: hidden;
|
|
|
+ height: 600px;
|
|
|
#stencil {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
@@ -423,10 +876,8 @@ onMounted(() => {
|
|
|
border-right: 1px solid #e8e8e8;
|
|
|
}
|
|
|
#container {
|
|
|
- height: 800px;
|
|
|
- width: 800px;
|
|
|
}
|
|
|
- #graph-container{
|
|
|
+ #graph-container {
|
|
|
width: 100%;
|
|
|
position: absolute;
|
|
|
right: 0;
|