fix(ts): 修复 BPMN 设计器类型错误
- 设计器/预览补 DOM 空值保护与局部 service 类型(canvas/elementRegistry)
- UserTaskCustomConfig/ElementForm/ElementMultiInstance 等补 ref/数组/element 类型
- ProcessListener/Expression Dialog 补声明实际已 emit 的 select 事件
- UserTask 删除 return 后不可达旧代码
- ElementMultiInstance:loopCharacteristics 按需写入,不影响 ApproveMethod 扩展保存
- 运行时:keyboard 配置 { bindTo: document } → { bind: true },适配 diagram-js 15
master
parent
cb9400e93d
commit
3f779091be
|
|
@ -405,7 +405,10 @@ console.log(additionalModules, 'additionalModules()')
|
||||||
console.log(moddleExtensions, 'moddleExtensions()')
|
console.log(moddleExtensions, 'moddleExtensions()')
|
||||||
const initBpmnModeler = () => {
|
const initBpmnModeler = () => {
|
||||||
if (bpmnModeler) return
|
if (bpmnModeler) return
|
||||||
let data = document.getElementById('bpmnCanvas')
|
const data = document.getElementById('bpmnCanvas')
|
||||||
|
if (!data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
console.log(data, 'data')
|
console.log(data, 'data')
|
||||||
console.log(props.keyboard, 'props.keyboard')
|
console.log(props.keyboard, 'props.keyboard')
|
||||||
console.log(additionalModules, 'additionalModules()')
|
console.log(additionalModules, 'additionalModules()')
|
||||||
|
|
@ -422,9 +425,9 @@ const initBpmnModeler = () => {
|
||||||
// propertiesPanel: {
|
// propertiesPanel: {
|
||||||
// parent: '#js-properties-panel'
|
// parent: '#js-properties-panel'
|
||||||
// },
|
// },
|
||||||
keyboard: props.keyboard ? { bindTo: document } : null,
|
keyboard: props.keyboard ? { bind: true } : null,
|
||||||
// additionalModules: additionalModules.value,
|
// additionalModules: additionalModules.value,
|
||||||
additionalModules: additionalModules.value,
|
additionalModules: additionalModules.value as any[],
|
||||||
moddleExtensions: moddleExtensions.value
|
moddleExtensions: moddleExtensions.value
|
||||||
|
|
||||||
// additionalModules: [
|
// additionalModules: [
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,8 @@
|
||||||
import '../theme/index.scss'
|
import '../theme/index.scss'
|
||||||
import BpmnViewer from 'bpmn-js/lib/Viewer'
|
import BpmnViewer from 'bpmn-js/lib/Viewer'
|
||||||
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'
|
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'
|
||||||
|
import type Canvas from 'diagram-js/lib/core/Canvas'
|
||||||
|
import type ElementRegistry from 'diagram-js/lib/core/ElementRegistry'
|
||||||
import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
|
import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
import { DICT_TYPE } from '@/utils/dict'
|
||||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||||
|
|
@ -170,10 +172,18 @@ const dialogTitle = ref<string | undefined>(undefined) // 弹窗标题
|
||||||
const selectActivityType = ref<string | undefined>(undefined) // 选中 Task 的活动编号
|
const selectActivityType = ref<string | undefined>(undefined) // 选中 Task 的活动编号
|
||||||
const selectTasks = ref<any[]>([]) // 选中的任务数组
|
const selectTasks = ref<any[]>([]) // 选中的任务数组
|
||||||
|
|
||||||
|
type BpmnCanvas = Omit<Canvas, 'zoom'> & {
|
||||||
|
_svg?: SVGSVGElement
|
||||||
|
zoom: (newScale?: number | 'fit-viewport', center?: 'auto' | { x: number; y: number }) => number
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCanvas = () => bpmnViewer.value?.get<BpmnCanvas>('canvas')
|
||||||
|
const getElementRegistry = () => bpmnViewer.value?.get<ElementRegistry>('elementRegistry')
|
||||||
|
|
||||||
/** Zoom:恢复 */
|
/** Zoom:恢复 */
|
||||||
const processReZoom = () => {
|
const processReZoom = () => {
|
||||||
defaultZoom.value = 1
|
defaultZoom.value = 1
|
||||||
bpmnViewer.value?.get('canvas').zoom('fit-viewport', 'auto')
|
getCanvas()?.zoom('fit-viewport', 'auto')
|
||||||
}
|
}
|
||||||
|
|
||||||
let resizeObserver: ResizeObserver | null = null
|
let resizeObserver: ResizeObserver | null = null
|
||||||
|
|
@ -218,7 +228,7 @@ const processZoomIn = (zoomStep = 0.1) => {
|
||||||
throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
|
throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
|
||||||
}
|
}
|
||||||
defaultZoom.value = newZoom
|
defaultZoom.value = newZoom
|
||||||
bpmnViewer.value?.get('canvas').zoom(defaultZoom.value)
|
getCanvas()?.zoom(defaultZoom.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Zoom:缩小 */
|
/** Zoom:缩小 */
|
||||||
|
|
@ -228,7 +238,7 @@ const processZoomOut = (zoomStep = 0.1) => {
|
||||||
throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
|
throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
|
||||||
}
|
}
|
||||||
defaultZoom.value = newZoom
|
defaultZoom.value = newZoom
|
||||||
bpmnViewer.value?.get('canvas').zoom(defaultZoom.value)
|
getCanvas()?.zoom(defaultZoom.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 流程图预览清空 */
|
/** 流程图预览清空 */
|
||||||
|
|
@ -249,9 +259,9 @@ const addCustomDefs = () => {
|
||||||
if (!bpmnViewer.value) {
|
if (!bpmnViewer.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const canvas = bpmnViewer.value?.get('canvas')
|
const canvas = getCanvas()
|
||||||
const svg = canvas?._svg
|
const svg = canvas?._svg
|
||||||
svg.appendChild(customDefs.value)
|
svg?.appendChild(customDefs.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 节点选中 */
|
/** 节点选中 */
|
||||||
|
|
@ -340,8 +350,11 @@ const setProcessStatus = (view: any) => {
|
||||||
finishedSequenceFlowActivityIds,
|
finishedSequenceFlowActivityIds,
|
||||||
rejectedTaskActivityIds
|
rejectedTaskActivityIds
|
||||||
} = view
|
} = view
|
||||||
const canvas = bpmnViewer.value.get('canvas')
|
const canvas = getCanvas()
|
||||||
const elementRegistry = bpmnViewer.value.get('elementRegistry')
|
const elementRegistry = getElementRegistry()
|
||||||
|
if (!canvas || !elementRegistry) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 已完成节点
|
// 已完成节点
|
||||||
if (Array.isArray(finishedSequenceFlowActivityIds)) {
|
if (Array.isArray(finishedSequenceFlowActivityIds)) {
|
||||||
|
|
@ -349,7 +362,7 @@ const setProcessStatus = (view: any) => {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
canvas.addMarker(item, 'success')
|
canvas.addMarker(item, 'success')
|
||||||
const element = elementRegistry.get(item)
|
const element = elementRegistry.get(item)
|
||||||
const conditionExpression = element.businessObject.conditionExpression
|
const conditionExpression = element?.businessObject.conditionExpression
|
||||||
if (conditionExpression) {
|
if (conditionExpression) {
|
||||||
canvas.addMarker(item, 'condition-expression')
|
canvas.addMarker(item, 'condition-expression')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ const maxRemindCount = ref(1)
|
||||||
|
|
||||||
const elExtensionElements = ref()
|
const elExtensionElements = ref()
|
||||||
const otherExtensions = ref()
|
const otherExtensions = ref()
|
||||||
const configExtensions = ref([])
|
const configExtensions = ref<any[]>([])
|
||||||
const eventDefinition = ref()
|
const eventDefinition = ref()
|
||||||
|
|
||||||
const resetElement = () => {
|
const resetElement = () => {
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,18 @@ import * as UserApi from '@/api/system/user'
|
||||||
import { useFormFieldsPermission } from '@/components/SimpleProcessDesignerV2/src/node'
|
import { useFormFieldsPermission } from '@/components/SimpleProcessDesignerV2/src/node'
|
||||||
import { BpmModelFormType } from '@/utils/constants'
|
import { BpmModelFormType } from '@/utils/constants'
|
||||||
|
|
||||||
|
type BpmnElement = {
|
||||||
|
id: string
|
||||||
|
type: string
|
||||||
|
businessObject: Record<string, any>
|
||||||
|
source?: BpmnElement
|
||||||
|
target?: BpmnElement
|
||||||
|
}
|
||||||
|
type ReturnTask = Record<string, any> & {
|
||||||
|
id: string
|
||||||
|
name?: string
|
||||||
|
}
|
||||||
|
|
||||||
defineOptions({ name: 'ElementCustomConfig4UserTask' })
|
defineOptions({ name: 'ElementCustomConfig4UserTask' })
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: String,
|
id: String,
|
||||||
|
|
@ -231,16 +243,16 @@ const rejectHandlerTypeEl = ref()
|
||||||
const rejectHandlerType = ref()
|
const rejectHandlerType = ref()
|
||||||
const returnNodeIdEl = ref()
|
const returnNodeIdEl = ref()
|
||||||
const returnNodeId = ref()
|
const returnNodeId = ref()
|
||||||
const returnTaskList = ref([])
|
const returnTaskList = ref<ReturnTask[]>([])
|
||||||
|
|
||||||
// 审批人为空时
|
// 审批人为空时
|
||||||
const assignEmptyHandlerTypeEl = ref()
|
const assignEmptyHandlerTypeEl = ref()
|
||||||
const assignEmptyHandlerType = ref()
|
const assignEmptyHandlerType = ref()
|
||||||
const assignEmptyUserIdsEl = ref()
|
const assignEmptyUserIdsEl = ref()
|
||||||
const assignEmptyUserIds = ref()
|
const assignEmptyUserIds = ref<Array<string | number>>([])
|
||||||
|
|
||||||
// 操作按钮
|
// 操作按钮
|
||||||
const buttonsSettingEl = ref()
|
const buttonsSettingEl = ref<any[]>([])
|
||||||
const { btnDisplayNameEdit, changeBtnDisplayName } = useButtonsSetting()
|
const { btnDisplayNameEdit, changeBtnDisplayName } = useButtonsSetting()
|
||||||
const btnDisplayNameBlurEvent = (index: number) => {
|
const btnDisplayNameBlurEvent = (index: number) => {
|
||||||
btnDisplayNameEdit.value[index] = false
|
btnDisplayNameEdit.value[index] = false
|
||||||
|
|
@ -250,7 +262,7 @@ const btnDisplayNameBlurEvent = (index: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字段权限
|
// 字段权限
|
||||||
const fieldsPermissionEl = ref([])
|
const fieldsPermissionEl = ref<any[]>([])
|
||||||
const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission(
|
const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission(
|
||||||
FieldPermissionType.READ
|
FieldPermissionType.READ
|
||||||
)
|
)
|
||||||
|
|
@ -451,18 +463,20 @@ watch(
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
function findAllPredecessorsExcludingStart(elementId, modeler) {
|
function findAllPredecessorsExcludingStart(elementId: string, modeler: any) {
|
||||||
const elementRegistry = modeler.get('elementRegistry')
|
const elementRegistry = modeler.get('elementRegistry')
|
||||||
const allConnections = elementRegistry.filter((element) => element.type === 'bpmn:SequenceFlow')
|
const allConnections = elementRegistry.filter(
|
||||||
const predecessors = new Set() // 使用 Set 来避免重复节点
|
(element: BpmnElement) => element.type === 'bpmn:SequenceFlow'
|
||||||
const visited = new Set() // 用于记录已访问的节点
|
)
|
||||||
|
const predecessors = new Set<Record<string, any>>() // 使用 Set 来避免重复节点
|
||||||
|
const visited = new Set<BpmnElement>() // 用于记录已访问的节点
|
||||||
|
|
||||||
// 检查是否是开始事件节点
|
// 检查是否是开始事件节点
|
||||||
function isStartEvent(element) {
|
function isStartEvent(element: BpmnElement) {
|
||||||
return element.type === 'bpmn:StartEvent'
|
return element.type === 'bpmn:StartEvent'
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPredecessorsRecursively(element) {
|
function findPredecessorsRecursively(element: BpmnElement) {
|
||||||
// 如果该节点已经访问过,直接返回,避免循环
|
// 如果该节点已经访问过,直接返回,避免循环
|
||||||
if (visited.has(element)) {
|
if (visited.has(element)) {
|
||||||
return
|
return
|
||||||
|
|
@ -472,10 +486,15 @@ function findAllPredecessorsExcludingStart(elementId, modeler) {
|
||||||
visited.add(element)
|
visited.add(element)
|
||||||
|
|
||||||
// 获取与当前节点相连的所有连接
|
// 获取与当前节点相连的所有连接
|
||||||
const incomingConnections = allConnections.filter((connection) => connection.target === element)
|
const incomingConnections = allConnections.filter(
|
||||||
|
(connection: BpmnElement) => connection.target === element
|
||||||
|
)
|
||||||
|
|
||||||
incomingConnections.forEach((connection) => {
|
incomingConnections.forEach((connection: BpmnElement) => {
|
||||||
const source = connection.source // 获取前置节点
|
const source = connection.source // 获取前置节点
|
||||||
|
if (!source) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 只添加不是开始事件的前置节点
|
// 只添加不是开始事件的前置节点
|
||||||
if (!isStartEvent(source)) {
|
if (!isStartEvent(source)) {
|
||||||
|
|
@ -491,7 +510,7 @@ function findAllPredecessorsExcludingStart(elementId, modeler) {
|
||||||
findPredecessorsRecursively(targetElement)
|
findPredecessorsRecursively(targetElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.from(predecessors) // 返回前置节点数组
|
return Array.from(predecessors) as ReturnTask[] // 返回前置节点数组
|
||||||
}
|
}
|
||||||
|
|
||||||
function useButtonsSetting() {
|
function useButtonsSetting() {
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
const prefix = inject('prefix')
|
const prefix = inject('prefix')
|
||||||
|
|
||||||
const formKey = ref(undefined)
|
const formKey = ref<number | undefined>()
|
||||||
const bpmnELement = ref()
|
const bpmnELement = ref()
|
||||||
const elExtensionElements = ref()
|
const elExtensionElements = ref()
|
||||||
const formData = ref()
|
const formData = ref()
|
||||||
|
|
@ -282,10 +282,10 @@ const updateElementExtensions = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const formList = ref([]) // 流程表单的下拉框的数据
|
const formList = ref<Array<{ id: number; name: string }>>([]) // 流程表单的下拉框的数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
formList.value = await FormApi.getFormSimpleList()
|
formList.value = await FormApi.getFormSimpleList()
|
||||||
formKey.value = parseInt(formKey.value)
|
formKey.value = formKey.value != null ? Number(formKey.value) : undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ const getList = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success', 'select']) // 定义 success/select 事件,用于操作成功后的回调
|
||||||
const select = async (row) => {
|
const select = async (row: ProcessListenerVO) => {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
// 发送操作成功的事件
|
// 发送操作成功的事件
|
||||||
emit('select', row)
|
emit('select', row)
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ const props = defineProps({
|
||||||
const prefix = inject('prefix')
|
const prefix = inject('prefix')
|
||||||
const loopCharacteristics = ref('')
|
const loopCharacteristics = ref('')
|
||||||
const loopInstanceForm = ref<any>({})
|
const loopInstanceForm = ref<any>({})
|
||||||
const bpmnElement = ref(null)
|
const bpmnElement = ref<any | null>(null)
|
||||||
const multiLoopInstance = ref(null)
|
const multiLoopInstance = ref<any | null>(null)
|
||||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||||
|
|
||||||
const changeLoopCharacteristicsType = (type) => {
|
const changeLoopCharacteristicsType = (type) => {
|
||||||
|
|
@ -261,7 +261,7 @@ const approveMethod = ref()
|
||||||
const approveRatio = ref(100)
|
const approveRatio = ref(100)
|
||||||
const otherExtensions = ref()
|
const otherExtensions = ref()
|
||||||
const getElementLoopNew = () => {
|
const getElementLoopNew = () => {
|
||||||
if (props.type === 'UserTask') {
|
if (props.type === 'UserTask' && bpmnElement.value) {
|
||||||
const extensionElements =
|
const extensionElements =
|
||||||
bpmnElement.value.businessObject?.extensionElements ??
|
bpmnElement.value.businessObject?.extensionElements ??
|
||||||
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
|
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
|
||||||
|
|
@ -286,6 +286,9 @@ const onApproveRatioChange = () => {
|
||||||
updateLoopCharacteristics()
|
updateLoopCharacteristics()
|
||||||
}
|
}
|
||||||
const updateLoopCharacteristics = () => {
|
const updateLoopCharacteristics = () => {
|
||||||
|
if (!bpmnElement.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 根据ApproveMethod生成multiInstanceLoopCharacteristics节点
|
// 根据ApproveMethod生成multiInstanceLoopCharacteristics节点
|
||||||
if (approveMethod.value === ApproveMethodType.RANDOM_SELECT_ONE_APPROVE) {
|
if (approveMethod.value === ApproveMethodType.RANDOM_SELECT_ONE_APPROVE) {
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||||
|
|
@ -334,9 +337,11 @@ const updateLoopCharacteristics = () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
if (multiLoopInstance.value) {
|
||||||
loopCharacteristics: toRaw(multiLoopInstance.value)
|
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||||
})
|
loopCharacteristics: toRaw(multiLoopInstance.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加ApproveMethod到ExtensionElements
|
// 添加ApproveMethod到ExtensionElements
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ const getList = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success', 'select']) // 定义 success/select 事件,用于操作成功后的回调
|
||||||
const select = async (row) => {
|
const select = async (row: ProcessExpressionVO) => {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
// 发送操作成功的事件
|
// 发送操作成功的事件
|
||||||
emit('select', row)
|
emit('select', row)
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,13 @@ const props = defineProps({
|
||||||
type: String
|
type: String
|
||||||
})
|
})
|
||||||
const prefix = inject('prefix')
|
const prefix = inject('prefix')
|
||||||
const userTaskForm = ref({
|
type CandidateParam = Array<string | number> | string | number
|
||||||
|
type UserTaskForm = {
|
||||||
|
candidateStrategy?: CandidateStrategy
|
||||||
|
candidateParam: CandidateParam
|
||||||
|
skipExpression: string
|
||||||
|
}
|
||||||
|
const userTaskForm = ref<UserTaskForm>({
|
||||||
candidateStrategy: undefined, // 分配规则
|
candidateStrategy: undefined, // 分配规则
|
||||||
candidateParam: [], // 分配选项
|
candidateParam: [], // 分配选项
|
||||||
skipExpression: '' // 跳过表达式
|
skipExpression: '' // 跳过表达式
|
||||||
|
|
@ -405,13 +411,6 @@ const updateElementTask = () => {
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||||
extensionElements: extensions
|
extensionElements: extensions
|
||||||
})
|
})
|
||||||
|
|
||||||
// 改用通过extensionElements来存储数据
|
|
||||||
return
|
|
||||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
|
||||||
candidateStrategy: userTaskForm.value.candidateStrategy,
|
|
||||||
candidateParam: userTaskForm.value.candidateParam.join(',')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateSkipExpression = () => {
|
const updateSkipExpression = () => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue