浏览代码

Merge branch 'master' of http://36.137.93.232:3000/hf/byte-sailing-new

cz 2 年之前
父节点
当前提交
040bbf85c3

+ 1 - 2
src/components/byForm/index.vue

@@ -89,7 +89,7 @@
           <el-checkbox
             v-for="j in i.data"
             :key="j.id || j.value"
-            ::label="j.id  || j.value"
+            :label="j.id  || j.value"
             name="type"
           >
             {{ j.name || j.label }}
@@ -196,7 +196,6 @@ const formData = computed(() => {
 });
 const formDataReset = ref({ ...proxy.modelValue });
 const commonsEmit = (prop, item) => {
-  console.log(formData);
   if (item.fn) {
     item.fn(prop);
   }

+ 2 - 1
src/views/process/processConfig/index.vue

@@ -302,7 +302,8 @@ const getDtl = (row) => {
 	router.push({
 		path: 'processChart',
 		query: {
-			id: row.id,
+			id: row.flowInfoId,
+			tenantId:row.tenantId
 		},
 	})
 }

+ 18 - 4
src/views/process/processConfig/processChart.vue

@@ -2,11 +2,19 @@
 	<div class="processChart">
 		<div class="from">
 			<div class="commons-title">基础配置</div>
+			<div>
+				<el-form labelPosition='top'>
+					<el-form-item label="流程标题" label-width="80px">
+						<el-input v-model="title" placeholder="请输入流程标题"></el-input>
+						
+					</el-form-item>
+				</el-form>
+			</div>
 		</div>
 		<div class="content">
-			<div class="commons-title">基础配置</div>
+			<div class="commons-title">流程节点配置</div>
 			<div class="chart-warp">
-				<vueFlow></vueFlow>
+				<vueFlow :title='title'></vueFlow>
 			</div>
 		</div>
 	</div>
@@ -15,7 +23,7 @@
 <script setup>
 import { VueFlow } from '@vue-flow/core'
 import vueFlow from '@/views/process/processConfig/vueFlow.vue'
-
+const title = ref('')
 onMounted(() => {
 	
 })
@@ -28,12 +36,18 @@ onMounted(() => {
 	justify-content: space-between;
 	.from {
 		width: 300px;
+		background: #fff;
+		border-radius: 5px;
+		padding: 20px;
 	}
 	.content {
 		width: calc(100% - 320px);
+		border-radius: 5px;
+		padding: 20px;
+		background: #fff;
 	}
 }
 .chart-warp {
-	height: calc(100vh - 180px);
+	height: calc(100vh - 280px);
 }
 </style>

+ 465 - 14
src/views/process/processConfig/vueFlow.vue

@@ -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;