du
2025-04-16 8fa24d8deb65a81a234795c05c52a5dba46627cf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<template>
  <div class="simple-flow-canvas" v-loading="loading">
    <div class="simple-flow-container">
      <div class="top-area-container">
        <div class="top-actions">
          <div class="canvas-control">
            <span class="control-scale-group">
              <span class="control-scale-button"> <Icon icon="ep:plus" @click="zoomOut()" /></span>
              <span class="control-scale-label">{{ scaleValue }}%</span>
              <span class="control-scale-button"><Icon icon="ep:minus" @click="zoomIn()" /></span>
            </span>
          </div>
          <el-button type="primary" @click="saveSimpleFlowModel">保存</el-button>
          <!-- <el-button type="primary">全局设置</el-button> -->
        </div>
      </div>
      <div class="scale-container" :style="`transform: scale(${scaleValue / 100});`">
        <ProcessNodeTree v-if="processNodeTree" v-model:flow-node="processNodeTree" />
      </div>
    </div>
    <Dialog v-model="errorDialogVisible" title="保存失败" width="400" :fullscreen="false">
      <div class="mb-2">以下节点内容不完善,请修改后保存</div>
      <div
        class="mb-3 b-rounded-1 bg-gray-100 p-2 line-height-normal"
        v-for="(item, index) in errorNodes"
        :key="index"
      >
        {{ item.name }} : {{ NODE_DEFAULT_TEXT.get(item.type) }}
      </div>
      <template #footer>
        <el-button type="primary" @click="errorDialogVisible = false">知道了</el-button>
      </template>
    </Dialog>
  </div>
</template>
 
<script setup lang="ts">
import ProcessNodeTree from './ProcessNodeTree.vue'
import { updateBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple'
import { SimpleFlowNode, NodeType, NodeId, NODE_DEFAULT_TEXT } from './consts'
import { getModel } from '@/api/bpm/model'
import { getForm, FormVO } from '@/api/bpm/form'
import { handleTree } from '@/utils/tree'
import * as RoleApi from '@/api/system/role'
import * as DeptApi from '@/api/system/dept'
import * as PostApi from '@/api/system/post'
import * as UserApi from '@/api/system/user'
import * as UserGroupApi from '@/api/bpm/userGroup'
 
defineOptions({
  name: 'SimpleProcessDesigner'
})
const router = useRouter() // 路由
const props = defineProps({
  modelId: {
    type: String,
    required: true
  }
})
const loading = ref(true)
const formFields = ref<string[]>([])
const formType = ref(20)
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
const postOptions = ref<PostApi.PostVO[]>([]) // 岗位列表
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
const deptOptions = ref<DeptApi.DeptVO[]>([]) // 部门列表
const deptTreeOptions = ref()
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
provide('formFields', formFields)
provide('formType', formType)
provide('roleList', roleOptions)
provide('postList', postOptions)
provide('userList', userOptions)
provide('deptList', deptOptions)
provide('userGroupList', userGroupOptions)
provide('deptTree', deptTreeOptions)
 
const message = useMessage() // 国际化
const processNodeTree = ref<SimpleFlowNode | undefined>()
const errorDialogVisible = ref(false)
let errorNodes: SimpleFlowNode[] = []
const saveSimpleFlowModel = async () => {
  if (!props.modelId) {
    message.error('缺少模型 modelId 编号')
    return
  }
  errorNodes = []
  validateNode(processNodeTree.value, errorNodes)
  if (errorNodes.length > 0) {
    errorDialogVisible.value = true
    return
  }
  const data = {
    id: props.modelId,
    simpleModel: processNodeTree.value
  }
 
  const result = await updateBpmSimpleModel(data)
  if (result) {
    message.success('修改成功')
    close()
  } else {
    message.alert('修改失败')
  }
}
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
  if (node) {
    const { type, showText, conditionNodes } = node
    if (type == NodeType.END_EVENT_NODE) {
      return
    }
    if (type == NodeType.START_USER_NODE) {
      validateNode(node.childNode, errorNodes)
    }
 
    if (type === NodeType.USER_TASK_NODE) {
      if (!showText) {
        errorNodes.push(node)
      }
      validateNode(node.childNode, errorNodes)
    }
    if (type === NodeType.COPY_TASK_NODE) {
      if (!showText) {
        errorNodes.push(node)
      }
      validateNode(node.childNode, errorNodes)
    }
    if (type === NodeType.CONDITION_NODE) {
      if (!showText) {
        errorNodes.push(node)
      }
      validateNode(node.childNode, errorNodes)
    }
 
    if (type == NodeType.CONDITION_BRANCH_NODE) {
      conditionNodes?.forEach((item) => {
        validateNode(item, errorNodes)
      })
      validateNode(node.childNode, errorNodes)
    }
  }
}
 
const close = () => {
  router.push({ path: '/bpm/manager/model' })
}
let scaleValue = ref(100)
const MAX_SCALE_VALUE = 200
const MIN_SCALE_VALUE = 50
// 放大
const zoomOut = () => {
  if (scaleValue.value == MAX_SCALE_VALUE) {
    return
  }
  scaleValue.value += 10
}
// 缩小
const zoomIn = () => {
  if (scaleValue.value == MIN_SCALE_VALUE) {
    return
  }
  scaleValue.value -= 10
}
 
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
      }
    }
    // 获得角色列表
    roleOptions.value = await RoleApi.getSimpleRoleList()
    // 获得岗位列表
    postOptions.value = await PostApi.getSimplePostList()
    // 获得用户列表
    userOptions.value = await UserApi.getSimpleUserList()
    // 获得部门列表
    deptOptions.value = await DeptApi.getSimpleDeptList()
 
    deptTreeOptions.value = handleTree(deptOptions.value as DeptApi.DeptVO[], 'id')
    // 获取用户组列表
    userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
 
    // 获取 SIMPLE 设计器模型
    const result = await getBpmSimpleModel(props.modelId)
    if (result) {
      processNodeTree.value = result
    } else {
      // 初始值
      processNodeTree.value = {
        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
        }
      }
    }
  } finally {
    loading.value = false
  }
})
</script>