From 22e9eb2add3479a0c958876f03a2927c1e88ffda Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 26 Nov 2024 09:45:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20bpm=E8=AE=BE=E8=AE=A1=E5=99=A8=E9=80=82?= =?UTF-8?q?=E9=85=8DSimple=E8=AE=BE=E8=AE=A1=E5=99=A8=EF=BC=8C=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../descriptor/flowableDescriptor.json | 25 ++- .../custom-config/ElementCustomConfig.vue | 210 +++++++++++++++++- src/views/bpm/model/editor/index.vue | 14 ++ 3 files changed, 245 insertions(+), 4 deletions(-) diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json index 5544b2d0..c60b524a 100644 --- a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json @@ -1305,8 +1305,31 @@ "isAttr": true } ] + }, + { + "name": "FieldsPermission", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "flowable:field", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:title", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:permission", + "type": "String", + "isAttr": true + } + ] } - ], "emumerations": [] } diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue b/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue index 9cf7e966..ac766bf9 100644 --- a/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue +++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue @@ -3,6 +3,7 @@ 2. 审批人拒绝时 3. 审批人为空时 4. 操作按钮 + 5. 字段权限 --> @@ -115,9 +157,11 @@ import { ASSIGN_EMPTY_HANDLER_TYPES, AssignEmptyHandlerType, OPERATION_BUTTON_NAME, - DEFAULT_BUTTON_SETTING + DEFAULT_BUTTON_SETTING, + FieldPermissionType } from '@/components/SimpleProcessDesignerV2/src/consts' import * as UserApi from '@/api/system/user' +import { cloneDeep } from 'lodash-es' defineOptions({ name: 'ElementCustomConfig' }) const props = defineProps({ @@ -148,6 +192,12 @@ const buttonsSettingEl = ref() const { buttonsSetting, btnDisplayNameEdit, changeBtnDisplayName, btnDisplayNameBlurEvent } = useButtonsSetting() +// 字段权限 +const fieldsPermissionEl = ref() +const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission( + FieldPermissionType.READ +) + const elExtensionElements = ref() const otherExtensions = ref() const bpmnElement = ref() @@ -218,6 +268,21 @@ const resetCustomConfigList = () => { }) } + // 字段权限 + if (formType.value === 10) { + fieldsPermissionEl.value = elExtensionElements.value.values?.filter( + (ex) => ex.$type === `${prefix}:FieldsPermission` + ) + if (fieldsPermissionEl.value.length === 0) { + getNodeConfigFormFields() + fieldsPermissionConfig.value.forEach((el) => { + fieldsPermissionEl.value.push( + bpmnInstances().moddle.create(`${prefix}:FieldsPermission`, el) + ) + }) + } + } + // 保留剩余扩展元素,便于后面更新该元素对应属性 otherExtensions.value = elExtensionElements.value.values?.filter( @@ -227,7 +292,8 @@ const resetCustomConfigList = () => { ex.$type !== `${prefix}:RejectReturnTaskId` && ex.$type !== `${prefix}:AssignEmptyHandlerType` && ex.$type !== `${prefix}:AssignEmptyUserIds` && - ex.$type !== `${prefix}:ButtonsSetting` + ex.$type !== `${prefix}:ButtonsSetting` && + ex.$type !== `${prefix}:FieldsPermission` ) ?? [] // 更新元素扩展属性,避免后续报错 @@ -276,7 +342,8 @@ const updateElementExtensions = () => { returnNodeIdEl.value, assignEmptyHandlerTypeEl.value, assignEmptyUserIdsEl.value, - ...buttonsSettingEl.value + ...buttonsSettingEl.value, + ...fieldsPermissionEl.value ] }) bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), { @@ -359,6 +426,69 @@ function useButtonsSetting() { } } +// 表单字段权限设置 +function useFormFieldsPermission(defaultPermission) { + // 字段权限配置. 需要有 field, title, permissioin 属性 + const fieldsPermissionConfig = ref>>([]) + + const formType = inject>('formType') // 表单类型 + + const formFields = inject>('formFields') // 流程表单字段 + + const getNodeConfigFormFields = (nodeFormFields?: Array>) => { + nodeFormFields = toRaw(nodeFormFields) + fieldsPermissionConfig.value = + cloneDeep(nodeFormFields) || getDefaultFieldsPermission(unref(formFields)) + } + // 默认的表单权限: 获取表单的所有字段,设置字段默认权限为只读 + const getDefaultFieldsPermission = (formFields?: string[]) => { + const defaultFieldsPermission: Array> = [] + if (formFields) { + formFields.forEach((fieldStr: string) => { + parseFieldsSetDefaultPermission(JSON.parse(fieldStr), defaultFieldsPermission) + }) + } + return defaultFieldsPermission + } + // 解析字段。赋给默认权限 + const parseFieldsSetDefaultPermission = ( + rule: Record, + fieldsPermission: Array>, + parentTitle: string = '' + ) => { + const { /**type,*/ field, title: tempTitle, children } = rule + if (field && tempTitle) { + let title = tempTitle + if (parentTitle) { + title = `${parentTitle}.${tempTitle}` + } + fieldsPermission.push({ + field, + title, + permission: defaultPermission + }) + // TODO 子表单 需要处理子表单字段 + // if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) { + // // 解析子表单的字段 + // rule.props.rule.forEach((item) => { + // parseFieldsSetDefaultPermission(item, fieldsPermission, title) + // }) + // } + } + if (children && Array.isArray(children)) { + children.forEach((rule) => { + parseFieldsSetDefaultPermission(rule, fieldsPermission) + }) + } + } + + return { + formType, + fieldsPermissionConfig, + getNodeConfigFormFields + } +} + const userOptions = ref([]) // 用户列表 onMounted(async () => { // 获得用户列表 @@ -449,4 +579,78 @@ onMounted(async () => { } } } + +.field-setting-pane { + display: flex; + flex-direction: column; + font-size: 14px; + + .field-setting-desc { + padding-right: 8px; + margin-bottom: 16px; + font-size: 16px; + font-weight: 700; + } + + .field-permit-title { + display: flex; + justify-content: space-between; + align-items: center; + height: 45px; + padding-left: 12px; + line-height: 45px; + background-color: #f8fafc0a; + border: 1px solid #1f38581a; + + .first-title { + text-align: left !important; + } + + .other-titles { + display: flex; + justify-content: space-between; + } + + .setting-title-label { + display: inline-block; + width: 100px; + padding: 5px 0; + font-size: 13px; + font-weight: 700; + color: #000; + text-align: center; + } + } + + .field-setting-item { + align-items: center; + display: flex; + justify-content: space-between; + height: 38px; + padding-left: 12px; + border: 1px solid #1f38581a; + border-top: 0; + + .field-setting-item-label { + display: inline-block; + width: 100px; + min-height: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: text; + } + + .field-setting-item-group { + display: flex; + justify-content: space-between; + + .item-radio-wrap { + display: inline-block; + width: 100px; + text-align: center; + } + } + } +} diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 3e773691..1a41a50c 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -31,6 +31,7 @@ import CustomContentPadProvider from '@/components/bpmnProcessDesigner/package/d // 自定义左侧菜单(修改 默认任务 为 用户任务) import CustomPaletteProvider from '@/components/bpmnProcessDesigner/package/designer/plugins/palette' import * as ModelApi from '@/api/bpm/model' +import { getForm, FormVO } from '@/api/bpm/form' defineOptions({ name: 'BpmModelEditor' }) @@ -38,6 +39,12 @@ const router = useRouter() // 路由 const { query } = useRoute() // 路由的查询 const message = useMessage() // 国际化 +// 表单信息 +const formFields = ref([]) +const formType = ref(20) +provide('formFields', formFields) +provide('formType', formType) + const xmlString = ref(undefined) // BPMN XML const modeler = ref(null) // BPMN Modeler const controlForm = ref({ @@ -99,6 +106,13 @@ onMounted(async () => { ` } + + formType.value = data.formType + if (data.formType === 10) { + const bpmnForm = (await getForm(data.formId)) as unknown as FormVO + formFields.value = bpmnForm?.fields + } + model.value = { ...data, bpmnXml: undefined // 清空 bpmnXml 属性