Skip to content

Commit 12f52b2

Browse files
authored
Merge pull request #98 from GoldenZqqq/feature/bpm
发起流程页面优化
2 parents a6f325b + a57840c commit 12f52b2

File tree

4 files changed

+442
-3
lines changed

4 files changed

+442
-3
lines changed

src/assets/svgs/bpm/finish.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
<template>
2+
<ContentWrap :bodyStyle="{ padding: '10px 20px 0' }">
3+
<div class="processInstance-wrap-main">
4+
<el-scrollbar>
5+
<div class="text-#878c93 h-15px">编号:{{ selectProcessDefinition.id }}</div>
6+
<el-divider class="!my-8px" />
7+
8+
<div class="flex items-center justify-between gap-5 mb-10px h-40px">
9+
<div class="text-26px font-bold mb-5px">{{ selectProcessDefinition.name }}</div>
10+
<el-button style="float: right" type="primary" @click="handleCancel">
11+
<Icon icon="ep:delete" /> 选择其它流程
12+
</el-button>
13+
</div>
14+
<!-- 中间主要内容tab栏 -->
15+
<el-tabs v-model="activeTab">
16+
<!-- 表单信息 -->
17+
<el-tab-pane label="表单填写" name="form">
18+
<div class="form-scroll-area">
19+
<el-scrollbar>
20+
<el-row>
21+
<el-col :span="17">
22+
<form-create
23+
:rule="detailForm.rule"
24+
v-model:api="fApi"
25+
v-model="detailForm.value"
26+
:option="detailForm.option"
27+
@submit="submitForm"
28+
>
29+
<template #type-startUserSelect>
30+
<el-col :span="24">
31+
<el-card class="mb-10px">
32+
<template #header>指定审批人</template>
33+
<el-form
34+
:model="startUserSelectAssignees"
35+
:rules="startUserSelectAssigneesFormRules"
36+
ref="startUserSelectAssigneesFormRef"
37+
>
38+
<el-form-item
39+
v-for="userTask in startUserSelectTasks"
40+
:key="userTask.id"
41+
:label="`任务【${userTask.name}】`"
42+
:prop="userTask.id"
43+
>
44+
<el-select
45+
v-model="startUserSelectAssignees[userTask.id]"
46+
multiple
47+
placeholder="请选择审批人"
48+
>
49+
<el-option
50+
v-for="user in userList"
51+
:key="user.id"
52+
:label="user.nickname"
53+
:value="user.id"
54+
/>
55+
</el-select>
56+
</el-form-item>
57+
</el-form>
58+
</el-card>
59+
</el-col>
60+
</template>
61+
</form-create>
62+
</el-col>
63+
64+
<el-col :span="6" :offset="1">
65+
<!-- 流程时间线 -->
66+
<ProcessInstanceTimeline
67+
ref="timelineRef"
68+
:approve-nodes="approveNodes"
69+
:show-status-icon="false"
70+
candidateField="candidateUserList"
71+
/>
72+
</el-col>
73+
</el-row>
74+
</el-scrollbar>
75+
</div>
76+
</el-tab-pane>
77+
<!-- 流程图 -->
78+
<el-tab-pane label="流程图" name="diagram">
79+
<div class="form-scroll-area">
80+
<!-- 流程图预览 -->
81+
<ProcessInstanceBpmnViewer :bpmn-xml="bpmnXML" />
82+
</div>
83+
</el-tab-pane>
84+
</el-tabs>
85+
86+
<!-- 底部操作栏 -->
87+
<div class="b-t-solid border-t-1px border-[var(--el-border-color)]">
88+
<!-- 操作栏按钮 -->
89+
<div
90+
v-if="activeTab === 'form'"
91+
class="h-50px bottom-10 text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
92+
>
93+
<el-button plain type="success" @click="submitForm">
94+
<Icon icon="ep:select" />&nbsp; 发起
95+
</el-button>
96+
<el-button plain type="danger" @click="handleCancel">
97+
<Icon icon="ep:close" />&nbsp; 取消
98+
</el-button>
99+
</div>
100+
</div>
101+
</el-scrollbar>
102+
</div>
103+
</ContentWrap>
104+
</template>
105+
<script lang="ts" setup>
106+
import { setConfAndFields2 } from '@/utils/formCreate'
107+
import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue'
108+
import ProcessInstanceTimeline from '../detail/ProcessInstanceTimeline.vue'
109+
import type { ApiAttrs } from '@form-create/element-ui/types/config'
110+
import { useTagsViewStore } from '@/store/modules/tagsView'
111+
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
112+
import * as DefinitionApi from '@/api/bpm/definition'
113+
import * as UserApi from '@/api/system/user'
114+
115+
defineOptions({ name: 'ProcessDefinitionDetail' })
116+
const props = defineProps<{
117+
selectProcessDefinition: any
118+
}>()
119+
const { push, currentRoute } = useRouter() // 路由
120+
const message = useMessage() // 消息弹窗
121+
const { delView } = useTagsViewStore() // 视图操作
122+
123+
const detailForm: any = ref({
124+
rule: [],
125+
option: {},
126+
value: {}
127+
}) // 流程表单详情
128+
const fApi = ref<ApiAttrs>()
129+
// 指定审批人
130+
const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref
131+
const startUserSelectTasks: any = ref([]) // 发起人需要选择审批人的用户任务列表
132+
const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
133+
const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules
134+
const userList = ref<any[]>([]) // 用户列表
135+
const bpmnXML: any = ref(null) // BPMN 数据
136+
/** 当前的Tab */
137+
const activeTab = ref('form')
138+
const emit = defineEmits(['cancel'])
139+
// 审批节点信息
140+
const approveNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([])
141+
142+
/** 设置表单信息、获取流程图数据 **/
143+
const initProcessInfo = async (row, formVariables?) => {
144+
// 重置指定审批人
145+
startUserSelectTasks.value = []
146+
startUserSelectAssignees.value = {}
147+
startUserSelectAssigneesFormRules.value = {}
148+
149+
// 情况一:流程表单
150+
if (row.formType == 10) {
151+
// 设置表单
152+
setConfAndFields2(detailForm, row.formConf, row.formFields, formVariables)
153+
await nextTick()
154+
fApi.value?.btn.show(false) // 隐藏提交按钮
155+
// 获取流程审批信息
156+
getApprovalDetail(row)
157+
158+
// 加载流程图
159+
const processDefinitionDetail = await DefinitionApi.getProcessDefinition(row.id)
160+
if (processDefinitionDetail) {
161+
bpmnXML.value = processDefinitionDetail.bpmnXml
162+
startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks
163+
164+
// 设置指定审批人
165+
if (startUserSelectTasks.value?.length > 0) {
166+
detailForm.value.rule.push({
167+
type: 'startUserSelect',
168+
props: {
169+
title: '指定审批人'
170+
}
171+
})
172+
// 设置校验规则
173+
for (const userTask of startUserSelectTasks.value) {
174+
startUserSelectAssignees.value[userTask.id] = []
175+
startUserSelectAssigneesFormRules.value[userTask.id] = [
176+
{ required: true, message: '请选择审批人', trigger: 'blur' }
177+
]
178+
}
179+
// 加载用户列表
180+
userList.value = await UserApi.getSimpleUserList()
181+
}
182+
}
183+
// 情况二:业务表单
184+
} else if (row.formCustomCreatePath) {
185+
await push({
186+
path: row.formCustomCreatePath
187+
})
188+
// 这里暂时无需加载流程图,因为跳出到另外个 Tab;
189+
}
190+
}
191+
192+
/** 获取审批详情 */
193+
const getApprovalDetail = async (row) => {
194+
try {
195+
const param = {
196+
processDefinitionId: row.id
197+
}
198+
const data = await ProcessInstanceApi.getApprovalDetail(param)
199+
if (!data) {
200+
message.error('查询不到审批详情信息!')
201+
return
202+
}
203+
// 获取审批节点,显示 Timeline 的数据
204+
approveNodes.value = data.approveNodes
205+
} finally {
206+
}
207+
}
208+
/** 提交按钮 */
209+
const submitForm = async (formData) => {
210+
if (!fApi.value || props.selectProcessDefinition) {
211+
return
212+
}
213+
// 如果有指定审批人,需要校验
214+
if (startUserSelectTasks.value?.length > 0) {
215+
await startUserSelectAssigneesFormRef.value.validate()
216+
}
217+
218+
// 提交请求
219+
fApi.value.btn.loading(true)
220+
try {
221+
await ProcessInstanceApi.createProcessInstance({
222+
processDefinitionId: props.selectProcessDefinition.id,
223+
variables: formData || detailForm.value.value,
224+
startUserSelectAssignees: startUserSelectAssignees.value
225+
})
226+
// 提示
227+
message.success('发起流程成功')
228+
// 跳转回去
229+
delView(unref(currentRoute))
230+
await push({
231+
name: 'BpmProcessInstanceMy'
232+
})
233+
} finally {
234+
fApi.value.btn.loading(false)
235+
}
236+
}
237+
238+
const handleCancel = () => {
239+
emit('cancel')
240+
}
241+
242+
defineExpose({ initProcessInfo })
243+
</script>
244+
245+
<style lang="scss" scoped>
246+
$wrap-padding-height: 20px;
247+
$wrap-margin-height: 15px;
248+
$button-height: 51px;
249+
$process-header-height: 194px;
250+
251+
.processInstance-wrap-main {
252+
height: calc(
253+
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px
254+
);
255+
max-height: calc(
256+
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px
257+
);
258+
overflow: auto;
259+
260+
.form-scroll-area {
261+
height: calc(
262+
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
263+
$process-header-height - 40px
264+
);
265+
max-height: calc(
266+
100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
267+
$process-header-height - 40px
268+
);
269+
overflow: auto;
270+
}
271+
}
272+
273+
.form-box {
274+
:deep(.el-card) {
275+
border: none;
276+
}
277+
}
278+
</style>

0 commit comments

Comments
 (0)