Merge branch 'feature/bpm' of https://github.com/yudaocode/yudao-ui-admin-vue3 into feature/bpm
# Conflicts: # src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue # src/views/bpm/model/editor/index.vue
This commit is contained in:
@@ -38,12 +38,21 @@ import * as UserGroupApi from '@/api/bpm/userGroup'
|
||||
defineOptions({
|
||||
name: 'SimpleProcessDesigner'
|
||||
})
|
||||
|
||||
const emits = defineEmits(['success']) // 保存成功事件
|
||||
|
||||
const props = defineProps({
|
||||
modelId: {
|
||||
type: String,
|
||||
required: true
|
||||
required: false
|
||||
},
|
||||
modelKey: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
modelName: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
})
|
||||
|
||||
@@ -69,6 +78,33 @@ const message = useMessage() // 国际化
|
||||
const processNodeTree = ref<SimpleFlowNode | undefined>()
|
||||
const errorDialogVisible = ref(false)
|
||||
let errorNodes: SimpleFlowNode[] = []
|
||||
|
||||
// 添加更新模型的方法
|
||||
const updateModel = (key?: string, name?: string) => {
|
||||
if (!processNodeTree.value) {
|
||||
processNodeTree.value = {
|
||||
name: name || '发起人',
|
||||
type: NodeType.START_USER_NODE,
|
||||
id: NodeId.START_USER_NODE_ID,
|
||||
childNode: {
|
||||
id: NodeId.END_EVENT_NODE_ID,
|
||||
name: '结束',
|
||||
type: NodeType.END_EVENT_NODE
|
||||
}
|
||||
}
|
||||
} else if (name) {
|
||||
// 更新现有模型的名称
|
||||
processNodeTree.value.name = name
|
||||
}
|
||||
}
|
||||
|
||||
// 监听属性变化
|
||||
watch([() => props.modelKey, () => props.modelName], ([newKey, newName]) => {
|
||||
if (!props.modelId && newKey && newName) {
|
||||
updateModel(newKey, newName)
|
||||
}
|
||||
}, { immediate: true, deep: true })
|
||||
|
||||
const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
|
||||
if (!simpleModelNode) {
|
||||
message.error('模型数据为空')
|
||||
@@ -76,21 +112,28 @@ const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
|
||||
}
|
||||
try {
|
||||
loading.value = true
|
||||
const data = {
|
||||
id: props.modelId,
|
||||
simpleModel: simpleModelNode
|
||||
}
|
||||
const result = await updateBpmSimpleModel(data)
|
||||
if (result) {
|
||||
message.success('修改成功')
|
||||
emits('success')
|
||||
if (props.modelId) {
|
||||
// 编辑模式
|
||||
const data = {
|
||||
id: props.modelId,
|
||||
simpleModel: simpleModelNode
|
||||
}
|
||||
const result = await updateBpmSimpleModel(data)
|
||||
if (result) {
|
||||
message.success('修改成功')
|
||||
emits('success')
|
||||
} else {
|
||||
message.alert('修改失败')
|
||||
}
|
||||
} else {
|
||||
message.alert('修改失败')
|
||||
// 新建模式,直接返回数据
|
||||
emits('success', simpleModelNode)
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
|
||||
const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
|
||||
if (node) {
|
||||
@@ -134,12 +177,14 @@ onMounted(async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
// 获取表单字段
|
||||
const bpmnModel = await getModel(props.modelId)
|
||||
if (bpmnModel) {
|
||||
formType.value = bpmnModel.formType
|
||||
if (formType.value === 10) {
|
||||
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
|
||||
formFields.value = bpmnForm?.fields
|
||||
if (props.modelId) {
|
||||
const bpmnModel = await getModel(props.modelId)
|
||||
if (bpmnModel) {
|
||||
formType.value = bpmnModel.formType
|
||||
if (formType.value === 10) {
|
||||
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
|
||||
formFields.value = bpmnForm?.fields
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获得角色列表
|
||||
@@ -155,14 +200,18 @@ onMounted(async () => {
|
||||
// 获取用户组列表
|
||||
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
|
||||
|
||||
//获取 SIMPLE 设计器模型
|
||||
const result = await getBpmSimpleModel(props.modelId)
|
||||
if (result) {
|
||||
processNodeTree.value = result
|
||||
} else {
|
||||
// 初始值
|
||||
if (props.modelId) {
|
||||
//获取 SIMPLE 设计器模型
|
||||
const result = await getBpmSimpleModel(props.modelId)
|
||||
if (result) {
|
||||
processNodeTree.value = result
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有现有模型,创建初始模型
|
||||
if (!processNodeTree.value) {
|
||||
processNodeTree.value = {
|
||||
name: '发起人',
|
||||
name: props.modelName || '发起人',
|
||||
type: NodeType.START_USER_NODE,
|
||||
id: NodeId.START_USER_NODE_ID,
|
||||
childNode: {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { defaultProps, findTreeNode, handleTree } from '@/utils/tree'
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import * as DeptApi from '@/api/system/dept'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
|
||||
@@ -50,6 +50,7 @@ const emit = defineEmits<{
|
||||
const { t } = useI18n() // 国际
|
||||
const message = useMessage() // 消息弹窗
|
||||
const deptTree = ref<Tree[]>([]) // 部门树形结构化
|
||||
const deptList = ref<any[]>([]) // 保存扁平化的部门列表数据
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 所有用户列表
|
||||
const filteredUserList = ref<UserApi.UserVO[]>([]) // 当前部门过滤后的用户列表
|
||||
const selectedUserIdList: any = ref([]) // 选中的用户列表
|
||||
@@ -79,7 +80,9 @@ const open = async (id: number, selectedList?: any[]) => {
|
||||
resetForm()
|
||||
|
||||
// 加载部门、用户列表
|
||||
deptTree.value = handleTree(await DeptApi.getSimpleDeptList())
|
||||
const deptData = await DeptApi.getSimpleDeptList()
|
||||
deptList.value = deptData // 保存扁平结构的部门数据
|
||||
deptTree.value = handleTree(deptData) // 转换成树形结构
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
|
||||
// 初始状态下,过滤列表等于所有用户列表
|
||||
@@ -88,16 +91,31 @@ const open = async (id: number, selectedList?: any[]) => {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 获取指定部门及其所有子部门的ID列表 */
|
||||
const getChildDeptIds = (deptId: number, deptList: any[]): number[] => {
|
||||
const ids = [deptId]
|
||||
const children = deptList.filter((dept) => dept.parentId === deptId)
|
||||
children.forEach((child) => {
|
||||
ids.push(...getChildDeptIds(child.id, deptList))
|
||||
})
|
||||
return ids
|
||||
}
|
||||
|
||||
/** 获取部门过滤后的用户列表 */
|
||||
const getUserList = async (deptId?: number) => {
|
||||
const filterUserList = async (deptId?: number) => {
|
||||
formLoading.value = true
|
||||
try {
|
||||
// @ts-ignore
|
||||
// TODO @芋艿:替换到 simple List 暂不支持 deptId 过滤
|
||||
// TODO @Zqqq:这个,可以使用前端过滤么?通过 deptList 获取到 deptId 子节点,然后去 userList
|
||||
const data = await UserApi.getUserPage({ pageSize: 100, pageNo: 1, deptId })
|
||||
// 更新过滤后的用户列表
|
||||
filteredUserList.value = data.list
|
||||
if (!deptId) {
|
||||
// 如果没有选择部门,显示所有用户
|
||||
filteredUserList.value = [...userList.value]
|
||||
return
|
||||
}
|
||||
|
||||
// 直接使用已保存的部门列表数据进行过滤
|
||||
const deptIds = getChildDeptIds(deptId, deptList.value)
|
||||
|
||||
// 过滤出这些部门下的用户
|
||||
filteredUserList.value = userList.value.filter((user) => deptIds.includes(user.deptId))
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
@@ -121,6 +139,7 @@ const submitForm = async () => {
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
deptTree.value = []
|
||||
deptList.value = []
|
||||
userList.value = []
|
||||
filteredUserList.value = []
|
||||
selectedUserIdList.value = []
|
||||
@@ -128,7 +147,7 @@ const resetForm = () => {
|
||||
|
||||
/** 处理部门被点击 */
|
||||
const handleNodeClick = (row: { [key: string]: any }) => {
|
||||
getUserList(row.id)
|
||||
filterUserList(row.id)
|
||||
}
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="process-panel__container" :style="{ width: `${width}px`, maxHeight: '700px' }">
|
||||
<el-collapse v-model="activeTab">
|
||||
<div class="process-panel__container" :style="{ width: `${width}px` }">
|
||||
<el-collapse v-model="activeTab" v-if="isReady">
|
||||
<el-collapse-item name="base">
|
||||
<!-- class="panel-tab__title" -->
|
||||
<template #title>
|
||||
@@ -119,24 +119,16 @@ const elementBusinessObject = ref<any>({}) // 元素 businessObject 镜像,提
|
||||
const conditionFormVisible = ref(false) // 流转条件设置
|
||||
const formVisible = ref(false) // 表单配置
|
||||
const bpmnElement = ref()
|
||||
const isReady = ref(false)
|
||||
|
||||
provide('prefix', props.prefix)
|
||||
provide('width', props.width)
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
// 监听 props.bpmnModeler 然后 initModels
|
||||
const unwatchBpmn = watch(
|
||||
() => props.bpmnModeler,
|
||||
() => {
|
||||
// 避免加载时 流程图 并未加载完成
|
||||
if (!props.bpmnModeler) {
|
||||
console.log('缺少props.bpmnModeler')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('props.bpmnModeler 有值了!!!')
|
||||
const w = window as any
|
||||
w.bpmnInstances = {
|
||||
// 初始化 bpmnInstances
|
||||
const initBpmnInstances = () => {
|
||||
if (!props.bpmnModeler) return false
|
||||
try {
|
||||
const instances = {
|
||||
modeler: props.bpmnModeler,
|
||||
modeling: props.bpmnModeler.get('modeling'),
|
||||
moddle: props.bpmnModeler.get('moddle'),
|
||||
@@ -148,9 +140,45 @@ const unwatchBpmn = watch(
|
||||
selection: props.bpmnModeler.get('selection')
|
||||
}
|
||||
|
||||
console.log(bpmnInstances(), 'window.bpmnInstances')
|
||||
getActiveElement()
|
||||
unwatchBpmn()
|
||||
// 检查所有实例是否都存在
|
||||
const allInstancesExist = Object.values(instances).every(instance => instance)
|
||||
if (allInstancesExist) {
|
||||
const w = window as any
|
||||
w.bpmnInstances = instances
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (error) {
|
||||
console.error('初始化 bpmnInstances 失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
// 监听 props.bpmnModeler 然后 initModels
|
||||
const unwatchBpmn = watch(
|
||||
() => props.bpmnModeler,
|
||||
async () => {
|
||||
// 避免加载时 流程图 并未加载完成
|
||||
if (!props.bpmnModeler) {
|
||||
console.log('缺少props.bpmnModeler')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 等待 modeler 初始化完成
|
||||
await nextTick()
|
||||
if (initBpmnInstances()) {
|
||||
isReady.value = true
|
||||
await nextTick()
|
||||
getActiveElement()
|
||||
} else {
|
||||
console.error('modeler 实例未完全初始化')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
@@ -158,6 +186,8 @@ const unwatchBpmn = watch(
|
||||
)
|
||||
|
||||
const getActiveElement = () => {
|
||||
if (!isReady.value || !props.bpmnModeler) return
|
||||
|
||||
// 初始第一个选中元素 bpmn:Process
|
||||
initFormOnChanged(null)
|
||||
props.bpmnModeler.on('import.done', (e) => {
|
||||
@@ -175,8 +205,11 @@ const getActiveElement = () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
const initFormOnChanged = (element) => {
|
||||
if (!isReady.value || !bpmnInstances()) return
|
||||
|
||||
let activatedElement = element
|
||||
if (!activatedElement) {
|
||||
activatedElement =
|
||||
@@ -184,32 +217,36 @@ const initFormOnChanged = (element) => {
|
||||
bpmnInstances().elementRegistry.find((el) => el.type === 'bpmn:Collaboration')
|
||||
}
|
||||
if (!activatedElement) return
|
||||
console.log(`
|
||||
----------
|
||||
select element changed:
|
||||
id: ${activatedElement.id}
|
||||
type: ${activatedElement.businessObject.$type}
|
||||
----------
|
||||
`)
|
||||
console.log('businessObject: ', activatedElement.businessObject)
|
||||
bpmnInstances().bpmnElement = activatedElement
|
||||
bpmnElement.value = activatedElement
|
||||
elementId.value = activatedElement.id
|
||||
elementType.value = activatedElement.type.split(':')[1] || ''
|
||||
elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
|
||||
conditionFormVisible.value = !!(
|
||||
elementType.value === 'SequenceFlow' &&
|
||||
activatedElement.source &&
|
||||
activatedElement.source.type.indexOf('StartEvent') === -1
|
||||
)
|
||||
formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
|
||||
|
||||
try {
|
||||
console.log(`
|
||||
----------
|
||||
select element changed:
|
||||
id: ${activatedElement.id}
|
||||
type: ${activatedElement.businessObject.$type}
|
||||
----------
|
||||
`)
|
||||
console.log('businessObject: ', activatedElement.businessObject)
|
||||
bpmnInstances().bpmnElement = activatedElement
|
||||
bpmnElement.value = activatedElement
|
||||
elementId.value = activatedElement.id
|
||||
elementType.value = activatedElement.type.split(':')[1] || ''
|
||||
elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
|
||||
conditionFormVisible.value = !!(
|
||||
elementType.value === 'SequenceFlow' &&
|
||||
activatedElement.source &&
|
||||
activatedElement.source.type.indexOf('StartEvent') === -1
|
||||
)
|
||||
formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
|
||||
} catch (error) {
|
||||
console.error('初始化表单数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
const w = window as any
|
||||
w.bpmnInstances = null
|
||||
console.log(props, 'props1')
|
||||
console.log(props.bpmnModeler, 'props.bpmnModeler1')
|
||||
isReady.value = false
|
||||
})
|
||||
|
||||
watch(
|
||||
|
||||
Reference in New Issue
Block a user