Skip to content

Commit d32a9a3

Browse files
committed
Merge branch 'feature/bpm' of https://github.com/yudaocode/yudao-ui-admin-vue3 into feature/bpm
# Conflicts: # src/views/bpm/simple/SimpleModelDesign.vue
2 parents f1ac8ba + 45cf482 commit d32a9a3

File tree

13 files changed

+172
-731
lines changed

13 files changed

+172
-731
lines changed

src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue

Lines changed: 9 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ defineOptions({
4040
name: 'SimpleProcessDesigner'
4141
})
4242
43-
const emits = defineEmits(['success', 'init-finished']) // 保存成功事件
43+
const emits = defineEmits(['success']) // 保存成功事件
4444
4545
const props = defineProps({
4646
modelId: {
@@ -59,13 +59,12 @@ const props = defineProps({
5959
startUserIds: {
6060
type: Array,
6161
required: false
62-
},
63-
value: {
64-
type: [String, Object],
65-
required: false
6662
}
6763
})
6864
65+
const processData = inject('processData') as Ref
66+
67+
6968
const loading = ref(false)
7069
const formFields = ref<string[]>([])
7170
const formType = ref(20)
@@ -76,9 +75,6 @@ const deptOptions = ref<DeptApi.DeptVO[]>([]) // 部门列表
7675
const deptTreeOptions = ref()
7776
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
7877
79-
// 添加当前值的引用
80-
const currentValue = ref<SimpleFlowNode | undefined>()
81-
8278
provide('formFields', formFields)
8379
provide('formType', formType)
8480
provide('roleList', roleOptions)
@@ -88,7 +84,8 @@ provide('deptList', deptOptions)
8884
provide('userGroupList', userGroupOptions)
8985
provide('deptTree', deptTreeOptions)
9086
provide('startUserIds', props.startUserIds)
91-
87+
provide('tasks', [])
88+
provide('processInstance', {})
9289
const message = useMessage() // 国际化
9390
const processNodeTree = ref<SimpleFlowNode | undefined>()
9491
provide('processNodeTree', processNodeTree)
@@ -113,70 +110,14 @@ const updateModel = () => {
113110
}
114111
}
115112
116-
// 加载流程数据
117-
const loadProcessData = async (data: any) => {
118-
try {
119-
if (data) {
120-
const parsedData = typeof data === 'string' ? JSON.parse(data) : data
121-
processNodeTree.value = parsedData
122-
currentValue.value = parsedData
123-
// 确保数据加载后刷新视图
124-
await nextTick()
125-
if (simpleProcessModelRef.value?.refresh) {
126-
await simpleProcessModelRef.value.refresh()
127-
}
128-
}
129-
} catch (error) {
130-
console.error('加载流程数据失败:', error)
131-
}
132-
}
133-
134-
// 监听属性变化
135-
watch(
136-
() => props.value,
137-
async (newValue, oldValue) => {
138-
if (newValue && newValue !== oldValue) {
139-
await loadProcessData(newValue)
140-
}
141-
},
142-
{ immediate: true, deep: true }
143-
)
144-
145-
// 监听流程节点树变化,自动保存
146-
watch(
147-
() => processNodeTree.value,
148-
async (newValue, oldValue) => {
149-
if (newValue && oldValue && JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
150-
await saveSimpleFlowModel(newValue)
151-
}
152-
},
153-
{ deep: true }
154-
)
155113
156114
const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
157115
if (!simpleModelNode) {
158116
return
159117
}
160118
161-
// 校验节点
162-
errorNodes = []
163-
validateNode(simpleModelNode, errorNodes)
164-
if (errorNodes.length > 0) {
165-
errorDialogVisible.value = true
166-
return
167-
}
168-
169119
try {
170-
if (props.modelId) {
171-
// 编辑模式
172-
const data = {
173-
id: props.modelId,
174-
simpleModel: simpleModelNode
175-
}
176-
await updateBpmSimpleModel(data)
177-
}
178-
// 无论是编辑还是新建模式,都更新当前值并触发事件
179-
currentValue.value = simpleModelNode
120+
processData.value = simpleModelNode
180121
emits('success', simpleModelNode)
181122
} catch (error) {
182123
console.error('保存失败:', error)
@@ -247,61 +188,20 @@ onMounted(async () => {
247188
deptTreeOptions.value = handleTree(deptOptions.value as DeptApi.DeptVO[], 'id')
248189
// 获取用户组列表
249190
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
250-
251191
// 加载流程数据
252-
if (props.modelId) {
253-
// 获取 SIMPLE 设计器模型
254-
const result = await getBpmSimpleModel(props.modelId)
255-
if (result) {
256-
await loadProcessData(result)
257-
} else {
258-
updateModel()
259-
}
260-
} else if (props.value) {
261-
await loadProcessData(props.value)
192+
if (processData.value) {
193+
processNodeTree.value = processData?.value
262194
} else {
263195
updateModel()
264196
}
265197
} finally {
266198
loading.value = false
267-
emits('init-finished')
268199
}
269200
})
270201
271202
const simpleProcessModelRef = ref()
272203
273-
/** 获取当前流程数据 */
274-
const getCurrentFlowData = async () => {
275-
try {
276-
if (simpleProcessModelRef.value) {
277-
const data = await simpleProcessModelRef.value.getCurrentFlowData()
278-
if (data) {
279-
currentValue.value = data
280-
return data
281-
}
282-
}
283-
return currentValue.value
284-
} catch (error) {
285-
console.error('获取流程数据失败:', error)
286-
return currentValue.value
287-
}
288-
}
289-
290-
// 刷新方法
291-
const refresh = async () => {
292-
try {
293-
if (currentValue.value) {
294-
await loadProcessData(currentValue.value)
295-
}
296-
} catch (error) {
297-
console.error('刷新失败:', error)
298-
}
299-
}
300204
301205
defineExpose({
302-
getCurrentFlowData,
303-
updateModel,
304-
loadProcessData,
305-
refresh
306206
})
307207
</script>

src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,31 @@
33
<div class="position-absolute top-0px right-0px bg-#fff">
44
<el-row type="flex" justify="end">
55
<el-button-group key="scale-control" size="default">
6+
<el-button size="default" @click="exportJson()"><Icon icon="ep:download" />导出</el-button>
7+
<el-button size="default" @click="importJson()"><Icon icon="ep:upload" />导入</el-button>
8+
<!-- 用于打开本地文件-->
9+
<input
10+
type="file"
11+
id="files"
12+
ref="refFile"
13+
style="display: none"
14+
accept=".json"
15+
@change="importLocalFile"
16+
/>
617
<el-button size="default" :icon="ScaleToOriginal" @click="processReZoom()" />
718
<el-button size="default" :plain="true" :icon="ZoomOut" @click="zoomOut()" />
819
<el-button size="default" class="w-80px"> {{ scaleValue }}% </el-button>
920
<el-button size="default" :plain="true" :icon="ZoomIn" @click="zoomIn()" />
1021
</el-button-group>
22+
<!-- <el-button-->
23+
<!-- v-if="!readonly"-->
24+
<!-- size="default"-->
25+
<!-- class="ml-4px"-->
26+
<!-- type="primary"-->
27+
<!-- :icon="Select"-->
28+
<!-- @click="saveSimpleFlowModel"-->
29+
<!-- >保存模型</el-button-->
30+
<!-- >-->
1131
</el-row>
1232
</div>
1333
<div class="simple-process-model" :style="`transform: scale(${scaleValue / 100});`">
@@ -33,7 +53,8 @@
3353
import ProcessNodeTree from './ProcessNodeTree.vue'
3454
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts'
3555
import { useWatchNode } from './node'
36-
import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
56+
import { ZoomOut, ZoomIn, ScaleToOriginal, Select } from '@element-plus/icons-vue'
57+
import { isString } from '@/utils/is'
3758
3859
defineOptions({
3960
name: 'SimpleProcessModel'
@@ -85,6 +106,16 @@ const processReZoom = () => {
85106
const errorDialogVisible = ref(false)
86107
let errorNodes: SimpleFlowNode[] = []
87108
109+
const saveSimpleFlowModel = async () => {
110+
errorNodes = []
111+
validateNode(processNodeTree.value, errorNodes)
112+
if (errorNodes.length > 0) {
113+
errorDialogVisible.value = true
114+
return
115+
}
116+
emits('save', processNodeTree.value)
117+
}
118+
88119
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
89120
const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
90121
if (node) {
@@ -143,6 +174,36 @@ const getCurrentFlowData = async () => {
143174
defineExpose({
144175
getCurrentFlowData
145176
})
177+
178+
const exportJson = () => {
179+
const blob = new Blob([JSON.stringify(processNodeTree.value)]);
180+
const tempLink = document.createElement('a'); // 创建a标签
181+
const href = window.URL.createObjectURL(blob); // 创建下载的链接
182+
//filename
183+
const fileName = `model.json`;
184+
tempLink.href = href;
185+
tempLink.target = '_blank';
186+
tempLink.download = fileName;
187+
document.body.appendChild(tempLink);
188+
tempLink.click(); // 点击下载
189+
document.body.removeChild(tempLink); // 下载完成移除元素
190+
window.URL.revokeObjectURL(href); // 释放掉blob对象
191+
}
192+
const importJson = () => {
193+
refFile.value.click()
194+
}
195+
const refFile = ref()
196+
// 加载本地文件
197+
const importLocalFile = () => {
198+
const file = refFile.value.files[0]
199+
const reader = new FileReader()
200+
reader.readAsText(file)
201+
reader.onload = function () {
202+
if (isString(this.result)) {
203+
processNodeTree.value = JSON.parse(this.result)
204+
}
205+
}
206+
}
146207
</script>
147208

148209
<style lang="scss" scoped></style>

src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -308,28 +308,6 @@ const props = defineProps({
308308
}
309309
})
310310
311-
// 监听value变化,重新加载流程图
312-
watch(
313-
() => props.value,
314-
(newValue) => {
315-
if (newValue && bpmnModeler) {
316-
createNewDiagram(newValue)
317-
}
318-
},
319-
{ immediate: true }
320-
)
321-
322-
// 监听processId和processName变化
323-
watch(
324-
[() => props.processId, () => props.processName],
325-
([newId, newName]) => {
326-
if (newId && newName && !props.value) {
327-
createNewDiagram(null)
328-
}
329-
},
330-
{ immediate: true }
331-
)
332-
333311
provide('configGlobal', props)
334312
let bpmnModeler: any = null
335313
const defaultZoom = ref(1)
@@ -480,6 +458,7 @@ const initModelListeners = () => {
480458
emit('commandStack-changed', event)
481459
emit('input', xml)
482460
emit('change', xml)
461+
emit('save', xml)
483462
} catch (e: any) {
484463
console.error(`[Process Designer Warn]: ${e.message || e}`)
485464
}

src/layout/components/TagsView/src/TagsView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ const move = (to: number) => {
243243
start()
244244
}
245245
246-
onMounted(() => {
246+
onBeforeMount(() => {
247247
initTags()
248248
addTags()
249249
})

src/router/modules/remaining.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
344344
}
345345
},
346346
{
347-
path: 'manager/model/update/:id',
347+
path: 'manager/model/:type/:id',
348348
component: () => import('@/views/bpm/model/form/index.vue'),
349349
name: 'BpmModelUpdate',
350350
meta: {

src/views/bpm/model/CategoryDraggableModel.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@
163163
>
164164
修改
165165
</el-button>
166+
<el-button
167+
link
168+
type="primary"
169+
@click="openModelForm('copy', scope.row.id)"
170+
v-hasPermi="['bpm:model:update']"
171+
:disabled="!isManagerUser(scope.row)"
172+
>
173+
复制
174+
</el-button>
166175
<el-button
167176
link
168177
class="!ml-5px"
@@ -473,7 +482,7 @@ const openModelForm = (type: string, id?: number) => {
473482
} else {
474483
push({
475484
name: 'BpmModelUpdate',
476-
params: { id }
485+
params: { id, type }
477486
})
478487
}
479488
}

0 commit comments

Comments
 (0)