Merge remote-tracking branch 'upstream/feature/bpm' into feature/bpm
						commit
						1e161d2e64
					
				|  | @ -381,7 +381,7 @@ const fieldOptions = computed(() => { | ||||||
| 
 | 
 | ||||||
| /** 获取字段名称 */ | /** 获取字段名称 */ | ||||||
| const getFieldTitle = (field: string) => { | const getFieldTitle = (field: string) => { | ||||||
|   const item = fieldsInfo.find((item) => item.field === field) |   const item = fieldOptions.value.find((item) => item.field === field) | ||||||
|   return item?.title |   return item?.title | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -173,13 +173,16 @@ | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   padding-top: 32px; |   padding-top: 32px; | ||||||
|   background-color: #fafafa; |   background-color: #fafafa; | ||||||
|  |   overflow-x: auto; | ||||||
|  |   width: 100%; | ||||||
|  | 
 | ||||||
|   .simple-process-model { |   .simple-process-model { | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     justify-content: center; |     justify-content: center; | ||||||
|     align-items: center; |     align-items: center; | ||||||
|     transform-origin: 50% 0 0; |     transform-origin: 50% 0 0; | ||||||
|     overflow: auto; |     min-width: fit-content; | ||||||
|     transform: scale(1); |     transform: scale(1); | ||||||
|     transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); |     transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); | ||||||
|     background: url(@/assets/svgs/bpm/simple-process-bg.svg) 0 0 repeat; |     background: url(@/assets/svgs/bpm/simple-process-bg.svg) 0 0 repeat; | ||||||
|  | @ -473,6 +476,7 @@ | ||||||
|       .branch-node-container { |       .branch-node-container { | ||||||
|         position: relative; |         position: relative; | ||||||
|         display: flex; |         display: flex; | ||||||
|  |         min-width: fit-content; | ||||||
| 
 | 
 | ||||||
|         &::before { |         &::before { | ||||||
|           position: absolute; |           position: absolute; | ||||||
|  | @ -548,6 +552,7 @@ | ||||||
|           background: transparent; |           background: transparent; | ||||||
|           border-top: 2px solid #dedede; |           border-top: 2px solid #dedede; | ||||||
|           border-bottom: 2px solid #dedede; |           border-bottom: 2px solid #dedede; | ||||||
|  |           flex-shrink: 0; | ||||||
| 
 | 
 | ||||||
|           &::before { |           &::before { | ||||||
|             position: absolute; |             position: absolute; | ||||||
|  |  | ||||||
|  | @ -309,18 +309,26 @@ const props = defineProps({ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| // 监听value变化,重新加载流程图 | // 监听value变化,重新加载流程图 | ||||||
| watch(() => props.value, (newValue) => { | watch( | ||||||
|   if (newValue && bpmnModeler) { |   () => props.value, | ||||||
|     createNewDiagram(newValue) |   (newValue) => { | ||||||
|   } |     if (newValue && bpmnModeler) { | ||||||
| }, { immediate: true }) |       createNewDiagram(newValue) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   { immediate: true } | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // 监听processId和processName变化 | // 监听processId和processName变化 | ||||||
| watch([() => props.processId, () => props.processName], ([newId, newName]) => { | watch( | ||||||
|   if (newId && newName && !props.value) { |   [() => props.processId, () => props.processName], | ||||||
|     createNewDiagram(null) |   ([newId, newName]) => { | ||||||
|   } |     if (newId && newName && !props.value) { | ||||||
| }, { immediate: true }) |       createNewDiagram(null) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   { immediate: true } | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| provide('configGlobal', props) | provide('configGlobal', props) | ||||||
| let bpmnModeler: any = null | let bpmnModeler: any = null | ||||||
|  | @ -599,16 +607,6 @@ const processZoomOut = (zoomStep = 0.1) => { | ||||||
|   defaultZoom.value = newZoom |   defaultZoom.value = newZoom | ||||||
|   bpmnModeler.get('canvas').zoom(defaultZoom.value) |   bpmnModeler.get('canvas').zoom(defaultZoom.value) | ||||||
| } | } | ||||||
| // const processZoomTo = (newZoom = 1) => { |  | ||||||
| //   if (newZoom < 0.2) { |  | ||||||
| //     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2') |  | ||||||
| //   } |  | ||||||
| //   if (newZoom > 4) { |  | ||||||
| //     throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4') |  | ||||||
| //   } |  | ||||||
| //   defaultZoom = newZoom |  | ||||||
| //   bpmnModeler.get('canvas').zoom(newZoom) |  | ||||||
| // } |  | ||||||
| const processReZoom = () => { | const processReZoom = () => { | ||||||
|   defaultZoom.value = 1 |   defaultZoom.value = 1 | ||||||
|   bpmnModeler.get('canvas').zoom('fit-viewport', 'auto') |   bpmnModeler.get('canvas').zoom('fit-viewport', 'auto') | ||||||
|  | @ -647,62 +645,19 @@ const previewProcessXML = () => { | ||||||
| } | } | ||||||
| const previewProcessJson = () => { | const previewProcessJson = () => { | ||||||
|   bpmnModeler.saveXML({ format: true }).then(({ xml }) => { |   bpmnModeler.saveXML({ format: true }).then(({ xml }) => { | ||||||
|     // console.log(xml, 'xml') |  | ||||||
| 
 |  | ||||||
|     // const rootNode = parseXmlString(xml) |  | ||||||
|     // console.log(rootNode, 'rootNoderootNode') |  | ||||||
|     const rootNodes = new XmlNode(XmlNodeType.Root, parseXmlString(xml)) |     const rootNodes = new XmlNode(XmlNodeType.Root, parseXmlString(xml)) | ||||||
|     // console.log(rootNodes, 'rootNodesrootNodesrootNodes') |  | ||||||
|     // console.log(rootNodes.parent.toJsObject(), 'rootNodes.toJSON()') |  | ||||||
|     // console.log(JSON.stringify(rootNodes.parent.toJsObject()), 'rootNodes.toJSON()') |  | ||||||
|     // console.log(JSON.stringify(rootNodes.parent.toJSON()), 'rootNodes.toJSON()') |  | ||||||
| 
 |  | ||||||
|     // const parser = new xml2js.XMLParser() |  | ||||||
|     // let jObj = parser.parse(xml) |  | ||||||
|     // console.log(jObj, 'jObjjObjjObjjObjjObj') |  | ||||||
|     // const builder = new xml2js.XMLBuilder(xml) |  | ||||||
|     // const xmlContent = builder |  | ||||||
|     // console.log(xmlContent, 'xmlContent') |  | ||||||
|     // console.log(xml2js, 'convertconvertconvert') |  | ||||||
|     previewResult.value = rootNodes.parent?.toJSON() as unknown as string |     previewResult.value = rootNodes.parent?.toJSON() as unknown as string | ||||||
|     // previewResult.value = jObj |  | ||||||
|     // previewResult.value = convert.xml2json(xml,  {explicitArray : false},{ spaces: 2 }) |  | ||||||
|     previewType.value = 'json' |     previewType.value = 'json' | ||||||
|     previewModelVisible.value = true |     previewModelVisible.value = true | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  | 
 | ||||||
| /* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */ | /* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */ | ||||||
| const processSave = async () => { |  | ||||||
|   try { |  | ||||||
|     const { err, xml } = await bpmnModeler.saveXML() |  | ||||||
|     if (err) { |  | ||||||
|       ElMessage.error('保存流程设计失败,请重试!') |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     emit('save', xml) |  | ||||||
|   } catch (error) { |  | ||||||
|     console.error(error) |  | ||||||
|     ElMessage.error('保存流程设计失败,请重试!') |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| /** 高亮显示 */ |  | ||||||
| // const highlightedCode = (previewType, previewResult) => { |  | ||||||
| //   console.log(previewType, 'previewType, previewResult') |  | ||||||
| //   console.log(previewResult, 'previewType, previewResult') |  | ||||||
| //   console.log(hljs.highlight, 'hljs.highlight') |  | ||||||
| //   const result = hljs.highlight(previewType, previewResult.value || '', true) |  | ||||||
| //   return result.value || ' ' |  | ||||||
| // } |  | ||||||
| onBeforeMount(() => { |  | ||||||
|   console.log(props, 'propspropspropsprops') |  | ||||||
| }) |  | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   initBpmnModeler() |   initBpmnModeler() | ||||||
|   createNewDiagram(props.value) |   createNewDiagram(props.value) | ||||||
| }) | }) | ||||||
| onBeforeUnmount(() => { | onBeforeUnmount(() => { | ||||||
|   // this.$once('hook:beforeDestroy', () => { |  | ||||||
|   // }) |  | ||||||
|   if (bpmnModeler) bpmnModeler.destroy() |   if (bpmnModeler) bpmnModeler.destroy() | ||||||
|   emit('destroy', bpmnModeler) |   emit('destroy', bpmnModeler) | ||||||
|   bpmnModeler = null |   bpmnModeler = null | ||||||
|  |  | ||||||
|  | @ -221,7 +221,7 @@ onBeforeUnmount(() => { | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| /** 获取XML字符串 */ | /** 获取 XML 字符串 */ | ||||||
| const saveXML = async () => { | const saveXML = async () => { | ||||||
|   if (!modeler.value) { |   if (!modeler.value) { | ||||||
|     return { xml: xmlString.value } |     return { xml: xmlString.value } | ||||||
|  | @ -273,7 +273,7 @@ defineExpose({ | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
| .process-panel__container { | .process-panel__container { | ||||||
|   position: absolute; |   position: absolute; | ||||||
|   top: 180px; |   top: 172px; | ||||||
|   right: 60px; |   right: 70px; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
|  | @ -79,14 +79,14 @@ | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { useRouter, useRoute } from 'vue-router' | import { useRoute, useRouter } from 'vue-router' | ||||||
| import { useMessage } from '@/hooks/web/useMessage' | import { useMessage } from '@/hooks/web/useMessage' | ||||||
| import * as ModelApi from '@/api/bpm/model' | import * as ModelApi from '@/api/bpm/model' | ||||||
| import * as FormApi from '@/api/bpm/form' | import * as FormApi from '@/api/bpm/form' | ||||||
| import { CategoryApi } from '@/api/bpm/category' | import { CategoryApi } from '@/api/bpm/category' | ||||||
| import * as UserApi from '@/api/system/user' | import * as UserApi from '@/api/system/user' | ||||||
| import { useUserStoreWithOut } from '@/store/modules/user' | import { useUserStoreWithOut } from '@/store/modules/user' | ||||||
| import { BpmModelType, BpmModelFormType } from '@/utils/constants' | import { BpmModelFormType, BpmModelType } from '@/utils/constants' | ||||||
| import BasicInfo from './BasicInfo.vue' | import BasicInfo from './BasicInfo.vue' | ||||||
| import FormDesign from './FormDesign.vue' | import FormDesign from './FormDesign.vue' | ||||||
| import ProcessDesign from './ProcessDesign.vue' | import ProcessDesign from './ProcessDesign.vue' | ||||||
|  | @ -108,16 +108,17 @@ const validateBasic = async () => { | ||||||
|   await basicInfoRef.value?.validate() |   await basicInfoRef.value?.validate() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** 表单设计校验 */ | ||||||
| const validateForm = async () => { | const validateForm = async () => { | ||||||
|   await formDesignRef.value?.validate() |   await formDesignRef.value?.validate() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** 流程设计校验 */ | ||||||
| const validateProcess = async () => { | const validateProcess = async () => { | ||||||
|   await processDesignRef.value?.validate() |   await processDesignRef.value?.validate() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 步骤控制 | const currentStep = ref(0) // 步骤控制 | ||||||
| const currentStep = ref(0) |  | ||||||
| const steps = [ | const steps = [ | ||||||
|   { title: '基本信息', validator: validateBasic }, |   { title: '基本信息', validator: validateBasic }, | ||||||
|   { title: '表单设计', validator: validateForm }, |   { title: '表单设计', validator: validateForm }, | ||||||
|  | @ -255,7 +256,6 @@ const handleSave = async () => { | ||||||
|     if (formData.value.id) { |     if (formData.value.id) { | ||||||
|       // 修改场景 |       // 修改场景 | ||||||
|       await ModelApi.updateModel(modelData) |       await ModelApi.updateModel(modelData) | ||||||
|       message.success('修改成功') |  | ||||||
|       // 询问是否发布流程 |       // 询问是否发布流程 | ||||||
|       try { |       try { | ||||||
|         await message.confirm('修改流程成功,是否发布流程?') |         await message.confirm('修改流程成功,是否发布流程?') | ||||||
|  | @ -266,8 +266,7 @@ const handleSave = async () => { | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       // 新增场景 |       // 新增场景 | ||||||
|       const result = await ModelApi.createModel(modelData) |       formData.value.id = await ModelApi.createModel(modelData) | ||||||
|       formData.value.id = result |  | ||||||
|       message.success('新增成功') |       message.success('新增成功') | ||||||
|       try { |       try { | ||||||
|         await message.confirm('创建流程成功,是否继续编辑?') |         await message.confirm('创建流程成功,是否继续编辑?') | ||||||
|  | @ -335,7 +334,7 @@ const handleDeploy = async () => { | ||||||
|     await ModelApi.deployModel(formData.value.id) |     await ModelApi.deployModel(formData.value.id) | ||||||
|     message.success('发布成功') |     message.success('发布成功') | ||||||
|     // 返回列表页 |     // 返回列表页 | ||||||
|     router.push({ name: 'BpmModel' }) |     await router.push({ name: 'BpmModel' }) | ||||||
|   } catch (error: any) { |   } catch (error: any) { | ||||||
|     console.error('发布失败:', error) |     console.error('发布失败:', error) | ||||||
|     message.warning(error.message || '发布失败') |     message.warning(error.message || '发布失败') | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
|         <!-- 中间主要内容 tab 栏 --> |         <!-- 中间主要内容 tab 栏 --> | ||||||
|         <el-tabs v-model="activeTab"> |         <el-tabs v-model="activeTab"> | ||||||
|           <!-- 表单信息 --> |           <!-- 表单信息 --> | ||||||
|           <el-tab-pane label="表单填写" name="form" > |           <el-tab-pane label="表单填写" name="form"> | ||||||
|             <div class="form-scroll-area" v-loading="processInstanceStartLoading"> |             <div class="form-scroll-area" v-loading="processInstanceStartLoading"> | ||||||
|               <el-scrollbar> |               <el-scrollbar> | ||||||
|                 <el-row> |                 <el-row> | ||||||
|  | @ -75,7 +75,11 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { decodeFields, setConfAndFields2 } from '@/utils/formCreate' | import { decodeFields, setConfAndFields2 } from '@/utils/formCreate' | ||||||
| import { BpmModelType } from '@/utils/constants' | import { BpmModelType } from '@/utils/constants' | ||||||
| import { CandidateStrategy } from '@/components/SimpleProcessDesignerV2/src/consts' | import { | ||||||
|  |   CandidateStrategy, | ||||||
|  |   NodeId, | ||||||
|  |   FieldPermissionType | ||||||
|  | } from '@/components/SimpleProcessDesignerV2/src/consts' | ||||||
| import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue' | import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue' | ||||||
| import ProcessInstanceSimpleViewer from '../detail/ProcessInstanceSimpleViewer.vue' | import ProcessInstanceSimpleViewer from '../detail/ProcessInstanceSimpleViewer.vue' | ||||||
| import ProcessInstanceTimeline from '../detail/ProcessInstanceTimeline.vue' | import ProcessInstanceTimeline from '../detail/ProcessInstanceTimeline.vue' | ||||||
|  | @ -129,8 +133,10 @@ const initProcessInfo = async (row: any, formVariables?: any) => { | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     setConfAndFields2(detailForm, row.formConf, row.formFields, formVariables) |     setConfAndFields2(detailForm, row.formConf, row.formFields, formVariables) | ||||||
|  | 
 | ||||||
|     await nextTick() |     await nextTick() | ||||||
|     fApi.value?.btn.show(false) // 隐藏提交按钮 |     fApi.value?.btn.show(false) // 隐藏提交按钮 | ||||||
|  | 
 | ||||||
|     // 获取流程审批信息 |     // 获取流程审批信息 | ||||||
|     await getApprovalDetail(row) |     await getApprovalDetail(row) | ||||||
| 
 | 
 | ||||||
|  | @ -152,7 +158,12 @@ const initProcessInfo = async (row: any, formVariables?: any) => { | ||||||
| /** 获取审批详情 */ | /** 获取审批详情 */ | ||||||
| const getApprovalDetail = async (row: any) => { | const getApprovalDetail = async (row: any) => { | ||||||
|   try { |   try { | ||||||
|     const data = await ProcessInstanceApi.getApprovalDetail({ processDefinitionId: row.id }) |     // TODO 获取审批详情,设置 activityId 为发起人节点(为了获取字段权限。暂时只对 Simple 设计器有效) | ||||||
|  |     const data = await ProcessInstanceApi.getApprovalDetail({ | ||||||
|  |       processDefinitionId: row.id, | ||||||
|  |       activityId: NodeId.START_USER_NODE_ID | ||||||
|  |     }) | ||||||
|  | 
 | ||||||
|     if (!data) { |     if (!data) { | ||||||
|       message.error('查询不到审批详情信息!') |       message.error('查询不到审批详情信息!') | ||||||
|       return |       return | ||||||
|  | @ -170,10 +181,36 @@ const getApprovalDetail = async (row: any) => { | ||||||
| 
 | 
 | ||||||
|     // 获取审批节点,显示 Timeline 的数据 |     // 获取审批节点,显示 Timeline 的数据 | ||||||
|     activityNodes.value = data.activityNodes |     activityNodes.value = data.activityNodes | ||||||
|  |     // 获取表单字段权限 | ||||||
|  |     const formFieldsPermission = data.formFieldsPermission | ||||||
|  |     // 设置表单字段权限 | ||||||
|  |     if (formFieldsPermission) { | ||||||
|  |       Object.keys(formFieldsPermission).forEach((item) => { | ||||||
|  |         setFieldPermission(item, formFieldsPermission[item]) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|   } finally { |   } finally { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * 设置表单权限 | ||||||
|  |  */ | ||||||
|  | const setFieldPermission = (field: string, permission: string) => { | ||||||
|  |   if (permission === FieldPermissionType.READ) { | ||||||
|  |     //@ts-ignore | ||||||
|  |     fApi.value?.disabled(true, field) | ||||||
|  |   } | ||||||
|  |   if (permission === FieldPermissionType.WRITE) { | ||||||
|  |     //@ts-ignore | ||||||
|  |     fApi.value?.disabled(false, field) | ||||||
|  |   } | ||||||
|  |   if (permission === FieldPermissionType.NONE) { | ||||||
|  |     //@ts-ignore | ||||||
|  |     fApi.value?.hidden(true, field) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** 提交按钮 */ | /** 提交按钮 */ | ||||||
| const submitForm = async () => { | const submitForm = async () => { | ||||||
|   if (!fApi.value || !props.selectProcessDefinition) { |   if (!fApi.value || !props.selectProcessDefinition) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 GoldenZqqq
						GoldenZqqq