1
1
<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"
47
11
>
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 =" 请选择请假类型" >
59
14
<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 "
64
19
/>
65
20
</el-select >
66
21
</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 >
74
61
</template >
75
62
<script lang="ts" setup>
76
63
import { DICT_TYPE , getIntDictOptions } from ' @/utils/dict'
77
64
import * as LeaveApi from ' @/api/bpm/leave'
78
65
import { useTagsViewStore } from ' @/store/modules/tagsView'
79
66
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 ========
82
73
defineOptions ({ name: ' BpmOALeaveCreate' })
83
74
84
75
const message = useMessage () // 消息弹窗
@@ -104,10 +95,11 @@ const formRef = ref() // 表单 Ref
104
95
const processDefineKey = ' oa_leave' // 流程定义 Key
105
96
const startUserSelectTasks = ref ([]) // 发起人需要选择审批人的用户任务列表
106
97
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 ========
111
103
/** 提交表单 */
112
104
const submitForm = async () => {
113
105
// 校验表单
@@ -116,7 +108,14 @@ const submitForm = async () => {
116
108
if (! valid ) return
117
109
// 校验指定审批人
118
110
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
+ }
120
119
}
121
120
122
121
// 提交请求
@@ -137,28 +136,94 @@ const submitForm = async () => {
137
136
}
138
137
}
139
138
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
+
140
190
/** 初始化 */
141
191
onMounted (async () => {
142
192
const processDefinitionDetail = await DefinitionApi .getProcessDefinition (
143
193
undefined ,
144
194
processDefineKey
145
195
)
196
+
146
197
if (! processDefinitionDetail ) {
147
198
message .error (' OA 请假的流程模型未配置,请检查!' )
148
199
return
149
200
}
201
+ processDefinitionId .value = processDefinitionDetail .id
150
202
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 ()
159
222
}
160
- // 加载用户列表
161
- userList .value = await UserApi .getSimpleUserList ()
223
+ },
224
+ {
225
+ immediate: true
162
226
}
163
- })
227
+ // 新增 ====== end ========
228
+ )
164
229
</script >
0 commit comments