diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java index 324fda596..5f4640a3d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java @@ -57,6 +57,13 @@ public class BpmTaskController { return success(true); } + @PutMapping("/update-assignee") + @ApiOperation(value = "更新任务的负责人", notes = "用于【流程详情】的【转派】按钮") + public CommonResult<Boolean> updateTaskAssignee(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) { + taskService.updateTaskAssignee(getLoginUserId(), reqVO); + return success(true); + } + @GetMapping("/historic-list-by-process-instance-id") @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的") @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java new file mode 100644 index 000000000..0ad6fbedc --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import net.bytebuddy.implementation.bind.annotation.Empty; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@ApiModel("流程任务的更新负责人的 Request VO") +@Data +public class BpmTaskUpdateAssigneeReqVO { + + @ApiModelProperty(value = "任务编号", required = true, example = "1024") + @NotEmpty(message = "任务编号不能为空") + private String id; + + @ApiModelProperty(value = "新审批人的用户编号", required = true, example = "2048") + @NotNull(message = "新审批人的用户编号不能为空") + private Long assigneeUserId; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java index 971e4c510..61568c8da 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java @@ -69,13 +69,21 @@ public interface BpmTaskService { */ PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO); + /** + * 将流程任务分配给指定用户 + * + * @param userId 用户编号 + * @param reqVO 分配请求 + */ + void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO); + /** * 将流程任务分配给指定用户 * * @param id 流程任务编号 * @param userId 用户编号 */ - void updateTaskAssign(String id, Long userId); + void updateTaskAssignee(String id, Long userId); /** * 通过任务 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java index 933b43c3f..e329ab7e3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java +++ b/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 { } @Override - public void updateTaskAssign(String id, Long userId) { + public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) { + // 校验任务存在 + Task task = getTask(reqVO.getId()); + if (task == null) { + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS); + } + if (!ActivitiUtils.equals(task.getAssignee(), userId)) { + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF); + } + + // 更新负责人 + updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId()); + } + + @Override + public void updateTaskAssignee(String id, Long userId) { taskService.setAssignee(id, String.valueOf(userId)); } diff --git a/yudao-admin-ui/src/api/bpm/task.js b/yudao-admin-ui/src/api/bpm/task.js index 650186e96..4e2ce65c4 100644 --- a/yudao-admin-ui/src/api/bpm/task.js +++ b/yudao-admin-ui/src/api/bpm/task.js @@ -40,6 +40,14 @@ export function rejectTask(data) { }) } +export function updateTaskAssignee(data) { + return request({ + url: '/bpm/task/update-assignee', + method: 'PUT', + data: data + }) +} + export function getHistoricTaskListByProcessInstanceId(processInstanceId) { return request({ url: '/bpm/task/historic-list-by-process-instance-id?processInstanceId=' + processInstanceId, diff --git a/yudao-admin-ui/src/views/bpm/processInstance/detail.vue b/yudao-admin-ui/src/views/bpm/processInstance/detail.vue index 9b2ac8277..6222f30ac 100644 --- a/yudao-admin-ui/src/views/bpm/processInstance/detail.vue +++ b/yudao-admin-ui/src/views/bpm/processInstance/detail.vue @@ -21,7 +21,7 @@ <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;"> <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button> <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button> - <!-- <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleAssign">转办</el-button>--> + <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button> <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button> <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button> </div> @@ -75,18 +75,34 @@ </div> <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" /> </el-card> + + <!-- 对话框(转派审批人) --> + <el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body> + <el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px"> + <el-form-item label="新审批人" prop="assigneeUserId"> + <el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%"> + <el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname" :value="parseInt(item.id)" /> + </el-select> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitUpdateAssigneeForm">确 定</el-button> + <el-button @click="cancelUpdateAssigneeForm">取 消</el-button> + </div> + </el-dialog> </div> </template> <script> -import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition"; +import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition"; import {DICT_TYPE, getDictDatas} from "@/utils/dict"; import store from "@/store"; import {decodeFields} from "@/utils/formGenerator"; import Parser from '@/components/parser/Parser' -import {createProcessInstance, getMyProcessInstancePage, getProcessInstance} from "@/api/bpm/processInstance"; -import {approveTask, getHistoricTaskListByProcessInstanceId, rejectTask} from "@/api/bpm/task"; +import {createProcessInstance, getProcessInstance} from "@/api/bpm/processInstance"; +import {approveTask, getHistoricTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task"; import {getDate} from "@/utils/dateUtils"; +import {listSimpleUsers} from "@/api/system/user"; // 流程实例的详情页,可用于审批 export default { @@ -124,6 +140,18 @@ export default { comment: [{ required: true, message: "审批建议不能为空", trigger: "blur" }], }, + // 转派审批人 + userOptions: [], + updateAssignee: { + open: false, + form: { + assigneeUserId: undefined, + }, + rules: { + assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }], + } + }, + // 数据字典 categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY), }; @@ -135,6 +163,12 @@ export default { return; } this.getDetail(); + + // 获得用户列表 + this.userOptions = []; + listSimpleUsers().then(response => { + this.userOptions.push(...response.data); + }); }, methods: { /** 获得流程实例 */ @@ -311,7 +345,41 @@ export default { this.getDetail(); // 获得最新详情 }); } - }) + }); + }, + /** 处理转派审批人 */ + handleUpdateAssignee(task) { + // 设置表单 + this.resetUpdateAssigneeForm(); + this.updateAssignee.form.id = task.id; + // 设置为打开 + this.updateAssignee.open = true; + }, + /** 提交转派审批人 */ + submitUpdateAssigneeForm() { + this.$refs['updateAssigneeForm'].validate(valid => { + if (!valid) { + return; + } + updateTaskAssignee(this.updateAssignee.form).then(response => { + this.msgSuccess("转派任务成功!"); + this.updateAssignee.open = false; + this.getDetail(); // 获得最新详情 + }); + }); + }, + /** 取消转派审批人 */ + cancelUpdateAssigneeForm() { + this.updateAssignee.open = false; + this.resetUpdateAssigneeForm(); + }, + /** 重置转派审批人 */ + resetUpdateAssigneeForm() { + this.updateAssignee.form = { + id: undefined, + assigneeUserId: undefined, + }; + this.resetForm("updateAssigneeForm"); }, /** 处理审批退回的操作 */ handleDelegate(task) {