Commit 0765f481ffcb13cdce660265fcbb2bcfea44f736
1 parent
c9b9eced
流程详情页 95% - 接入任务的转派
Showing
6 changed files
with
138 additions
and
7 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java
| @@ -57,6 +57,13 @@ public class BpmTaskController { | @@ -57,6 +57,13 @@ public class BpmTaskController { | ||
| 57 | return success(true); | 57 | return success(true); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | + @PutMapping("/update-assignee") | ||
| 61 | + @ApiOperation(value = "更新任务的负责人", notes = "用于【流程详情】的【转派】按钮") | ||
| 62 | + public CommonResult<Boolean> updateTaskAssignee(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) { | ||
| 63 | + taskService.updateTaskAssignee(getLoginUserId(), reqVO); | ||
| 64 | + return success(true); | ||
| 65 | + } | ||
| 66 | + | ||
| 60 | @GetMapping("/historic-list-by-process-instance-id") | 67 | @GetMapping("/historic-list-by-process-instance-id") |
| 61 | @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的") | 68 | @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的") |
| 62 | @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class) | 69 | @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class) |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | +import net.bytebuddy.implementation.bind.annotation.Empty; | ||
| 9 | + | ||
| 10 | +import javax.validation.constraints.NotEmpty; | ||
| 11 | +import javax.validation.constraints.NotNull; | ||
| 12 | + | ||
| 13 | +@ApiModel("流程任务的更新负责人的 Request VO") | ||
| 14 | +@Data | ||
| 15 | +public class BpmTaskUpdateAssigneeReqVO { | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "任务编号", required = true, example = "1024") | ||
| 18 | + @NotEmpty(message = "任务编号不能为空") | ||
| 19 | + private String id; | ||
| 20 | + | ||
| 21 | + @ApiModelProperty(value = "新审批人的用户编号", required = true, example = "2048") | ||
| 22 | + @NotNull(message = "新审批人的用户编号不能为空") | ||
| 23 | + private Long assigneeUserId; | ||
| 24 | + | ||
| 25 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java
| @@ -72,10 +72,18 @@ public interface BpmTaskService { | @@ -72,10 +72,18 @@ public interface BpmTaskService { | ||
| 72 | /** | 72 | /** |
| 73 | * 将流程任务分配给指定用户 | 73 | * 将流程任务分配给指定用户 |
| 74 | * | 74 | * |
| 75 | + * @param userId 用户编号 | ||
| 76 | + * @param reqVO 分配请求 | ||
| 77 | + */ | ||
| 78 | + void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO); | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * 将流程任务分配给指定用户 | ||
| 82 | + * | ||
| 75 | * @param id 流程任务编号 | 83 | * @param id 流程任务编号 |
| 76 | * @param userId 用户编号 | 84 | * @param userId 用户编号 |
| 77 | */ | 85 | */ |
| 78 | - void updateTaskAssign(String id, Long userId); | 86 | + void updateTaskAssignee(String id, Long userId); |
| 79 | 87 | ||
| 80 | /** | 88 | /** |
| 81 | * 通过任务 | 89 | * 通过任务 |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java
| @@ -195,7 +195,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -195,7 +195,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | @Override | 197 | @Override |
| 198 | - public void updateTaskAssign(String id, Long userId) { | 198 | + public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) { |
| 199 | + // 校验任务存在 | ||
| 200 | + Task task = getTask(reqVO.getId()); | ||
| 201 | + if (task == null) { | ||
| 202 | + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS); | ||
| 203 | + } | ||
| 204 | + if (!ActivitiUtils.equals(task.getAssignee(), userId)) { | ||
| 205 | + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + // 更新负责人 | ||
| 209 | + updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId()); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + @Override | ||
| 213 | + public void updateTaskAssignee(String id, Long userId) { | ||
| 199 | taskService.setAssignee(id, String.valueOf(userId)); | 214 | taskService.setAssignee(id, String.valueOf(userId)); |
| 200 | } | 215 | } |
| 201 | 216 |
yudao-admin-ui/src/api/bpm/task.js
| @@ -40,6 +40,14 @@ export function rejectTask(data) { | @@ -40,6 +40,14 @@ export function rejectTask(data) { | ||
| 40 | }) | 40 | }) |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | +export function updateTaskAssignee(data) { | ||
| 44 | + return request({ | ||
| 45 | + url: '/bpm/task/update-assignee', | ||
| 46 | + method: 'PUT', | ||
| 47 | + data: data | ||
| 48 | + }) | ||
| 49 | +} | ||
| 50 | + | ||
| 43 | export function getHistoricTaskListByProcessInstanceId(processInstanceId) { | 51 | export function getHistoricTaskListByProcessInstanceId(processInstanceId) { |
| 44 | return request({ | 52 | return request({ |
| 45 | url: '/bpm/task/historic-list-by-process-instance-id?processInstanceId=' + processInstanceId, | 53 | url: '/bpm/task/historic-list-by-process-instance-id?processInstanceId=' + processInstanceId, |
yudao-admin-ui/src/views/bpm/processInstance/detail.vue
| @@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
| 21 | <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;"> | 21 | <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;"> |
| 22 | <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button> | 22 | <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button> |
| 23 | <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button> | 23 | <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button> |
| 24 | - <!-- <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleAssign">转办</el-button>--> | 24 | + <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button> |
| 25 | <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button> | 25 | <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button> |
| 26 | <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button> | 26 | <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button> |
| 27 | </div> | 27 | </div> |
| @@ -75,18 +75,34 @@ | @@ -75,18 +75,34 @@ | ||
| 75 | </div> | 75 | </div> |
| 76 | <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" /> | 76 | <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" /> |
| 77 | </el-card> | 77 | </el-card> |
| 78 | + | ||
| 79 | + <!-- 对话框(转派审批人) --> | ||
| 80 | + <el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body> | ||
| 81 | + <el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px"> | ||
| 82 | + <el-form-item label="新审批人" prop="assigneeUserId"> | ||
| 83 | + <el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%"> | ||
| 84 | + <el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname" :value="parseInt(item.id)" /> | ||
| 85 | + </el-select> | ||
| 86 | + </el-form-item> | ||
| 87 | + </el-form> | ||
| 88 | + <div slot="footer" class="dialog-footer"> | ||
| 89 | + <el-button type="primary" @click="submitUpdateAssigneeForm">确 定</el-button> | ||
| 90 | + <el-button @click="cancelUpdateAssigneeForm">取 消</el-button> | ||
| 91 | + </div> | ||
| 92 | + </el-dialog> | ||
| 78 | </div> | 93 | </div> |
| 79 | </template> | 94 | </template> |
| 80 | 95 | ||
| 81 | <script> | 96 | <script> |
| 82 | -import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition"; | 97 | +import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition"; |
| 83 | import {DICT_TYPE, getDictDatas} from "@/utils/dict"; | 98 | import {DICT_TYPE, getDictDatas} from "@/utils/dict"; |
| 84 | import store from "@/store"; | 99 | import store from "@/store"; |
| 85 | import {decodeFields} from "@/utils/formGenerator"; | 100 | import {decodeFields} from "@/utils/formGenerator"; |
| 86 | import Parser from '@/components/parser/Parser' | 101 | import Parser from '@/components/parser/Parser' |
| 87 | -import {createProcessInstance, getMyProcessInstancePage, getProcessInstance} from "@/api/bpm/processInstance"; | ||
| 88 | -import {approveTask, getHistoricTaskListByProcessInstanceId, rejectTask} from "@/api/bpm/task"; | 102 | +import {createProcessInstance, getProcessInstance} from "@/api/bpm/processInstance"; |
| 103 | +import {approveTask, getHistoricTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task"; | ||
| 89 | import {getDate} from "@/utils/dateUtils"; | 104 | import {getDate} from "@/utils/dateUtils"; |
| 105 | +import {listSimpleUsers} from "@/api/system/user"; | ||
| 90 | 106 | ||
| 91 | // 流程实例的详情页,可用于审批 | 107 | // 流程实例的详情页,可用于审批 |
| 92 | export default { | 108 | export default { |
| @@ -124,6 +140,18 @@ export default { | @@ -124,6 +140,18 @@ export default { | ||
| 124 | comment: [{ required: true, message: "审批建议不能为空", trigger: "blur" }], | 140 | comment: [{ required: true, message: "审批建议不能为空", trigger: "blur" }], |
| 125 | }, | 141 | }, |
| 126 | 142 | ||
| 143 | + // 转派审批人 | ||
| 144 | + userOptions: [], | ||
| 145 | + updateAssignee: { | ||
| 146 | + open: false, | ||
| 147 | + form: { | ||
| 148 | + assigneeUserId: undefined, | ||
| 149 | + }, | ||
| 150 | + rules: { | ||
| 151 | + assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }], | ||
| 152 | + } | ||
| 153 | + }, | ||
| 154 | + | ||
| 127 | // 数据字典 | 155 | // 数据字典 |
| 128 | categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY), | 156 | categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY), |
| 129 | }; | 157 | }; |
| @@ -135,6 +163,12 @@ export default { | @@ -135,6 +163,12 @@ export default { | ||
| 135 | return; | 163 | return; |
| 136 | } | 164 | } |
| 137 | this.getDetail(); | 165 | this.getDetail(); |
| 166 | + | ||
| 167 | + // 获得用户列表 | ||
| 168 | + this.userOptions = []; | ||
| 169 | + listSimpleUsers().then(response => { | ||
| 170 | + this.userOptions.push(...response.data); | ||
| 171 | + }); | ||
| 138 | }, | 172 | }, |
| 139 | methods: { | 173 | methods: { |
| 140 | /** 获得流程实例 */ | 174 | /** 获得流程实例 */ |
| @@ -311,7 +345,41 @@ export default { | @@ -311,7 +345,41 @@ export default { | ||
| 311 | this.getDetail(); // 获得最新详情 | 345 | this.getDetail(); // 获得最新详情 |
| 312 | }); | 346 | }); |
| 313 | } | 347 | } |
| 314 | - }) | 348 | + }); |
| 349 | + }, | ||
| 350 | + /** 处理转派审批人 */ | ||
| 351 | + handleUpdateAssignee(task) { | ||
| 352 | + // 设置表单 | ||
| 353 | + this.resetUpdateAssigneeForm(); | ||
| 354 | + this.updateAssignee.form.id = task.id; | ||
| 355 | + // 设置为打开 | ||
| 356 | + this.updateAssignee.open = true; | ||
| 357 | + }, | ||
| 358 | + /** 提交转派审批人 */ | ||
| 359 | + submitUpdateAssigneeForm() { | ||
| 360 | + this.$refs['updateAssigneeForm'].validate(valid => { | ||
| 361 | + if (!valid) { | ||
| 362 | + return; | ||
| 363 | + } | ||
| 364 | + updateTaskAssignee(this.updateAssignee.form).then(response => { | ||
| 365 | + this.msgSuccess("转派任务成功!"); | ||
| 366 | + this.updateAssignee.open = false; | ||
| 367 | + this.getDetail(); // 获得最新详情 | ||
| 368 | + }); | ||
| 369 | + }); | ||
| 370 | + }, | ||
| 371 | + /** 取消转派审批人 */ | ||
| 372 | + cancelUpdateAssigneeForm() { | ||
| 373 | + this.updateAssignee.open = false; | ||
| 374 | + this.resetUpdateAssigneeForm(); | ||
| 375 | + }, | ||
| 376 | + /** 重置转派审批人 */ | ||
| 377 | + resetUpdateAssigneeForm() { | ||
| 378 | + this.updateAssignee.form = { | ||
| 379 | + id: undefined, | ||
| 380 | + assigneeUserId: undefined, | ||
| 381 | + }; | ||
| 382 | + this.resetForm("updateAssigneeForm"); | ||
| 315 | }, | 383 | }, |
| 316 | /** 处理审批退回的操作 */ | 384 | /** 处理审批退回的操作 */ |
| 317 | handleDelegate(task) { | 385 | handleDelegate(task) { |