Commit ee8dcd08882f0bcd05c82760bf7ede0adee280bb

Authored by jason
1 parent 1bb10d00

1.实现了工作流引擎 中 请假流程demo(定义在 resources/leave.bpmn)

2.增加一个一级菜单 OA 办公 下面两个菜单: 请假申请,待办任务
3.暂时不知如何找部门领导, 暂时写死为 admin
4.activity 用户组使用 用户岗位来代替。
5.新增一个用户 hradmin, 密码 123456  岗位是 人力资源
6.演示流程。
  a. admin 登陆 申请请假
  b. admin 待办任务(审批)
  c. hradmin 登陆 待办任务(审批)
  d. admin 登陆 待办任务 (确认)
Showing 43 changed files with 2405 additions and 17 deletions
sql/ruoyi-vue-pro.sql
... ... @@ -1108,6 +1108,12 @@ INSERT INTO `sys_dict_data` VALUES (76, 2, '接收失败', '20', 'sys_sms_receiv
1108 1108 INSERT INTO `sys_dict_data` VALUES (77, 0, '调试(钉钉)', 'DEBUG_DING_TALK', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-13 00:20:37', '1', '2021-04-13 00:20:37', b'0');
1109 1109 INSERT INTO `sys_dict_data` VALUES (78, 1, '自动生成', '1', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:06:48', '1', '2021-04-13 22:06:44', b'0');
1110 1110 INSERT INTO `sys_dict_data` VALUES (79, 2, '手动编辑', '2', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:07:14', '1', '2021-04-13 22:06:49', b'0');
  1111 +INSERT INTO `sys_dict_data` VALUES (80,0,'病假','1','oa_leave_type',0,NULL,'1','2021-09-21 22:35:28','1','2021-09-21 14:59:27',0x00);
  1112 +INSERT INTO `sys_dict_data` VALUES (81,1,'事假','2','oa_leave_type',0,NULL,'1','2021-09-21 22:36:11','1','2021-09-21 14:59:27',0x00);
  1113 +INSERT INTO `sys_dict_data` VALUES (82,2,'婚假','3','oa_leave_type',0,NULL,'1','2021-09-21 22:36:38','1','2021-09-21 14:59:27',0x00);
  1114 +INSERT INTO `sys_dict_data` VALUES (83,0,'处理中','1','oa_leave_status',0,NULL,'1','2021-09-21 22:46:46','1','2021-10-12 22:12:20',0x00);
  1115 +INSERT INTO `sys_dict_data` VALUES (84,1,'流程结束','2','oa_leave_status',0,NULL,'1','2021-09-21 22:47:03','1','2021-10-12 22:12:58',0x00);
  1116 +INSERT INTO `sys_dict_data` VALUES (85,2,'完成','3','oa_leave_status',0,NULL,'1','2021-09-21 22:47:25','1','2021-10-12 14:13:06',0x01);
1111 1117 COMMIT;
1112 1118  
1113 1119 -- ----------------------------
... ... @@ -1155,6 +1161,9 @@ INSERT INTO `sys_dict_type` VALUES (112, '短信模板的类型', 'sys_sms_templ
1155 1161 INSERT INTO `sys_dict_type` VALUES (113, '短信发送状态', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2021-04-11 09:30:02', b'0');
1156 1162 INSERT INTO `sys_dict_type` VALUES (114, '短信接收状态', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2021-04-11 20:27:14', b'0');
1157 1163 INSERT INTO `sys_dict_type` VALUES (115, '错误码的类型', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2021-04-13 22:07:12', b'0');
  1164 +INSERT INTO `sys_dict_type` VALUES (116,'请假类型','oa_leave_type',0,NULL,'1','2021-09-21 22:34:33','1','2021-09-21 15:00:38',0x00);
  1165 +INSERT INTO `sys_dict_type` VALUES (117,'请假流程状态','oa_leave_status',0,NULL,'1','2021-09-21 22:46:04','1','2021-09-21 15:00:38',0x00);
  1166 +
1158 1167 COMMIT;
1159 1168  
1160 1169 -- ----------------------------
... ... @@ -1357,6 +1366,7 @@ INSERT INTO `sys_menu` VALUES (1, '系统管理', '', 1, 1, 0, '/system', 'syste
1357 1366 INSERT INTO `sys_menu` VALUES (2, '基础设施', '', 1, 2, 0, '/infra', 'monitor', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:18:35', b'0');
1358 1367 INSERT INTO `sys_menu` VALUES (3, '研发工具', '', 1, 3, 0, '/tool', 'tool', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 12:44:42', b'0');
1359 1368 INSERT INTO `sys_menu` VALUES (4, '若依官网', '', 1, 4, 0, 'http://ruoyi.vip', 'guide', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 21:54:28', b'1');
  1369 +INSERT INTO `sys_menu` VALUES (5,'OA 办公','',1,4,0,'/oa','people',NULL,0,'admin','2021-09-20 16:26:19','1','2021-09-20 13:55:54',0x00);
1360 1370 INSERT INTO `sys_menu` VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'user', 'system/user/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
1361 1371 INSERT INTO `sys_menu` VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'peoples', 'system/role/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:49', b'0');
1362 1372 INSERT INTO `sys_menu` VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'tree-table', 'system/menu/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:28', b'0');
... ... @@ -1485,6 +1495,14 @@ INSERT INTO `sys_menu` VALUES (1113, '错误码更新', 'system:error-code:updat
1485 1495 INSERT INTO `sys_menu` VALUES (1114, '错误码删除', 'system:error-code:delete', 3, 4, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:51', b'0');
1486 1496 INSERT INTO `sys_menu` VALUES (1115, '错误码导出', 'system:error-code:export', 3, 5, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:55', b'0');
1487 1497 INSERT INTO `sys_menu` VALUES (1116, '日志中心', '', 2, 8, 2, 'log-center', 'log', 'infra/skywalking/log', 0, '1', '2021-04-26 22:35:45', '1', '2021-04-26 22:37:25', b'0');
  1498 +INSERT INTO `sys_menu` VALUES (1118,'请假申请','',2,0,5,'oa/leave','user','oa/leave/index',0,'','2021-09-20 08:51:03','1','2021-10-12 22:19:02',0x00);
  1499 +INSERT INTO `sys_menu` VALUES (1119,'请假申请查询','oa:leave:query',3,1,1118,'','','',0,'','2021-09-20 08:51:03','','2021-09-20 08:51:03',0x00);
  1500 +INSERT INTO `sys_menu` VALUES (1120,'请假申请创建','oa:leave:create',3,2,1118,'','','',0,'','2021-09-20 08:51:03','','2021-09-20 08:51:03',0x00);
  1501 +INSERT INTO `sys_menu` VALUES (1121,'请假申请更新','oa:leave:update',3,3,1118,'','','',0,'','2021-09-20 08:51:03','','2021-09-20 08:51:03',0x00);
  1502 +INSERT INTO `sys_menu` VALUES (1122,'请假申请删除','oa:leave:delete',3,4,1118,'','','',0,'','2021-09-20 08:51:03','','2021-09-20 08:51:03',0x00);
  1503 +INSERT INTO `sys_menu` VALUES (1123,'请假申请导出','oa:leave:export',3,5,1118,'','','',0,'','2021-09-20 08:51:03','','2021-09-20 08:51:03',0x00);
  1504 +INSERT INTO `sys_menu` VALUES (1124,'待办任务','',2,2,5,'todo','edit','oa/todo/index',0,'1','2021-09-20 22:10:09','1','2021-09-21 23:17:12',0x00);
  1505 +
1488 1506 COMMIT;
1489 1507  
1490 1508 -- ----------------------------
... ... @@ -1958,6 +1976,7 @@ INSERT INTO `sys_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ul
1958 1976 INSERT INTO `sys_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 100, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '1', '2021-03-14 22:35:17', b'0');
1959 1977 INSERT INTO `sys_user` VALUES (103, 'yuanma', '', '源码', NULL, 100, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '', NULL, '', '2021-01-13 23:50:35', '', '2021-01-13 23:50:35', b'0');
1960 1978 INSERT INTO `sys_user` VALUES (104, 'test', '$2a$10$.TOFpaIiI3PzEwkGrNq0Eu6Cc3rOqJMxTb1DqeSEM8StxaGPBRKoi', '测试号', NULL, 100, '[]', '', '15601691200', 1, '', 0, '', NULL, '', '2021-01-21 02:13:53', '1', '2021-03-14 22:36:38', b'0');
  1979 +INSERT INTO `sys_user` VALUES (105,'hradmin','$2a$10$JEhJOL25X1eMnFfR3PILo.MoAljf29YukpL2w6H9GvVGjmqOCuh.O','hr-mgr','hr 管理员',100,'[3]','','',1,'',0,'',NULL,'1','2021-09-25 16:50:41','1','2021-09-25 01:14:09',0x00);
1961 1980 COMMIT;
1962 1981  
1963 1982 -- ----------------------------
... ... @@ -1987,6 +2006,7 @@ INSERT INTO `sys_user_role` VALUES (4, 100, 101, '', NULL, '', NULL, b'0');
1987 2006 INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0');
1988 2007 INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0');
1989 2008 INSERT INTO `sys_user_role` VALUES (7, 104, 101, '', NULL, '', NULL, b'0');
  2009 +INSERT INTO `sys_user_role` VALUES (8,105,1,'1','2021-09-25 16:51:44','1','2021-09-25 16:51:44',0x00);
1990 2010 COMMIT;
1991 2011  
1992 2012 -- ----------------------------
... ... @@ -2425,4 +2445,27 @@ INSERT INTO `tool_test_demo` VALUES (106, '老五1', 0, 1, 1, '牛逼哈2', '',
2425 2445 INSERT INTO `tool_test_demo` VALUES (107, '哈哈哈哈', 1, 0, 1, 'biubiubui', '', '2021-02-06 14:00:54', '', '2021-02-06 14:00:54', b'0');
2426 2446 COMMIT;
2427 2447  
  2448 +
  2449 +DROP TABLE IF EXISTS `oa_leave`;
  2450 +/*!40101 SET @saved_cs_client = @@character_set_client */;
  2451 +/*!40101 SET character_set_client = utf8 */;
  2452 +CREATE TABLE `oa_leave` (
  2453 + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '请假表单主键',
  2454 + `process_instance_id` varchar(64) DEFAULT NULL COMMENT '流程id',
  2455 + `status` tinyint(4) NOT NULL COMMENT '状态',
  2456 + `user_id` varchar(20) NOT NULL COMMENT '申请人id',
  2457 + `start_time` datetime NOT NULL COMMENT '开始时间',
  2458 + `end_time` datetime NOT NULL COMMENT '结束时间',
  2459 + `leave_type` varchar(20) DEFAULT NULL COMMENT '请假类型',
  2460 + `reason` varchar(2000) DEFAULT NULL COMMENT '原因',
  2461 + `apply_time` datetime NOT NULL COMMENT '申请时间',
  2462 + `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  2463 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  2464 + `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  2465 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  2466 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  2467 + PRIMARY KEY (`id`)
  2468 +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='请假申请表';
  2469 +/*!40101 SET character_set_client = @saved_cs_client */;
  2470 +
2428 2471 SET FOREIGN_KEY_CHECKS = 1;
... ...
yudao-admin-server/pom.xml
... ... @@ -31,6 +31,11 @@
31 31 <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
32 32 </dependency>
33 33  
  34 + <dependency>
  35 + <groupId>cn.iocoder.boot</groupId>
  36 + <artifactId>yudao-spring-boot-starter-activiti</artifactId>
  37 + </dependency>
  38 +
34 39 <!-- Web 相关 -->
35 40 <dependency>
36 41 <groupId>cn.iocoder.boot</groupId>
... ... @@ -107,6 +112,8 @@
107 112 <artifactId>yudao-spring-boot-starter-excel</artifactId>
108 113 </dependency>
109 114  
  115 +
  116 +
110 117 <dependency>
111 118 <groupId>org.apache.velocity</groupId>
112 119 <artifactId>velocity-engine-core</artifactId>
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/OaLeaveController.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  4 +import org.springframework.web.bind.annotation.*;
  5 +import javax.annotation.Resource;
  6 +import org.springframework.validation.annotation.Validated;
  7 +import org.springframework.security.access.prepost.PreAuthorize;
  8 +
  9 +import io.swagger.annotations.*;
  10 +
  11 +import javax.validation.constraints.*;
  12 +import javax.validation.*;
  13 +import javax.servlet.http.*;
  14 +import java.util.*;
  15 +import java.io.IOException;
  16 +
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  18 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  22 +
  23 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  24 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
  25 +
  26 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
  27 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  28 +import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
  29 +import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
  30 +
  31 +@Api(tags = "请假申请")
  32 +@RestController
  33 +@RequestMapping("/oa/leave")
  34 +@Validated
  35 +public class OaLeaveController {
  36 +
  37 + @Resource
  38 + private OaLeaveService leaveService;
  39 +
  40 + @PostMapping("/create")
  41 + @ApiOperation("创建请假申请")
  42 + @PreAuthorize("@ss.hasPermission('oa:leave:create')")
  43 + public CommonResult<Long> createLeave(@Valid @RequestBody OaLeaveCreateReqVO createReqVO) {
  44 + return success(leaveService.createLeave(createReqVO));
  45 + }
  46 +
  47 + @PutMapping("/update")
  48 + @ApiOperation("更新请假申请")
  49 + @PreAuthorize("@ss.hasPermission('oa:leave:update')")
  50 + public CommonResult<Boolean> updateLeave(@Valid @RequestBody OaLeaveUpdateReqVO updateReqVO) {
  51 + leaveService.updateLeave(updateReqVO);
  52 + return success(true);
  53 + }
  54 +
  55 + @DeleteMapping("/delete")
  56 + @ApiOperation("删除请假申请")
  57 + @ApiImplicitParam(name = "id", value = "编号", required = true)
  58 + @PreAuthorize("@ss.hasPermission('oa:leave:delete')")
  59 + public CommonResult<Boolean> deleteLeave(@RequestParam("id") Long id) {
  60 + leaveService.deleteLeave(id);
  61 + return success(true);
  62 + }
  63 +
  64 + @GetMapping("/get")
  65 + @ApiOperation("获得请假申请")
  66 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  67 + @PreAuthorize("@ss.hasPermission('oa:leave:query')")
  68 + public CommonResult<OaLeaveRespVO> getLeave(@RequestParam("id") Long id) {
  69 + OaLeaveDO leave = leaveService.getLeave(id);
  70 + return success(OaLeaveConvert.INSTANCE.convert(leave));
  71 + }
  72 +
  73 + @GetMapping("/list")
  74 + @ApiOperation("获得请假申请列表")
  75 + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
  76 + @PreAuthorize("@ss.hasPermission('oa:leave:query')")
  77 + public CommonResult<List<OaLeaveRespVO>> getLeaveList(@RequestParam("ids") Collection<Long> ids) {
  78 + List<OaLeaveDO> list = leaveService.getLeaveList(ids);
  79 + return success(OaLeaveConvert.INSTANCE.convertList(list));
  80 + }
  81 +
  82 + @GetMapping("/page")
  83 + @ApiOperation("获得请假申请分页")
  84 + @PreAuthorize("@ss.hasPermission('oa:leave:query')")
  85 + public CommonResult<PageResult<OaLeaveRespVO>> getLeavePage(@Valid OaLeavePageReqVO pageVO) {
  86 + //值查询自己申请请假
  87 + pageVO.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
  88 + PageResult<OaLeaveDO> pageResult = leaveService.getLeavePage(pageVO);
  89 + return success(OaLeaveConvert.INSTANCE.convertPage(pageResult));
  90 + }
  91 +
  92 + @GetMapping("/export-excel")
  93 + @ApiOperation("导出请假申请 Excel")
  94 + @PreAuthorize("@ss.hasPermission('oa:leave:export')")
  95 + @OperateLog(type = EXPORT)
  96 + public void exportLeaveExcel(@Valid OaLeaveExportReqVO exportReqVO,
  97 + HttpServletResponse response) throws IOException {
  98 + List<OaLeaveDO> list = leaveService.getLeaveList(exportReqVO);
  99 + // 导出 Excel
  100 + List<OaLeaveExcelVO> datas = OaLeaveConvert.INSTANCE.convertList02(list);
  101 + ExcelUtils.write(response, "请假申请.xls", "数据", OaLeaveExcelVO.class, datas);
  102 + }
  103 +
  104 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +/**
  12 +* 请假申请 Base VO,提供给添加、修改、详细的子 VO 使用
  13 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  14 +*/
  15 +@Data
  16 +public class OaLeaveBaseVO {
  17 +
  18 + @ApiModelProperty(value = "流程id")
  19 + private String processInstanceId;
  20 +
  21 + @ApiModelProperty(value = "状态", required = true)
  22 + private Integer status;
  23 +
  24 + @ApiModelProperty(value = "申请人id", required = true)
  25 + private String userId;
  26 +
  27 + @ApiModelProperty(value = "开始时间", required = true)
  28 + @NotNull(message = "开始时间不能为空")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private Date startTime;
  31 +
  32 + @ApiModelProperty(value = "结束时间", required = true)
  33 + @NotNull(message = "结束时间不能为空")
  34 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  35 + private Date endTime;
  36 +
  37 + @ApiModelProperty(value = "请假类型")
  38 + private String leaveType;
  39 +
  40 + @ApiModelProperty(value = "原因")
  41 + private String reason;
  42 +
  43 + @ApiModelProperty(value = "申请时间", required = true)
  44 + @NotNull(message = "申请时间不能为空")
  45 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  46 + private Date applyTime;
  47 +
  48 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@ApiModel("请假申请创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class OaLeaveCreateReqVO extends OaLeaveBaseVO {
  13 +
  14 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +
  7 +import com.alibaba.excel.annotation.ExcelProperty;
  8 +
  9 +/**
  10 + * 请假申请 Excel VO
  11 + *
  12 + * @author 芋艿
  13 + */
  14 +@Data
  15 +public class OaLeaveExcelVO {
  16 +
  17 + @ExcelProperty("请假表单主键")
  18 + private Long id;
  19 +
  20 + @ExcelProperty("流程id")
  21 + private String processInstanceId;
  22 +
  23 + @ExcelProperty("状态")
  24 + private Integer status;
  25 +
  26 + @ExcelProperty("申请人id")
  27 + private String userId;
  28 +
  29 + @ExcelProperty("开始时间")
  30 + private Date startTime;
  31 +
  32 + @ExcelProperty("结束时间")
  33 + private Date endTime;
  34 +
  35 + @ExcelProperty("请假类型")
  36 + private String leaveType;
  37 +
  38 + @ExcelProperty("原因")
  39 + private String reason;
  40 +
  41 + @ExcelProperty("申请时间")
  42 + private Date applyTime;
  43 +
  44 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +@ApiModel(value = "请假申请 Excel 导出 Request VO", description = "参数和 OaLeavePageReqVO 是一致的")
  12 +@Data
  13 +public class OaLeaveExportReqVO {
  14 +
  15 + @ApiModelProperty(value = "流程id")
  16 + private String processInstanceId;
  17 +
  18 + @ApiModelProperty(value = "状态")
  19 + private Integer status;
  20 +
  21 + @ApiModelProperty(value = "申请人id")
  22 + private String userId;
  23 +
  24 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  25 + @ApiModelProperty(value = "开始开始时间")
  26 + private Date beginStartTime;
  27 +
  28 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  29 + @ApiModelProperty(value = "结束开始时间")
  30 + private Date endStartTime;
  31 +
  32 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  33 + @ApiModelProperty(value = "开始结束时间")
  34 + private Date beginEndTime;
  35 +
  36 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  37 + @ApiModelProperty(value = "结束结束时间")
  38 + private Date endEndTime;
  39 +
  40 + @ApiModelProperty(value = "请假类型")
  41 + private String leaveType;
  42 +
  43 + @ApiModelProperty(value = "原因")
  44 + private String reason;
  45 +
  46 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  47 + @ApiModelProperty(value = "开始申请时间")
  48 + private Date beginApplyTime;
  49 +
  50 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  51 + @ApiModelProperty(value = "结束申请时间")
  52 + private Date endApplyTime;
  53 +
  54 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeavePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +@ApiModel("请假申请分页 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class OaLeavePageReqVO extends PageParam {
  16 +
  17 + @ApiModelProperty(value = "流程id")
  18 + private String processInstanceId;
  19 +
  20 + @ApiModelProperty(value = "状态")
  21 + private Integer status;
  22 +
  23 + @ApiModelProperty(value = "申请人id")
  24 + private String userId;
  25 +
  26 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  27 + @ApiModelProperty(value = "开始开始时间")
  28 + private Date beginStartTime;
  29 +
  30 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  31 + @ApiModelProperty(value = "结束开始时间")
  32 + private Date endStartTime;
  33 +
  34 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  35 + @ApiModelProperty(value = "开始结束时间")
  36 + private Date beginEndTime;
  37 +
  38 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  39 + @ApiModelProperty(value = "结束结束时间")
  40 + private Date endEndTime;
  41 +
  42 + @ApiModelProperty(value = "请假类型")
  43 + private String leaveType;
  44 +
  45 + @ApiModelProperty(value = "原因")
  46 + private String reason;
  47 +
  48 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  49 + @ApiModelProperty(value = "开始申请时间")
  50 + private Date beginApplyTime;
  51 +
  52 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  53 + @ApiModelProperty(value = "结束申请时间")
  54 + private Date endApplyTime;
  55 +
  56 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +
  7 +@ApiModel("请假申请 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class OaLeaveRespVO extends OaLeaveBaseVO {
  12 +
  13 + @ApiModelProperty(value = "请假表单主键", required = true)
  14 + private Long id;
  15 +
  16 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@ApiModel("请假申请更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class OaLeaveUpdateReqVO extends OaLeaveBaseVO {
  13 +
  14 + @ApiModelProperty(value = "请假表单主键", required = true)
  15 + @NotNull(message = "请假表单主键不能为空")
  16 + private Long id;
  17 +
  18 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/TaskController.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
  4 +import cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.TaskService;
  5 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiOperation;
  9 +import org.springframework.web.bind.annotation.*;
  10 +
  11 +import javax.annotation.Resource;
  12 +import javax.validation.Valid;
  13 +import java.util.List;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  16 +
  17 +@Api(tags = "工作流待办任务")
  18 +@RestController
  19 +@RequestMapping("/workflow/task")
  20 +public class TaskController {
  21 +
  22 + @Resource
  23 + private TaskService taskService;
  24 +
  25 +
  26 +
  27 + @GetMapping("/todo/page")
  28 + @ApiOperation("获取待办任务分页")
  29 + public CommonResult<PageResult<TodoTaskRespVO>> getTodoTaskPage(@Valid TodoTaskPageReqVO pageVO) {
  30 + return success(taskService.getTodoTaskPage(pageVO));
  31 + }
  32 +
  33 + @GetMapping("/claim")
  34 + @ApiOperation("签收任务")
  35 + public CommonResult<Boolean> claimTask(@RequestParam("id") String taskId) {
  36 + taskService.claimTask(taskId);
  37 + return success(true);
  38 + }
  39 +
  40 +
  41 + @PostMapping("/task-steps")
  42 + public CommonResult<TaskHandleVO> getTaskSteps(@RequestBody TaskQueryReqVO taskQuery) {
  43 + return success( taskService.getTaskSteps(taskQuery));
  44 + }
  45 +
  46 + @PostMapping("/complete")
  47 + public CommonResult<Boolean> complete(@RequestBody TaskReqVO taskReq) {
  48 + taskService.completeTask(taskReq);
  49 + return success(true);
  50 + }
  51 +
  52 +
  53 + @GetMapping("/process/history-steps")
  54 + public CommonResult<List<TaskStepVO>> getHistorySteps(@RequestParam("id") String processInstanceId) {
  55 + return success( taskService.getHistorySteps(processInstanceId));
  56 + }
  57 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskHandleVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.ToString;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Data
  9 +@ToString
  10 +public class TaskHandleVO {
  11 +
  12 + private Object formObject;
  13 +
  14 +
  15 + private List<TaskStepVO> historyTask;
  16 +
  17 +
  18 + private String taskVariable;
  19 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskQueryReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.ToString;
  5 +
  6 +@Data
  7 +@ToString
  8 +public class TaskQueryReqVO {
  9 +
  10 + private String processKey;
  11 +
  12 + private String taskId;
  13 +
  14 + private String businessKey;
  15 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.ToString;
  5 +
  6 +import java.util.Map;
  7 +
  8 +@Data
  9 +@ToString
  10 +public class TaskReqVO {
  11 +
  12 + private String taskId;
  13 +
  14 + private Map<String,Object> variables;
  15 +
  16 + private String comment;
  17 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskStepVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.ToString;
  5 +
  6 +import java.util.Date;
  7 +
  8 +@Data
  9 +@ToString
  10 +public class TaskStepVO {
  11 +
  12 + private String stepName;
  13 +
  14 + private Date startTime;
  15 +
  16 + private Date endTime;
  17 +
  18 + private String assignee;
  19 +
  20 + private String comment;
  21 +
  22 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@ApiModel("待办任务申请分页 Request VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class TodoTaskPageReqVO extends PageParam {
  14 +
  15 + private String assignee;
  16 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@ApiModel("待办任务 Response VO")
  9 +@Data
  10 +@ToString
  11 +public class TodoTaskRespVO {
  12 +
  13 + private String id;
  14 +
  15 + /**
  16 + * 1:未签收
  17 + * 2:已签收
  18 + */
  19 + private Integer status;
  20 +
  21 +
  22 + private String processName;
  23 +
  24 +
  25 + private String processKey;
  26 +
  27 +
  28 + private String businessKey;
  29 +
  30 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/oa/OaLeaveConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.convert.oa;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
  10 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  11 +
  12 +/**
  13 + * 请假申请 Convert
  14 + *
  15 + * @author 芋艿
  16 + */
  17 +@Mapper
  18 +public interface OaLeaveConvert {
  19 +
  20 + OaLeaveConvert INSTANCE = Mappers.getMapper(OaLeaveConvert.class);
  21 +
  22 + OaLeaveDO convert(OaLeaveCreateReqVO bean);
  23 +
  24 + OaLeaveDO convert(OaLeaveUpdateReqVO bean);
  25 +
  26 + OaLeaveRespVO convert(OaLeaveDO bean);
  27 +
  28 + List<OaLeaveRespVO> convertList(List<OaLeaveDO> list);
  29 +
  30 + PageResult<OaLeaveRespVO> convertPage(PageResult<OaLeaveDO> page);
  31 +
  32 + List<OaLeaveExcelVO> convertList02(List<OaLeaveDO> list);
  33 +
  34 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/workflow/TodoTaskConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.convert.workflow;
  2 +
  3 +import org.mapstruct.Mapper;
  4 +import org.mapstruct.factory.Mappers;
  5 +
  6 +@Mapper
  7 +public interface TodoTaskConvert {
  8 + TodoTaskConvert INSTANCE = Mappers.getMapper(TodoTaskConvert.class);
  9 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/oa/OaLeaveDO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import com.baomidou.mybatisplus.annotation.*;
  6 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  7 +
  8 +/**
  9 + * 请假申请 DO
  10 + *
  11 + * @author 芋艿
  12 + */
  13 +@TableName("oa_leave")
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +@ToString(callSuper = true)
  17 +@Builder
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
  20 +public class OaLeaveDO extends BaseDO {
  21 +
  22 + /**
  23 + * 请假表单主键
  24 + */
  25 + @TableId
  26 + private Long id;
  27 + /**
  28 + * 流程id
  29 + */
  30 + private String processInstanceId;
  31 + /**
  32 + * 状态
  33 + */
  34 + private Integer status;
  35 + /**
  36 + * 申请人id
  37 + */
  38 + private String userId;
  39 + /**
  40 + * 开始时间
  41 + */
  42 + private Date startTime;
  43 + /**
  44 + * 结束时间
  45 + */
  46 + private Date endTime;
  47 + /**
  48 + * 请假类型
  49 + */
  50 + private String leaveType;
  51 + /**
  52 + * 原因
  53 + */
  54 + private String reason;
  55 + /**
  56 + * 申请时间
  57 + */
  58 + private Date applyTime;
  59 +
  60 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/mysql/oa/OaLeaveMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
  11 +
  12 +/**
  13 + * 请假申请 Mapper
  14 + *
  15 + * @author 芋艿
  16 + */
  17 +@Mapper
  18 +public interface OaLeaveMapper extends BaseMapperX<OaLeaveDO> {
  19 +
  20 + default PageResult<OaLeaveDO> selectPage(OaLeavePageReqVO reqVO) {
  21 + return selectPage(reqVO, new QueryWrapperX<OaLeaveDO>()
  22 + .eqIfPresent("process_instance_id", reqVO.getProcessInstanceId())
  23 + .eqIfPresent("status", reqVO.getStatus())
  24 + .eqIfPresent("user_id", reqVO.getUserId())
  25 + .betweenIfPresent("start_time", reqVO.getBeginStartTime(), reqVO.getEndStartTime())
  26 + .betweenIfPresent("end_time", reqVO.getBeginEndTime(), reqVO.getEndEndTime())
  27 + .eqIfPresent("leave_type", reqVO.getLeaveType())
  28 + .eqIfPresent("reason", reqVO.getReason())
  29 + .betweenIfPresent("apply_time", reqVO.getBeginApplyTime(), reqVO.getEndApplyTime())
  30 + .orderByDesc("id") );
  31 + }
  32 +
  33 + default List<OaLeaveDO> selectList(OaLeaveExportReqVO reqVO) {
  34 + return selectList(new QueryWrapperX<OaLeaveDO>()
  35 + .eqIfPresent("process_instance_id", reqVO.getProcessInstanceId())
  36 + .eqIfPresent("status", reqVO.getStatus())
  37 + .eqIfPresent("user_id", reqVO.getUserId())
  38 + .betweenIfPresent("start_time", reqVO.getBeginStartTime(), reqVO.getEndStartTime())
  39 + .betweenIfPresent("end_time", reqVO.getBeginEndTime(), reqVO.getEndEndTime())
  40 + .eqIfPresent("leave_type", reqVO.getLeaveType())
  41 + .eqIfPresent("reason", reqVO.getReason())
  42 + .betweenIfPresent("apply_time", reqVO.getBeginApplyTime(), reqVO.getEndApplyTime())
  43 + .orderByDesc("id") );
  44 + }
  45 +
  46 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/enums/OaErrorCodeConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.common.exception.ErrorCode;
  4 +/**
  5 + * activiti 系统 错误码枚举类
  6 + *
  7 + * 003 activiti
  8 + * 001 oa
  9 + * activiti 系统,使用 1-003-000-000 段
  10 + */
  11 +public interface OaErrorCodeConstants {
  12 + ErrorCode LEAVE_NOT_EXISTS = new ErrorCode(1003001001, "请假申请不存在");
  13 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupManagerService.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.config;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
  4 +import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
  5 +import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
  6 +import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  7 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  8 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  9 +import org.activiti.api.runtime.shared.identity.UserGroupManager;
  10 +import org.springframework.security.core.userdetails.UserDetails;
  11 +import org.springframework.security.core.userdetails.UserDetailsService;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +
  15 +import javax.annotation.Resource;
  16 +import java.util.*;
  17 +import java.util.stream.Collectors;
  18 +
  19 +import static java.util.Collections.singleton;
  20 +
  21 +@Service
  22 +public class UserGroupManagerService implements UserGroupManager {
  23 +
  24 + @Resource
  25 + private UserDetailsService userDetailsService;
  26 +
  27 + @Resource
  28 + private SysUserService userService;
  29 +
  30 + @Resource
  31 + private SysPostService sysPostService;
  32 +
  33 + /**
  34 + * 暂时使用岗位来代替
  35 + * @param userId
  36 + * @return
  37 + */
  38 + @Override
  39 + public List<String> getUserGroups(String userId) {
  40 + final LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(userId);
  41 + final Long id = loginUser.getId();
  42 + final SysUserDO user = userService.getUser(id);
  43 + return sysPostService.getPosts(user.getPostIds()).stream().map(post -> post.getCode()).collect(Collectors.toList());
  44 +
  45 + }
  46 +
  47 + @Override
  48 + public List<String> getUserRoles(String userId) {
  49 + return Arrays.asList("ROLE_ACTIVITI_USER");
  50 + }
  51 +
  52 + @Override
  53 + public List<String> getGroups() {
  54 + throw new UnsupportedOperationException("getGroups is now un supported");
  55 + }
  56 +
  57 + @Override
  58 + public List<String> getUsers() {
  59 + throw new UnsupportedOperationException("getGroups is now un supported");
  60 + }
  61 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupsProvider.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.config;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  4 +import org.activiti.api.runtime.shared.security.PrincipalGroupsProvider;
  5 +import org.springframework.security.core.Authentication;
  6 +import org.springframework.stereotype.Service;
  7 +
  8 +import java.security.Principal;
  9 +import java.util.Collections;
  10 +import java.util.List;
  11 +
  12 +@Service
  13 +public class UserGroupsProvider implements PrincipalGroupsProvider {
  14 +
  15 + @Override
  16 + public List<String> getGroups(Principal principal) {
  17 +
  18 + if(principal instanceof Authentication){
  19 + Authentication authentication = (Authentication) principal;
  20 + final Object user = authentication.getPrincipal();
  21 + if( user instanceof LoginUser){
  22 + return ((LoginUser) user).getGroups();
  23 + }else{
  24 + return Collections.emptyList();
  25 + }
  26 + }else{
  27 + return Collections.emptyList();
  28 + }
  29 +
  30 + }
  31 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/OaLeaveService.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.oa;
  2 +
  3 +
  4 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveCreateReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveExportReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeavePageReqVO;
  7 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveUpdateReqVO;
  8 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +
  11 +import javax.validation.Valid;
  12 +import java.util.Collection;
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * 请假申请 Service 接口
  17 + *
  18 + * @author 芋艿
  19 + */
  20 +public interface OaLeaveService {
  21 +
  22 + /**
  23 + * 创建请假申请
  24 + *
  25 + * @param createReqVO 创建信息
  26 + * @return 编号
  27 + */
  28 + Long createLeave(@Valid OaLeaveCreateReqVO createReqVO);
  29 +
  30 + /**
  31 + * 更新请假申请
  32 + *
  33 + * @param updateReqVO 更新信息
  34 + */
  35 + void updateLeave(@Valid OaLeaveUpdateReqVO updateReqVO);
  36 +
  37 + /**
  38 + * 删除请假申请
  39 + *
  40 + * @param id 编号
  41 + */
  42 + void deleteLeave(Long id);
  43 +
  44 + /**
  45 + * 获得请假申请
  46 + *
  47 + * @param id 编号
  48 + * @return 请假申请
  49 + */
  50 + OaLeaveDO getLeave(Long id);
  51 +
  52 + /**
  53 + * 获得请假申请列表
  54 + *
  55 + * @param ids 编号
  56 + * @return 请假申请列表
  57 + */
  58 + List<OaLeaveDO> getLeaveList(Collection<Long> ids);
  59 +
  60 + /**
  61 + * 获得请假申请分页
  62 + *
  63 + * @param pageReqVO 分页查询
  64 + * @return 请假申请分页
  65 + */
  66 + PageResult<OaLeaveDO> getLeavePage(OaLeavePageReqVO pageReqVO);
  67 +
  68 + /**
  69 + * 获得请假申请列表, 用于 Excel 导出
  70 + *
  71 + * @param exportReqVO 查询条件
  72 + * @return 请假申请列表
  73 + */
  74 + List<OaLeaveDO> getLeaveList(OaLeaveExportReqVO exportReqVO);
  75 +
  76 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/ReportBackEndProcessor.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.oa;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  4 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
  5 +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  6 +import org.activiti.engine.delegate.DelegateTask;
  7 +import org.activiti.engine.delegate.TaskListener;
  8 +import org.springframework.stereotype.Component;
  9 +import org.springframework.transaction.annotation.Transactional;
  10 +
  11 +import javax.annotation.Resource;
  12 +
  13 +@Component
  14 +public class ReportBackEndProcessor implements TaskListener {
  15 +
  16 + @Resource
  17 + private OaLeaveMapper leaveMapper;
  18 +
  19 +
  20 + @Override
  21 + @Transactional(rollbackFor = Exception.class)
  22 + public void notify(DelegateTask delegateTask) {
  23 + final String businessKey = delegateTask.getExecution().getProcessInstanceBusinessKey();
  24 + UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
  25 + updateWrapper.eq("id", Long.valueOf(businessKey));
  26 + OaLeaveDO updateDo = new OaLeaveDO();
  27 + updateDo.setStatus(2);
  28 + leaveMapper.update(updateDo, updateWrapper);
  29 + }
  30 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/impl/OaLeaveServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.oa.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  4 +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  5 +import org.activiti.engine.RuntimeService;
  6 +import org.activiti.engine.runtime.ProcessInstance;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Service;
  9 +import javax.annotation.Resource;
  10 +
  11 +import org.springframework.transaction.annotation.Transactional;
  12 +import org.springframework.validation.annotation.Validated;
  13 +
  14 +import java.util.*;
  15 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
  16 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  18 +
  19 +import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
  20 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
  21 +import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  24 +import static cn.iocoder.yudao.adminserver.modules.activiti.enums.OaErrorCodeConstants.*;
  25 +
  26 +/**
  27 + * 请假申请 Service 实现类
  28 + *
  29 + * @author 芋艿
  30 + */
  31 +@Service
  32 +@Validated
  33 +public class OaLeaveServiceImpl implements OaLeaveService {
  34 +
  35 + @Resource
  36 + private OaLeaveMapper leaveMapper;
  37 +
  38 + @Resource
  39 + private RuntimeService runtimeService;
  40 +
  41 + @Override
  42 + @Transactional(rollbackFor = Exception.class)
  43 + public Long createLeave(OaLeaveCreateReqVO createReqVO) {
  44 + // 插入
  45 + OaLeaveDO leave = OaLeaveConvert.INSTANCE.convert(createReqVO);
  46 + leave.setStatus(1);
  47 + leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
  48 + leaveMapper.insert(leave);
  49 +
  50 + Map<String, Object> variables = new HashMap<>();
  51 + //如何得到部门领导人, 暂时写死
  52 + variables.put("deptLeader", "admin");
  53 + final Long id = leave.getId();
  54 + String businessKey = String.valueOf(id);
  55 + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables);
  56 +
  57 + final String processInstanceId = processInstance.getProcessInstanceId();
  58 +
  59 +
  60 + UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
  61 + updateWrapper.eq("id", id);
  62 + OaLeaveDO updateDo = new OaLeaveDO();
  63 + updateDo.setProcessInstanceId(processInstanceId);
  64 + leaveMapper.update(updateDo, updateWrapper);
  65 + // 返回
  66 + return id;
  67 + }
  68 +
  69 + @Override
  70 + public void updateLeave(OaLeaveUpdateReqVO updateReqVO) {
  71 + // 校验存在
  72 + this.validateLeaveExists(updateReqVO.getId());
  73 + // 更新
  74 + OaLeaveDO updateObj = OaLeaveConvert.INSTANCE.convert(updateReqVO);
  75 + leaveMapper.updateById(updateObj);
  76 + }
  77 +
  78 + @Override
  79 + public void deleteLeave(Long id) {
  80 + // 校验存在
  81 + this.validateLeaveExists(id);
  82 + // 删除
  83 + leaveMapper.deleteById(id);
  84 + }
  85 +
  86 + private void validateLeaveExists(Long id) {
  87 + if (leaveMapper.selectById(id) == null) {
  88 + throw exception(LEAVE_NOT_EXISTS);
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + public OaLeaveDO getLeave(Long id) {
  94 + return leaveMapper.selectById(id);
  95 + }
  96 +
  97 + @Override
  98 + public List<OaLeaveDO> getLeaveList(Collection<Long> ids) {
  99 + return leaveMapper.selectBatchIds(ids);
  100 + }
  101 +
  102 + @Override
  103 + public PageResult<OaLeaveDO> getLeavePage(OaLeavePageReqVO pageReqVO) {
  104 + return leaveMapper.selectPage(pageReqVO);
  105 + }
  106 +
  107 + @Override
  108 + public List<OaLeaveDO> getLeaveList(OaLeaveExportReqVO exportReqVO) {
  109 + return leaveMapper.selectList(exportReqVO);
  110 + }
  111 +
  112 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/TaskService.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +
  6 +import javax.servlet.http.HttpServletResponse;
  7 +import java.util.List;
  8 +
  9 +public interface TaskService {
  10 +
  11 + PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO);
  12 +
  13 + void claimTask(String taskId);
  14 +
  15 + void getTaskHistory(String taskId);
  16 +
  17 + void completeTask(TaskReqVO taskReq);
  18 +
  19 +// void flowImage(String taskId, HttpServletResponse response);
  20 + TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery);
  21 +
  22 + List<TaskStepVO> getHistorySteps(String processInstanceId);
  23 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/impl/TaskServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.impl;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
  4 +import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
  5 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
  6 +import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
  7 +import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
  8 +import cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.TaskService;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  11 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  12 +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  13 +import com.google.common.collect.ImmutableMap;
  14 +import org.activiti.api.process.runtime.ProcessRuntime;
  15 +import org.activiti.api.runtime.shared.query.Page;
  16 +import org.activiti.api.runtime.shared.query.Pageable;
  17 +import org.activiti.api.task.model.Task;
  18 +import org.activiti.api.task.model.builders.ClaimTaskPayloadBuilder;
  19 +import org.activiti.api.task.model.builders.GetTasksPayloadBuilder;
  20 +import org.activiti.api.task.model.builders.TaskPayloadBuilder;
  21 +import org.activiti.api.task.runtime.TaskRuntime;
  22 +import org.activiti.bpmn.model.BpmnModel;
  23 +import org.activiti.bpmn.model.Process;
  24 +import org.activiti.engine.HistoryService;
  25 +import org.activiti.engine.RepositoryService;
  26 +import org.activiti.engine.history.HistoricActivityInstance;
  27 +import org.activiti.engine.history.HistoricProcessInstance;
  28 +import org.activiti.engine.history.HistoricVariableInstance;
  29 +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
  30 +import org.activiti.engine.repository.ProcessDefinition;
  31 +import org.activiti.engine.task.Comment;
  32 +import org.springframework.stereotype.Service;
  33 +import org.springframework.transaction.annotation.Transactional;
  34 +
  35 +import javax.annotation.Resource;
  36 +import javax.servlet.http.HttpServletResponse;
  37 +import java.util.ArrayList;
  38 +import java.util.List;
  39 +import java.util.Map;
  40 +import java.util.Optional;
  41 +import java.util.stream.Collectors;
  42 +
  43 +@Service
  44 +public class TaskServiceImpl implements TaskService {
  45 +
  46 + @Resource
  47 + private TaskRuntime taskRuntime;
  48 +
  49 + @Resource
  50 + private org.activiti.engine.TaskService activitiTaskService;
  51 +
  52 + @Resource
  53 + private HistoryService historyService;
  54 +
  55 + @Resource
  56 + private RepositoryService repositoryService;
  57 +
  58 + @Resource
  59 + private OaLeaveMapper leaveMapper;
  60 +
  61 + private static Map<String,String> taskVariable = ImmutableMap.<String,String>builder()
  62 + .put("deptLeaderVerify","deptLeaderApproved")
  63 + .put("hrVerify","hrApproved")
  64 + .build();
  65 +
  66 + public TaskServiceImpl() {
  67 +
  68 + }
  69 +
  70 + @Override
  71 + public PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO) {
  72 + final LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
  73 + final Pageable pageable = Pageable.of((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), pageReqVO.getPageSize());
  74 + Page<Task> pageTasks = taskRuntime.tasks(pageable);
  75 + List<Task> tasks = pageTasks.getContent();
  76 + int totalItems = pageTasks.getTotalItems();
  77 + final List<TodoTaskRespVO> respVOList = tasks.stream().map(task -> {
  78 + TodoTaskRespVO respVO = new TodoTaskRespVO();
  79 + respVO.setId(task.getId());
  80 + final ProcessDefinition definition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
  81 + respVO.setProcessName(definition.getName());
  82 + respVO.setProcessKey(definition.getKey());
  83 + respVO.setBusinessKey(task.getBusinessKey());
  84 + respVO.setStatus(task.getAssignee() == null ? 1 : 2);
  85 + return respVO;
  86 + }).collect(Collectors.toList());
  87 + return new PageResult(respVOList, Long.valueOf(totalItems));
  88 + }
  89 +
  90 +
  91 + @Override
  92 + public void claimTask(String taskId) {
  93 + taskRuntime.claim(new ClaimTaskPayloadBuilder()
  94 + .withTaskId(taskId)
  95 + .withAssignee(SecurityFrameworkUtils.getLoginUser().getUsername())
  96 + .build());
  97 + }
  98 +
  99 + @Override
  100 + public void getTaskHistory(String taskId) {
  101 +
  102 + final List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().
  103 + processInstanceId("8e2801fc-1a38-11ec-98ce-74867a13730f").list();
  104 +
  105 + }
  106 +
  107 + @Override
  108 + @Transactional
  109 + public void completeTask(TaskReqVO taskReq) {
  110 + final Task task = taskRuntime.task(taskReq.getTaskId());
  111 +
  112 + final Map<String, Object> variables = taskReq.getVariables();
  113 +
  114 + activitiTaskService.addComment(taskReq.getTaskId(), task.getProcessInstanceId(), taskReq.getComment());
  115 +
  116 + taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskReq.getTaskId())
  117 + .withVariables(taskReq.getVariables())
  118 + .build());
  119 +
  120 + if(variables.containsValue(Boolean.FALSE)){
  121 + final String businessKey = task.getBusinessKey();
  122 + UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
  123 + updateWrapper.eq("id", Long.valueOf(businessKey));
  124 + OaLeaveDO updateDo = new OaLeaveDO();
  125 + updateDo.setStatus(2);
  126 + leaveMapper.update(updateDo, updateWrapper);
  127 + }
  128 +
  129 + }
  130 +
  131 +// @Override
  132 +// public void flowImage(String taskId, HttpServletResponse response) {
  133 +//
  134 +// final Task task = taskRuntime.task(taskId);
  135 +// BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
  136 +// final Process process = bpmnModel.getMainProcess();
  137 +// ProcessDefinitionEntity processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
  138 +// List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
  139 +// List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstance.getId());
  140 +// ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
  141 +// InputStream imageStream =diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows);
  142 +//
  143 +// // 输出资源内容到相应对象
  144 +// byte[] b = new byte[1024];
  145 +// int len;
  146 +// while ((len = imageStream.read(b, 0, 1024)) != -1) {
  147 +// response.getOutputStream().write(b, 0, len);
  148 +// }
  149 +// }
  150 +
  151 + @Override
  152 + public TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery) {
  153 + TaskHandleVO handleVO = new TaskHandleVO();
  154 +
  155 + String processKey = taskQuery.getProcessKey();
  156 + if ("leave".equals(processKey)) {
  157 + String businessKey = taskQuery.getBusinessKey();
  158 + final OaLeaveDO leave = leaveMapper.selectById(Long.valueOf(businessKey));
  159 + handleVO.setFormObject( OaLeaveConvert.INSTANCE.convert(leave));
  160 + }
  161 +
  162 + final Task task = taskRuntime.task(taskQuery.getTaskId());
  163 + final String taskDefKey = task.getTaskDefinitionKey();
  164 + final String variableName = Optional.ofNullable(taskVariable.get(taskDefKey)).orElse("");
  165 +
  166 +
  167 + handleVO.setTaskVariable(variableName);
  168 + List<TaskStepVO> steps = getTaskSteps(task.getProcessInstanceId());
  169 +
  170 + handleVO.setHistoryTask(steps);
  171 + return handleVO;
  172 + }
  173 +
  174 +
  175 + private List<TaskStepVO> getTaskSteps(String processInstanceId) {
  176 +
  177 + List<TaskStepVO> steps = new ArrayList<>();
  178 +
  179 + List<HistoricActivityInstance> finished = historyService
  180 + .createHistoricActivityInstanceQuery()
  181 + .processInstanceId(processInstanceId)
  182 + .activityType("userTask")
  183 + .finished()
  184 + .orderByHistoricActivityInstanceStartTime().asc().list();
  185 +
  186 + finished.forEach(instance->{
  187 + TaskStepVO step = new TaskStepVO();
  188 + step.setStepName(instance.getActivityName());
  189 + step.setStartTime(instance.getStartTime());
  190 + step.setEndTime(instance.getEndTime());
  191 + step.setAssignee(instance.getAssignee());
  192 + final List<Comment> comments = activitiTaskService.getTaskComments(instance.getTaskId());
  193 + if(comments.size()>0){
  194 + step.setComment(comments.get(0).getFullMessage());
  195 + }else{
  196 + step.setComment("");
  197 + }
  198 + steps.add(step);
  199 + });
  200 +
  201 + List<HistoricActivityInstance> unfinished = historyService
  202 + .createHistoricActivityInstanceQuery()
  203 + .processInstanceId(processInstanceId)
  204 + .activityType("userTask")
  205 + .unfinished().list();
  206 +
  207 + if(unfinished.size()>0) {
  208 +
  209 + final HistoricActivityInstance unFinishedActiviti = unfinished.get(0);
  210 + TaskStepVO step = new TaskStepVO();
  211 + step.setStepName(unFinishedActiviti.getActivityName());
  212 + step.setStartTime(unFinishedActiviti.getStartTime());
  213 + step.setEndTime(unFinishedActiviti.getEndTime());
  214 + step.setAssignee(Optional.ofNullable(unFinishedActiviti.getAssignee()).orElse(""));
  215 + step.setComment("");
  216 + steps.add(step);
  217 + }
  218 + return steps;
  219 + }
  220 +
  221 +
  222 + @Override
  223 + public List<TaskStepVO> getHistorySteps(String processInstanceId) {
  224 +
  225 + return getTaskSteps(processInstanceId);
  226 + }
  227 +
  228 +
  229 +
  230 +// private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
  231 +//
  232 +// List<String> highLightedFlows = new ArrayList<String>();
  233 +// List<HistoricActivityInstance> historicActivityInstances = historyService
  234 +// .createHistoricActivityInstanceQuery()
  235 +// .processInstanceId(processInstanceId)
  236 +// .orderByHistoricActivityInstanceStartTime().asc().list();
  237 +//
  238 +// List<String> historicActivityInstanceList = new ArrayList<String>();
  239 +// for (HistoricActivityInstance hai : historicActivityInstances) {
  240 +// historicActivityInstanceList.add(hai.getActivityId());
  241 +// }
  242 +
  243 +// // add current activities to list
  244 +// List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
  245 +// historicActivityInstanceList.addAll(highLightedActivities);
  246 +
  247 + // activities and their sequence-flows
  248 +// for (ActivityImpl activity : processDefinition.getActivities()) {
  249 +// int index = historicActivityInstanceList.indexOf(activity.getId());
  250 +//
  251 +// if (index >= 0 && index + 1 < historicActivityInstanceList.size()) {
  252 +// List<PvmTransition> pvmTransitionList = activity
  253 +// .getOutgoingTransitions();
  254 +// for (PvmTransition pvmTransition : pvmTransitionList) {
  255 +// String destinationFlowId = pvmTransition.getDestination().getId();
  256 +// if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) {
  257 +// highLightedFlows.add(pvmTransition.getId());
  258 +// }
  259 +// }
  260 +// }
  261 +// }
  262 +// return highLightedFlows;
  263 +// }
  264 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
2 2  
  3 +import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
3 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 5 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
5 6 import cn.iocoder.yudao.framework.security.core.LoginUser;
... ... @@ -31,10 +32,14 @@ import org.springframework.stereotype.Service;
31 32 import org.springframework.util.Assert;
32 33  
33 34 import javax.annotation.Resource;
  35 +import java.util.List;
  36 +import java.util.Optional;
34 37 import java.util.Set;
  38 +import java.util.stream.Collectors;
35 39  
36 40 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 41 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
  42 +import static java.util.Collections.EMPTY_LIST;
38 43 import static java.util.Collections.singleton;
39 44  
40 45 /**
... ... @@ -59,6 +64,8 @@ public class SysAuthServiceImpl implements SysAuthService {
59 64 private SysLoginLogService loginLogService;
60 65 @Resource
61 66 private SysUserSessionService userSessionService;
  67 + @Resource
  68 + private SysPostService sysPostService;
62 69  
63 70 @Override
64 71 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
... ... @@ -68,7 +75,9 @@ public class SysAuthServiceImpl implements SysAuthService {
68 75 throw new UsernameNotFoundException(username);
69 76 }
70 77 // 创建 LoginUser 对象
71   - return SysAuthConvert.INSTANCE.convert(user);
  78 + LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
  79 + loginUser.setPostIds(user.getPostIds());
  80 + return loginUser;
72 81 }
73 82  
74 83 @Override
... ... @@ -92,11 +101,18 @@ public class SysAuthServiceImpl implements SysAuthService {
92 101 // 使用账号密码,进行登陆。
93 102 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
94 103 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
95   -
  104 + loginUser.setGroups(this.getUserPosts(loginUser.getPostIds()));
96 105 // 缓存登陆用户到 Redis 中,返回 sessionId 编号
97 106 return userSessionService.createUserSession(loginUser, userIp, userAgent);
98 107 }
99 108  
  109 +
  110 + private List<String> getUserPosts(Set<Long> postIds) {
  111 + return Optional.ofNullable(postIds).map(ids->
  112 + sysPostService.getPosts(ids).stream().map(post -> post.getCode()).collect(Collectors.toList())
  113 + ).orElse(EMPTY_LIST);
  114 + }
  115 +
100 116 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
101 117 String code = captchaService.getCaptchaCode(captchaUUID);
102 118 // 验证码不存在
... ... @@ -122,6 +138,7 @@ public class SysAuthServiceImpl implements SysAuthService {
122 138 // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
123 139 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
124 140 authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
  141 + // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
125 142 } catch (BadCredentialsException badCredentialsException) {
126 143 this.createLoginLog(username, SysLoginResultEnum.BAD_CREDENTIALS);
127 144 throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
... ...
yudao-admin-server/src/main/resources/application.yaml
... ... @@ -22,9 +22,10 @@ spring:
22 22  
23 23 # MyBatis Plus 的配置项
24 24 mybatis-plus:
25   - configuration:
26   - map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
27   - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
  25 +# 在 mybatis-config/mybatis-config.xml 中设置
  26 +# configuration:
  27 +# map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
  28 +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
28 29 global-config:
29 30 db-config:
30 31 id-type: AUTO # 自增 ID
... ... @@ -32,6 +33,18 @@ mybatis-plus:
32 33 logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
33 34 mapper-locations: classpath*:mapper/*.xml
34 35 type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject
  36 + config-location: classpath:mybatis-config/mybatis-config.xml
  37 + configuration-properties:
  38 + prefix: ""
  39 + wildcardEscapeClause: ""
  40 + limitBefore: ""
  41 + limitAfter: "LIMIT #{maxResults} OFFSET #{firstResult}"
  42 + limitBetween: ""
  43 + limitOuterJoinBetween: ""
  44 + limitBeforeNativeQuery: ""
  45 + orderBy: "order by ${orderByColumns}"
  46 + blobType: "BLOB"
  47 + boolValue: "TRUE"
35 48  
36 49 --- #################### 芋道相关配置 ####################
37 50  
... ...
yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +
  3 +<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4 +
  5 +<configuration>
  6 + <settings>
  7 + <setting name="lazyLoadingEnabled" value="false" />
  8 + <setting name="mapUnderscoreToCamelCase" value="true"/>
  9 + </settings>
  10 + <typeAliases>
  11 + <typeAlias type="org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler" alias="ByteArrayRefTypeHandler"/>
  12 + <typeAlias type="org.activiti.engine.impl.db.IbatisVariableTypeHandler" alias="IbatisVariableTypeHandler"/>
  13 + </typeAliases>
  14 + <typeHandlers>
  15 + <typeHandler handler="ByteArrayRefTypeHandler"
  16 + javaType="org.activiti.engine.impl.persistence.entity.ByteArrayRef"
  17 + jdbcType="VARCHAR"/>
  18 + <typeHandler handler="IbatisVariableTypeHandler"
  19 + javaType="org.activiti.engine.impl.variable.VariableType"
  20 + jdbcType="VARCHAR"/>
  21 + </typeHandlers>
  22 + <mappers>
  23 + <mapper resource="org/activiti/db/mapping/common.xml" />
  24 + <mapper resource="org/activiti/db/mapping/entity/Attachment.xml" />
  25 + <mapper resource="org/activiti/db/mapping/entity/ByteArray.xml" />
  26 + <mapper resource="org/activiti/db/mapping/entity/Comment.xml" />
  27 + <mapper resource="org/activiti/db/mapping/entity/DeadLetterJob.xml" />
  28 + <mapper resource="org/activiti/db/mapping/entity/Deployment.xml" />
  29 + <mapper resource="org/activiti/db/mapping/entity/Execution.xml" />
  30 + <mapper resource="org/activiti/db/mapping/entity/HistoricActivityInstance.xml" />
  31 + <mapper resource="org/activiti/db/mapping/entity/HistoricDetail.xml" />
  32 + <mapper resource="org/activiti/db/mapping/entity/HistoricProcessInstance.xml" />
  33 + <mapper resource="org/activiti/db/mapping/entity/HistoricVariableInstance.xml" />
  34 + <mapper resource="org/activiti/db/mapping/entity/HistoricTaskInstance.xml" />
  35 + <mapper resource="org/activiti/db/mapping/entity/HistoricIdentityLink.xml" />
  36 + <mapper resource="org/activiti/db/mapping/entity/IdentityLink.xml" />
  37 + <mapper resource="org/activiti/db/mapping/entity/Job.xml" />
  38 + <mapper resource="org/activiti/db/mapping/entity/Model.xml" />
  39 + <mapper resource="org/activiti/db/mapping/entity/ProcessDefinition.xml" />
  40 + <mapper resource="org/activiti/db/mapping/entity/ProcessDefinitionInfo.xml" />
  41 + <mapper resource="org/activiti/db/mapping/entity/Property.xml" />
  42 + <mapper resource="org/activiti/db/mapping/entity/Resource.xml" />
  43 + <mapper resource="org/activiti/db/mapping/entity/SuspendedJob.xml" />
  44 + <mapper resource="org/activiti/db/mapping/entity/TableData.xml" />
  45 + <mapper resource="org/activiti/db/mapping/entity/Task.xml" />
  46 + <mapper resource="org/activiti/db/mapping/entity/TimerJob.xml" />
  47 + <mapper resource="org/activiti/db/mapping/entity/VariableInstance.xml" />
  48 + <mapper resource="org/activiti/db/mapping/entity/EventSubscription.xml" />
  49 + <mapper resource="org/activiti/db/mapping/entity/EventLogEntry.xml" />
  50 + <mapper resource="org/activiti/db/mapping/entity/IntegrationContext.xml" />
  51 + </mappers>
  52 +</configuration>
... ...
yudao-admin-server/src/main/resources/processes/leave.bpmn 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://bpmn.io/schema/bpmn">
  3 + <process id="leave" name="请假流程-普通表单" isExecutable="true">
  4 + <documentation>请假流程演示</documentation>
  5 + <startEvent id="startevent1" name="Start" activiti:initiator="applyUserId"></startEvent>
  6 + <userTask id="deptLeaderVerify" name="部门领导审批" activiti:assignee="${deptLeader}"></userTask>
  7 + <exclusiveGateway id="exclusivegateway5" name="Exclusive Gateway"></exclusiveGateway>
  8 + <userTask id="hrVerify" name="人事审批" activiti:candidateGroups="hr"></userTask>
  9 + <exclusiveGateway id="exclusivegateway6" name="Exclusive Gateway"></exclusiveGateway>
  10 + <userTask id="reportBack" name="申请人确认" activiti:assignee="${applyUserId}">
  11 + <extensionElements>
  12 + <activiti:taskListener event="complete" delegateExpression="${reportBackEndProcessor}"></activiti:taskListener>
  13 + </extensionElements>
  14 + </userTask>
  15 + <endEvent id="endevent1" name="End"></endEvent>
  16 + <sequenceFlow id="flow2" sourceRef="startevent1" targetRef="deptLeaderVerify"></sequenceFlow>
  17 + <sequenceFlow id="flow3" sourceRef="deptLeaderVerify" targetRef="exclusivegateway5"></sequenceFlow>
  18 + <sequenceFlow id="flow5" name="部门领导审批-同意" sourceRef="exclusivegateway5" targetRef="hrVerify">
  19 + <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApproved}]]></conditionExpression>
  20 + </sequenceFlow>
  21 + <sequenceFlow id="flow6" sourceRef="hrVerify" targetRef="exclusivegateway6"></sequenceFlow>
  22 + <sequenceFlow id="flow7" name="人事审批-同意" sourceRef="exclusivegateway6" targetRef="reportBack">
  23 + <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrApproved}]]></conditionExpression>
  24 + </sequenceFlow>
  25 + <sequenceFlow id="flow8" sourceRef="reportBack" targetRef="endevent1"></sequenceFlow>
  26 + <sequenceFlow id="flow4" name="部门领导审批-不同意" sourceRef="exclusivegateway5" targetRef="endevent1" >
  27 + <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!deptLeaderApproved}]]></conditionExpression>
  28 + </sequenceFlow>
  29 + <sequenceFlow sourceRef="exclusivegateway6" name="人事审批-不同意" targetRef="endevent1" id="flow9">
  30 + <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!hrApproved}]]></conditionExpression>
  31 + </sequenceFlow>
  32 + </process>
  33 + <bpmndi:BPMNDiagram id="BPMNDiagram_leave">
  34 + <bpmndi:BPMNPlane bpmnElement="leave" id="BPMNPlane_leave">
  35 + <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
  36 + <omgdc:Bounds height="35.0" width="35.0" x="0.0" y="46.0"></omgdc:Bounds>
  37 + </bpmndi:BPMNShape>
  38 + <bpmndi:BPMNShape bpmnElement="deptLeaderVerify" id="BPMNShape_deptLeaderVerify">
  39 + <omgdc:Bounds height="55.0" width="105.0" x="80.0" y="36.0"></omgdc:Bounds>
  40 + </bpmndi:BPMNShape>
  41 + <bpmndi:BPMNShape bpmnElement="exclusivegateway5" id="BPMNShape_exclusivegateway5">
  42 + <omgdc:Bounds height="40.0" width="40.0" x="240.0" y="43.0"></omgdc:Bounds>
  43 + </bpmndi:BPMNShape>
  44 + <bpmndi:BPMNShape bpmnElement="hrVerify" id="BPMNShape_hrVerify">
  45 + <omgdc:Bounds height="55.0" width="105.0" x="348.0" y="36.0"></omgdc:Bounds>
  46 + </bpmndi:BPMNShape>
  47 + <bpmndi:BPMNShape bpmnElement="exclusivegateway6" id="BPMNShape_exclusivegateway6">
  48 + <omgdc:Bounds height="40.0" width="40.0" x="485.0" y="43.0"></omgdc:Bounds>
  49 + </bpmndi:BPMNShape>
  50 + <bpmndi:BPMNShape bpmnElement="reportBack" id="BPMNShape_reportBack">
  51 + <omgdc:Bounds height="55.0" width="105.0" x="580.0" y="36.0"></omgdc:Bounds>
  52 + </bpmndi:BPMNShape>
  53 + <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
  54 + <omgdc:Bounds height="35.0" width="35.0" x="615.0" y="195.0"></omgdc:Bounds>
  55 + </bpmndi:BPMNShape>
  56 + <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
  57 + <omgdi:waypoint x="35.0" y="63.0"></omgdi:waypoint>
  58 + <omgdi:waypoint x="80.0" y="63.0"></omgdi:waypoint>
  59 + </bpmndi:BPMNEdge>
  60 + <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
  61 + <omgdi:waypoint x="185.0" y="63.0"></omgdi:waypoint>
  62 + <omgdi:waypoint x="240.0" y="63.0"></omgdi:waypoint>
  63 + </bpmndi:BPMNEdge>
  64 + <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
  65 + <omgdi:waypoint x="260.0" y="83.0"></omgdi:waypoint>
  66 + <omgdi:waypoint x="260.0" y="114.0"></omgdi:waypoint>
  67 + <bpmndi:BPMNLabel>
  68 + <omgdc:Bounds height="11.0" width="33.0" x="270.0" y="83.0"></omgdc:Bounds>
  69 + </bpmndi:BPMNLabel>
  70 + </bpmndi:BPMNEdge>
  71 + <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
  72 + <omgdi:waypoint x="280.0" y="63.0"></omgdi:waypoint>
  73 + <omgdi:waypoint x="348.0" y="63.0"></omgdi:waypoint>
  74 + <bpmndi:BPMNLabel>
  75 + <omgdc:Bounds height="11.0" width="22.0" x="300.0" y="46.0"></omgdc:Bounds>
  76 + </bpmndi:BPMNLabel>
  77 + </bpmndi:BPMNEdge>
  78 + <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
  79 + <omgdi:waypoint x="453.0" y="63.0"></omgdi:waypoint>
  80 + <omgdi:waypoint x="485.0" y="63.0"></omgdi:waypoint>
  81 + </bpmndi:BPMNEdge>
  82 + <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
  83 + <omgdi:waypoint x="525.0" y="63.0"></omgdi:waypoint>
  84 + <omgdi:waypoint x="580.0" y="63.0"></omgdi:waypoint>
  85 + <bpmndi:BPMNLabel>
  86 + <omgdc:Bounds height="11.0" width="22.0" x="539.0" y="46.0"></omgdc:Bounds>
  87 + </bpmndi:BPMNLabel>
  88 + </bpmndi:BPMNEdge>
  89 + <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
  90 + <omgdi:waypoint x="632.0" y="91.0"></omgdi:waypoint>
  91 + <omgdi:waypoint x="632.0" y="195.0"></omgdi:waypoint>
  92 + </bpmndi:BPMNEdge>
  93 + <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
  94 + <omgdi:waypoint x="505.0" y="83.0"></omgdi:waypoint>
  95 + <omgdi:waypoint x="504.0" y="141.0"></omgdi:waypoint>
  96 + <omgdi:waypoint x="313.0" y="141.0"></omgdi:waypoint>
  97 + <bpmndi:BPMNLabel>
  98 + <omgdc:Bounds height="11.0" width="33.0" x="515.0" y="83.0"></omgdc:Bounds>
  99 + </bpmndi:BPMNLabel>
  100 + </bpmndi:BPMNEdge>
  101 + <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
  102 + <omgdi:waypoint x="240.0" y="212.0"></omgdi:waypoint>
  103 + <omgdi:waypoint x="132.0" y="212.0"></omgdi:waypoint>
  104 + <omgdi:waypoint x="132.0" y="91.0"></omgdi:waypoint>
  105 + <bpmndi:BPMNLabel>
  106 + <omgdc:Bounds height="11.0" width="44.0" x="142.0" y="192.0"></omgdc:Bounds>
  107 + </bpmndi:BPMNLabel>
  108 + </bpmndi:BPMNEdge>
  109 + <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
  110 + <omgdi:waypoint x="260.0" y="169.0"></omgdi:waypoint>
  111 + <omgdi:waypoint x="260.0" y="192.0"></omgdi:waypoint>
  112 + </bpmndi:BPMNEdge>
  113 + <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
  114 + <omgdi:waypoint x="280.0" y="212.0"></omgdi:waypoint>
  115 + <omgdi:waypoint x="615.0" y="212.0"></omgdi:waypoint>
  116 + <bpmndi:BPMNLabel>
  117 + <omgdc:Bounds height="11.0" width="44.0" x="429.0" y="219.0"></omgdc:Bounds>
  118 + </bpmndi:BPMNLabel>
  119 + </bpmndi:BPMNEdge>
  120 + <bpmndi:BPMNEdge bpmnElement="flow4">
  121 + <omgdi:waypoint x="260.0" y="63.0"/>
  122 + <omgdi:waypoint x="632.5" y="212.5"/>
  123 + </bpmndi:BPMNEdge>
  124 + <bpmndi:BPMNEdge bpmnElement="flow9">
  125 + <omgdi:waypoint x="505.0" y="63.0"/>
  126 + <omgdi:waypoint x="632.5" y="212.5"/>
  127 + </bpmndi:BPMNEdge>
  128 + </bpmndi:BPMNPlane>
  129 + </bpmndi:BPMNDiagram>
  130 +</definitions>
0 131 \ No newline at end of file
... ...
yudao-admin-ui/src/api/oa/leave.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 创建请假申请
  4 +export function createLeave(data) {
  5 + return request({
  6 + url: '/oa/leave/create',
  7 + method: 'post',
  8 + data: data
  9 + })
  10 +}
  11 +
  12 +// 更新请假申请
  13 +export function updateLeave(data) {
  14 + return request({
  15 + url: '/oa/leave/update',
  16 + method: 'put',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 删除请假申请
  22 +export function deleteLeave(id) {
  23 + return request({
  24 + url: '/oa/leave/delete?id=' + id,
  25 + method: 'delete'
  26 + })
  27 +}
  28 +
  29 +// 获得请假申请
  30 +export function getLeave(id) {
  31 + return request({
  32 + url: '/oa/leave/get?id=' + id,
  33 + method: 'get'
  34 + })
  35 +}
  36 +
  37 +// 获得请假申请分页
  38 +export function getLeavePage(query) {
  39 + return request({
  40 + url: '/oa/leave/page',
  41 + method: 'get',
  42 + params: query
  43 + })
  44 +}
  45 +
  46 +// 导出请假申请 Excel
  47 +export function exportLeaveExcel(query) {
  48 + return request({
  49 + url: '/oa/leave/export-excel',
  50 + method: 'get',
  51 + params: query,
  52 + responseType: 'blob'
  53 + })
  54 +}
... ...
yudao-admin-ui/src/api/oa/todo.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 创建请假申请
  4 +export function createLeave(data) {
  5 + return request({
  6 + url: '/oa/leave/create',
  7 + method: 'post',
  8 + data: data
  9 + })
  10 +}
  11 +
  12 +// 更新请假申请
  13 +export function updateLeave(data) {
  14 + return request({
  15 + url: '/oa/leave/update',
  16 + method: 'put',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 删除请假申请
  22 +export function deleteLeave(id) {
  23 + return request({
  24 + url: '/oa/leave/delete?id=' + id,
  25 + method: 'delete'
  26 + })
  27 +}
  28 +
  29 +// 获得请假申请
  30 +export function getLeave(id) {
  31 + return request({
  32 + url: '/oa/leave/get?id=' + id,
  33 + method: 'get'
  34 + })
  35 +}
  36 +
  37 +// 获得待办任务分页
  38 +export function getTodoTaskPage(query) {
  39 + return request({
  40 + url: '/workflow/task/todo/page',
  41 + method: 'get',
  42 + params: query
  43 + })
  44 +}
  45 +
  46 +// 签收任务
  47 +export function claimTask(id) {
  48 + return request({
  49 + url: '/workflow/task/claim?id=' + id,
  50 + method: 'get'
  51 + })
  52 +}
  53 +
  54 +export function completeTask(data) {
  55 + return request({
  56 + url: '/workflow/task/complete',
  57 + method: 'post',
  58 + data: data
  59 + })
  60 +}
  61 +
  62 +export function taskSteps(data) {
  63 + return request({
  64 + url: '/workflow/task/task-steps',
  65 + method: 'post',
  66 + data: data
  67 + })
  68 +}
  69 +
  70 +export function processHistorySteps(id) {
  71 + return request({
  72 + url: '/workflow/task/process/history-steps?id='+id,
  73 + method: 'get'
  74 + })
  75 +}
... ...
yudao-admin-ui/src/utils/dict.js
... ... @@ -29,6 +29,9 @@ export const DICT_TYPE = {
29 29 INF_API_ERROR_LOG_PROCESS_STATUS: 'inf_api_error_log_process_status',
30 30  
31 31 TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type',
  32 +
  33 + OA_LEAVE_STATUS: 'oa_leave_status',
  34 + OA_LEAVE_TYPE: 'oa_leave_type'
32 35 }
33 36  
34 37 /**
... ...
yudao-admin-ui/src/views/oa/leave/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="流程id" prop="processInstanceId">
  7 + <el-input v-model="queryParams.processInstanceId" placeholder="请输入流程id" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="状态" prop="status">
  10 + <el-select v-model="queryParams.status" placeholder="请选择状态">
  11 + <el-option
  12 + v-for="dict in leaveStatusData"
  13 + :key="parseInt(dict.value)"
  14 + :label="dict.label"
  15 + :value="parseInt(dict.value)"
  16 + />
  17 + </el-select>
  18 + </el-form-item>
  19 + <el-form-item label="开始时间">
  20 + <el-date-picker v-model="dateRangeStartTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  21 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  22 + </el-form-item>
  23 + <el-form-item label="结束时间">
  24 + <el-date-picker v-model="dateRangeEndTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  25 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  26 + </el-form-item>
  27 + <el-form-item label="请假类型" prop="leaveType">
  28 + <el-select v-model="queryParams.leaveType" placeholder="请选择请假类型">
  29 + <el-option
  30 + v-for="dict in leaveTypeDictData"
  31 + :key="parseInt(dict.value)"
  32 + :label="dict.label"
  33 + :value="parseInt(dict.value)"
  34 + />
  35 + </el-select>
  36 + </el-form-item>
  37 + <el-form-item label="原因" prop="reason">
  38 + <el-input v-model="queryParams.reason" placeholder="请输入原因" clearable size="small" @keyup.enter.native="handleQuery"/>
  39 + </el-form-item>
  40 + <el-form-item label="申请时间">
  41 + <el-date-picker v-model="dateRangeApplyTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  42 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  43 + </el-form-item>
  44 + <el-form-item>
  45 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  46 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  47 + </el-form-item>
  48 + </el-form>
  49 +
  50 + <!-- 操作工具栏 -->
  51 + <el-row :gutter="10" class="mb8">
  52 + <el-col :span="1.5">
  53 + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
  54 + v-hasPermi="['oa:leave:create']">新增</el-button>
  55 + </el-col>
  56 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  57 + </el-row>
  58 +
  59 + <!-- 列表 -->
  60 + <el-table v-loading="loading" :data="list">
  61 + <el-table-column label="请假表单主键" align="center" prop="id" />
  62 + <el-table-column label="状态" align="center" prop="status" :formatter="statusFormat" />
  63 + <el-table-column label="申请人id" align="center" prop="userId" />
  64 + <el-table-column label="开始时间" align="center" prop="startTime" width="180">
  65 + <template slot-scope="scope">
  66 + <span>{{ parseTime(scope.row.startTime) }}</span>
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column label="结束时间" align="center" prop="endTime" width="180">
  70 + <template slot-scope="scope">
  71 + <span>{{ parseTime(scope.row.endTime) }}</span>
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column label="请假类型" align="center" prop="leaveType" />
  75 + <el-table-column label="原因" align="center" prop="reason" />
  76 + <el-table-column label="申请时间" align="center" prop="applyTime" width="180">
  77 + <template slot-scope="scope">
  78 + <span>{{ parseTime(scope.row.applyTime) }}</span>
  79 + </template>
  80 + </el-table-column>
  81 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  82 + <template slot-scope="scope">
  83 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleStep(scope.row)">审批进度</el-button>
  84 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)">详情</el-button>
  85 + </template>
  86 + </el-table-column>
  87 + </el-table>
  88 + <!-- 分页组件 -->
  89 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  90 + @pagination="getList"/>
  91 +
  92 + <!-- 对话框(添加 / 修改) -->
  93 + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  94 + <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  95 + <el-form-item label="开始时间" prop="startTime">
  96 + <el-date-picker clearable size="small" v-model="form.startTime" type="date" value-format="timestamp" placeholder="选择开始时间" />
  97 + </el-form-item>
  98 + <el-form-item label="结束时间" prop="endTime">
  99 + <el-date-picker clearable size="small" v-model="form.endTime" type="date" value-format="timestamp" placeholder="选择结束时间" />
  100 + </el-form-item>
  101 + <el-form-item label="请假类型" prop="leaveType">
  102 + <el-select v-model="form.leaveType" placeholder="请选择">
  103 + <el-option
  104 + v-for="dict in leaveTypeDictData"
  105 + :key="parseInt(dict.value)"
  106 + :label="dict.label"
  107 + :value="parseInt(dict.value)"
  108 + />
  109 + </el-select>
  110 + </el-form-item>
  111 + <el-form-item label="原因" prop="reason">
  112 + <el-input v-model="form.reason" placeholder="请输入原因" />
  113 + </el-form-item>
  114 + <el-form-item label="申请时间" prop="applyTime">
  115 + <el-date-picker clearable size="small" v-model="form.applyTime" type="date" value-format="timestamp" placeholder="选择申请时间" />
  116 + </el-form-item>
  117 + </el-form>
  118 + <div slot="footer" class="dialog-footer">
  119 + <el-button type="primary" @click="submitForm">确 定</el-button>
  120 + <el-button @click="cancel">取 消</el-button>
  121 + </div>
  122 + </el-dialog>
  123 +
  124 + <el-dialog :title="title" :visible.sync="dialogDetailVisible" width="500px" append-to-body>
  125 + <el-form ref="form" :model="form" label-width="80px">
  126 + <el-form-item label="状态" >
  127 + {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_STATUS, form.status) }}
  128 + </el-form-item>
  129 + <el-form-item label="申请人id" >{{form.userId}}</el-form-item>
  130 + <el-form-item label="开始时间" >{{ parseTime(form.startTime) }}</el-form-item>
  131 + <el-form-item label="结束时间" prop="endTime">{{ parseTime(form.endTime) }}</el-form-item>
  132 + <el-form-item label="请假类型" prop="leaveType">
  133 + {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_TYPE, form.leaveType) }}
  134 + </el-form-item>
  135 + <el-form-item label="原因" prop="reason">{{form.reason}}</el-form-item>
  136 + <el-form-item label="申请时间" prop="applyTime">{{ parseTime(form.applyTime) }}</el-form-item>
  137 + </el-form>
  138 + <div slot="footer" class="dialog-footer">
  139 + <el-button type="primary" @click="dialogDetailVisible = false">确 定</el-button>
  140 + <el-button @click="dialogDetailVisible = false">取 消</el-button>
  141 + </div>
  142 + </el-dialog>
  143 +
  144 + <el-dialog :title="title" :visible.sync="dialogStepsVisible" width="600px" append-to-body>
  145 + <el-steps :active="handleTask.historyTask.length-1" finish-status="success" >
  146 + <el-step :title="item.stepName " :description="' 办理人:' + item.assignee " icon="el-icon-edit" v-for="(item) in handleTask.historyTask"></el-step>
  147 + </el-steps>
  148 + <br/>
  149 + <el-steps direction="vertical" :active="handleTask.historyTask.length-1">
  150 + <el-step :title="item.stepName" :description=" ' 意见:'+ item.comment" v-for="(item) in handleTask.historyTask"></el-step>
  151 + </el-steps>
  152 + <div slot="footer" class="dialog-footer">
  153 + <el-button type="primary" @click="dialogStepsVisible = false">确 定</el-button>
  154 + <el-button @click="dialogStepsVisible = false">取 消</el-button>
  155 + </div>
  156 + </el-dialog>
  157 + </div>
  158 +</template>
  159 +
  160 +<script>
  161 +import { createLeave, updateLeave, deleteLeave, getLeave, getLeavePage, exportLeaveExcel } from "@/api/oa/leave"
  162 +import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict'
  163 +import { processHistorySteps } from '@/api/oa/todo'
  164 +export default {
  165 + name: "Leave",
  166 + components: {
  167 + },
  168 + data() {
  169 + return {
  170 + // 遮罩层
  171 + loading: true,
  172 + // 显示搜索条件
  173 + showSearch: true,
  174 + // 总条数
  175 + total: 0,
  176 + // 请假申请列表
  177 + list: [],
  178 + // 弹出层标题
  179 + title: "",
  180 + // 是否显示弹出层
  181 + open: false,
  182 + //进度弹出层
  183 + dialogDetailVisible: false,
  184 + //审批进度弹出层
  185 + dialogStepsVisible: false,
  186 + dateRangeStartTime: [],
  187 + dateRangeEndTime: [],
  188 + dateRangeApplyTime: [],
  189 + // 查询参数
  190 + queryParams: {
  191 + pageNo: 1,
  192 + pageSize: 10,
  193 + processInstanceId: null,
  194 + status: null,
  195 + userId: null,
  196 + leaveType: null,
  197 + reason: null,
  198 + },
  199 + // 表单参数
  200 + form: {},
  201 + handleTask: {
  202 + historyTask:[{
  203 + stepName:"步骤一"
  204 + }
  205 + ],
  206 + taskVariable: "",
  207 + formObject: {}
  208 + },
  209 + steps:[{
  210 + stepName:"步骤一"
  211 + }],
  212 + // 表单校验
  213 + rules: {
  214 + startTime: [{ required: true, message: "开始时间不能为空", trigger: "blur" }],
  215 + endTime: [{ required: true, message: "结束时间不能为空", trigger: "blur" }],
  216 + applyTime: [{ required: true, message: "申请时间不能为空", trigger: "blur" }],
  217 + },
  218 + statusFormat(row, column) {
  219 + return getDictDataLabel(DICT_TYPE.OA_LEAVE_STATUS, row.status)
  220 + },
  221 + leaveTypeDictData: getDictDatas(DICT_TYPE.OA_LEAVE_TYPE),
  222 + leaveStatusData: getDictDatas(DICT_TYPE.OA_LEAVE_STATUS)
  223 + };
  224 + },
  225 + created() {
  226 + this.getList();
  227 + },
  228 + methods: {
  229 + /** 查询列表 */
  230 + getList() {
  231 + this.loading = true;
  232 + // 处理查询参数
  233 + let params = {...this.queryParams};
  234 + this.addBeginAndEndTime(params, this.dateRangeStartTime, 'startTime');
  235 + this.addBeginAndEndTime(params, this.dateRangeEndTime, 'endTime');
  236 + this.addBeginAndEndTime(params, this.dateRangeApplyTime, 'applyTime');
  237 + // 执行查询
  238 + getLeavePage(params).then(response => {
  239 + this.list = response.data.list;
  240 + this.total = response.data.total;
  241 + this.loading = false;
  242 + });
  243 + },
  244 + /** 取消按钮 */
  245 + cancel() {
  246 + this.open = false;
  247 + this.reset();
  248 + },
  249 + /** 表单重置 */
  250 + reset() {
  251 + this.form = {
  252 + id: undefined,
  253 + processInstanceId: undefined,
  254 + status: undefined,
  255 + userId: undefined,
  256 + startTime: undefined,
  257 + endTime: undefined,
  258 + leaveType: undefined,
  259 + reason: undefined,
  260 + applyTime: undefined,
  261 + };
  262 + this.resetForm("form");
  263 + },
  264 + /** 搜索按钮操作 */
  265 + handleQuery() {
  266 + this.queryParams.pageNo = 1;
  267 + this.getList();
  268 + },
  269 + /** 重置按钮操作 */
  270 + resetQuery() {
  271 + this.dateRangeStartTime = [];
  272 + this.dateRangeEndTime = [];
  273 + this.dateRangeApplyTime = [];
  274 + this.resetForm("queryForm");
  275 + this.handleQuery();
  276 + },
  277 + /** 新增按钮操作 */
  278 + handleAdd() {
  279 + this.reset();
  280 + this.open = true;
  281 + this.title = "添加请假申请";
  282 + },
  283 + /** 详情按钮操作 */
  284 + handleDetail(row) {
  285 + this.reset();
  286 + const id = row.id;
  287 + getLeave(id).then(response => {
  288 + this.form = response.data;
  289 + this.dialogDetailVisible = true
  290 + this.title = "请假详情";
  291 + });
  292 + },
  293 + /** 提交按钮 */
  294 + submitForm() {
  295 + this.$refs["form"].validate(valid => {
  296 + if (!valid) {
  297 + return;
  298 + }
  299 + // 修改的提交
  300 + if (this.form.id != null) {
  301 + updateLeave(this.form).then(response => {
  302 + this.msgSuccess("修改成功");
  303 + this.open = false;
  304 + this.getList();
  305 + });
  306 + return;
  307 + }
  308 + // 添加的提交
  309 + createLeave(this.form).then(response => {
  310 + this.msgSuccess("新增成功");
  311 + this.open = false;
  312 + this.getList();
  313 + });
  314 + });
  315 + },
  316 + /** 审批进度 */
  317 + handleStep(row) {
  318 + const id = row.processInstanceId;
  319 + processHistorySteps(id).then(response => {
  320 + this.handleTask.historyTask = response.data;
  321 + this.dialogStepsVisible = true
  322 + this.title = "审批进度";
  323 + });
  324 + },
  325 + /** 导出按钮操作 */
  326 + handleExport() {
  327 + // 处理查询参数
  328 + let params = {...this.queryParams};
  329 + params.pageNo = undefined;
  330 + params.pageSize = undefined;
  331 + this.addBeginAndEndTime(params, this.dateRangeStartTime, 'startTime');
  332 + this.addBeginAndEndTime(params, this.dateRangeEndTime, 'endTime');
  333 + this.addBeginAndEndTime(params, this.dateRangeApplyTime, 'applyTime');
  334 + // 执行导出
  335 + this.$confirm('是否确认导出所有请假申请数据项?', "警告", {
  336 + confirmButtonText: "确定",
  337 + cancelButtonText: "取消",
  338 + type: "warning"
  339 + }).then(function() {
  340 + return exportLeaveExcel(params);
  341 + }).then(response => {
  342 + this.downloadExcel(response, '请假申请.xls');
  343 + })
  344 + }
  345 + }
  346 +};
  347 +</script>
... ...
yudao-admin-ui/src/views/oa/todo/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="状态" prop="status">
  7 + <el-select v-model="queryParams.status" placeholder="请选择状态">
  8 + <el-option
  9 + v-for="dict in leaveStatusData"
  10 + :key="parseInt(dict.value)"
  11 + :label="dict.label"
  12 + :value="parseInt(dict.value)"
  13 + />
  14 + </el-select>
  15 + </el-form-item>
  16 + <el-form-item>
  17 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  18 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  19 + </el-form-item>
  20 + </el-form>
  21 +
  22 +
  23 +
  24 + <!-- 列表 -->
  25 + <el-table v-loading="loading" :data="list">
  26 + <el-table-column label="任务Id" align="center" prop="id" />
  27 + <el-table-column label="流程名称" align="center" prop="processName" />
  28 + <el-table-column label="任务状态" align="center" :formatter="statusFormat" prop="status" />
  29 +<!-- <el-table-column label="申请人id" align="center" prop="userId" />-->
  30 +<!-- <el-table-column label="开始时间" align="center" prop="startTime" width="180">-->
  31 +<!-- <template slot-scope="scope">-->
  32 +<!-- <span>{{ parseTime(scope.row.startTime) }}</span>-->
  33 +<!-- </template>-->
  34 +<!-- </el-table-column>-->
  35 +<!-- <el-table-column label="结束时间" align="center" prop="endTime" width="180">-->
  36 +<!-- <template slot-scope="scope">-->
  37 +<!-- <span>{{ parseTime(scope.row.endTime) }}</span>-->
  38 +<!-- </template>-->
  39 +<!-- </el-table-column>-->
  40 +<!-- <el-table-column label="请假类型" align="center" prop="leaveType" />-->
  41 +<!-- <el-table-column label="原因" align="center" prop="reason" />-->
  42 +<!-- <el-table-column label="申请时间" align="center" prop="applyTime" width="180">-->
  43 +<!-- <template slot-scope="scope">-->
  44 +<!-- <span>{{ parseTime(scope.row.applyTime) }}</span>-->
  45 +<!-- </template>-->
  46 +<!-- </el-table-column>-->
  47 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  48 + <template slot-scope="scope">
  49 + <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.status == 1" @click="handleClaim(scope.row)">签收</el-button>
  50 + <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.status == 2" @click="handleLeaveApprove(scope.row)">办理</el-button>
  51 + </template>
  52 + </el-table-column>
  53 + </el-table>
  54 + <!-- 分页组件 -->
  55 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  56 + @pagination="getList"/>
  57 +
  58 + <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
  59 + <el-tabs tab-position="left" style="height: 500px;">
  60 + <el-tab-pane label="详情">
  61 + <el-form ref="form" :model="handleTask.formObject" label-width="80px">
  62 + <el-form-item label="状态" >
  63 + {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_STATUS, handleTask.formObject.status) }}
  64 + </el-form-item>
  65 + <el-form-item label="申请人id" >{{handleTask.formObject.userId}}</el-form-item>
  66 + <el-form-item label="开始时间" >{{ parseTime(handleTask.formObject.startTime) }}</el-form-item>
  67 + <el-form-item label="结束时间" prop="endTime">{{ parseTime(handleTask.formObject.endTime) }}</el-form-item>
  68 + <el-form-item label="请假类型" prop="leaveType">
  69 + {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_TYPE, handleTask.formObject.leaveType) }}
  70 + </el-form-item>
  71 + <el-form-item label="原因" prop="reason">{{handleTask.formObject.reason}}</el-form-item>
  72 + <el-form-item label="申请时间" prop="applyTime">{{ parseTime(handleTask.formObject.applyTime) }}</el-form-item>
  73 + </el-form>
  74 + </el-tab-pane>
  75 + <el-tab-pane label="任务处理">
  76 + <el-steps :active="handleTask.historyTask.length-1" simple finish-status="success">
  77 + <el-step :title="item.stepName" icon="el-icon-edit" v-for="(item) in handleTask.historyTask" ></el-step>
  78 + </el-steps>
  79 + <br/>
  80 + <el-steps direction="vertical" :active="handleTask.historyTask.length-1" finish-status="success" space="60px">
  81 + <el-step :title="item.stepName" :description="item.comment" v-for="(item) in handleTask.historyTask" ></el-step>
  82 + </el-steps>
  83 + <br/>
  84 + <el-form ref="taskForm" :model="task" label-width="80px" v-show="handleTask.taskVariable !=''">
  85 + <el-form-item label="处理意见" prop="approved">
  86 + <el-select v-model="task.approved" placeholder="处理意见">
  87 + <el-option
  88 + v-for="dict in approvedData"
  89 + :key="parseInt(dict.value)"
  90 + :label="dict.label"
  91 + :value="parseInt(dict.value)"
  92 + />
  93 + </el-select>
  94 + </el-form-item>
  95 + <el-input
  96 + type="textarea"
  97 + :rows="2"
  98 + v-model="task.comment">
  99 + </el-input>
  100 + </el-form>
  101 + <br/>
  102 + <el-button type="primary" @click="submitTask">提交</el-button>
  103 + </el-tab-pane>
  104 + </el-tabs>
  105 + </el-dialog>
  106 + </div>
  107 +</template>
  108 +
  109 +<script>
  110 +import { completeTask, taskSteps, deleteLeave, getLeave, getTodoTaskPage, claimTask } from "@/api/oa/todo";
  111 +import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict'
  112 +export default {
  113 + name: "Todo",
  114 + components: {
  115 + },
  116 + data() {
  117 + return {
  118 + // 遮罩层
  119 + loading: true,
  120 + // 显示搜索条件
  121 + showSearch: true,
  122 + // 总条数
  123 + total: 0,
  124 + // 请假申请列表
  125 + list: [],
  126 + // 弹出层标题
  127 + title: "",
  128 + // 是否显示弹出层
  129 + open: false,
  130 + // 查询参数
  131 + queryParams: {
  132 + pageNo: 1,
  133 + pageSize: 10
  134 + },
  135 + // 表单参数
  136 + form: {},
  137 + handleTask: {
  138 + historyTask:[{
  139 + stepName:"步骤一"
  140 + }
  141 + ],
  142 + taskVariable: "",
  143 + formObject: {}
  144 + },
  145 + steps:[{
  146 + stepName:"步骤一"
  147 + }],
  148 + task: {
  149 + approved : 1,
  150 + variables: {},
  151 + taskId: undefined,
  152 + comment: ""
  153 + },
  154 + rules: {
  155 + },
  156 + leaveTypeDictData: getDictDatas(DICT_TYPE.OA_LEAVE_TYPE),
  157 + leaveStatusData: getDictDatas(DICT_TYPE.OA_LEAVE_STATUS),
  158 + approvedData: [
  159 + {
  160 + value: 1,
  161 + label: '同意'
  162 + },
  163 + {
  164 + value: 0,
  165 + label: '不同意'
  166 + }
  167 + ]
  168 + };
  169 + },
  170 + created() {
  171 + this.getList();
  172 + },
  173 + methods: {
  174 + /** 查询列表 */
  175 + getList() {
  176 + this.loading = true;
  177 + // 处理查询参数
  178 + let params = {...this.queryParams};
  179 + // 执行查询
  180 + getTodoTaskPage(params).then(response => {
  181 + this.list = response.data.list;
  182 + this.total = response.data.total;
  183 + this.loading = false;
  184 + });
  185 + },
  186 + /** 取消按钮 */
  187 + cancel() {
  188 + this.open = false;
  189 + this.reset();
  190 + },
  191 + /** 表单重置 */
  192 + reset() {
  193 + this.form = {
  194 + id: undefined,
  195 + processInstanceId: undefined,
  196 + status: undefined,
  197 + userId: undefined,
  198 + startTime: undefined,
  199 + endTime: undefined,
  200 + leaveType: undefined,
  201 + reason: undefined,
  202 + applyTime: undefined,
  203 + };
  204 + this.resetForm("form");
  205 + },
  206 +
  207 + statusFormat(row, column) {
  208 + return row.status == 1 ? "未签收" : "已签收";
  209 + },
  210 + /** 搜索按钮操作 */
  211 + handleQuery() {
  212 + this.queryParams.pageNo = 1;
  213 + this.getList();
  214 + },
  215 + /** 重置按钮操作 */
  216 + resetQuery() {
  217 + this.dateRangeStartTime = [];
  218 + this.dateRangeEndTime = [];
  219 + this.dateRangeApplyTime = [];
  220 + this.resetForm("queryForm");
  221 + this.handleQuery();
  222 + },
  223 +
  224 + handleLeaveApprove(row) {
  225 + this.reset();
  226 + const businessKey = row.businessKey;
  227 + const taskId = row.id;
  228 + const processKey = row.processKey;
  229 + const data = {
  230 + taskId : taskId,
  231 + businessKey: businessKey,
  232 + processKey: processKey
  233 + }
  234 + taskSteps(data).then(response => {
  235 + this.form = {};
  236 + this.handleTask = response.data;
  237 + this.task.taskId = taskId;
  238 + this.open = true;
  239 + this.title = "任务办理";
  240 + });
  241 + },
  242 + /** 任务签收操作 */
  243 + handleClaim(row) {
  244 + this.reset();
  245 + const id = row.id;
  246 + claimTask(id).then(() => {
  247 + this.getList();
  248 + this.msgSuccess("签收成功");
  249 + });
  250 + },
  251 + /** 提交任务 */
  252 + submitTask() {
  253 + const taskVariableName = this.handleTask.taskVariable;
  254 + if (taskVariableName != "") {
  255 + if (this.task.approved == 1) {
  256 + this.task.variables[taskVariableName] = true;
  257 + }
  258 + if (this.task.approved == 0) {
  259 + this.task.variables[taskVariableName] = false;
  260 + }
  261 + }
  262 + completeTask(this.task).then(response => {
  263 + this.msgSuccess("执行任务成功");
  264 + this.open = false;
  265 + this.getList();
  266 + })
  267 + },
  268 + /** 删除按钮操作 */
  269 + handleDelete(row) {
  270 + const id = row.id;
  271 + this.$confirm('是否确认删除请假申请编号为"' + id + '"的数据项?', "警告", {
  272 + confirmButtonText: "确定",
  273 + cancelButtonText: "取消",
  274 + type: "warning"
  275 + }).then(function() {
  276 + return deleteLeave(id);
  277 + }).then(() => {
  278 + this.getList();
  279 + this.msgSuccess("删除成功");
  280 + })
  281 + }
  282 + }
  283 +};
  284 +</script>
... ...
yudao-framework/yudao-spring-boot-starter-activiti/pom.xml
... ... @@ -19,20 +19,29 @@
19 19 <properties>
20 20 <activiti.version>7.1.0.M6</activiti.version>
21 21 </properties>
22   -
  22 + <dependencyManagement>
  23 + <dependencies>
  24 + <dependency>
  25 + <groupId>org.activiti.dependencies</groupId>
  26 + <artifactId>activiti-dependencies</artifactId>
  27 + <version>${activiti.version}</version>
  28 + <scope>import</scope>
  29 + <type>pom</type>
  30 + </dependency>
  31 + </dependencies>
  32 + </dependencyManagement>
23 33 <dependencies>
24 34 <dependency>
25 35 <groupId>cn.iocoder.boot</groupId>
26 36 <artifactId>yudao-common</artifactId>
27 37 </dependency>
28 38  
29   -
30 39 <dependency>
31   - <groupId>org.activiti.dependencies</groupId>
32   - <artifactId>activiti-dependencies</artifactId>
33   - <version>${activiti.version}</version>
34   - <type>pom</type>
  40 + <groupId>org.mybatis</groupId>
  41 + <artifactId>mybatis</artifactId>
  42 + <optional>true</optional>
35 43 </dependency>
  44 +
36 45 <!--使用mybatis plus需排除掉mybatis-->
37 46 <dependency>
38 47 <groupId>org.activiti</groupId>
... ... @@ -51,6 +60,10 @@
51 60 <groupId>org.mybatis</groupId>
52 61 <artifactId>mybatis</artifactId>
53 62 </exclusion>
  63 + <exclusion>
  64 + <artifactId>el-api</artifactId>
  65 + <groupId>javax.el</groupId>
  66 + </exclusion>
54 67 </exclusions>
55 68 </dependency>
56 69 </dependencies>
... ...
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.activiti.config;
  2 +
  3 +import org.activiti.api.runtime.shared.identity.UserGroupManager;
  4 +import org.activiti.spring.SpringProcessEngineConfiguration;
  5 +import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
  6 +import org.apache.ibatis.session.SqlSessionFactory;
  7 +import org.springframework.context.annotation.Configuration;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +@Configuration
  11 +public class YudaoActivitiConfiguration {
  12 +
  13 +
  14 +
  15 +
  16 + @Component
  17 + public static class SqlSessionFactoryProcessEngineConfigurationConfigurer
  18 + implements ProcessEngineConfigurationConfigurer {
  19 +
  20 + private final SqlSessionFactory sqlSessionFactory;
  21 + public SqlSessionFactoryProcessEngineConfigurationConfigurer(SqlSessionFactory sessionFactory) {
  22 + this.sqlSessionFactory = sessionFactory;
  23 + }
  24 +
  25 + @Override
  26 + public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
  27 + springProcessEngineConfiguration.setSqlSessionFactory(sqlSessionFactory);
  28 + }
  29 + }
  30 +
  31 +
  32 +}
... ...
yudao-framework/yudao-spring-boot-starter-security/pom.xml
... ... @@ -39,6 +39,18 @@
39 39 <artifactId>spring-boot-starter-security</artifactId>
40 40 </dependency>
41 41  
  42 + <dependency>
  43 + <groupId>org.activiti</groupId>
  44 + <artifactId>activiti-engine</artifactId>
  45 + <version>7.1.0.M6</version>
  46 + <exclusions>
  47 + <exclusion>
  48 + <groupId>*</groupId>
  49 + <artifactId>*</artifactId>
  50 + </exclusion>
  51 + </exclusions>
  52 + <optional>true</optional>
  53 + </dependency>
42 54 </dependencies>
43 55  
44 56 </project>
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
... ... @@ -4,11 +4,10 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 4 import com.fasterxml.jackson.annotation.JsonIgnore;
5 5 import lombok.Data;
6 6 import org.springframework.security.core.GrantedAuthority;
  7 +import org.springframework.security.core.authority.SimpleGrantedAuthority;
7 8 import org.springframework.security.core.userdetails.UserDetails;
8 9  
9   -import java.util.Collection;
10   -import java.util.Date;
11   -import java.util.Set;
  10 +import java.util.*;
12 11  
13 12 /**
14 13 * 登陆用户信息
... ... @@ -48,6 +47,18 @@ public class LoginUser implements UserDetails {
48 47 */
49 48 private Integer status;
50 49  
  50 +
  51 + /**
  52 + * 所属岗位
  53 + */
  54 + private Set<Long> postIds;
  55 +
  56 + /**
  57 + * group 目前指岗位代替
  58 + */
  59 + private List<String> groups;
  60 +
  61 +
51 62 @Override
52 63 @JsonIgnore// 避免序列化
53 64 public String getPassword() {
... ... @@ -55,7 +66,6 @@ public class LoginUser implements UserDetails {
55 66 }
56 67  
57 68 @Override
58   - @JsonIgnore
59 69 public String getUsername() {
60 70 return username;
61 71 }
... ... @@ -69,7 +79,9 @@ public class LoginUser implements UserDetails {
69 79 @Override
70 80 @JsonIgnore// 避免序列化
71 81 public Collection<? extends GrantedAuthority> getAuthorities() {
72   - return null;
  82 + List<GrantedAuthority> list = new ArrayList<>(1);
  83 + list.add(new SimpleGrantedAuthority("ROLE_ACTIVITI_USER"));
  84 + return list;
73 85 }
74 86  
75 87 @Override
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
... ... @@ -90,13 +90,18 @@ public class SecurityFrameworkUtils {
90 90 public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
91 91 // 创建 UsernamePasswordAuthenticationToken 对象
92 92 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
93   - loginUser, null, null);
  93 + loginUser, null, loginUser.getAuthorities());
94 94 authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
95 95 // 设置到上下文
  96 + //何时调用 SecurityContextHolder.clearContext. spring security filter 应该会调用 clearContext
96 97 SecurityContextHolder.getContext().setAuthentication(authenticationToken);
97 98 // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
98 99 // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
99 100 WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
  101 +
  102 + org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
  103 +
  104 +
100 105 }
101 106  
102 107 }
... ...