Commit c9b9eced071f53beda1754371b6d489e40e3151c
1 parent
cf7a434f
流程详情页 90% - 接入审批通过、审批不通过的功能
Showing
12 changed files
with
49 additions
and
12 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java
| ... | ... | @@ -46,14 +46,14 @@ public class BpmTaskController { |
| 46 | 46 | @PutMapping("/approve") |
| 47 | 47 | @ApiOperation("通过任务") |
| 48 | 48 | public CommonResult<Boolean> approveTask(@Valid @RequestBody BpmTaskApproveReqVO reqVO) { |
| 49 | - taskService.approveTask(reqVO); | |
| 49 | + taskService.approveTask(getLoginUserId(), reqVO); | |
| 50 | 50 | return success(true); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | @PutMapping("/reject") |
| 54 | 54 | @ApiOperation("不通过任务") |
| 55 | 55 | public CommonResult<Boolean> rejectTask(@Valid @RequestBody BpmTaskRejectReqVO reqVO) { |
| 56 | - taskService.rejectTask(reqVO); | |
| 56 | + taskService.rejectTask(getLoginUserId(), reqVO); | |
| 57 | 57 | return success(true); |
| 58 | 58 | } |
| 59 | 59 | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
| ... | ... | @@ -42,6 +42,7 @@ public interface BpmErrorCodeConstants { |
| 42 | 42 | |
| 43 | 43 | // ========== 流程任务 1-009-005-000 ========== |
| 44 | 44 | ErrorCode TASK_COMPLETE_FAIL_NOT_EXISTS = new ErrorCode(1009004000, "审批任务失败,原因:该任务不处于未审批"); |
| 45 | + ErrorCode TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1009004001, "审批任务失败,原因:该任务的审批人不是你"); | |
| 45 | 46 | |
| 46 | 47 | // ========== 流程任务分配规则 1-009-006-000 ========== |
| 47 | 48 | ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1009006000, "流程({}) 的任务({}) 已经存在分配规则"); | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java
| ... | ... | @@ -21,7 +21,6 @@ public interface BpmTaskService { |
| 21 | 21 | * 获得指定流程实例的 Running 进行中的流程任务列表 |
| 22 | 22 | * |
| 23 | 23 | * @param processInstanceId 流程实例的编号 |
| 24 | - * @return 流程任务列表 | |
| 25 | 24 | */ |
| 26 | 25 | List<Task> getRunningTaskListByProcessInstanceId(String processInstanceId); |
| 27 | 26 | |
| ... | ... | @@ -81,16 +80,18 @@ public interface BpmTaskService { |
| 81 | 80 | /** |
| 82 | 81 | * 通过任务 |
| 83 | 82 | * |
| 83 | + * @param userId 用户编号 | |
| 84 | 84 | * @param reqVO 通过请求 |
| 85 | 85 | */ |
| 86 | - void approveTask(@Valid BpmTaskApproveReqVO reqVO); | |
| 86 | + void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO); | |
| 87 | 87 | |
| 88 | 88 | /** |
| 89 | 89 | * 不通过任务 |
| 90 | 90 | * |
| 91 | + * @param userId 用户编号 | |
| 91 | 92 | * @param reqVO 不通过请求 |
| 92 | 93 | */ |
| 93 | - void rejectTask(@Valid BpmTaskRejectReqVO reqVO); | |
| 94 | + void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO); | |
| 94 | 95 | |
| 95 | 96 | /** |
| 96 | 97 | * 返回高亮的流转进程 | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java
| ... | ... | @@ -14,6 +14,7 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO |
| 14 | 14 | import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; |
| 15 | 15 | import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; |
| 16 | 16 | import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; |
| 17 | +import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; | |
| 17 | 18 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 18 | 19 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 19 | 20 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| ... | ... | @@ -200,12 +201,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 200 | 201 | |
| 201 | 202 | @Override |
| 202 | 203 | @Transactional(rollbackFor = Exception.class) |
| 203 | - public void approveTask(BpmTaskApproveReqVO reqVO) { | |
| 204 | + public void approveTask(Long userId, BpmTaskApproveReqVO reqVO) { | |
| 204 | 205 | // 校验任务存在 |
| 205 | 206 | Task task = getTask(reqVO.getId()); |
| 206 | 207 | if (task == null) { |
| 207 | 208 | throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS); |
| 208 | 209 | } |
| 210 | + if (!ActivitiUtils.equals(task.getAssignee(), userId)) { | |
| 211 | + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF); | |
| 212 | + } | |
| 209 | 213 | // 校验流程实例存在 |
| 210 | 214 | ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); |
| 211 | 215 | if (instance == null) { |
| ... | ... | @@ -224,12 +228,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 224 | 228 | |
| 225 | 229 | @Override |
| 226 | 230 | @Transactional(rollbackFor = Exception.class) |
| 227 | - public void rejectTask(@Valid BpmTaskRejectReqVO reqVO) { | |
| 231 | + public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) { | |
| 228 | 232 | // 校验任务存在 |
| 229 | 233 | Task task = getTask(reqVO.getId()); |
| 230 | 234 | if (task == null) { |
| 231 | 235 | throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS); |
| 232 | 236 | } |
| 237 | + if (!ActivitiUtils.equals(task.getAssignee(), userId)) { | |
| 238 | + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF); | |
| 239 | + } | |
| 233 | 240 | // 校验流程实例存在 |
| 234 | 241 | ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); |
| 235 | 242 | if (instance == null) { | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java
| ... | ... | @@ -32,6 +32,9 @@ public class SysAuthPermissionInfoRespVO { |
| 32 | 32 | @Builder |
| 33 | 33 | public static class UserVO { |
| 34 | 34 | |
| 35 | + @ApiModelProperty(value = "用户编号", required = true, example = "1024") | |
| 36 | + private Long id; | |
| 37 | + | |
| 35 | 38 | @ApiModelProperty(value = "用户昵称", required = true, example = "芋道源码") |
| 36 | 39 | private String nickname; |
| 37 | 40 | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java
| ... | ... | @@ -31,7 +31,7 @@ public interface SysAuthConvert { |
| 31 | 31 | |
| 32 | 32 | default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) { |
| 33 | 33 | return SysAuthPermissionInfoRespVO.builder() |
| 34 | - .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build()) | |
| 34 | + .user(SysAuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) | |
| 35 | 35 | .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode)) |
| 36 | 36 | .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission)) |
| 37 | 37 | .build(); | ... | ... |
yudao-admin-ui/src/store/getters.js
| ... | ... | @@ -4,6 +4,7 @@ const getters = { |
| 4 | 4 | device: state => state.app.device, |
| 5 | 5 | visitedViews: state => state.tagsView.visitedViews, |
| 6 | 6 | cachedViews: state => state.tagsView.cachedViews, |
| 7 | + userId: state => state.user.id, | |
| 7 | 8 | token: state => state.user.token, |
| 8 | 9 | avatar: state => state.user.avatar, |
| 9 | 10 | name: state => state.user.name, | ... | ... |
yudao-admin-ui/src/store/modules/user.js
| ... | ... | @@ -4,6 +4,7 @@ import { getToken, setToken, removeToken } from '@/utils/auth' |
| 4 | 4 | const user = { |
| 5 | 5 | state: { |
| 6 | 6 | token: getToken(), |
| 7 | + id: 0, // 用户编号 | |
| 7 | 8 | name: '', |
| 8 | 9 | avatar: '', |
| 9 | 10 | roles: [], |
| ... | ... | @@ -11,6 +12,9 @@ const user = { |
| 11 | 12 | }, |
| 12 | 13 | |
| 13 | 14 | mutations: { |
| 15 | + SET_ID: (state, id) => { | |
| 16 | + state.id = id | |
| 17 | + }, | |
| 14 | 18 | SET_TOKEN: (state, token) => { |
| 15 | 19 | state.token = token |
| 16 | 20 | }, |
| ... | ... | @@ -96,6 +100,7 @@ const user = { |
| 96 | 100 | } else { |
| 97 | 101 | commit('SET_ROLES', ['ROLE_DEFAULT']) |
| 98 | 102 | } |
| 103 | + commit('SET_ID', user.id) | |
| 99 | 104 | commit('SET_NAME', user.userName) |
| 100 | 105 | commit('SET_AVATAR', avatar) |
| 101 | 106 | resolve(res) | ... | ... |
yudao-admin-ui/src/views/bpm/processInstance/detail.vue
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;"> |
| 22 | 22 | <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button> |
| 23 | 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="handleAssign">转办</el-button>--> | |
| 25 | 25 | <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button> |
| 26 | 26 | <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button> |
| 27 | 27 | </div> |
| ... | ... | @@ -81,7 +81,7 @@ |
| 81 | 81 | <script> |
| 82 | 82 | import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition"; |
| 83 | 83 | import {DICT_TYPE, getDictDatas} from "@/utils/dict"; |
| 84 | -import {getForm} from "@/api/bpm/form"; | |
| 84 | +import store from "@/store"; | |
| 85 | 85 | import {decodeFields} from "@/utils/formGenerator"; |
| 86 | 86 | import Parser from '@/components/parser/Parser' |
| 87 | 87 | import {createProcessInstance, getMyProcessInstancePage, getProcessInstance} from "@/api/bpm/processInstance"; |
| ... | ... | @@ -196,10 +196,14 @@ export default { |
| 196 | 196 | }); |
| 197 | 197 | |
| 198 | 198 | // 需要审核的记录 |
| 199 | + const userId = store.getters.userId; | |
| 199 | 200 | this.historicTasks.forEach(task => { |
| 200 | 201 | if (task.result !== 1) { // 只有待处理才需要 |
| 201 | 202 | return; |
| 202 | 203 | } |
| 204 | + if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人 | |
| 205 | + return; | |
| 206 | + } | |
| 203 | 207 | this.tasks.push({...task}); |
| 204 | 208 | this.auditForms.push({ |
| 205 | 209 | comment: '' | ... | ... |
yudao-admin-ui/src/views/bpm/processInstance/index.vue
| ... | ... | @@ -106,6 +106,7 @@ |
| 106 | 106 | <!-- TODO 芋艿:权限 --> |
| 107 | 107 | <el-button type="text" size="small" icon="el-icon-delete" v-if="scope.row.result === 1" |
| 108 | 108 | @click="handleCancel(scope.row)">取消</el-button> |
| 109 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)">详情</el-button> | |
| 109 | 110 | </template> |
| 110 | 111 | </el-table-column> |
| 111 | 112 | </el-table> |
| ... | ... | @@ -204,6 +205,10 @@ export default { |
| 204 | 205 | this.msgSuccess("取消成功"); |
| 205 | 206 | }) |
| 206 | 207 | }, |
| 208 | + /** 处理详情按钮 */ | |
| 209 | + handleDetail(row) { | |
| 210 | + this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.id}}); | |
| 211 | + }, | |
| 207 | 212 | } |
| 208 | 213 | }; |
| 209 | 214 | </script> | ... | ... |
yudao-admin-ui/src/views/bpm/task/done.vue
| ... | ... | @@ -60,7 +60,7 @@ |
| 60 | 60 | <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width"> |
| 61 | 61 | <template slot-scope="scope"> |
| 62 | 62 | <!-- TODO 权限、颜色 --> |
| 63 | - <el-button size="mini" type="text" icon="el-icon-edit">详情</el-button> | |
| 63 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)">详情</el-button> | |
| 64 | 64 | </template> |
| 65 | 65 | </el-table-column> |
| 66 | 66 | </el-table> |
| ... | ... | @@ -127,7 +127,11 @@ export default { |
| 127 | 127 | }, |
| 128 | 128 | getDateStar(ms) { |
| 129 | 129 | return getDate(ms); |
| 130 | - } | |
| 130 | + }, | |
| 131 | + /** 处理审批按钮 */ | |
| 132 | + handleAudit(row) { | |
| 133 | + this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.processInstance.id}}); | |
| 134 | + }, | |
| 131 | 135 | } |
| 132 | 136 | }; |
| 133 | 137 | </script> | ... | ... |
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.activiti.core.util; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ReflectUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | |
| 5 | 6 | import com.alibaba.ttl.TransmittableThreadLocal; |
| 6 | 7 | import org.activiti.bpmn.converter.BpmnXMLConverter; |
| 7 | 8 | import org.activiti.bpmn.model.BpmnModel; |
| ... | ... | @@ -13,6 +14,7 @@ import org.activiti.engine.impl.util.io.BytesStreamSource; |
| 13 | 14 | import javax.xml.bind.Element; |
| 14 | 15 | import java.util.ArrayList; |
| 15 | 16 | import java.util.List; |
| 17 | +import java.util.Objects; | |
| 16 | 18 | import java.util.function.Consumer; |
| 17 | 19 | |
| 18 | 20 | /** |
| ... | ... | @@ -45,6 +47,10 @@ public class ActivitiUtils { |
| 45 | 47 | Authentication.setAuthenticatedUserId(null); |
| 46 | 48 | } |
| 47 | 49 | |
| 50 | + public static boolean equals(String userIdStr, Long userId) { | |
| 51 | + return Objects.equals(userId, NumberUtils.parseLong(userIdStr)); | |
| 52 | + } | |
| 53 | + | |
| 48 | 54 | // ========== BPMN XML 相关 ========== |
| 49 | 55 | |
| 50 | 56 | /** | ... | ... |