Skip to content

Commit 9685fbf

Browse files
authored
Merge pull request #111 from GoldenZqqq/feature/bpm
工作流模块改造优化
2 parents 24e1374 + 746aeaf commit 9685fbf

File tree

10 files changed

+1179
-161
lines changed

10 files changed

+1179
-161
lines changed

src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,21 @@ import * as UserGroupApi from '@/api/bpm/userGroup'
3838
defineOptions({
3939
name: 'SimpleProcessDesigner'
4040
})
41+
4142
const emits = defineEmits(['success']) // 保存成功事件
4243
4344
const props = defineProps({
4445
modelId: {
4546
type: String,
46-
required: true
47+
required: false
48+
},
49+
modelKey: {
50+
type: String,
51+
required: false
52+
},
53+
modelName: {
54+
type: String,
55+
required: false
4756
}
4857
})
4958
@@ -69,28 +78,62 @@ const message = useMessage() // 国际化
6978
const processNodeTree = ref<SimpleFlowNode | undefined>()
7079
const errorDialogVisible = ref(false)
7180
let errorNodes: SimpleFlowNode[] = []
81+
82+
// 添加更新模型的方法
83+
const updateModel = (key?: string, name?: string) => {
84+
if (!processNodeTree.value) {
85+
processNodeTree.value = {
86+
name: name || '发起人',
87+
type: NodeType.START_USER_NODE,
88+
id: NodeId.START_USER_NODE_ID,
89+
childNode: {
90+
id: NodeId.END_EVENT_NODE_ID,
91+
name: '结束',
92+
type: NodeType.END_EVENT_NODE
93+
}
94+
}
95+
} else if (name) {
96+
// 更新现有模型的名称
97+
processNodeTree.value.name = name
98+
}
99+
}
100+
101+
// 监听属性变化
102+
watch([() => props.modelKey, () => props.modelName], ([newKey, newName]) => {
103+
if (!props.modelId && newKey && newName) {
104+
updateModel(newKey, newName)
105+
}
106+
}, { immediate: true, deep: true })
107+
72108
const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
73109
if (!simpleModelNode) {
74110
message.error('模型数据为空')
75111
return
76112
}
77113
try {
78114
loading.value = true
79-
const data = {
80-
id: props.modelId,
81-
simpleModel: simpleModelNode
82-
}
83-
const result = await updateBpmSimpleModel(data)
84-
if (result) {
85-
message.success('修改成功')
86-
emits('success')
115+
if (props.modelId) {
116+
// 编辑模式
117+
const data = {
118+
id: props.modelId,
119+
simpleModel: simpleModelNode
120+
}
121+
const result = await updateBpmSimpleModel(data)
122+
if (result) {
123+
message.success('修改成功')
124+
emits('success')
125+
} else {
126+
message.alert('修改失败')
127+
}
87128
} else {
88-
message.alert('修改失败')
129+
// 新建模式,直接返回数据
130+
emits('success', simpleModelNode)
89131
}
90132
} finally {
91133
loading.value = false
92134
}
93135
}
136+
94137
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
95138
const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
96139
if (node) {
@@ -134,12 +177,14 @@ onMounted(async () => {
134177
try {
135178
loading.value = true
136179
// 获取表单字段
137-
const bpmnModel = await getModel(props.modelId)
138-
if (bpmnModel) {
139-
formType.value = bpmnModel.formType
140-
if (formType.value === 10) {
141-
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
142-
formFields.value = bpmnForm?.fields
180+
if (props.modelId) {
181+
const bpmnModel = await getModel(props.modelId)
182+
if (bpmnModel) {
183+
formType.value = bpmnModel.formType
184+
if (formType.value === 10) {
185+
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
186+
formFields.value = bpmnForm?.fields
187+
}
143188
}
144189
}
145190
// 获得角色列表
@@ -155,14 +200,18 @@ onMounted(async () => {
155200
// 获取用户组列表
156201
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
157202
158-
//获取 SIMPLE 设计器模型
159-
const result = await getBpmSimpleModel(props.modelId)
160-
if (result) {
161-
processNodeTree.value = result
162-
} else {
163-
// 初始值
203+
if (props.modelId) {
204+
//获取 SIMPLE 设计器模型
205+
const result = await getBpmSimpleModel(props.modelId)
206+
if (result) {
207+
processNodeTree.value = result
208+
}
209+
}
210+
211+
// 如果没有现有模型,创建初始模型
212+
if (!processNodeTree.value) {
164213
processNodeTree.value = {
165-
name: '发起人',
214+
name: props.modelName || '发起人',
166215
type: NodeType.START_USER_NODE,
167216
id: NodeId.START_USER_NODE_ID,
168217
childNode: {

src/components/UserSelectForm/index.vue

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
</Dialog>
4040
</template>
4141
<script lang="ts" setup>
42-
import { defaultProps, findTreeNode, handleTree } from '@/utils/tree'
42+
import { defaultProps, handleTree } from '@/utils/tree'
4343
import * as DeptApi from '@/api/system/dept'
4444
import * as UserApi from '@/api/system/user'
4545
@@ -50,6 +50,7 @@ const emit = defineEmits<{
5050
const { t } = useI18n() // 国际
5151
const message = useMessage() // 消息弹窗
5252
const deptTree = ref<Tree[]>([]) // 部门树形结构化
53+
const deptList = ref<any[]>([]) // 保存扁平化的部门列表数据
5354
const userList = ref<UserApi.UserVO[]>([]) // 所有用户列表
5455
const filteredUserList = ref<UserApi.UserVO[]>([]) // 当前部门过滤后的用户列表
5556
const selectedUserIdList: any = ref([]) // 选中的用户列表
@@ -79,7 +80,9 @@ const open = async (id: number, selectedList?: any[]) => {
7980
resetForm()
8081
8182
// 加载部门、用户列表
82-
deptTree.value = handleTree(await DeptApi.getSimpleDeptList())
83+
const deptData = await DeptApi.getSimpleDeptList()
84+
deptList.value = deptData // 保存扁平结构的部门数据
85+
deptTree.value = handleTree(deptData) // 转换成树形结构
8386
userList.value = await UserApi.getSimpleUserList()
8487
8588
// 初始状态下,过滤列表等于所有用户列表
@@ -88,16 +91,31 @@ const open = async (id: number, selectedList?: any[]) => {
8891
dialogVisible.value = true
8992
}
9093
94+
/** 获取指定部门及其所有子部门的ID列表 */
95+
const getChildDeptIds = (deptId: number, deptList: any[]): number[] => {
96+
const ids = [deptId]
97+
const children = deptList.filter((dept) => dept.parentId === deptId)
98+
children.forEach((child) => {
99+
ids.push(...getChildDeptIds(child.id, deptList))
100+
})
101+
return ids
102+
}
103+
91104
/** 获取部门过滤后的用户列表 */
92-
const getUserList = async (deptId?: number) => {
105+
const filterUserList = async (deptId?: number) => {
93106
formLoading.value = true
94107
try {
95-
// @ts-ignore
96-
// TODO @芋艿:替换到 simple List 暂不支持 deptId 过滤
97-
// TODO @Zqqq:这个,可以使用前端过滤么?通过 deptList 获取到 deptId 子节点,然后去 userList
98-
const data = await UserApi.getUserPage({ pageSize: 100, pageNo: 1, deptId })
99-
// 更新过滤后的用户列表
100-
filteredUserList.value = data.list
108+
if (!deptId) {
109+
// 如果没有选择部门,显示所有用户
110+
filteredUserList.value = [...userList.value]
111+
return
112+
}
113+
114+
// 直接使用已保存的部门列表数据进行过滤
115+
const deptIds = getChildDeptIds(deptId, deptList.value)
116+
117+
// 过滤出这些部门下的用户
118+
filteredUserList.value = userList.value.filter((user) => deptIds.includes(user.deptId))
101119
} finally {
102120
formLoading.value = false
103121
}
@@ -121,14 +139,15 @@ const submitForm = async () => {
121139
/** 重置表单 */
122140
const resetForm = () => {
123141
deptTree.value = []
142+
deptList.value = []
124143
userList.value = []
125144
filteredUserList.value = []
126145
selectedUserIdList.value = []
127146
}
128147
129148
/** 处理部门被点击 */
130149
const handleNodeClick = (row: { [key: string]: any }) => {
131-
getUserList(row.id)
150+
filterUserList(row.id)
132151
}
133152
134153
defineExpose({ open }) // 提供 open 方法,用于打开弹窗

src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="process-panel__container" :style="{ width: `${width}px` }">
3-
<el-collapse v-model="activeTab">
3+
<el-collapse v-model="activeTab" v-if="isReady">
44
<el-collapse-item name="base">
55
<!-- class="panel-tab__title" -->
66
<template #title>
@@ -108,24 +108,16 @@ const elementBusinessObject = ref<any>({}) // 元素 businessObject 镜像,提
108108
const conditionFormVisible = ref(false) // 流转条件设置
109109
const formVisible = ref(false) // 表单配置
110110
const bpmnElement = ref()
111+
const isReady = ref(false)
111112
112113
provide('prefix', props.prefix)
113114
provide('width', props.width)
114-
const bpmnInstances = () => (window as any)?.bpmnInstances
115-
116-
// 监听 props.bpmnModeler 然后 initModels
117-
const unwatchBpmn = watch(
118-
() => props.bpmnModeler,
119-
() => {
120-
// 避免加载时 流程图 并未加载完成
121-
if (!props.bpmnModeler) {
122-
console.log('缺少props.bpmnModeler')
123-
return
124-
}
125115
126-
console.log('props.bpmnModeler 有值了!!!')
127-
const w = window as any
128-
w.bpmnInstances = {
116+
// 初始化 bpmnInstances
117+
const initBpmnInstances = () => {
118+
if (!props.bpmnModeler) return false
119+
try {
120+
const instances = {
129121
modeler: props.bpmnModeler,
130122
modeling: props.bpmnModeler.get('modeling'),
131123
moddle: props.bpmnModeler.get('moddle'),
@@ -136,17 +128,55 @@ const unwatchBpmn = watch(
136128
replace: props.bpmnModeler.get('replace'),
137129
selection: props.bpmnModeler.get('selection')
138130
}
131+
132+
// 检查所有实例是否都存在
133+
const allInstancesExist = Object.values(instances).every(instance => instance)
134+
if (allInstancesExist) {
135+
const w = window as any
136+
w.bpmnInstances = instances
137+
return true
138+
}
139+
return false
140+
} catch (error) {
141+
console.error('初始化 bpmnInstances 失败:', error)
142+
return false
143+
}
144+
}
145+
146+
const bpmnInstances = () => (window as any)?.bpmnInstances
139147
140-
console.log(bpmnInstances(), 'window.bpmnInstances')
141-
getActiveElement()
142-
unwatchBpmn()
148+
// 监听 props.bpmnModeler 然后 initModels
149+
const unwatchBpmn = watch(
150+
() => props.bpmnModeler,
151+
async () => {
152+
// 避免加载时 流程图 并未加载完成
153+
if (!props.bpmnModeler) {
154+
console.log('缺少props.bpmnModeler')
155+
return
156+
}
157+
158+
try {
159+
// 等待 modeler 初始化完成
160+
await nextTick()
161+
if (initBpmnInstances()) {
162+
isReady.value = true
163+
await nextTick()
164+
getActiveElement()
165+
} else {
166+
console.error('modeler 实例未完全初始化')
167+
}
168+
} catch (error) {
169+
console.error('初始化失败:', error)
170+
}
143171
},
144172
{
145173
immediate: true
146174
}
147175
)
148176
149177
const getActiveElement = () => {
178+
if (!isReady.value || !props.bpmnModeler) return
179+
150180
// 初始第一个选中元素 bpmn:Process
151181
initFormOnChanged(null)
152182
props.bpmnModeler.on('import.done', (e) => {
@@ -164,41 +194,48 @@ const getActiveElement = () => {
164194
}
165195
})
166196
}
197+
167198
// 初始化数据
168199
const initFormOnChanged = (element) => {
200+
if (!isReady.value || !bpmnInstances()) return
201+
169202
let activatedElement = element
170203
if (!activatedElement) {
171204
activatedElement =
172205
bpmnInstances().elementRegistry.find((el) => el.type === 'bpmn:Process') ??
173206
bpmnInstances().elementRegistry.find((el) => el.type === 'bpmn:Collaboration')
174207
}
175208
if (!activatedElement) return
176-
console.log(`
177-
----------
178-
select element changed:
179-
id: ${activatedElement.id}
180-
type: ${activatedElement.businessObject.$type}
181-
----------
182-
`)
183-
console.log('businessObject: ', activatedElement.businessObject)
184-
bpmnInstances().bpmnElement = activatedElement
185-
bpmnElement.value = activatedElement
186-
elementId.value = activatedElement.id
187-
elementType.value = activatedElement.type.split(':')[1] || ''
188-
elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
189-
conditionFormVisible.value = !!(
190-
elementType.value === 'SequenceFlow' &&
191-
activatedElement.source &&
192-
activatedElement.source.type.indexOf('StartEvent') === -1
193-
)
194-
formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
209+
210+
try {
211+
console.log(`
212+
----------
213+
select element changed:
214+
id: ${activatedElement.id}
215+
type: ${activatedElement.businessObject.$type}
216+
----------
217+
`)
218+
console.log('businessObject: ', activatedElement.businessObject)
219+
bpmnInstances().bpmnElement = activatedElement
220+
bpmnElement.value = activatedElement
221+
elementId.value = activatedElement.id
222+
elementType.value = activatedElement.type.split(':')[1] || ''
223+
elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
224+
conditionFormVisible.value = !!(
225+
elementType.value === 'SequenceFlow' &&
226+
activatedElement.source &&
227+
activatedElement.source.type.indexOf('StartEvent') === -1
228+
)
229+
formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
230+
} catch (error) {
231+
console.error('初始化表单数据失败:', error)
232+
}
195233
}
196234
197235
onBeforeUnmount(() => {
198236
const w = window as any
199237
w.bpmnInstances = null
200-
console.log(props, 'props1')
201-
console.log(props.bpmnModeler, 'props.bpmnModeler1')
238+
isReady.value = false
202239
})
203240
204241
watch(

0 commit comments

Comments
 (0)