Skip to content

Commit 6197c14

Browse files
YunaiVgitee-org
authored andcommitted
!745 feat:增加oa案例流程,业务表单发起时选择审批人
Merge pull request !745 from SamllNorth_Lee/feature/bpm
2 parents 772deb5 + 913c995 commit 6197c14

File tree

1 file changed

+150
-85
lines changed

1 file changed

+150
-85
lines changed

src/views/bpm/oa/leave/create.vue

Lines changed: 150 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,75 @@
11
<template>
2-
<el-form
3-
ref="formRef"
4-
v-loading="formLoading"
5-
:model="formData"
6-
:rules="formRules"
7-
label-width="80px"
8-
>
9-
<el-form-item label="请假类型" prop="type">
10-
<el-select v-model="formData.type" clearable placeholder="请选择请假类型">
11-
<el-option
12-
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)"
13-
:key="dict.value"
14-
:label="dict.label"
15-
:value="dict.value"
16-
/>
17-
</el-select>
18-
</el-form-item>
19-
<el-form-item label="开始时间" prop="startTime">
20-
<el-date-picker
21-
v-model="formData.startTime"
22-
clearable
23-
placeholder="请选择开始时间"
24-
type="datetime"
25-
value-format="x"
26-
/>
27-
</el-form-item>
28-
<el-form-item label="结束时间" prop="endTime">
29-
<el-date-picker
30-
v-model="formData.endTime"
31-
clearable
32-
placeholder="请选择结束时间"
33-
type="datetime"
34-
value-format="x"
35-
/>
36-
</el-form-item>
37-
<el-form-item label="原因" prop="reason">
38-
<el-input v-model="formData.reason" placeholder="请输请假原因" type="textarea" />
39-
</el-form-item>
40-
<el-col v-if="startUserSelectTasks.length > 0">
41-
<el-card class="mb-10px">
42-
<template #header>指定审批人</template>
43-
<el-form
44-
:model="startUserSelectAssignees"
45-
:rules="startUserSelectAssigneesFormRules"
46-
ref="startUserSelectAssigneesFormRef"
2+
<ContentWrap :bodyStyle="{ padding: '10px 20px 0' }">
3+
<el-row :gutter="20">
4+
<el-col :span="16"
5+
><el-form
6+
ref="formRef"
7+
v-loading="formLoading"
8+
:model="formData"
9+
:rules="formRules"
10+
label-width="80px"
4711
>
48-
<el-form-item
49-
v-for="userTask in startUserSelectTasks"
50-
:key="userTask.id"
51-
:label="`任务【${userTask.name}】`"
52-
:prop="userTask.id"
53-
>
54-
<el-select
55-
v-model="startUserSelectAssignees[userTask.id]"
56-
multiple
57-
placeholder="请选择审批人"
58-
>
12+
<el-form-item label="请假类型" prop="type">
13+
<el-select v-model="formData.type" clearable placeholder="请选择请假类型">
5914
<el-option
60-
v-for="user in userList"
61-
:key="user.id"
62-
:label="user.nickname"
63-
:value="user.id"
15+
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)"
16+
:key="dict.value"
17+
:label="dict.label"
18+
:value="dict.value"
6419
/>
6520
</el-select>
6621
</el-form-item>
67-
</el-form>
68-
</el-card>
69-
</el-col>
70-
<el-form-item>
71-
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
72-
</el-form-item>
73-
</el-form>
22+
<el-form-item label="开始时间" prop="startTime">
23+
<el-date-picker
24+
v-model="formData.startTime"
25+
clearable
26+
placeholder="请选择开始时间"
27+
type="datetime"
28+
value-format="x"
29+
/>
30+
</el-form-item>
31+
<el-form-item label="结束时间" prop="endTime">
32+
<el-date-picker
33+
v-model="formData.endTime"
34+
clearable
35+
placeholder="请选择结束时间"
36+
type="datetime"
37+
value-format="x"
38+
/>
39+
</el-form-item>
40+
<el-form-item label="原因" prop="reason">
41+
<el-input v-model="formData.reason" placeholder="请输入请假原因" type="textarea" />
42+
</el-form-item>
43+
<el-form-item>
44+
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
45+
</el-form-item>
46+
</el-form></el-col
47+
>
48+
<!-- 新增 ====== begin ======== -->
49+
<el-col :span="8"
50+
><!-- 流程时间线 -->
51+
<ProcessInstanceTimeline
52+
ref="timelineRef"
53+
:activity-nodes="activityNodes"
54+
:show-status-icon="false"
55+
@select-user-confirm="selectUserConfirm"
56+
/>
57+
</el-col>
58+
<!-- 新增 ====== end ======== -->
59+
</el-row>
60+
</ContentWrap>
7461
</template>
7562
<script lang="ts" setup>
7663
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
7764
import * as LeaveApi from '@/api/bpm/leave'
7865
import { useTagsViewStore } from '@/store/modules/tagsView'
7966
import * as DefinitionApi from '@/api/bpm/definition'
80-
import * as UserApi from '@/api/system/user'
81-
67+
// 新增 ====== begin ========
68+
import ProcessInstanceTimeline from '../../processInstance/detail/ProcessInstanceTimeline.vue'
69+
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
70+
import { CandidateStrategy, NodeId } from '@/components/SimpleProcessDesignerV2/src/consts'
71+
import { ApprovalNodeInfo } from '@/api/bpm/processInstance'
72+
// 新增 ====== end ========
8273
defineOptions({ name: 'BpmOALeaveCreate' })
8374
8475
const message = useMessage() // 消息弹窗
@@ -104,10 +95,11 @@ const formRef = ref() // 表单 Ref
10495
const processDefineKey = 'oa_leave' // 流程定义 Key
10596
const startUserSelectTasks = ref([]) // 发起人需要选择审批人的用户任务列表
10697
const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
107-
const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref
108-
const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules
109-
const userList = ref<any[]>([]) // 用户列表
110-
98+
// 新增 ====== begin ========
99+
const tempStartUserSelectAssignees = ref({}) // 历史发起人选择审批人的数据,用于每次表单变更时,临时保存
100+
const activityNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([]) // 审批节点信息
101+
const processDefinitionId = ref('')
102+
// 新增 ====== end ========
111103
/** 提交表单 */
112104
const submitForm = async () => {
113105
// 校验表单
@@ -116,7 +108,14 @@ const submitForm = async () => {
116108
if (!valid) return
117109
// 校验指定审批人
118110
if (startUserSelectTasks.value?.length > 0) {
119-
await startUserSelectAssigneesFormRef.value.validate()
111+
for (const userTask of startUserSelectTasks.value) {
112+
if (
113+
Array.isArray(startUserSelectAssignees.value[userTask.id]) &&
114+
startUserSelectAssignees.value[userTask.id].length === 0
115+
) {
116+
return message.warning(`请选择${userTask.name}的审批人`)
117+
}
118+
}
120119
}
121120
122121
// 提交请求
@@ -137,28 +136,94 @@ const submitForm = async () => {
137136
}
138137
}
139138
139+
// 新增 ====== begin ========
140+
/** 获取审批详情 */
141+
const getApprovalDetail = async () => {
142+
try {
143+
const data = await ProcessInstanceApi.getApprovalDetail({
144+
processDefinitionId: processDefinitionId.value,
145+
activityId: NodeId.START_USER_NODE_ID,
146+
processVariablesStr: JSON.stringify({ day: daysDifference() }) // 解决 GET 无法传递对象的问题,后端 String 再转 JSON
147+
})
148+
149+
if (!data) {
150+
message.error('查询不到审批详情信息!')
151+
return
152+
}
153+
// 获取审批节点,显示 Timeline 的数据
154+
activityNodes.value = data.activityNodes
155+
156+
// 获取发起人自选的任务
157+
startUserSelectTasks.value = data.activityNodes?.filter(
158+
(node: ApprovalNodeInfo) => CandidateStrategy.START_USER_SELECT === node.candidateStrategy
159+
)
160+
// 恢复之前的选择审批人
161+
if (startUserSelectTasks.value?.length > 0) {
162+
for (const node of startUserSelectTasks.value) {
163+
if (
164+
tempStartUserSelectAssignees.value[node.id] &&
165+
tempStartUserSelectAssignees.value[node.id].length > 0
166+
) {
167+
startUserSelectAssignees.value[node.id] = tempStartUserSelectAssignees.value[node.id]
168+
} else {
169+
startUserSelectAssignees.value[node.id] = []
170+
}
171+
}
172+
}
173+
} finally {
174+
}
175+
}
176+
177+
/** 选择发起人 */
178+
const selectUserConfirm = (id: string, userList: any[]) => {
179+
startUserSelectAssignees.value[id] = userList?.map((item: any) => item.id)
180+
}
181+
182+
// 计算天数差
183+
const daysDifference = () => {
184+
const oneDay = 24 * 60 * 60 * 1000 // 一天的毫秒数
185+
const diffTime = Math.abs(Number(formData.value.endTime) - Number(formData.value.startTime))
186+
return Math.floor(diffTime / oneDay)
187+
}
188+
// 新增 ====== end ========
189+
140190
/** 初始化 */
141191
onMounted(async () => {
142192
const processDefinitionDetail = await DefinitionApi.getProcessDefinition(
143193
undefined,
144194
processDefineKey
145195
)
196+
146197
if (!processDefinitionDetail) {
147198
message.error('OA 请假的流程模型未配置,请检查!')
148199
return
149200
}
201+
processDefinitionId.value = processDefinitionDetail.id
150202
startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks
151-
// 设置指定审批人
152-
if (startUserSelectTasks.value?.length > 0) {
153-
// 设置校验规则
154-
for (const userTask of startUserSelectTasks.value) {
155-
startUserSelectAssignees.value[userTask.id] = []
156-
startUserSelectAssigneesFormRules.value[userTask.id] = [
157-
{ required: true, message: '请选择审批人', trigger: 'blur' }
158-
]
203+
// 新增 ====== begin ========
204+
// 加载最新的审批详情,主要用于节点预测
205+
getApprovalDetail()
206+
// 新增 ====== end ========
207+
})
208+
// 新增 ====== begin ========
209+
/** 预测流程节点会因为输入的参数值而产生新的预测结果值,所以需重新预测一次, formData.value可改成实际业务中的特定字段 */
210+
watch(
211+
formData.value,
212+
(newValue, oldValue) => {
213+
if (!oldValue) {
214+
return
215+
}
216+
if (newValue && Object.keys(newValue).length > 0) {
217+
// 记录之前的节点审批人
218+
tempStartUserSelectAssignees.value = startUserSelectAssignees.value
219+
startUserSelectAssignees.value = {}
220+
// 加载最新的审批详情,主要用于节点预测
221+
getApprovalDetail()
159222
}
160-
// 加载用户列表
161-
userList.value = await UserApi.getSimpleUserList()
223+
},
224+
{
225+
immediate: true
162226
}
163-
})
227+
// 新增 ====== end ========
228+
)
164229
</script>

0 commit comments

Comments
 (0)