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()')
|
||||
const initBpmnModeler = () => {
|
||||
if (bpmnModeler) return
|
||||
let data = document.getElementById('bpmnCanvas')
|
||||
const data = document.getElementById('bpmnCanvas')
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
console.log(data, 'data')
|
||||
console.log(props.keyboard, 'props.keyboard')
|
||||
console.log(additionalModules, 'additionalModules()')
|
||||
|
|
@ -422,9 +425,9 @@ const initBpmnModeler = () => {
|
|||
// propertiesPanel: {
|
||||
// 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 as any[],
|
||||
moddleExtensions: moddleExtensions.value
|
||||
|
||||
// additionalModules: [
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@
|
|||
import '../theme/index.scss'
|
||||
import BpmnViewer from 'bpmn-js/lib/Viewer'
|
||||
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 { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||
|
|
@ -170,10 +172,18 @@ const dialogTitle = ref<string | undefined>(undefined) // 弹窗标题
|
|||
const selectActivityType = ref<string | undefined>(undefined) // 选中 Task 的活动编号
|
||||
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:恢复 */
|
||||
const processReZoom = () => {
|
||||
defaultZoom.value = 1
|
||||
bpmnViewer.value?.get('canvas').zoom('fit-viewport', 'auto')
|
||||
getCanvas()?.zoom('fit-viewport', 'auto')
|
||||
}
|
||||
|
||||
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')
|
||||
}
|
||||
defaultZoom.value = newZoom
|
||||
bpmnViewer.value?.get('canvas').zoom(defaultZoom.value)
|
||||
getCanvas()?.zoom(defaultZoom.value)
|
||||
}
|
||||
|
||||
/** 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')
|
||||
}
|
||||
defaultZoom.value = newZoom
|
||||
bpmnViewer.value?.get('canvas').zoom(defaultZoom.value)
|
||||
getCanvas()?.zoom(defaultZoom.value)
|
||||
}
|
||||
|
||||
/** 流程图预览清空 */
|
||||
|
|
@ -249,9 +259,9 @@ const addCustomDefs = () => {
|
|||
if (!bpmnViewer.value) {
|
||||
return
|
||||
}
|
||||
const canvas = bpmnViewer.value?.get('canvas')
|
||||
const canvas = getCanvas()
|
||||
const svg = canvas?._svg
|
||||
svg.appendChild(customDefs.value)
|
||||
svg?.appendChild(customDefs.value)
|
||||
}
|
||||
|
||||
/** 节点选中 */
|
||||
|
|
@ -340,8 +350,11 @@ const setProcessStatus = (view: any) => {
|
|||
finishedSequenceFlowActivityIds,
|
||||
rejectedTaskActivityIds
|
||||
} = view
|
||||
const canvas = bpmnViewer.value.get('canvas')
|
||||
const elementRegistry = bpmnViewer.value.get('elementRegistry')
|
||||
const canvas = getCanvas()
|
||||
const elementRegistry = getElementRegistry()
|
||||
if (!canvas || !elementRegistry) {
|
||||
return
|
||||
}
|
||||
|
||||
// 已完成节点
|
||||
if (Array.isArray(finishedSequenceFlowActivityIds)) {
|
||||
|
|
@ -349,7 +362,7 @@ const setProcessStatus = (view: any) => {
|
|||
if (item != null) {
|
||||
canvas.addMarker(item, 'success')
|
||||
const element = elementRegistry.get(item)
|
||||
const conditionExpression = element.businessObject.conditionExpression
|
||||
const conditionExpression = element?.businessObject.conditionExpression
|
||||
if (conditionExpression) {
|
||||
canvas.addMarker(item, 'condition-expression')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ const maxRemindCount = ref(1)
|
|||
|
||||
const elExtensionElements = ref()
|
||||
const otherExtensions = ref()
|
||||
const configExtensions = ref([])
|
||||
const configExtensions = ref<any[]>([])
|
||||
const eventDefinition = ref()
|
||||
|
||||
const resetElement = () => {
|
||||
|
|
|
|||
|
|
@ -215,6 +215,18 @@ import * as UserApi from '@/api/system/user'
|
|||
import { useFormFieldsPermission } from '@/components/SimpleProcessDesignerV2/src/node'
|
||||
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' })
|
||||
const props = defineProps({
|
||||
id: String,
|
||||
|
|
@ -231,16 +243,16 @@ const rejectHandlerTypeEl = ref()
|
|||
const rejectHandlerType = ref()
|
||||
const returnNodeIdEl = ref()
|
||||
const returnNodeId = ref()
|
||||
const returnTaskList = ref([])
|
||||
const returnTaskList = ref<ReturnTask[]>([])
|
||||
|
||||
// 审批人为空时
|
||||
const assignEmptyHandlerTypeEl = ref()
|
||||
const assignEmptyHandlerType = 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 btnDisplayNameBlurEvent = (index: number) => {
|
||||
btnDisplayNameEdit.value[index] = false
|
||||
|
|
@ -250,7 +262,7 @@ const btnDisplayNameBlurEvent = (index: number) => {
|
|||
}
|
||||
|
||||
// 字段权限
|
||||
const fieldsPermissionEl = ref([])
|
||||
const fieldsPermissionEl = ref<any[]>([])
|
||||
const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission(
|
||||
FieldPermissionType.READ
|
||||
)
|
||||
|
|
@ -451,18 +463,20 @@ watch(
|
|||
{ immediate: true }
|
||||
)
|
||||
|
||||
function findAllPredecessorsExcludingStart(elementId, modeler) {
|
||||
function findAllPredecessorsExcludingStart(elementId: string, modeler: any) {
|
||||
const elementRegistry = modeler.get('elementRegistry')
|
||||
const allConnections = elementRegistry.filter((element) => element.type === 'bpmn:SequenceFlow')
|
||||
const predecessors = new Set() // 使用 Set 来避免重复节点
|
||||
const visited = new Set() // 用于记录已访问的节点
|
||||
const allConnections = elementRegistry.filter(
|
||||
(element: BpmnElement) => element.type === 'bpmn:SequenceFlow'
|
||||
)
|
||||
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'
|
||||
}
|
||||
|
||||
function findPredecessorsRecursively(element) {
|
||||
function findPredecessorsRecursively(element: BpmnElement) {
|
||||
// 如果该节点已经访问过,直接返回,避免循环
|
||||
if (visited.has(element)) {
|
||||
return
|
||||
|
|
@ -472,10 +486,15 @@ function findAllPredecessorsExcludingStart(elementId, modeler) {
|
|||
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 // 获取前置节点
|
||||
if (!source) {
|
||||
return
|
||||
}
|
||||
|
||||
// 只添加不是开始事件的前置节点
|
||||
if (!isStartEvent(source)) {
|
||||
|
|
@ -491,7 +510,7 @@ function findAllPredecessorsExcludingStart(elementId, modeler) {
|
|||
findPredecessorsRecursively(targetElement)
|
||||
}
|
||||
|
||||
return Array.from(predecessors) // 返回前置节点数组
|
||||
return Array.from(predecessors) as ReturnTask[] // 返回前置节点数组
|
||||
}
|
||||
|
||||
function useButtonsSetting() {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ const props = defineProps({
|
|||
})
|
||||
const prefix = inject('prefix')
|
||||
|
||||
const formKey = ref(undefined)
|
||||
const formKey = ref<number | undefined>()
|
||||
const bpmnELement = ref()
|
||||
const elExtensionElements = ref()
|
||||
const formData = ref()
|
||||
|
|
@ -282,10 +282,10 @@ const updateElementExtensions = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const formList = ref([]) // 流程表单的下拉框的数据
|
||||
const formList = ref<Array<{ id: number; name: string }>>([]) // 流程表单的下拉框的数据
|
||||
onMounted(async () => {
|
||||
formList.value = await FormApi.getFormSimpleList()
|
||||
formKey.value = parseInt(formKey.value)
|
||||
formKey.value = formKey.value != null ? Number(formKey.value) : undefined
|
||||
})
|
||||
|
||||
watch(
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ const getList = async () => {
|
|||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
const emit = defineEmits(['success', 'select']) // 定义 success/select 事件,用于操作成功后的回调
|
||||
const select = async (row: ProcessListenerVO) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ const props = defineProps({
|
|||
const prefix = inject('prefix')
|
||||
const loopCharacteristics = ref('')
|
||||
const loopInstanceForm = ref<any>({})
|
||||
const bpmnElement = ref(null)
|
||||
const multiLoopInstance = ref(null)
|
||||
const bpmnElement = ref<any | null>(null)
|
||||
const multiLoopInstance = ref<any | null>(null)
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
const changeLoopCharacteristicsType = (type) => {
|
||||
|
|
@ -261,7 +261,7 @@ const approveMethod = ref()
|
|||
const approveRatio = ref(100)
|
||||
const otherExtensions = ref()
|
||||
const getElementLoopNew = () => {
|
||||
if (props.type === 'UserTask') {
|
||||
if (props.type === 'UserTask' && bpmnElement.value) {
|
||||
const extensionElements =
|
||||
bpmnElement.value.businessObject?.extensionElements ??
|
||||
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
|
||||
|
|
@ -286,6 +286,9 @@ const onApproveRatioChange = () => {
|
|||
updateLoopCharacteristics()
|
||||
}
|
||||
const updateLoopCharacteristics = () => {
|
||||
if (!bpmnElement.value) {
|
||||
return
|
||||
}
|
||||
// 根据ApproveMethod生成multiInstanceLoopCharacteristics节点
|
||||
if (approveMethod.value === ApproveMethodType.RANDOM_SELECT_ONE_APPROVE) {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
|
|
@ -334,9 +337,11 @@ const updateLoopCharacteristics = () => {
|
|||
}
|
||||
)
|
||||
}
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
loopCharacteristics: toRaw(multiLoopInstance.value)
|
||||
})
|
||||
if (multiLoopInstance.value) {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
loopCharacteristics: toRaw(multiLoopInstance.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 添加ApproveMethod到ExtensionElements
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ const getList = async () => {
|
|||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
const emit = defineEmits(['success', 'select']) // 定义 success/select 事件,用于操作成功后的回调
|
||||
const select = async (row: ProcessExpressionVO) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
|
|
|
|||
|
|
@ -233,7 +233,13 @@ const props = defineProps({
|
|||
type: String
|
||||
})
|
||||
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, // 分配规则
|
||||
candidateParam: [], // 分配选项
|
||||
skipExpression: '' // 跳过表达式
|
||||
|
|
@ -405,13 +411,6 @@ const updateElementTask = () => {
|
|||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
extensionElements: extensions
|
||||
})
|
||||
|
||||
// 改用通过extensionElements来存储数据
|
||||
return
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
candidateStrategy: userTaskForm.value.candidateStrategy,
|
||||
candidateParam: userTaskForm.value.candidateParam.join(',')
|
||||
})
|
||||
}
|
||||
|
||||
const updateSkipExpression = () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue