Skip to content

Commit 612fa4a

Browse files
committed
2 parents 0112e72 + 324217a commit 612fa4a

File tree

5 files changed

+341
-344
lines changed

5 files changed

+341
-344
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
<template>
2+
<el-affix target=".formCol" position="bottom" class="h-50px" v-if="runningTask?.id">
3+
<el-divider class="!mb-8px !mt-0" />
4+
<div
5+
class="pl-50px text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
6+
>
7+
<el-popover :visible="passVisible" placement="top-end" :width="500" trigger="click">
8+
<template #reference>
9+
<el-button plain type="success" @click="openPopover('1')">
10+
<Icon icon="ep:select" />&nbsp; 通过
11+
</el-button>
12+
</template>
13+
<div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
14+
<el-form
15+
label-position="top"
16+
class="mb-auto"
17+
ref="formRef"
18+
:model="auditForm"
19+
:rules="auditRule"
20+
label-width="100px"
21+
>
22+
<el-form-item v-if="processInstance && processInstance.startUser" label="流程发起人">
23+
{{ processInstance?.startUser.nickname }}
24+
<el-tag size="small" type="info" class="ml-8px">
25+
{{ processInstance?.startUser.deptName }}
26+
</el-tag>
27+
</el-form-item>
28+
<el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
29+
<template #header>
30+
<span class="el-icon-picture-outline">
31+
填写表单【{{ runningTask?.formName }}】
32+
</span>
33+
</template>
34+
<form-create
35+
v-model="approveForm.value"
36+
v-model:api="approveFormFApi"
37+
:option="approveForm.option"
38+
:rule="approveForm.rule"
39+
/>
40+
</el-card>
41+
<el-form-item label="审批建议" prop="reason">
42+
<el-input v-model="auditForm.reason" placeholder="请输入审批建议" type="textarea" />
43+
</el-form-item>
44+
<el-form-item label="抄送人" prop="copyUserIds">
45+
<el-select v-model="auditForm.copyUserIds" multiple placeholder="请选择抄送人">
46+
<el-option
47+
v-for="itemx in userOptions"
48+
:key="itemx.id"
49+
:label="itemx.nickname"
50+
:value="itemx.id"
51+
/>
52+
</el-select>
53+
</el-form-item>
54+
55+
<el-form-item>
56+
<el-button :disabled="formLoading" type="success" @click="handleAudit(true)">
57+
通过
58+
</el-button>
59+
<el-button @click="passVisible = false"> 取消 </el-button>
60+
</el-form-item>
61+
</el-form>
62+
</div>
63+
</el-popover>
64+
<el-popover :visible="rejectVisible" placement="top-end" :width="500" trigger="click">
65+
<template #reference>
66+
<el-button class="mr-20px" plain type="danger" @click="openPopover('2')">
67+
<Icon icon="ep:close" />&nbsp; 拒绝
68+
</el-button>
69+
</template>
70+
<div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
71+
<el-form
72+
label-position="top"
73+
class="mb-auto"
74+
ref="formRef"
75+
:model="auditForm"
76+
:rules="auditRule"
77+
label-width="100px"
78+
>
79+
<el-form-item v-if="processInstance && processInstance.startUser" label="流程发起人">
80+
{{ processInstance?.startUser.nickname }}
81+
<el-tag size="small" type="info" class="ml-8px">
82+
{{ processInstance?.startUser.deptName }}
83+
</el-tag>
84+
</el-form-item>
85+
<el-card v-if="runningTask.formId > 0" class="mb-15px !-mt-10px">
86+
<template #header>
87+
<span class="el-icon-picture-outline">
88+
填写表单【{{ runningTask?.formName }}】
89+
</span>
90+
</template>
91+
<form-create
92+
v-model="approveForm.value"
93+
v-model:api="approveFormFApi"
94+
:option="approveForm.option"
95+
:rule="approveForm.rule"
96+
/>
97+
</el-card>
98+
<el-form-item label="审批建议" prop="reason">
99+
<el-input v-model="auditForm.reason" placeholder="请输入审批建议" type="textarea" />
100+
</el-form-item>
101+
<el-form-item label="抄送人" prop="copyUserIds">
102+
<el-select v-model="auditForm.copyUserIds" multiple placeholder="请选择抄送人">
103+
<el-option
104+
v-for="itemx in userOptions"
105+
:key="itemx.id"
106+
:label="itemx.nickname"
107+
:value="itemx.id"
108+
/>
109+
</el-select>
110+
</el-form-item>
111+
112+
<el-form-item>
113+
<el-button :disabled="formLoading" type="danger" @click="handleAudit(false)">
114+
拒绝
115+
</el-button>
116+
<el-button @click="rejectVisible = false"> 取消 </el-button>
117+
</el-form-item>
118+
</el-form>
119+
</div>
120+
</el-popover>
121+
<div @click="handleSend"> <Icon :size="14" icon="svg-icon:send" />&nbsp;抄送 </div>
122+
<div @click="openTaskUpdateAssigneeForm">
123+
<Icon :size="14" icon="fa:share-square-o" />&nbsp;转交
124+
</div>
125+
<div @click="handleDelegate"> <Icon :size="14" icon="ep:position" />&nbsp;委派 </div>
126+
<div @click="handleSign"> <Icon :size="14" icon="ep:plus" />&nbsp;加签 </div>
127+
<div @click="handleBack"> <Icon :size="14" icon="fa:mail-reply" />&nbsp;退回 </div>
128+
</div>
129+
</el-affix>
130+
<!-- 弹窗:转派审批人 -->
131+
<TaskTransferForm ref="taskTransferFormRef" @success="getDetail" />
132+
<!-- 弹窗:回退节点 -->
133+
<TaskReturnForm ref="taskReturnFormRef" @success="getDetail" />
134+
<!-- 弹窗:委派,将任务委派给别人处理,处理完成后,会重新回到原审批人手中-->
135+
<TaskDelegateForm ref="taskDelegateForm" @success="getDetail" />
136+
<!-- 弹窗:加签,当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
137+
<TaskSignCreateForm ref="taskSignCreateFormRef" @success="getDetail" />
138+
</template>
139+
140+
<script lang="ts" setup>
141+
import { setConfAndFields2 } from '@/utils/formCreate'
142+
import { useUserStore } from '@/store/modules/user'
143+
import * as TaskApi from '@/api/bpm/task'
144+
import { propTypes } from '@/utils/propTypes'
145+
import TaskReturnForm from './dialog/TaskReturnForm.vue'
146+
import TaskDelegateForm from './dialog/TaskDelegateForm.vue'
147+
import TaskTransferForm from './dialog/TaskTransferForm.vue'
148+
import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue'
149+
import { isEmpty } from '@/utils/is'
150+
151+
defineOptions({ name: 'ProcessInstanceBtnConatiner' })
152+
153+
const userId = useUserStore().getUser.id // 当前登录的编号
154+
const message = useMessage() // 消息弹窗
155+
const { proxy } = getCurrentInstance() as any
156+
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
157+
defineProps({
158+
processInstance: propTypes.any, // 流程实例信息
159+
userOptions: propTypes.any
160+
})
161+
const formLoading = ref(false) // 表单加载中
162+
const passVisible = ref(false) // 是否显示
163+
const rejectVisible = ref(false) // 是否显示
164+
// ========== 审批信息 ==========
165+
const runningTask = ref<any>({}) // 运行中的任务
166+
const auditForm = ref<any>({}) // 审批任务的表单
167+
const approveForm = ref<any>({}) // 审批通过时,额外的补充信息
168+
const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
169+
const formRef = ref()
170+
const auditRule = reactive({
171+
reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
172+
})
173+
174+
/** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
175+
watch(
176+
() => approveFormFApi.value,
177+
(val) => {
178+
val?.btn?.show(false)
179+
val?.resetBtn?.show(false)
180+
},
181+
{
182+
deep: true
183+
}
184+
)
185+
/**
186+
* 设置 runningTasks 中的任务
187+
*/
188+
const loadRunningTask = (tasks) => {
189+
runningTask.value = {}
190+
auditForm.value = {}
191+
approveForm.value = {}
192+
approveFormFApi.value = {}
193+
tasks.forEach((task) => {
194+
if (!isEmpty(task.children)) {
195+
loadRunningTask(task.children)
196+
}
197+
// 2.1 只有待处理才需要
198+
if (task.status !== 1 && task.status !== 6) {
199+
return
200+
}
201+
// 2.2 自己不是处理人
202+
if (!task.assigneeUser || task.assigneeUser.id !== userId) {
203+
return
204+
}
205+
// 2.3 添加到处理任务
206+
runningTask.value = { ...task }
207+
auditForm.value = {
208+
reason: '',
209+
copyUserIds: []
210+
}
211+
212+
// 2.4 处理 approve 表单
213+
if (task.formId && task.formConf) {
214+
const tempApproveForm = {}
215+
setConfAndFields2(tempApproveForm, task.formConf, task.formFields, task.formVariables)
216+
approveForm.value = tempApproveForm
217+
} else {
218+
approveForm.value = {} // 占位,避免为空
219+
}
220+
})
221+
}
222+
223+
/** 处理审批通过和不通过的操作 */
224+
const handleAudit = async (pass) => {
225+
formLoading.value = true
226+
try {
227+
const auditFormRef = proxy.$refs['formRef']
228+
// 1.2 校验表单
229+
const elForm = unref(auditFormRef)
230+
if (!elForm) return
231+
const valid = await elForm.validate()
232+
if (!valid) return
233+
234+
// 2.1 提交审批
235+
const data = {
236+
id: runningTask.value.id,
237+
reason: auditForm.value.reason,
238+
copyUserIds: auditForm.value.copyUserIds
239+
}
240+
if (pass) {
241+
// 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
242+
const formCreateApi = approveFormFApi.value
243+
if (Object.keys(formCreateApi)?.length > 0) {
244+
await formCreateApi.validate()
245+
// @ts-ignore
246+
data.variables = approveForm.value.value
247+
}
248+
await TaskApi.approveTask(data)
249+
message.success('审批通过成功')
250+
} else {
251+
await TaskApi.rejectTask(data)
252+
message.success('审批不通过成功')
253+
}
254+
// 2.2 加载最新数据
255+
getDetail()
256+
} finally {
257+
formLoading.value = false
258+
}
259+
}
260+
261+
/* 抄送 TODO */
262+
const handleSend = () => {}
263+
264+
const openPopover = (flag) => {
265+
passVisible.value = false
266+
rejectVisible.value = false
267+
formRef.value.resetFields()
268+
flag === '1' ? (passVisible.value = true) : (rejectVisible.value = true)
269+
}
270+
271+
/** 转派审批人 */
272+
const taskTransferFormRef = ref()
273+
const openTaskUpdateAssigneeForm = () => {
274+
taskTransferFormRef.value.open(runningTask.value.id)
275+
}
276+
277+
/** 处理审批退回的操作 */
278+
const taskDelegateForm = ref()
279+
const handleDelegate = async () => {
280+
taskDelegateForm.value.open(runningTask.value.id)
281+
}
282+
283+
/** 处理审批退回的操作 */
284+
const taskReturnFormRef = ref()
285+
const handleBack = async () => {
286+
taskReturnFormRef.value.open(runningTask.value.id)
287+
}
288+
289+
/** 处理审批加签的操作 */
290+
const taskSignCreateFormRef = ref()
291+
const handleSign = async () => {
292+
taskSignCreateFormRef.value.open(runningTask.value.id)
293+
}
294+
/** 获得详情 */
295+
const getDetail = () => {
296+
emit('success')
297+
}
298+
299+
defineExpose({ loadRunningTask })
300+
</script>
301+
302+
<style lang="scss" scoped>
303+
:deep(.el-affix--fixed) {
304+
background-color: var(--el-bg-color);
305+
}
306+
307+
.btn-container {
308+
> div {
309+
margin: 0 15px;
310+
cursor: pointer;
311+
display: flex;
312+
align-items: center;
313+
&:hover {
314+
color: #6db5ff;
315+
}
316+
}
317+
}
318+
</style>

0 commit comments

Comments
 (0)