From 172e3520e0347cc4c43808cd1701b9fd412e2a70 Mon Sep 17 00:00:00 2001 From: lijiaqi Date: Thu, 23 Feb 2023 11:26:02 +0800 Subject: [PATCH] =?UTF-8?q?OA=E6=9D=BF=E5=9D=97=E6=95=B4=E5=90=88=E4=B8=8E?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ydool/YdoolApplication.java | 1 + .../common/advice/BaseControllerAdvice.java | 14 +- .../com/ydool/common/base/BaseController.java | 4 +- .../com/ydool/common/base/BaseService.java | 5 +- .../com/ydool/common/cache/ConfigCache.java | 2 + .../ydool/common/data/dto/IResultCode.java | 24 ++ .../com/ydool/common/data/dto/Result.java | 245 ++++++++++++++++++ .../com/ydool/common/data/dto/ResultCode.java | 37 +++ .../common/exception/AjaxResultException.java | 26 ++ .../common/exception/NotLoginException.java | 17 ++ .../common/exception/ResultException.java | 29 +-- .../ydool/common/utils/HttpServletUtil.java | 6 +- .../java/com/ydool/common/utils/PathUtil.java | 20 ++ .../com/ydool/common/utils/UploadUtil.java | 34 +++ .../java/com/ydool/common/utils/WebUtil.java | 145 +++++++++++ .../ydool/oa/flow/constant/FlowConstant.java | 150 +++++++++++ .../oa/flow/controller/ProcessController.java | 97 +++++++ .../com/ydool/oa/flow/data/dto/FlowDto.java | 25 ++ .../ydool/oa/flow/data/dto/FlowStepDto.java | 29 +++ .../com/ydool/oa/flow/data/entity/Flow.java | 34 +++ .../ydool/oa/flow/data/entity/FlowStep.java | 50 ++++ .../oa/flow/data/entity/FlowStepLog.java | 33 +++ .../ydool/oa/flow/data/vo/FlowStepLogVo.java | 19 ++ .../com/ydool/oa/flow/data/vo/FlowStepVo.java | 21 ++ .../com/ydool/oa/flow/data/vo/FlowVo.java | 14 + .../com/ydool/oa/flow/data/vo/ProcessVo.java | 24 ++ .../oa/flow/data/wrapper/BaseWrapper.java | 44 ++++ .../flow/data/wrapper/FlowStepLogWrapper.java | 31 +++ .../oa/flow/data/wrapper/FlowStepWrapper.java | 61 +++++ .../oa/flow/data/wrapper/FlowWrapper.java | 23 ++ .../oa/flow/data/wrapper/ProcessWrapper.java | 47 ++++ .../com/ydool/oa/flow/engine/FlowProcess.java | 22 ++ .../ydool/oa/flow/engine/ProcessNoBody.java | 14 + .../ydool/oa/flow/engine/ProcessProps.java | 34 +++ .../ydool/oa/flow/engine/ProcessRefuse.java | 14 + .../engine/factory/ProcessTypeFactory.java | 40 +++ .../oa/flow/engine/service/IProcessType.java | 17 ++ .../engine/service/impl/ProcessApproval.java | 189 ++++++++++++++ .../com/ydool/oa/flow/mapper/FlowMapper.java | 10 + .../oa/flow/mapper/FlowStepLogMapper.java | 10 + .../ydool/oa/flow/mapper/FlowStepMapper.java | 11 + .../ydool/oa/flow/service/FlowService.java | 98 +++++++ .../oa/flow/service/FlowStepLogService.java | 37 +++ .../oa/flow/service/FlowStepService.java | 90 +++++++ .../ydool/oa/formily/constant/GrapeConst.java | 7 + .../formily/controller/FormilyController.java | 107 ++++++++ .../formily/controller/GroupController.java | 77 ++++++ .../oa/formily/controller/TreeController.java | 35 +++ .../ydool/oa/formily/data/dto/FormilyDto.java | 9 + .../ydool/oa/formily/data/dto/GroupDto.java | 10 + .../ydool/oa/formily/data/entity/Formily.java | 32 +++ .../ydool/oa/formily/data/entity/Group.java | 22 ++ .../oa/formily/data/vo/FormilyStartVo.java | 17 ++ .../ydool/oa/formily/data/vo/FormilyVo.java | 24 ++ .../com/ydool/oa/formily/data/vo/GroupVo.java | 23 ++ .../oa/formily/mapper/FormilyMapper.java | 9 + .../ydool/oa/formily/mapper/GroupMapper.java | 10 + .../oa/formily/service/FormilyService.java | 19 ++ .../oa/formily/service/GroupService.java | 11 + .../oa/formily/userdept/IUserDeptService.java | 60 +++++ .../ydool/oa/formily/userdept/UserDept.java | 98 +++++++ .../userdept/impl/UserDeptServiceImpl.java | 200 ++++++++++++++ .../mybatis/config/MybatisPlusConfig.java | 2 +- .../swagger/config/SwaggerConfig.java | 32 +++ .../ydool/system/service/IUserService.java | 7 + .../system/service/impl/UserServiceImpl.java | 65 +++++ src/main/resources/application.yml | 6 + 67 files changed, 2753 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/ydool/common/data/dto/IResultCode.java create mode 100644 src/main/java/com/ydool/common/data/dto/Result.java create mode 100644 src/main/java/com/ydool/common/data/dto/ResultCode.java create mode 100644 src/main/java/com/ydool/common/exception/AjaxResultException.java create mode 100644 src/main/java/com/ydool/common/exception/NotLoginException.java create mode 100644 src/main/java/com/ydool/common/utils/PathUtil.java create mode 100644 src/main/java/com/ydool/common/utils/UploadUtil.java create mode 100644 src/main/java/com/ydool/common/utils/WebUtil.java create mode 100644 src/main/java/com/ydool/oa/flow/constant/FlowConstant.java create mode 100644 src/main/java/com/ydool/oa/flow/controller/ProcessController.java create mode 100644 src/main/java/com/ydool/oa/flow/data/dto/FlowDto.java create mode 100644 src/main/java/com/ydool/oa/flow/data/dto/FlowStepDto.java create mode 100644 src/main/java/com/ydool/oa/flow/data/entity/Flow.java create mode 100644 src/main/java/com/ydool/oa/flow/data/entity/FlowStep.java create mode 100644 src/main/java/com/ydool/oa/flow/data/entity/FlowStepLog.java create mode 100644 src/main/java/com/ydool/oa/flow/data/vo/FlowStepLogVo.java create mode 100644 src/main/java/com/ydool/oa/flow/data/vo/FlowStepVo.java create mode 100644 src/main/java/com/ydool/oa/flow/data/vo/FlowVo.java create mode 100644 src/main/java/com/ydool/oa/flow/data/vo/ProcessVo.java create mode 100644 src/main/java/com/ydool/oa/flow/data/wrapper/BaseWrapper.java create mode 100644 src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepLogWrapper.java create mode 100644 src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepWrapper.java create mode 100644 src/main/java/com/ydool/oa/flow/data/wrapper/FlowWrapper.java create mode 100644 src/main/java/com/ydool/oa/flow/data/wrapper/ProcessWrapper.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/FlowProcess.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/ProcessNoBody.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/ProcessProps.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/ProcessRefuse.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/factory/ProcessTypeFactory.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/service/IProcessType.java create mode 100644 src/main/java/com/ydool/oa/flow/engine/service/impl/ProcessApproval.java create mode 100644 src/main/java/com/ydool/oa/flow/mapper/FlowMapper.java create mode 100644 src/main/java/com/ydool/oa/flow/mapper/FlowStepLogMapper.java create mode 100644 src/main/java/com/ydool/oa/flow/mapper/FlowStepMapper.java create mode 100644 src/main/java/com/ydool/oa/flow/service/FlowService.java create mode 100644 src/main/java/com/ydool/oa/flow/service/FlowStepLogService.java create mode 100644 src/main/java/com/ydool/oa/flow/service/FlowStepService.java create mode 100644 src/main/java/com/ydool/oa/formily/constant/GrapeConst.java create mode 100644 src/main/java/com/ydool/oa/formily/controller/FormilyController.java create mode 100644 src/main/java/com/ydool/oa/formily/controller/GroupController.java create mode 100644 src/main/java/com/ydool/oa/formily/controller/TreeController.java create mode 100644 src/main/java/com/ydool/oa/formily/data/dto/FormilyDto.java create mode 100644 src/main/java/com/ydool/oa/formily/data/dto/GroupDto.java create mode 100644 src/main/java/com/ydool/oa/formily/data/entity/Formily.java create mode 100644 src/main/java/com/ydool/oa/formily/data/entity/Group.java create mode 100644 src/main/java/com/ydool/oa/formily/data/vo/FormilyStartVo.java create mode 100644 src/main/java/com/ydool/oa/formily/data/vo/FormilyVo.java create mode 100644 src/main/java/com/ydool/oa/formily/data/vo/GroupVo.java create mode 100644 src/main/java/com/ydool/oa/formily/mapper/FormilyMapper.java create mode 100644 src/main/java/com/ydool/oa/formily/mapper/GroupMapper.java create mode 100644 src/main/java/com/ydool/oa/formily/service/FormilyService.java create mode 100644 src/main/java/com/ydool/oa/formily/service/GroupService.java create mode 100644 src/main/java/com/ydool/oa/formily/userdept/IUserDeptService.java create mode 100644 src/main/java/com/ydool/oa/formily/userdept/UserDept.java create mode 100644 src/main/java/com/ydool/oa/formily/userdept/impl/UserDeptServiceImpl.java diff --git a/src/main/java/com/ydool/YdoolApplication.java b/src/main/java/com/ydool/YdoolApplication.java index 9092b59..b60d8f3 100644 --- a/src/main/java/com/ydool/YdoolApplication.java +++ b/src/main/java/com/ydool/YdoolApplication.java @@ -1,5 +1,6 @@ package com.ydool; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; diff --git a/src/main/java/com/ydool/common/advice/BaseControllerAdvice.java b/src/main/java/com/ydool/common/advice/BaseControllerAdvice.java index 642611a..ae33ae8 100644 --- a/src/main/java/com/ydool/common/advice/BaseControllerAdvice.java +++ b/src/main/java/com/ydool/common/advice/BaseControllerAdvice.java @@ -3,7 +3,10 @@ package com.ydool.common.advice; import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.util.SaResult; import com.ydool.common.data.dto.AjaxResult; +import com.ydool.common.data.dto.Result; +import com.ydool.common.exception.AjaxResultException; import com.ydool.common.exception.ResultException; + import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; @@ -12,6 +15,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; + import javax.servlet.http.HttpServletResponse; import javax.validation.ConstraintViolationException; import java.lang.reflect.Field; @@ -59,8 +63,8 @@ public class BaseControllerAdvice { return AjaxResult.fail("参数校验失败"); } - @ExceptionHandler(ResultException.class) - public AjaxResult handlerResultException(ResultException e) { + @ExceptionHandler(AjaxResultException.class) + public AjaxResult handlerResultException(AjaxResultException e) { return e.getResult(); } @@ -93,4 +97,10 @@ public class BaseControllerAdvice { } + @ExceptionHandler(value = { ResultException.class, com.ydool.common.exception.NotLoginException.class }) + public Result handlerResultException(ResultException e) { + return e.getResult(); + } + + } diff --git a/src/main/java/com/ydool/common/base/BaseController.java b/src/main/java/com/ydool/common/base/BaseController.java index 4944b45..7f04cd0 100644 --- a/src/main/java/com/ydool/common/base/BaseController.java +++ b/src/main/java/com/ydool/common/base/BaseController.java @@ -5,7 +5,7 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ydool.common.data.dto.AjaxResult; -import com.ydool.common.exception.ResultException; +import com.ydool.common.exception.AjaxResultException; import org.springframework.beans.factory.annotation.Autowired; @@ -40,7 +40,7 @@ public class BaseController { } public void renderJson(AjaxResult ajaxResult) { - throw new ResultException(ajaxResult); + throw new AjaxResultException(ajaxResult); } public void fail(String msg) { diff --git a/src/main/java/com/ydool/common/base/BaseService.java b/src/main/java/com/ydool/common/base/BaseService.java index 3851beb..1e43b03 100644 --- a/src/main/java/com/ydool/common/base/BaseService.java +++ b/src/main/java/com/ydool/common/base/BaseService.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ydool.common.data.dto.PageResult; import com.ydool.common.data.vo.BaseRequest; -import com.ydool.common.exception.ResultException; +import com.ydool.common.exception.AjaxResultException; import com.ydool.common.factory.PageFactory; import com.ydool.common.factory.PageResultFactory; import org.springframework.transaction.annotation.Transactional; @@ -16,7 +16,6 @@ import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.time.LocalDateTime; -import java.util.Date; public class BaseService, T extends BaseEntity> extends ServiceImpl { @@ -36,7 +35,7 @@ public class BaseService, T extends BaseEntity> extends public T get(Serializable id) { T result = getById(id); - if(result == null) throw new ResultException("数据不存在"); + if(result == null) throw new AjaxResultException("数据不存在"); return result; } diff --git a/src/main/java/com/ydool/common/cache/ConfigCache.java b/src/main/java/com/ydool/common/cache/ConfigCache.java index 496a216..0979405 100644 --- a/src/main/java/com/ydool/common/cache/ConfigCache.java +++ b/src/main/java/com/ydool/common/cache/ConfigCache.java @@ -27,6 +27,8 @@ public class ConfigCache { */ public static final String USER_INIT_PASSWORD = "sys.user.initPassword"; + public static final String USER_ADMIN = "sys.user.admin"; + public static final String SYS_USER_LEADERSHIP = "sys.user.leadership"; public static final String SYS_USER_PERSONNEL_DIRECTOR= "sys.user.personnel.director"; diff --git a/src/main/java/com/ydool/common/data/dto/IResultCode.java b/src/main/java/com/ydool/common/data/dto/IResultCode.java new file mode 100644 index 0000000..89d9a89 --- /dev/null +++ b/src/main/java/com/ydool/common/data/dto/IResultCode.java @@ -0,0 +1,24 @@ +package com.ydool.common.data.dto; + +import java.io.Serializable; + +/** + * 业务代码接口 + */ +public interface IResultCode extends Serializable { + + /** + * 获取消息 + * + * @return + */ + String getMessage(); + + /** + * 获取状态码 + * + * @return + */ + int getCode(); + +} diff --git a/src/main/java/com/ydool/common/data/dto/Result.java b/src/main/java/com/ydool/common/data/dto/Result.java new file mode 100644 index 0000000..3806ff2 --- /dev/null +++ b/src/main/java/com/ydool/common/data/dto/Result.java @@ -0,0 +1,245 @@ +package com.ydool.common.data.dto; + +import cn.hutool.core.util.ObjectUtil; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.springframework.lang.Nullable; + +import javax.servlet.http.HttpServletResponse; +import java.io.Serializable; +import java.util.List; +import java.util.Optional; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class Result implements Serializable { + + /** + * 默认成功消息 + */ + public static final String DEFAULT_SUCCESS_MESSAGE = "操作成功"; + /** + * 默认失败消息 + */ + public static final String DEFAULT_FAILURE_MESSAGE = "操作失败"; + + /** + * 默认为空消息 + */ + public static final String DEFAULT_NULL_MESSAGE = "暂无承载数据"; + + /** + * 默认未授权消息 + */ + public static final String DEFAULT_UNAUTHORIZED_MESSAGE = "签名认证失败"; + + private int code; + + private boolean success; + + private T data; + + private Integer count; + + private String msg; + + private Result(IResultCode resultCode) { + this(resultCode, null, resultCode.getMessage()); + } + + private Result(IResultCode resultCode, String msg) { + this(resultCode, null, msg); + } + + private Result(IResultCode resultCode, T data) { + this(resultCode, data, resultCode.getMessage()); + } + + private Result(IResultCode resultCode, T data, String msg) { + this(resultCode.getCode(), data, msg); + } + + private Result(int code, T data, String msg) { + this.code = code; + this.data = data; + this.msg = msg; + this.success = ResultCode.SUCCESS.code == code; + } + + private Result(int code,int count, T data, String msg) { + this(code,data,msg); + this.count = count; + } + + /** + * 判断返回是否为成功 + * + * @param result Result + * @return 是否成功 + */ + public static boolean isSuccess(@Nullable Result result) { + return Optional.ofNullable(result) + .map(x -> ObjectUtil.equals(ResultCode.SUCCESS.code, x.code)) + .orElse(Boolean.FALSE); + } + + /** + * 判断返回是否为成功 + * + * @param result Result + * @return 是否成功 + */ + public static boolean isNotSuccess(@Nullable Result result) { + return !Result.isSuccess(result); + } + + /** + * 返回Result + * + * @param data 数据 + * @param T 泛型标记 + * @return Result + */ + public static Result data(T data) { + return data(data, DEFAULT_SUCCESS_MESSAGE); + } + + /** + * 返回Result + * + * @param data 数据 + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result data(T data, String msg) { + return data(HttpServletResponse.SC_OK, data, msg); + } + + /** + * 返回Result + * + * @param code 状态码 + * @param data 数据 + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result data(int code, T data, String msg) { + return new Result<>(code, data, data == null ? DEFAULT_NULL_MESSAGE : msg); + } + + public static Result data(int code,int count, T data, String msg) { + return new Result<>(code,count, data, data == null ? DEFAULT_NULL_MESSAGE : msg); + } + + public static Result> page(PageResult pageResult) { + return data(HttpServletResponse.SC_OK,pageResult.getCount(),pageResult.getRows(),null); + } + + /** + * 返回Result + * + * @param T 泛型标记 + * @return Result + */ + public static Result success() { + return new Result<>(ResultCode.SUCCESS, DEFAULT_SUCCESS_MESSAGE); + } + + /** + * 返回Result + * + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result success(String msg) { + return new Result<>(ResultCode.SUCCESS, msg); + } + + /** + * 返回Result + * + * @param resultCode 业务代码 + * @param T 泛型标记 + * @return Result + */ + public static Result success(IResultCode resultCode) { + return new Result<>(resultCode); + } + + /** + * 返回Result + * + * @param resultCode 业务代码 + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result success(IResultCode resultCode, String msg) { + return new Result<>(resultCode, msg); + } + + /** + * 返回Result + * + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result fail(String msg) { + return new Result<>(ResultCode.FAILURE, msg); + } + + + /** + * 返回Result + * + * @param code 状态码 + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result fail(int code, String msg) { + return new Result<>(code, null, msg); + } + + /** + * 返回Result + * + * @param resultCode 业务代码 + * @param T 泛型标记 + * @return Result + */ + public static Result fail(IResultCode resultCode) { + return new Result<>(resultCode); + } + + /** + * 返回Result + * + * @param resultCode 业务代码 + * @param msg 消息 + * @param T 泛型标记 + * @return Result + */ + public static Result fail(IResultCode resultCode, String msg) { + return new Result<>(resultCode, msg); + } + + /** + * 返回Result + * + * @param flag 成功状态 + * @return Result + */ + public static Result status(boolean flag) { + return flag ? success(DEFAULT_SUCCESS_MESSAGE) : fail(DEFAULT_FAILURE_MESSAGE); + } +} diff --git a/src/main/java/com/ydool/common/data/dto/ResultCode.java b/src/main/java/com/ydool/common/data/dto/ResultCode.java new file mode 100644 index 0000000..a76e7b0 --- /dev/null +++ b/src/main/java/com/ydool/common/data/dto/ResultCode.java @@ -0,0 +1,37 @@ +package com.ydool.common.data.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import javax.servlet.http.HttpServletResponse; + +@Getter +@AllArgsConstructor +public enum ResultCode implements IResultCode{ + /** + * 操作成功 + */ + SUCCESS(HttpServletResponse.SC_OK, "操作成功"), + + /** + * 业务异常 + */ + FAILURE(HttpServletResponse.SC_BAD_REQUEST, "业务异常"), + + /** + * 请求未授权 + */ + UN_AUTHORIZED(HttpServletResponse.SC_UNAUTHORIZED, "请求未授权"), + + NOT_LOGIN(HttpServletResponse.SC_UNAUTHORIZED, "请先登录"); + ; + + /** + * code编码 + */ + final int code; + /** + * 中文信息描述 + */ + final String message; +} diff --git a/src/main/java/com/ydool/common/exception/AjaxResultException.java b/src/main/java/com/ydool/common/exception/AjaxResultException.java new file mode 100644 index 0000000..f47ea3f --- /dev/null +++ b/src/main/java/com/ydool/common/exception/AjaxResultException.java @@ -0,0 +1,26 @@ +package com.ydool.common.exception; + + +import com.ydool.common.data.dto.AjaxResult; + +public class AjaxResultException extends RuntimeException { + + private AjaxResult ajaxResult; + + public AjaxResultException(){ + this.ajaxResult = AjaxResult.ok(); + } + + public AjaxResultException(String msg) { + this.ajaxResult = AjaxResult.fail(msg); + } + + public AjaxResultException(AjaxResult ajaxResult){ + this.ajaxResult = ajaxResult; + } + + public AjaxResult getResult() { + return ajaxResult; + } + +} diff --git a/src/main/java/com/ydool/common/exception/NotLoginException.java b/src/main/java/com/ydool/common/exception/NotLoginException.java new file mode 100644 index 0000000..419a79a --- /dev/null +++ b/src/main/java/com/ydool/common/exception/NotLoginException.java @@ -0,0 +1,17 @@ +package com.ydool.common.exception; + + +import com.ydool.common.data.dto.Result; +import com.ydool.common.data.dto.ResultCode; + +public class NotLoginException extends ResultException { + + public NotLoginException() { + this.result = Result.fail(ResultCode.NOT_LOGIN); + } + + public NotLoginException(String msg) { + this.result = Result.fail(ResultCode.NOT_LOGIN, msg); + } + +} diff --git a/src/main/java/com/ydool/common/exception/ResultException.java b/src/main/java/com/ydool/common/exception/ResultException.java index d0e6290..1eae978 100644 --- a/src/main/java/com/ydool/common/exception/ResultException.java +++ b/src/main/java/com/ydool/common/exception/ResultException.java @@ -1,26 +1,25 @@ package com.ydool.common.exception; -import com.ydool.common.data.dto.AjaxResult; +import com.ydool.common.data.dto.Result; public class ResultException extends RuntimeException { - private AjaxResult ajaxResult; + protected Result result; - public ResultException(){ - this.ajaxResult = AjaxResult.ok(); - } + public ResultException(){ + this.result = Result.success(); + } - public ResultException(String msg) { - this.ajaxResult = AjaxResult.fail(msg); - } + public ResultException(String msg) { + this.result = Result.fail(msg); + } - public ResultException(AjaxResult ajaxResult){ - this.ajaxResult = ajaxResult; - } - - public AjaxResult getResult() { - return ajaxResult; - } + public ResultException(Result result){ + this.result = result; + } + public Result getResult() { + return result; + } } diff --git a/src/main/java/com/ydool/common/utils/HttpServletUtil.java b/src/main/java/com/ydool/common/utils/HttpServletUtil.java index d436ee0..f5756f8 100644 --- a/src/main/java/com/ydool/common/utils/HttpServletUtil.java +++ b/src/main/java/com/ydool/common/utils/HttpServletUtil.java @@ -2,7 +2,7 @@ package com.ydool.common.utils; import cn.hutool.core.util.StrUtil; import com.ydool.common.data.dto.AjaxResult; -import com.ydool.common.exception.ResultException; +import com.ydool.common.exception.AjaxResultException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -56,7 +56,7 @@ public class HttpServletUtil { public static HttpServletRequest getRequest() { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (requestAttributes == null) { - throw new ResultException(AjaxResult.fail("获取不到http context,请确认当前请求是http请求")); + throw new AjaxResultException(AjaxResult.fail("获取不到http context,请确认当前请求是http请求")); } else { return requestAttributes.getRequest(); } @@ -71,7 +71,7 @@ public class HttpServletUtil { public static HttpServletResponse getResponse() { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (requestAttributes == null) { - throw new ResultException(AjaxResult.fail("获取不到http context,请确认当前请求是http请求")); + throw new AjaxResultException(AjaxResult.fail("获取不到http context,请确认当前请求是http请求")); } else { return requestAttributes.getResponse(); } diff --git a/src/main/java/com/ydool/common/utils/PathUtil.java b/src/main/java/com/ydool/common/utils/PathUtil.java new file mode 100644 index 0000000..0ef6c56 --- /dev/null +++ b/src/main/java/com/ydool/common/utils/PathUtil.java @@ -0,0 +1,20 @@ +package com.ydool.common.utils; + +import org.springframework.util.StringUtils; + +public class PathUtil { + + public static String normalizePath(String path) { + if (StringUtils.hasText(path)) { + return path; + } + String normalizedPath = path; + if (!normalizedPath.startsWith("/")) { + normalizedPath = "/" + normalizedPath; + } + if (normalizedPath.endsWith("/")) { + normalizedPath = normalizedPath.substring(0, normalizedPath.length() - 1); + } + return normalizedPath; + } +} diff --git a/src/main/java/com/ydool/common/utils/UploadUtil.java b/src/main/java/com/ydool/common/utils/UploadUtil.java new file mode 100644 index 0000000..d251172 --- /dev/null +++ b/src/main/java/com/ydool/common/utils/UploadUtil.java @@ -0,0 +1,34 @@ +package com.ydool.common.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.IdUtil; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Date; + +public class UploadUtil { + + public static String uploadFile(MultipartFile file) { + try { + String fileName = getFileUploadPath() + "/" + IdUtil.simpleUUID() + "." + FileUtil.extName(file.getOriginalFilename()); + String fullFilePath = getWebRoot() + fileName; + FileUtil.writeFromStream(file.getInputStream(), fullFilePath); + return fileName; + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + + public static String getFileUploadPath() { + String folder = DateUtil.format(new Date(), "yyyy/MM/dd"); + return "/upload/" + folder; + } + + public static String getWebRoot() { + return System.getProperty("user.dir"); + } + +} diff --git a/src/main/java/com/ydool/common/utils/WebUtil.java b/src/main/java/com/ydool/common/utils/WebUtil.java new file mode 100644 index 0000000..2124550 --- /dev/null +++ b/src/main/java/com/ydool/common/utils/WebUtil.java @@ -0,0 +1,145 @@ +package com.ydool.common.utils; + +import cn.hutool.core.collection.ArrayIter; +import cn.hutool.core.collection.IterUtil; +import cn.hutool.core.map.CaseInsensitiveMap; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; + +import com.ydool.common.data.dto.Result; +import com.ydool.common.exception.ResultException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Map; +import java.util.function.Predicate; + +@Slf4j +public class WebUtil { + + private static final String[] IP_HEADER_NAMES = new String[]{ + "x-forwarded-for", + "Proxy-Client-IP", + "WL-Proxy-Client-IP", + "HTTP_CLIENT_IP", + "HTTP_X_FORWARDED_FOR" + }; + + private static final Predicate IP_PREDICATE = (ip) -> StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip); + + public static String getRemoteAddress() { + return getRemoteAddress(getRequest()); + } + + public static String getRemoteAddress(HttpServletRequest request) { + if (request == null) { + return "unknown"; + } + String ip = null; + for (String ipHeader : IP_HEADER_NAMES) { + ip = request.getHeader(ipHeader); + if (!IP_PREDICATE.test(ip)) { + break; + } + } + if (IP_PREDICATE.test(ip)) { + ip = request.getRemoteAddr(); + } + return StrUtil.isBlank(ip) ? null : StrUtil.splitTrim(ip, ",").get(0); + } + + /** + * 获取当前请求的request对象 + * + * @author fengshuonan + * @date 2020/10/15 17:48 + */ + public static HttpServletRequest getRequest() { + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (requestAttributes == null) { + throw new ResultException(Result.fail("获取不到http context,请确认当前请求是http请求")); + } else { + return requestAttributes.getRequest(); + } + } + + /** + * 获取当前请求的response对象 + * + * @author fengshuonan + * @date 2020/10/15 17:48 + */ + public static HttpServletResponse getResponse() { + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (requestAttributes == null) { + throw new ResultException(Result.fail("获取不到http context,请确认当前请求是http请求")); + } else { + return requestAttributes.getResponse(); + } + } + + + public static boolean write(Object result) { + HttpServletResponse response = getResponse(); + return write(response, result); + } + + public static boolean write(HttpServletResponse response, Object result) { + if(result instanceof Result){ + response.setStatus(((Result) result).getCode()); + } + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + try (PrintWriter out = response.getWriter()) { + out.append(JSONUtil.toJsonStr(result)); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + return false; + } + + + public static Map readCookieMap(HttpServletRequest httpServletRequest) { + Cookie[] cookies = httpServletRequest.getCookies(); + return ArrayUtil.isEmpty(cookies) ? MapUtil.empty() : IterUtil.toMap(new ArrayIter(httpServletRequest.getCookies()), new CaseInsensitiveMap(), Cookie::getName); + } + + public static void addCookie(String name, String value) { + getResponse().addCookie(new Cookie(name, value)); + } + + public static void addCookie(String name, String value, int expiry) { + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(expiry); + cookie.setPath("/"); + getResponse().addCookie(cookie); + } + + + public static String getCookie(String name) { + Map cookieMap = readCookieMap(getRequest()); + return cookieMap.containsKey(name) ? cookieMap.get(name).getValue() : null; + } + + public static boolean isAjax(){ + HttpServletRequest request = getRequest(); + /*if(!StrUtil.isBlank(request.getHeader("x-requested-with")) && request.getHeader("x-requested-with").equals("XMLHttpRequest")){ + return true; + }*/ + String accept = request.getHeader("accept"); + if (accept != null && accept.indexOf("application/json") != -1) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/ydool/oa/flow/constant/FlowConstant.java b/src/main/java/com/ydool/oa/flow/constant/FlowConstant.java new file mode 100644 index 0000000..230a27b --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/constant/FlowConstant.java @@ -0,0 +1,150 @@ +package com.ydool.oa.flow.constant; + +public interface FlowConstant { + + /** + * 执行中 + */ + String FLOW_STATUS_ACTIVE = "ACTIVE"; + + /** + * 通过 + */ + String FLOW_STATUS_PASS = "PASS"; + + /** + * 驳回 + */ + String FLOW_STATUS_REFUSE = "REFUSE"; + + /** + * 结束 + */ + String FLOW_STATUS_DONE = "DONE"; + + /** + * 驳回 + */ + String STEP_STATUS_ACTIVE = "ACTIVE"; + + /** + * 通过 + */ + String STEP_STATUS_PASS = "PASS"; + + /** + * 驳回 + */ + String STEP_STATUS_REFUSE = "REFUSE"; + + /** + * 审批人 + */ + String PROCESS_TYPE_APPROVAL = "APPROVAL"; + + /** + * 抄送人 + */ + String PROCESS_TYPE_CC = "CC"; + + /** + * 条件分支 + */ + String PROCESS_TYPE_CONDITIONS = "CONDITIONS"; + + /** + * 延迟等待 + */ + String PROCESS_TYPE_DELAY = "DELAY"; + + /** + * 触发器 + */ + String PROCESS_TYPE_TRIGGER = "TRIGGER"; + + /** + * 并行分支 + */ + String PROCESS_TYPE_CONCURRENTS = "CONCURRENTS"; + + + /** + * 指定用户 + */ + String ASSIGNED_TYPE_ASSIGN_USER = "ASSIGN_USER"; + + /** + * 指定部门 + */ + String ASSIGNED_TYPE_ASSIGN_DEPT = "ASSIGN_DEPT"; + + /** + * 用户所在部门主管 + */ + String ASSIGNED_TYPE_LEADER = "LEADER"; + + /** + * 发起人自己 + */ + String ASSIGNED_TYPE_SELF = "SELF"; + + /** + * 表单内联系人 + */ + String ASSIGNED_TYPE_FORM_USER = "FORM_USER"; + + /** + * 表单内部门 + */ + String ASSIGNED_TYPE_FORM_DEPT = "FORM_DEPT"; + + /** + * 会签(按选择顺序审批,每个人必须同意)) + */ + String MODE_NEXT = "NEXT"; + + /** + * 会签(可同时审批,每个人必须同意) + */ + String MODE_AND = "AND"; + + /** + * 或签(有一人同意即可) + */ + String MODE_OR = "OR"; + + /** + * 自动通过 + */ + String NOBODY_O_PASS = "O_PASS"; + + /** + * 自动驳回 + */ + String NOBODY_O_REFUSE = "O_REFUSE"; + + /** + * 转交审批管理员 + */ + String NOBODY_TO_ADMIN = "TO_ADMIN"; + + /** + * 转交指定人员 + */ + String NOBODY_O_USER = "O_user"; + /** + * 直接结束流程 + */ + String REFUSE_TYPE_TO_END = "TO_END"; + + /** + * 当前节点 + */ + String REFUSE_TYPE_TO_CURRENT = "TO_CURRENT"; + + + /** + * 驳回到指定节点 + */ + String REFUSE_TYPE_TO_NODE = "TO_NODE"; +} diff --git a/src/main/java/com/ydool/oa/flow/controller/ProcessController.java b/src/main/java/com/ydool/oa/flow/controller/ProcessController.java new file mode 100644 index 0000000..9bdfeb3 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/controller/ProcessController.java @@ -0,0 +1,97 @@ +package com.ydool.oa.flow.controller; + + +import com.ydool.common.data.dto.PageResult; +import com.ydool.common.data.dto.Result; +import com.ydool.oa.flow.data.dto.FlowDto; +import com.ydool.oa.flow.data.dto.FlowStepDto; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.data.vo.FlowStepVo; +import com.ydool.oa.flow.data.vo.FlowVo; +import com.ydool.oa.flow.data.vo.ProcessVo; +import com.ydool.oa.flow.data.wrapper.FlowStepWrapper; +import com.ydool.oa.flow.data.wrapper.FlowWrapper; +import com.ydool.oa.flow.data.wrapper.ProcessWrapper; +import com.ydool.oa.flow.service.FlowService; +import com.ydool.oa.flow.service.FlowStepService; + +import com.ydool.oa.formily.constant.GrapeConst; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@RestController +@RequestMapping(value = GrapeConst.API + "/formily/process") +@Api(tags = "流程管理", value = "流程管理") +public class ProcessController { + + @Resource + private FlowService flowService; + + @Resource + private FlowStepService flowStepService; + + @PostMapping("{id}/start") + @ApiOperation("发起流程") + public Result start(@RequestBody FlowDto dto) { + return flowService.startProcessById(dto); + } + + @PostMapping("{id}/restart") + @ApiOperation("重新发起流程") + public Result restart(@RequestBody FlowDto dto) { + return flowService.restartProcessById(dto); + } + + + @GetMapping("{id}/task") + @ApiOperation("查看任务") + public Result task(@PathVariable String id, String stepId) { + Flow flow = flowService.getById(id); + if(flow == null) return Result.fail("流程不存在"); + FlowStep flowStep = null; + if(stepId != null) { + flowStep = flowStepService.getById(stepId); + if (flowStep == null) return Result.fail("流程节点不存在"); + } + + return Result.data(ProcessWrapper.build().toVo(flow, flowStep)); + } + + @PostMapping("{id}/complete") + @ApiOperation("完成任务") + public Result complete(@RequestBody FlowStepDto dto) { + return flowStepService.completeFlowStep(dto); + } + + /** + * 我发起的 + * @return + */ + @GetMapping("query_create") + public Result> queryCreate() { + return Result.data(FlowWrapper.build().toVo(flowService.getCreateList())); + } + + + /** + * 我待处理 + * @return + */ + @GetMapping("query_todo") + public Result> queryTodo() { + return Result.data(FlowStepWrapper.build().toVo(flowStepService.getFlowTodoList(false))); + } + + /** + * 已完成的 + * @return + */ + @GetMapping("query_done") + public Result> queryDone() { + return Result.data(FlowStepWrapper.build().toVo(flowStepService.getFlowTodoList(true))); + } +} diff --git a/src/main/java/com/ydool/oa/flow/data/dto/FlowDto.java b/src/main/java/com/ydool/oa/flow/data/dto/FlowDto.java new file mode 100644 index 0000000..18b9e64 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/dto/FlowDto.java @@ -0,0 +1,25 @@ +package com.ydool.oa.flow.data.dto; + +import cn.hutool.json.JSONObject; +import lombok.Data; + +@Data +public class FlowDto { + + /** + * 表单ID + */ + private String formId; + + /** + * 表单内容 + */ + private JSONObject data; + + /** + * 流程ID + */ + private String flowId; + + +} diff --git a/src/main/java/com/ydool/oa/flow/data/dto/FlowStepDto.java b/src/main/java/com/ydool/oa/flow/data/dto/FlowStepDto.java new file mode 100644 index 0000000..492759b --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/dto/FlowStepDto.java @@ -0,0 +1,29 @@ +package com.ydool.oa.flow.data.dto; + +import cn.hutool.json.JSONObject; +import lombok.Data; + +@Data +public class FlowStepDto { + + /** + * 流程 Step ID + */ + private String id; + + /** + * 表单内容 + */ + private JSONObject data; + + /** + * 通过 or 驳回 + * PASS or REFUSE + */ + private String action; + + /** + * 驳回理由 + */ + private String refuse; +} diff --git a/src/main/java/com/ydool/oa/flow/data/entity/Flow.java b/src/main/java/com/ydool/oa/flow/data/entity/Flow.java new file mode 100644 index 0000000..df78b82 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/entity/Flow.java @@ -0,0 +1,34 @@ +package com.ydool.oa.flow.data.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.ydool.common.base.BaseEntity; +import lombok.Data; + +@Data +@TableName(value = "t_bc_flow") +public class +Flow extends BaseEntity { + + private String formId; + + private String userId; + + private String name; + + private Integer step; + + private String stepName; + + @JsonIgnore + private String items; + + @JsonIgnore + private String data; + + @JsonIgnore + private String formPerms; + + private String status; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/entity/FlowStep.java b/src/main/java/com/ydool/oa/flow/data/entity/FlowStep.java new file mode 100644 index 0000000..60bdab4 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/entity/FlowStep.java @@ -0,0 +1,50 @@ +package com.ydool.oa.flow.data.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.ydool.common.base.BaseEntity; +import lombok.Data; + +@Data +@TableName(value = "t_bc_flow_step") +public class FlowStep extends BaseEntity { + + + @JsonSerialize(using = ToStringSerializer.class) + private String formId; + + @JsonSerialize(using = ToStringSerializer.class) + private String flowId; + + private Integer step; + + private String stepName; + + @JsonIgnore + private String userIds; + + @JsonIgnore + private String mode; + + /** + * 驳回后 + */ + @JsonIgnore + private String refuseType; + + private String status; + + private String type; + + @JsonIgnore + private String assignedType; + + @JsonIgnore + private String nextStep; + + @JsonIgnore + private String formPerms; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/entity/FlowStepLog.java b/src/main/java/com/ydool/oa/flow/data/entity/FlowStepLog.java new file mode 100644 index 0000000..42b259f --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/entity/FlowStepLog.java @@ -0,0 +1,33 @@ +package com.ydool.oa.flow.data.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ydool.common.base.BaseEntity; +import lombok.Data; + +@Data +@TableName(value = "t_bc_flow_step_log") +public class FlowStepLog extends BaseEntity { + + private String formId; + + private String flowId; + + private String stepId; + + private String userId; + + private Integer step; + + private String status; + + /** + * Approval + * cc + * write + * done + */ + private String type; + + private String msg; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/vo/FlowStepLogVo.java b/src/main/java/com/ydool/oa/flow/data/vo/FlowStepLogVo.java new file mode 100644 index 0000000..29fc778 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/vo/FlowStepLogVo.java @@ -0,0 +1,19 @@ +package com.ydool.oa.flow.data.vo; + +import com.ydool.oa.flow.data.entity.FlowStepLog; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class FlowStepLogVo extends FlowStepLog { + + private String name; + + private String avatar; + + private String status; + + private String msg; +} diff --git a/src/main/java/com/ydool/oa/flow/data/vo/FlowStepVo.java b/src/main/java/com/ydool/oa/flow/data/vo/FlowStepVo.java new file mode 100644 index 0000000..70763c2 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/vo/FlowStepVo.java @@ -0,0 +1,21 @@ +package com.ydool.oa.flow.data.vo; + +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.formily.userdept.UserDept; +import lombok.Getter; +import lombok.Setter; + + +import java.util.List; + +@Getter +@Setter +public class FlowStepVo extends FlowStep { + + private String name; + + private List users; + + private List logs; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/vo/FlowVo.java b/src/main/java/com/ydool/oa/flow/data/vo/FlowVo.java new file mode 100644 index 0000000..2f18c98 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/vo/FlowVo.java @@ -0,0 +1,14 @@ +package com.ydool.oa.flow.data.vo; + +import com.ydool.oa.flow.data.entity.Flow; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class FlowVo extends Flow { + + private String avatar; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/vo/ProcessVo.java b/src/main/java/com/ydool/oa/flow/data/vo/ProcessVo.java new file mode 100644 index 0000000..4773380 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/vo/ProcessVo.java @@ -0,0 +1,24 @@ +package com.ydool.oa.flow.data.vo; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class ProcessVo { + + private FlowVo flow; + + private JSONObject data; + + private JSONArray items; + + private JSONArray formPerms; + + private List steps; + +} diff --git a/src/main/java/com/ydool/oa/flow/data/wrapper/BaseWrapper.java b/src/main/java/com/ydool/oa/flow/data/wrapper/BaseWrapper.java new file mode 100644 index 0000000..badc00e --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/wrapper/BaseWrapper.java @@ -0,0 +1,44 @@ +package com.ydool.oa.flow.data.wrapper; + +import cn.hutool.core.bean.BeanUtil; +import com.ydool.common.data.dto.PageResult; + + +import java.util.List; +import java.util.stream.Collectors; + +public abstract class BaseWrapper { + + /** + * 单个实体类包装 + * + * @param entity 实体类 + * @return V + */ + public abstract V toVo(T entity); + + /** + * 实体类集合包装 + * + * @param list 实体类集合 + * @return List + */ + public List toVo(List list) { + return list.stream().map(this::toVo).collect(Collectors.toList()); + } + + /** + * 分页实体类集合包装 + * + * @param t 分页对象 + * @return IPage + */ + public PageResult toVo(PageResult t) { + List list = t.getRows(); + List dtoList = toVo(list); + PageResult pageResult = new PageResult<>(); + BeanUtil.copyProperties(t, pageResult); + pageResult.setRows(dtoList); + return pageResult; + } +} diff --git a/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepLogWrapper.java b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepLogWrapper.java new file mode 100644 index 0000000..543ad75 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepLogWrapper.java @@ -0,0 +1,31 @@ +package com.ydool.oa.flow.data.wrapper; + +import cn.hutool.extra.spring.SpringUtil; +import com.ydool.oa.flow.data.entity.FlowStepLog; +import com.ydool.oa.flow.data.vo.FlowStepLogVo; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; + + +public class FlowStepLogWrapper extends BaseWrapper { + + public static FlowStepLogWrapper build() { + return new FlowStepLogWrapper(); + } + + @Override + public FlowStepLogVo toVo(FlowStepLog entity) { + IUserDeptService userDeptService = SpringUtil.getBean(IUserDeptService.class); + FlowStepLogVo vo = new FlowStepLogVo(); + vo.setStatus(entity.getStatus()); + vo.setMsg(entity.getMsg()); + vo.setCreatedAt(entity.getCreatedAt()); + UserDept userDept = userDeptService.getUserById(entity.getUserId()); + vo.setName(userDept.getName()); + vo.setAvatar(userDept.getAvatar()); + return vo; + } + + + +} diff --git a/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepWrapper.java b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepWrapper.java new file mode 100644 index 0000000..e6123a3 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowStepWrapper.java @@ -0,0 +1,61 @@ +package com.ydool.oa.flow.data.wrapper; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.data.entity.FlowStepLog; +import com.ydool.oa.flow.data.vo.FlowStepVo; +import com.ydool.oa.flow.service.FlowStepLogService; +import com.ydool.oa.formily.data.entity.Formily; +import com.ydool.oa.formily.service.FormilyService; +import com.ydool.oa.formily.userdept.IUserDeptService; + + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class FlowStepWrapper extends BaseWrapper { + + public static FlowStepWrapper build() { + return new FlowStepWrapper(); + } + + @Override + public FlowStepVo toVo(FlowStep entity) { + IUserDeptService userDeptService = SpringUtil.getBean(IUserDeptService.class); + FlowStepVo vo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FlowStepVo.class)); + vo.setUsers(userDeptService.getUserListByUserId(StrUtil.split(entity.getUserIds(), ","))); + + FormilyService formilyService = SpringUtil.getBean(FormilyService.class); + Formily formily = formilyService.getById(entity.getFormId()); + if(formily != null) { + vo.setName(formily.getName()); + + } + + return vo; + } + + public FlowStepVo toLogVo(FlowStep entity) { + IUserDeptService userDeptService = SpringUtil.getBean(IUserDeptService.class); + FlowStepVo vo = new FlowStepVo(); + vo.setStep(entity.getStep()); + vo.setStepName(entity.getStepName()); + vo.setUsers(userDeptService.getUserListByUserId(StrUtil.split(entity.getUserIds(), ","))); + vo.setCreatedAt(entity.getCreatedAt()); + vo.setStatus(entity.getStatus()); + vo.setType(entity.getType()); + FlowStepLogService flowStepLogService = SpringUtil.getBean(FlowStepLogService.class); + List logs = flowStepLogService.getFlowStepLogListByStepId(entity.getId()); + vo.setLogs(FlowStepLogWrapper.build().toVo(logs)); + return vo; + } + + public List toLogVo(List list) { + return list.stream().map(this::toLogVo).collect(Collectors.toList()); + } + + +} diff --git a/src/main/java/com/ydool/oa/flow/data/wrapper/FlowWrapper.java b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowWrapper.java new file mode 100644 index 0000000..2a2d326 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/wrapper/FlowWrapper.java @@ -0,0 +1,23 @@ +package com.ydool.oa.flow.data.wrapper; + +import cn.hutool.core.bean.BeanUtil; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.vo.FlowVo; + + +import java.util.Objects; + +public class FlowWrapper extends BaseWrapper { + + public static FlowWrapper build() { + return new FlowWrapper(); + } + + @Override + public FlowVo toVo(Flow entity) { + FlowVo flowVo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FlowVo.class)); + return flowVo; + } + + +} diff --git a/src/main/java/com/ydool/oa/flow/data/wrapper/ProcessWrapper.java b/src/main/java/com/ydool/oa/flow/data/wrapper/ProcessWrapper.java new file mode 100644 index 0000000..0dc9287 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/data/wrapper/ProcessWrapper.java @@ -0,0 +1,47 @@ +package com.ydool.oa.flow.data.wrapper; + +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONUtil; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.data.vo.FlowVo; +import com.ydool.oa.flow.data.vo.ProcessVo; +import com.ydool.oa.flow.service.FlowStepService; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; + + +import java.util.List; + + +public class ProcessWrapper { + + public static ProcessWrapper build() { + return new ProcessWrapper(); + } + + public ProcessVo toVo(Flow flow, FlowStep flowStep) { + IUserDeptService userDeptService = SpringUtil.getBean(IUserDeptService.class); + UserDept user = userDeptService.getUserById(flow.getUserId()); + ProcessVo vo = new ProcessVo(); + FlowVo fvo = new FlowVo(); + fvo.setName(user.getName()); + fvo.setAvatar(user.getAvatar()); + fvo.setStatus(flow.getStatus()); + fvo.setCreatedAt(flow.getCreatedAt()); + vo.setFlow(fvo); + vo.setItems(JSONUtil.parseArray(flow.getItems())); + vo.setData(JSONUtil.parseObj(flow.getData())); + if(flowStep == null) { + vo.setFormPerms(JSONUtil.parseArray(flow.getFormPerms())); + }else { + vo.setFormPerms(JSONUtil.parseArray(flowStep.getFormPerms())); + } + FlowStepService flowStepService = SpringUtil.getBean(FlowStepService.class); + List flowStepList = flowStepService.getFlowStepListByFlowId(flow.getId()); + vo.setSteps(FlowStepWrapper.build().toLogVo(flowStepList)); + + return vo; + } + +} diff --git a/src/main/java/com/ydool/oa/flow/engine/FlowProcess.java b/src/main/java/com/ydool/oa/flow/engine/FlowProcess.java new file mode 100644 index 0000000..e9e02ec --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/FlowProcess.java @@ -0,0 +1,22 @@ +package com.ydool.oa.flow.engine; + +import lombok.Data; + +@Data +public class FlowProcess { + + private String id; + + private String parentId; + + private String type; + + private String name; + + private String desc; + + private ProcessProps props; + + private FlowProcess children; + +} diff --git a/src/main/java/com/ydool/oa/flow/engine/ProcessNoBody.java b/src/main/java/com/ydool/oa/flow/engine/ProcessNoBody.java new file mode 100644 index 0000000..43a9f34 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/ProcessNoBody.java @@ -0,0 +1,14 @@ +package com.ydool.oa.flow.engine; + +import com.ydool.oa.formily.userdept.UserDept; +import lombok.Data; + +import java.util.List; + +@Data +public class ProcessNoBody { + + private String handler; + + private List assignedUser; +} diff --git a/src/main/java/com/ydool/oa/flow/engine/ProcessProps.java b/src/main/java/com/ydool/oa/flow/engine/ProcessProps.java new file mode 100644 index 0000000..e9a57a0 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/ProcessProps.java @@ -0,0 +1,34 @@ +package com.ydool.oa.flow.engine; + +import cn.hutool.json.JSONArray; +import com.ydool.oa.formily.userdept.UserDept; +import lombok.Data; + +import java.util.List; + +@Data +public class ProcessProps { + + /** + * 审批方式 + */ + private String assignedType; + + /** + * 多人审批时审批方式 + * NEXT 会签 + * AND 会签 + * OR 或签 + */ + private String mode; + + private ProcessNoBody nobody; + + private ProcessRefuse refuse; + + private JSONArray formPerms; + + private List assignedUser; + + private List assignedDept; +} diff --git a/src/main/java/com/ydool/oa/flow/engine/ProcessRefuse.java b/src/main/java/com/ydool/oa/flow/engine/ProcessRefuse.java new file mode 100644 index 0000000..ccd49ba --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/ProcessRefuse.java @@ -0,0 +1,14 @@ +package com.ydool.oa.flow.engine; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ProcessRefuse { + + private String type; + + private String target; + +} diff --git a/src/main/java/com/ydool/oa/flow/engine/factory/ProcessTypeFactory.java b/src/main/java/com/ydool/oa/flow/engine/factory/ProcessTypeFactory.java new file mode 100644 index 0000000..77a5f50 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/factory/ProcessTypeFactory.java @@ -0,0 +1,40 @@ +package com.ydool.oa.flow.engine.factory; + +import com.ydool.common.exception.ResultException; +import com.ydool.oa.flow.engine.service.IProcessType; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class ProcessTypeFactory implements ApplicationContextAware, ApplicationListener { + + private Map processTypeMap = new ConcurrentHashMap<>(); + + private ApplicationContext applicationContext; + + public IProcessType getProcessType(String processType) { + IProcessType targetProcessType = Optional.ofNullable(processTypeMap.get(processType)).orElseThrow(() -> new ResultException("找不到 [" + processType + "] 流程节点的处理类")); + return targetProcessType; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + Map beansOfType = applicationContext.getBeansOfType(IProcessType.class); + beansOfType.values().forEach(source -> processTypeMap.put(source.getName(), source)); + } +} diff --git a/src/main/java/com/ydool/oa/flow/engine/service/IProcessType.java b/src/main/java/com/ydool/oa/flow/engine/service/IProcessType.java new file mode 100644 index 0000000..0775ae6 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/service/IProcessType.java @@ -0,0 +1,17 @@ +package com.ydool.oa.flow.engine.service; + + +import com.ydool.oa.flow.data.dto.FlowStepDto; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.engine.FlowProcess; + +public interface IProcessType { + + void execute(Flow flow, FlowProcess process); + + void complete(Flow flow, FlowStep flowStep, FlowStepDto dto); + + String getName(); + +} diff --git a/src/main/java/com/ydool/oa/flow/engine/service/impl/ProcessApproval.java b/src/main/java/com/ydool/oa/flow/engine/service/impl/ProcessApproval.java new file mode 100644 index 0000000..48b60af --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/engine/service/impl/ProcessApproval.java @@ -0,0 +1,189 @@ +package com.ydool.oa.flow.engine.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.ydool.oa.flow.constant.FlowConstant; +import com.ydool.oa.flow.data.dto.FlowStepDto; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.data.entity.FlowStepLog; +import com.ydool.oa.flow.engine.FlowProcess; +import com.ydool.oa.flow.engine.ProcessNoBody; +import com.ydool.oa.flow.engine.ProcessProps; +import com.ydool.oa.flow.engine.service.IProcessType; +import com.ydool.oa.flow.service.FlowService; +import com.ydool.oa.flow.service.FlowStepLogService; +import com.ydool.oa.flow.service.FlowStepService; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; +import org.springframework.stereotype.Service; + + +import javax.annotation.Resource; +import java.util.List; + +/** + * 根据审批人进行审批逻辑 + */ +@Service +public class ProcessApproval implements IProcessType { + + + @Resource + private IUserDeptService userDeptService; + + @Resource + private FlowService flowService; + + @Resource + private FlowStepService flowStepService; + + @Resource + private FlowStepLogService flowStepLogService; + + @Override + public void execute(Flow flow, FlowProcess process) { + ProcessProps props = process.getProps(); + FlowStep flowStep = new FlowStep(); + flowStep.setFlowId(flow.getId()); + flowStep.setFormId(flow.getFormId()); + flowStep.setStep(flow.getStep()); + flowStep.setStepName(process.getName()); + flowStep.setMode(props.getMode()); + flowStep.setRefuseType(props.getRefuse().getType()); + flowStep.setType(process.getType()); + flowStep.setAssignedType(props.getAssignedType()); + flowStep.setStatus(FlowConstant.STEP_STATUS_ACTIVE); + flowStep.setNextStep(JSONUtil.toJsonStr(process.getChildren())); + flowStep.setFormPerms(process.getProps().getFormPerms().toString()); + switch (props.getAssignedType()){ + case FlowConstant.ASSIGNED_TYPE_ASSIGN_USER: { // 指定用户 + if(props.getAssignedUser().size() == 0) { + this.doNoBody(flowStep, props.getNobody()); + } else { + flowStep.setUserIds(StrUtil.join(",", CollUtil.getFieldValues(props.getAssignedUser(), "id", String.class))); + } + } + case FlowConstant.ASSIGNED_TYPE_ASSIGN_DEPT: { // 指定部门负责人 + List userDeptList = userDeptService.getUserListByDeptId(CollUtil.getFieldValues(props.getAssignedDept(), "id", String.class)); + flowStep.setUserIds(StrUtil.join(",", CollUtil.getFieldValues(userDeptList, "id", String.class))); + } + case FlowConstant.ASSIGNED_TYPE_LEADER: { // 用户所在部门领导 + UserDept leader = userDeptService.getUserDeptLeader(flow.getUserId()); + if(leader == null) this.doNoBody(flowStep, props.getNobody()); + else flowStep.setUserIds(leader.getId().toString()); + } + case FlowConstant.ASSIGNED_TYPE_SELF: { // 发起人自己 + flowStep.setUserIds(flow.getUserId().toString()); + } + case FlowConstant.ASSIGNED_TYPE_FORM_USER: { // 表单内联系人 + + } + case FlowConstant.ASSIGNED_TYPE_FORM_DEPT: { // 表单内部门 + + } + } + + if(StrUtil.isEmpty(flowStep.getUserIds())) { + this.doNoBody(flowStep, props.getNobody()); + } + + flowStepService.save(flowStep); + } + + @Override + public void complete(Flow flow, FlowStep flowStep, FlowStepDto dto) { + UserDept current = userDeptService.getCurrentUser(); + FlowStepLog log = new FlowStepLog(); + log.setType(FlowConstant.PROCESS_TYPE_APPROVAL); + log.setFormId(flowStep.getFormId()); + log.setFlowId(flowStep.getFlowId()); + log.setStepId(flowStep.getId()); + log.setStep(flowStep.getStep()); + log.setStatus(dto.getAction()); + log.setMsg(dto.getRefuse()); + log.setUserId(current.getId()); + flowStepLogService.save(log); + + if(FlowConstant.STEP_STATUS_PASS.equals(dto.getAction())) { + // 判断是否全部完成 + switch (flowStep.getMode()) { + case FlowConstant.MODE_OR: { // 会签 只要一个同意 就提交到下一节点 + this.doCreateNextFlowStep(flow, flowStep); + } + case FlowConstant.MODE_AND: { // 与签 需要全部签完 才能提交到下一节点 + if(flowStepLogService.isAllApproval(flowStep, StrUtil.split(flowStep.getUserIds(), ","))){ + this.doCreateNextFlowStep(flow, flowStep); + } + } + } + } else { // 拒绝 + this.doRefuse(flow, flowStep); + } + } + + /** + * 找不到审批人或者审批部门 + * @param flowStep + * @param noBody + */ + public void doNoBody(FlowStep flowStep, ProcessNoBody noBody) { + switch (noBody.getHandler()){ + case FlowConstant.NOBODY_O_PASS: { // 直接通过 + flowStep.setStatus(FlowConstant.STEP_STATUS_PASS); + } + case FlowConstant.NOBODY_O_REFUSE: { // 直接拒绝 + flowStep.setStatus(FlowConstant.STEP_STATUS_REFUSE); + } + case FlowConstant.NOBODY_O_USER: { // 指定人员 + flowStep.setUserIds(StrUtil.join(",", CollUtil.getFieldValues(noBody.getAssignedUser(), "id", String.class))); + } + case FlowConstant.NOBODY_TO_ADMIN: { // 指定管理员 + UserDept admin = userDeptService.getAdminUserDepot(); + if(admin != null) flowStep.setUserIds(admin.getId().toString()); + } + } + } + + + /** + * 创建下一节点 + * @param flow + * @param flowStep + */ + public void doCreateNextFlowStep(Flow flow, FlowStep flowStep) { + flowStep.setStatus(FlowConstant.STEP_STATUS_PASS); + flowStepService.updateById(flowStep); + FlowProcess nextFlow = JSONUtil.toBean(flowStep.getNextStep(), FlowProcess.class); + if(StrUtil.isEmpty(nextFlow.getId())) { + flow.setStatus(FlowConstant.FLOW_STATUS_PASS); + }else { + flow.setStep(flow.getStep()+1); + flow.setStepName(nextFlow.getName()); + flowStepService.createFlowStep(flow, nextFlow); + } + } + + + /** + * 决绝操作 + * @param flow + * @param flowStep + */ + public void doRefuse(Flow flow, FlowStep flowStep) { + flowStep.setStatus(FlowConstant.STEP_STATUS_REFUSE); + flowStepService.updateById(flowStep); + if(FlowConstant.REFUSE_TYPE_TO_END.equals(flowStep.getRefuseType())) { + flow.setStatus(FlowConstant.FLOW_STATUS_DONE); + }else { + flow.setStatus(FlowConstant.FLOW_STATUS_REFUSE); + } + } + + @Override + public String getName() { + return FlowConstant.PROCESS_TYPE_APPROVAL; + } + +} diff --git a/src/main/java/com/ydool/oa/flow/mapper/FlowMapper.java b/src/main/java/com/ydool/oa/flow/mapper/FlowMapper.java new file mode 100644 index 0000000..016a161 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/mapper/FlowMapper.java @@ -0,0 +1,10 @@ +package com.ydool.oa.flow.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ydool.oa.flow.data.entity.Flow; +import org.apache.ibatis.annotations.Mapper; + + +@Mapper +public interface FlowMapper extends BaseMapper { +} diff --git a/src/main/java/com/ydool/oa/flow/mapper/FlowStepLogMapper.java b/src/main/java/com/ydool/oa/flow/mapper/FlowStepLogMapper.java new file mode 100644 index 0000000..0884e97 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/mapper/FlowStepLogMapper.java @@ -0,0 +1,10 @@ +package com.ydool.oa.flow.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ydool.oa.flow.data.entity.FlowStepLog; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FlowStepLogMapper extends BaseMapper { +} diff --git a/src/main/java/com/ydool/oa/flow/mapper/FlowStepMapper.java b/src/main/java/com/ydool/oa/flow/mapper/FlowStepMapper.java new file mode 100644 index 0000000..c5e0df2 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/mapper/FlowStepMapper.java @@ -0,0 +1,11 @@ +package com.ydool.oa.flow.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ydool.oa.flow.data.entity.FlowStep; +import org.apache.ibatis.annotations.Mapper; + + +@Mapper +public interface FlowStepMapper extends BaseMapper { +} diff --git a/src/main/java/com/ydool/oa/flow/service/FlowService.java b/src/main/java/com/ydool/oa/flow/service/FlowService.java new file mode 100644 index 0000000..68b1dcd --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/service/FlowService.java @@ -0,0 +1,98 @@ +package com.ydool.oa.flow.service; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ydool.common.base.BaseService; +import com.ydool.common.data.dto.PageResult; +import com.ydool.common.data.dto.Result; +import com.ydool.common.factory.PageFactory; +import com.ydool.common.factory.PageResultFactory; +import com.ydool.oa.flow.constant.FlowConstant; +import com.ydool.oa.flow.data.dto.FlowDto; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.engine.FlowProcess; +import com.ydool.oa.flow.mapper.FlowMapper; +import com.ydool.oa.formily.data.entity.Formily; +import com.ydool.oa.formily.service.FormilyService; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; + +@Service +public class FlowService extends BaseService { + + @Resource + private IUserDeptService userDeptService; + @Resource + private FormilyService formilyService; + + @Resource + private FlowStepService flowStepService; + + + /** + * 我发起的 + * @return + */ + public PageResult getCreateList() { + UserDept currentUser = userDeptService.getCurrentUser(); + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(Flow.class).eq(Flow::getUserId, currentUser.getId()).orderByDesc(Flow::getCreatedAt); + PageResult pageResult = PageResultFactory.createPageResult(page(PageFactory.defaultPage(),qw)); + return pageResult; + } + + /** + * 根据表单ID开启一个流程 + * @param dto + * @return + */ + @Transactional + public Result startProcessById(FlowDto dto) { + Formily formily = formilyService.getById(dto.getFormId()); + if(formily == null) return Result.fail("表单不存在"); + FlowProcess root = JSONUtil.toBean(formily.getProcess(), FlowProcess.class); + FlowProcess firstProcess = root.getChildren(); + if(firstProcess == null) return Result.fail("表单内不存在第一步设置"); + Flow flow = this.doCreateFlow(formily, dto, root, firstProcess); + flowStepService.createFlowStep(flow, firstProcess); + return Result.success(); + } + + @Transactional + public Result restartProcessById(FlowDto dto) { + Flow flow = getById(dto.getFlowId()); + if(flow == null) return Result.fail("流程不存在"); + FlowStep flowStep = flowStepService.getLastApprovalFlowStep(flow.getId()); + if(flowStep != null) { + flow.setStep(flow.getStep() + 1); + flow.setData(dto.getData().toString()); + this.updateById(flow); + flowStep.setStep(flow.getStep()); + flowStep.setStatus(FlowConstant.STEP_STATUS_ACTIVE); + flowStepService.save(flowStep); + } + return Result.success(); + } + + public Flow doCreateFlow(Formily formily, FlowDto dto, FlowProcess root, FlowProcess firstProcess) { + Flow flow = new Flow(); + flow.setUserId(userDeptService.getCurrentUser().getId()); + flow.setFormId(dto.getFormId()); + flow.setName(formily.getName()); + flow.setStep(1); + flow.setStepName(firstProcess.getName()); + flow.setName(firstProcess.getName()); + flow.setItems(formily.getItems()); + flow.setData(dto.getData().toString()); + flow.setFormPerms(root.getProps().getFormPerms().toString()); + flow.setStatus(FlowConstant.FLOW_STATUS_ACTIVE); + save(flow); + return flow; + } + +} diff --git a/src/main/java/com/ydool/oa/flow/service/FlowStepLogService.java b/src/main/java/com/ydool/oa/flow/service/FlowStepLogService.java new file mode 100644 index 0000000..6562e42 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/service/FlowStepLogService.java @@ -0,0 +1,37 @@ +package com.ydool.oa.flow.service; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ydool.common.base.BaseService; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.data.entity.FlowStepLog; +import com.ydool.oa.flow.mapper.FlowStepLogMapper; +import org.springframework.stereotype.Service; + + +import java.util.List; +import java.util.stream.Collectors; + + +@Service +public class FlowStepLogService extends BaseService { + + /** + * 判断是否已全部审批 + * @param flowStep 审批节点 + * @param userIds 需要审批的用户id + * @return + */ + public Boolean isAllApproval(FlowStep flowStep, List userIds) { + List flowStepLogList = getFlowStepLogListByStepId(flowStep.getId()); + List idList = CollUtil.getFieldValues(flowStepLogList, "userId", String.class); + List reduceId = userIds.stream().filter(item -> !idList.contains(item)).collect(Collectors.toList()); + return reduceId.isEmpty(); + } + + public List getFlowStepLogListByStepId(String stepId) { + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(FlowStepLog::getStepId, stepId).orderByDesc(FlowStepLog::getCreatedAt); + return list(qw); + } +} diff --git a/src/main/java/com/ydool/oa/flow/service/FlowStepService.java b/src/main/java/com/ydool/oa/flow/service/FlowStepService.java new file mode 100644 index 0000000..2c95b06 --- /dev/null +++ b/src/main/java/com/ydool/oa/flow/service/FlowStepService.java @@ -0,0 +1,90 @@ +package com.ydool.oa.flow.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ydool.common.base.BaseService; +import com.ydool.common.data.dto.PageResult; +import com.ydool.common.data.dto.Result; +import com.ydool.common.factory.PageFactory; +import com.ydool.common.factory.PageResultFactory; +import com.ydool.oa.flow.constant.FlowConstant; +import com.ydool.oa.flow.data.dto.FlowStepDto; +import com.ydool.oa.flow.data.entity.Flow; +import com.ydool.oa.flow.data.entity.FlowStep; +import com.ydool.oa.flow.engine.FlowProcess; +import com.ydool.oa.flow.engine.factory.ProcessTypeFactory; +import com.ydool.oa.flow.mapper.FlowStepMapper; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +@Service +public class FlowStepService extends BaseService { + + @Resource + private ProcessTypeFactory processTypeFactory; + + @Resource + private IUserDeptService userDeptService; + + @Resource + private FlowService flowService; + + /** + * 我待处理 + * @param isDone true: 返回 PASS 和 REFUSE false: 返回 ACTIVE + * @return + */ + public PageResult getFlowTodoList(Boolean isDone) { + UserDept currentUser = userDeptService.getCurrentUser(); + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(FlowStep.class).orderByDesc(FlowStep::getCreatedAt); + if(isDone) qw.ne(FlowStep::getStatus, FlowConstant.FLOW_STATUS_DONE); + else qw.eq(FlowStep::getStatus, FlowConstant.STEP_STATUS_ACTIVE); + qw.apply("FIND_IN_SET (" + currentUser.getId() + ", user_ids)"); + PageResult pageResult = PageResultFactory.createPageResult(page(PageFactory.defaultPage(),qw)); + return pageResult; + } + + // 设置审批人 + public void createFlowStep(Flow flow, FlowProcess process) { + processTypeFactory.getProcessType(process.getType()).execute(flow, process); + } + + public Result completeFlowStep(FlowStepDto dto) { + FlowStep flowStep = getById(dto.getId()); + if(flowStep != null) { + Flow flow = flowService.getById(flowStep.getFlowId()); + flow.setData(dto.getData().toString()); + processTypeFactory.getProcessType(flowStep.getType()).complete(flow, flowStep, dto); + flowService.updateById(flow); + + + } + return Result.success(); + } + + /** + * 返回最后一个审批节点 + * @param flowId 流程ID + * @return + */ + public FlowStep getLastApprovalFlowStep(String flowId) { + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(FlowStep::getFlowId, flowId).eq(FlowStep::getType, FlowConstant.PROCESS_TYPE_APPROVAL).orderByDesc(FlowStep::getCreatedAt); + qw.last("limit 1"); + return getOne(qw); + } + + /** + * 返回所有的步骤 + * @param flowId + * @return + */ + public List getFlowStepListByFlowId(String flowId) { + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(FlowStep::getFlowId, flowId).orderByAsc(FlowStep::getCreatedAt); + return list(qw); + } +} diff --git a/src/main/java/com/ydool/oa/formily/constant/GrapeConst.java b/src/main/java/com/ydool/oa/formily/constant/GrapeConst.java new file mode 100644 index 0000000..832fa81 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/constant/GrapeConst.java @@ -0,0 +1,7 @@ +package com.ydool.oa.formily.constant; + +public interface GrapeConst { + + String API = "/api"; + +} diff --git a/src/main/java/com/ydool/oa/formily/controller/FormilyController.java b/src/main/java/com/ydool/oa/formily/controller/FormilyController.java new file mode 100644 index 0000000..f408d5a --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/controller/FormilyController.java @@ -0,0 +1,107 @@ +package com.ydool.oa.formily.controller; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; +import com.ydool.common.data.dto.Result; +import com.ydool.common.utils.UploadUtil; +import com.ydool.oa.flow.engine.FlowProcess; +import com.ydool.oa.flow.service.FlowService; +import com.ydool.oa.formily.constant.GrapeConst; + +import com.ydool.oa.formily.data.dto.FormilyDto; +import com.ydool.oa.formily.data.entity.Formily; +import com.ydool.oa.formily.data.vo.FormilyStartVo; +import com.ydool.oa.formily.service.FormilyService; +import com.ydool.oa.formily.userdept.IUserDeptService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + + +import javax.annotation.Resource; +import javax.validation.constraints.NotNull; +import java.util.regex.Pattern; + +@RestController +@RequestMapping(value = GrapeConst.API + "/formily") +@Api(tags = "表单", value = "表单") +public class FormilyController { + + @Resource + private FormilyService formilyService; + + @Resource + private FlowService flowService; + + @Resource + private IUserDeptService userDeptService; + + @PostMapping + @ApiOperation("新增表单") + public Result save(@Validated @RequestBody FormilyDto dto){ + Formily formily = new Formily(); + BeanUtil.copyProperties(dto,formily); + boolean flag = formilyService.save(formily); + return flag ? Result.success() : Result.fail("操作失败"); + } + + @PostMapping("update") + @ApiOperation("修改表单") + public Result update(@Validated @RequestBody FormilyDto dto){ + Formily formily = formilyService.get(dto.getId()); + BeanUtil.copyProperties(dto,formily); + boolean flag = formilyService.updateById(formily); + return flag ? Result.success() : Result.fail("操作失败"); + } + + @GetMapping("{id}") + @ApiOperation( "表单详情") + public Result show(@PathVariable String id){ + Formily formily = formilyService.get(id); + if(formily == null) return Result.fail("表单不存在"); + return Result.data(formily); + } + + @GetMapping("{id}/items") + @ApiOperation( "获取流程表单") + public Result items(@PathVariable String id) { + Formily formily = formilyService.get(id); + if(formily == null) return Result.fail("表单不存在"); + JSONArray items = JSONUtil.parseArray(formily.getItems()); + FlowProcess root = JSONUtil.toBean(formily.getProcess(), FlowProcess.class); + JSONArray formPerms = root.getProps().getFormPerms(); + FormilyStartVo vo = new FormilyStartVo(items, formPerms); + return Result.data(vo); + } + + @DeleteMapping("{id}") + @ApiOperation("删除表单") + public Result delete(@PathVariable String id){ + boolean flag = formilyService.removeById(id); + return flag ? Result.success() : Result.fail("操作失败"); + } + + @GetMapping("menu_list") + public Result getMenuList() { + return Result.data(userDeptService.getUserMenuList()); + } + + @PostMapping("upload") + @ApiOperation("上传文件") + public Result upload(@NotNull(message = "请选择需要上传的文件") MultipartFile file) { + String reg = ".+(.exe|.bat|.sh|.java|.php|.js|.py)$"; + String suffix = FileUtil.getSuffix(file.getOriginalFilename()); + if (Pattern.matches(reg, file.getOriginalFilename())) { + return Result.fail("不能上传后缀为" + suffix + "的文件"); + } + String path = UploadUtil.uploadFile(file); + Dict data = Dict.create().set("path", path).set("preview", path).set("name", file.getOriginalFilename()); + return (StrUtil.isNotBlank(path) ? Result.data(data) : Result.fail("上传失败")); + } +} diff --git a/src/main/java/com/ydool/oa/formily/controller/GroupController.java b/src/main/java/com/ydool/oa/formily/controller/GroupController.java new file mode 100644 index 0000000..1b20973 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/controller/GroupController.java @@ -0,0 +1,77 @@ +package com.ydool.oa.formily.controller; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.ydool.common.data.dto.Result; +import com.ydool.oa.formily.constant.GrapeConst; +import com.ydool.oa.formily.data.dto.GroupDto; +import com.ydool.oa.formily.data.entity.Group; +import com.ydool.oa.formily.data.vo.FormilyVo; +import com.ydool.oa.formily.data.vo.GroupVo; +import com.ydool.oa.formily.service.FormilyService; +import com.ydool.oa.formily.service.GroupService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequestMapping(value = GrapeConst.API + "/group") +@Api(tags = "应用分组", value = "应用分组") +public class GroupController { + + @Resource + private GroupService groupService; + + @Resource + private FormilyService formilyService; + + @PostMapping + @ApiOperation("新增应用分组") + public Result save(@Validated @RequestBody GroupDto dto){ + Group group = new Group(); + BeanUtil.copyProperties(dto,group); + boolean flag = groupService.save(group); + return flag ? Result.success() : Result.fail("操作失败"); + } + + @GetMapping + @ApiOperation("应用分组列表") + public Result list() { + List list = groupService.list(new LambdaQueryWrapper<>(Group.class).orderByAsc(Group::getSortNo)); + List groupList = new ArrayList<>(); + + for(Group group : list) { + GroupVo vo = new GroupVo(group); + vo.setFormilies(formilyService.getFormilyByGroup(vo.getId()).stream().map(formily -> new FormilyVo(formily)).collect(Collectors.toList())); + groupList.add(vo); + } + return Result.data(groupList); + } + + @PostMapping(value = "update_position") + @ApiOperation("更新应用分组顺序") + public Result updatePosition(@RequestBody JSONObject body) { + JSONArray ids = body.getJSONArray("ids"); + for(int i = 0; i < ids.size(); i++) { + Object id = ids.get(i); + LambdaUpdateWrapper uw = new LambdaUpdateWrapper(); + uw.set(Group::getSortNo, i + 1).eq(Group::getId, id.toString()); + groupService.update(uw); + } + return Result.success(); + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/ydool/oa/formily/controller/TreeController.java b/src/main/java/com/ydool/oa/formily/controller/TreeController.java new file mode 100644 index 0000000..1b2dbf6 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/controller/TreeController.java @@ -0,0 +1,35 @@ +package com.ydool.oa.formily.controller; + +import com.ydool.common.data.dto.Result; +import com.ydool.oa.formily.constant.GrapeConst; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; +import io.swagger.annotations.Api; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping(value = GrapeConst.API + "/tree") +@Api(tags = "部门/用户", value = "部门/用户") + +public class TreeController { + + @Resource + private IUserDeptService userDeptService; + + /** + * 获取部门或者用户 + * @param type user or depot + * @return + */ + @GetMapping + public Result getList(String type,String deptId) { + List result = userDeptService.getTree(type, deptId); + return Result.data(result); + } +} diff --git a/src/main/java/com/ydool/oa/formily/data/dto/FormilyDto.java b/src/main/java/com/ydool/oa/formily/data/dto/FormilyDto.java new file mode 100644 index 0000000..d02de48 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/dto/FormilyDto.java @@ -0,0 +1,9 @@ +package com.ydool.oa.formily.data.dto; + +import com.ydool.oa.formily.data.entity.Formily; +import lombok.Data; + + +@Data +public class FormilyDto extends Formily { +} diff --git a/src/main/java/com/ydool/oa/formily/data/dto/GroupDto.java b/src/main/java/com/ydool/oa/formily/data/dto/GroupDto.java new file mode 100644 index 0000000..1bc98a3 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/dto/GroupDto.java @@ -0,0 +1,10 @@ +package com.ydool.oa.formily.data.dto; + +import com.ydool.oa.formily.data.entity.Group; +import lombok.Data; + + + +@Data +public class GroupDto extends Group { +} diff --git a/src/main/java/com/ydool/oa/formily/data/entity/Formily.java b/src/main/java/com/ydool/oa/formily/data/entity/Formily.java new file mode 100644 index 0000000..13e9ee0 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/entity/Formily.java @@ -0,0 +1,32 @@ +package com.ydool.oa.formily.data.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; + +import com.ydool.common.base.BaseEntity; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +@TableName(value = "t_bc_formily") +public class Formily extends BaseEntity { + + @NotBlank(message = "请输入表单名称") + private String name; + + @NotBlank(message = "请选择应用分组") + @JsonSerialize(using = ToStringSerializer.class) + private String groupId; + + private String items; + + private String logo; + + private String process; + + private String remark; + + private String settings; +} diff --git a/src/main/java/com/ydool/oa/formily/data/entity/Group.java b/src/main/java/com/ydool/oa/formily/data/entity/Group.java new file mode 100644 index 0000000..da4e486 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/entity/Group.java @@ -0,0 +1,22 @@ +package com.ydool.oa.formily.data.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ydool.common.base.BaseEntity; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +@TableName(value = "t_bc_group") +public class Group extends BaseEntity { + + @NotBlank(message = "请输入应用分组名称") + private String name; + + + private Integer sortNo; + + public Group() { + this.sortNo = 99; + } +} diff --git a/src/main/java/com/ydool/oa/formily/data/vo/FormilyStartVo.java b/src/main/java/com/ydool/oa/formily/data/vo/FormilyStartVo.java new file mode 100644 index 0000000..4ccd801 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/vo/FormilyStartVo.java @@ -0,0 +1,17 @@ +package com.ydool.oa.formily.data.vo; + +import cn.hutool.json.JSONArray; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class FormilyStartVo { + + private JSONArray items; + + private JSONArray formPerms; + +} diff --git a/src/main/java/com/ydool/oa/formily/data/vo/FormilyVo.java b/src/main/java/com/ydool/oa/formily/data/vo/FormilyVo.java new file mode 100644 index 0000000..63c8f0e --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/vo/FormilyVo.java @@ -0,0 +1,24 @@ +package com.ydool.oa.formily.data.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.ydool.oa.formily.data.entity.Formily; +import lombok.Data; + +@Data +public class FormilyVo { + + @JsonSerialize(using = ToStringSerializer.class) + private String id; + + private String name; + + private String logo; + + public FormilyVo(Formily formily) { + this.id = formily.getId(); + this.name = formily.getName(); + this.logo = formily.getLogo(); + } + +} diff --git a/src/main/java/com/ydool/oa/formily/data/vo/GroupVo.java b/src/main/java/com/ydool/oa/formily/data/vo/GroupVo.java new file mode 100644 index 0000000..4a6e68f --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/data/vo/GroupVo.java @@ -0,0 +1,23 @@ +package com.ydool.oa.formily.data.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.ydool.oa.formily.data.entity.Group; +import lombok.Data; + +import java.util.List; + +@Data +public class GroupVo { + + @JsonSerialize(using = ToStringSerializer.class) + private String id; + private String name; + + private List formilies; + + public GroupVo(Group group) { + this.id = group.getId(); + this.name = group.getName(); + } +} diff --git a/src/main/java/com/ydool/oa/formily/mapper/FormilyMapper.java b/src/main/java/com/ydool/oa/formily/mapper/FormilyMapper.java new file mode 100644 index 0000000..ae2f67b --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/mapper/FormilyMapper.java @@ -0,0 +1,9 @@ +package com.ydool.oa.formily.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ydool.oa.formily.data.entity.Formily; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FormilyMapper extends BaseMapper { +} diff --git a/src/main/java/com/ydool/oa/formily/mapper/GroupMapper.java b/src/main/java/com/ydool/oa/formily/mapper/GroupMapper.java new file mode 100644 index 0000000..2d1d7b8 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/mapper/GroupMapper.java @@ -0,0 +1,10 @@ +package com.ydool.oa.formily.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ydool.oa.formily.data.entity.Group; +import org.apache.ibatis.annotations.Mapper; + + +@Mapper +public interface GroupMapper extends BaseMapper { +} diff --git a/src/main/java/com/ydool/oa/formily/service/FormilyService.java b/src/main/java/com/ydool/oa/formily/service/FormilyService.java new file mode 100644 index 0000000..62ddc72 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/service/FormilyService.java @@ -0,0 +1,19 @@ +package com.ydool.oa.formily.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ydool.common.base.BaseService; +import com.ydool.oa.formily.data.entity.Formily; +import com.ydool.oa.formily.mapper.FormilyMapper; +import org.springframework.stereotype.Service; + + +import java.util.List; + +@Service +public class FormilyService extends BaseService { + + public List getFormilyByGroup(String groupId) { + return list(new LambdaQueryWrapper<>(Formily.class).eq(Formily::getGroupId, groupId)); + } + +} diff --git a/src/main/java/com/ydool/oa/formily/service/GroupService.java b/src/main/java/com/ydool/oa/formily/service/GroupService.java new file mode 100644 index 0000000..8c2b13e --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/service/GroupService.java @@ -0,0 +1,11 @@ +package com.ydool.oa.formily.service; + +import com.ydool.common.base.BaseService; +import com.ydool.oa.formily.data.entity.Group; +import com.ydool.oa.formily.mapper.GroupMapper; +import org.springframework.stereotype.Service; + + +@Service +public class GroupService extends BaseService { +} diff --git a/src/main/java/com/ydool/oa/formily/userdept/IUserDeptService.java b/src/main/java/com/ydool/oa/formily/userdept/IUserDeptService.java new file mode 100644 index 0000000..7cb5c05 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/userdept/IUserDeptService.java @@ -0,0 +1,60 @@ +package com.ydool.oa.formily.userdept; + +import java.util.List; + +public interface IUserDeptService { + + /** + * 返回用户部门列表 + * @param type user or dept + * @param deptId 部门ID + * @return + */ + List getTree(String type, String deptId); + + /** + * 根据用户ID, 返回用户所在部门的领导 + * @param userId + * @return + */ + UserDept getUserDeptLeader(String userId); + + /** + * 根据部门ID,返回该部门负责人 + * @param deptIds + * @return + */ + List getUserListByDeptId(List deptIds) ; + + /** + * 根据部门ID,返回该部门负责人 + * @param userIds + * @return + */ + List getUserListByUserId(List userIds); + + /** + * 当审批人员为空时,转交给管理员审批 + * @return + */ + UserDept getAdminUserDepot(); + + /** + * 根据ID 返回用户 + * @param userId + * @return + */ + UserDept getUserById(String userId); + + /** + * 返回当前登录的用户 + * @return + */ + UserDept getCurrentUser(); + + /** + * 返回当前登录用户的菜单列表 + * @return + */ + Object getUserMenuList(); +} diff --git a/src/main/java/com/ydool/oa/formily/userdept/UserDept.java b/src/main/java/com/ydool/oa/formily/userdept/UserDept.java new file mode 100644 index 0000000..fdf6f68 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/userdept/UserDept.java @@ -0,0 +1,98 @@ +package com.ydool.oa.formily.userdept; + +public class UserDept { + + /** + * 主键 + */ + private String id; + + /** + * 姓名 + */ + private String name; + + /** + * 类型 user or dept + */ + private String type; + + /** + * 头像 + */ + private String avatar; + + /** + * 是否领导 + */ + private Boolean isLeader; + + /** + * 选中状态 + */ + private Boolean selected; + + + public UserDept(String id, String name, String type) { + this.id = id; + this.name = name; + this.type = type; + } + + public UserDept(String id, String name, String type, String avatar, Boolean isLeader) { + this.id = id; + this.name = name; + this.type = type; + this.avatar = avatar; + this.isLeader = isLeader; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public Boolean getLeader() { + return isLeader; + } + + public void setLeader(Boolean leader) { + isLeader = leader; + } + + public Boolean getSelected() { + return selected; + } + + public void setSelected(Boolean selected) { + this.selected = selected; + } + +} diff --git a/src/main/java/com/ydool/oa/formily/userdept/impl/UserDeptServiceImpl.java b/src/main/java/com/ydool/oa/formily/userdept/impl/UserDeptServiceImpl.java new file mode 100644 index 0000000..35253d1 --- /dev/null +++ b/src/main/java/com/ydool/oa/formily/userdept/impl/UserDeptServiceImpl.java @@ -0,0 +1,200 @@ +package com.ydool.oa.formily.userdept.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ydool.common.cache.ConfigCache; +import com.ydool.oa.formily.userdept.IUserDeptService; +import com.ydool.oa.formily.userdept.UserDept; +import com.ydool.system.entity.Dept; +import com.ydool.system.entity.Job; +import com.ydool.system.entity.User; +import com.ydool.system.service.impl.DeptServiceImpl; +import com.ydool.system.service.impl.JobServiceImpl; +import com.ydool.system.service.impl.UserServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserDeptServiceImpl implements IUserDeptService { + + @Autowired + private UserServiceImpl userService; + + @Autowired + private JobServiceImpl jobService; + + @Autowired + private DeptServiceImpl deptService; + + @Override + public List getTree(String type, String deptId) { + List result = new ArrayList(); + + List depts = deptService.list(new QueryWrapper().lambda() + .eq(Dept::getPid, StrUtil.isNotBlank(deptId) ? deptId : "0") + ); + + if (CollUtil.isNotEmpty(depts)) { + depts.forEach(dept -> { + result.add(new UserDept(dept.getId(), dept.getName(), "dept")); + }); + } + + + if ("user".equals(type) && StrUtil.isNotBlank(deptId)) { + List users = userService.list(new QueryWrapper().lambda() + .eq(User::getDept, deptId) + .eq(User::getStatus, true) + ); + if (CollUtil.isNotEmpty(users)) { + users.forEach(user -> { + result.add(new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob()))); + }); + } + } + + return result; + } + + @Override + public UserDept getUserDeptLeader(String userId) { + if (StrUtil.isBlank(userId)) return null; + + User user = userService.getOne(new QueryWrapper().lambda() + .eq(User::getId, userId) + .eq(User::getStatus, true) + .last("limit 1") + ); + + if (ObjectUtil.isNull(user)) return null; + + Boolean isLeader = isLeader(user.getJob()); + + if (isLeader) { + return new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob())); + } + + String leaderJobId = getLeaderJobId(); + + User leaderUser = userService.getOne(new QueryWrapper().lambda() + .eq(User::getDept, user.getDept()) + .eq(User::getJob, leaderJobId) + .eq(User::getStatus, true) + .last("limit 1") + ); + + if (ObjectUtil.isNull(leaderUser)) return null; + + return new UserDept(leaderUser.getId(), leaderUser.getUserName(), "user", "", isLeader(user.getJob())); + } + + @Override + public List getUserListByDeptId(List deptIds) { + if (CollUtil.isEmpty(deptIds)) return null; + + List userList = userService.list(new QueryWrapper().lambda() + .in(User::getDept, deptIds) + .eq(User::getJob, getLeaderJobId()) + .eq(User::getStatus, true) + ); + + + List userDeptList = new ArrayList(); + if (CollUtil.isNotEmpty(userList)) { + userList.forEach(user -> { + userDeptList.add(new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob()))); + }); + + } + + return userDeptList; + } + + @Override + public List getUserListByUserId(List userIds) { + if (CollUtil.isEmpty(userIds)) return null; + List userList = userService.list(new QueryWrapper().lambda() + .in(User::getId, userIds) + .eq(User::getStatus, true) + ); + if (CollUtil.isEmpty(userList)) return null; + List deptIds = userList.stream().map(User::getDept).collect(Collectors.toList()); + + return getUserListByDeptId(deptIds); + + } + + @Override + public UserDept getAdminUserDepot() { + User user = userService.getOne(new QueryWrapper().lambda() + .eq(User::getLoginName, ConfigCache.getStr(ConfigCache.USER_ADMIN, "admin")) + .eq(User::getStatus, true) + .last("limit 1") + ); + if (ObjectUtil.isNull(user)) return null; + return new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob())); + } + + @Override + public UserDept getUserById(String userId) { + User user = userService.getOne(new QueryWrapper().lambda() + .eq(User::getId, userId) + .eq(User::getStatus, true) + .last("limit 1") + ); + if (ObjectUtil.isNull(user)) return null; + return new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob())); + } + + @Override + public UserDept getCurrentUser() { + User user = userService.getOne(new QueryWrapper().lambda() + .eq(User::getId, StpUtil.getLoginIdAsString()) + .eq(User::getStatus, true) + .last("limit 1") + ); + if (ObjectUtil.isNull(user)) return null; + return new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob())); + } + + @Override + public Object getUserMenuList() { + return userService.menuTreesByUserId(StpUtil.getLoginIdAsString()); + } + + + private Boolean isLeader(String jobId) { + Job job = jobService.getOne(new QueryWrapper().lambda() + .eq(Job::getId, jobId) + .eq(Job::getStatus, true) + .last("limit 1") + ); + boolean isLeader = false; + if (ObjectUtil.isNotNull(job)) { + if ("负责人".equals(job.getName())) { + isLeader = true; + } + } + return isLeader; + } + + private String getLeaderJobId() { + Job job = jobService.getOne(new QueryWrapper().lambda() + .eq(Job::getName, "负责人") + .eq(Job::getStatus, true) + .last("limit 1") + ); + String jobId = ""; + if (ObjectUtil.isNotNull(job)) { + jobId = job.getId(); + } + return jobId; + } +} diff --git a/src/main/java/com/ydool/platform/mybatis/config/MybatisPlusConfig.java b/src/main/java/com/ydool/platform/mybatis/config/MybatisPlusConfig.java index 69e63cf..8c1f26b 100644 --- a/src/main/java/com/ydool/platform/mybatis/config/MybatisPlusConfig.java +++ b/src/main/java/com/ydool/platform/mybatis/config/MybatisPlusConfig.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration -@MapperScan("com.ydool.**.mapper.**") +@MapperScan({"com.ydool.**.mapper.**","com.ydool.oa.**.mapper.**"}) public class MybatisPlusConfig { /** diff --git a/src/main/java/com/ydool/platform/swagger/config/SwaggerConfig.java b/src/main/java/com/ydool/platform/swagger/config/SwaggerConfig.java index 33a7009..1b8ba1d 100644 --- a/src/main/java/com/ydool/platform/swagger/config/SwaggerConfig.java +++ b/src/main/java/com/ydool/platform/swagger/config/SwaggerConfig.java @@ -59,6 +59,38 @@ public class SwaggerConfig { return docket; } + @Bean(value = "defaultApi3") + public Docket defaultApi3() { + String groupName="OA-flow"; + Docket docket=new Docket(DocumentationType.SWAGGER_2) + .host("http://www.ydool.com/") + .apiInfo(apiInfo()) + .groupName(groupName) + .select() + .apis(RequestHandlerSelectors.basePackage("com.ydool.oa.flow.controller")) + .paths(PathSelectors.any()) + .build() + //赋予插件体系 + .extensions(openApiExtensionResolver.buildExtensions(groupName)); + return docket; + } + + @Bean(value = "defaultApi4") + public Docket defaultApi4() { + String groupName="OA-formily"; + Docket docket=new Docket(DocumentationType.SWAGGER_2) + .host("http://www.ydool.com/") + .apiInfo(apiInfo()) + .groupName(groupName) + .select() + .apis(RequestHandlerSelectors.basePackage("com.ydool.oa.formily.controller")) + .paths(PathSelectors.any()) + .build() + //赋予插件体系 + .extensions(openApiExtensionResolver.buildExtensions(groupName)); + return docket; + } + private ApiInfo apiInfo() { return new ApiInfoBuilder().title("接口文档系统") .description("接口文档系统") diff --git a/src/main/java/com/ydool/system/service/IUserService.java b/src/main/java/com/ydool/system/service/IUserService.java index 1d29972..5953d80 100644 --- a/src/main/java/com/ydool/system/service/IUserService.java +++ b/src/main/java/com/ydool/system/service/IUserService.java @@ -112,6 +112,13 @@ public interface IUserService { */ List menuTreesByUser(String id); + /** + * 获取菜单树 + * @param id + * @return + */ + List menuTreesByUserId(String id); + /** * 获取菜单 * @param id diff --git a/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java b/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java index 00bebbc..2c8fec1 100644 --- a/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java @@ -315,6 +315,71 @@ public class UserServiceImpl extends BaseService implements IU return null; } + + /** + * 获取菜单树 + * + * @return + */ + @Override + public List menuTreesByUserId(String id) { + List roles = roleListByUser(id); + if (CollUtil.isNotEmpty(roles)) { + String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(",")); + + List> menuMap = menuService.listMaps(new QueryWrapper().lambda() + .in(Menu::getId, Arrays.asList(menus.split( + ","))) + .eq(Menu::getStatus, true) + .eq(Menu::getVisible, false) + .ne(Menu::getMenuType, "F") + .orderByAsc(Menu::getSortNo) + ); + + //树结构下搜索,如果子级符合条件,就把父级也放进去,确保其能显示 + Iterator> iterator = menuMap.iterator(); + List> parentList = new ArrayList<>(); + + QueryWrapper wrapper = new QueryWrapper(); + wrapper.lambda().eq(Menu::getStatus, true) + .eq(Menu::getVisible, false).orderByAsc(Menu::getSortNo); + + //获取所有菜单 + List> allMenuMap = menuService.listMaps(wrapper); + Map allMap = new HashMap(); + + allMenuMap.forEach(item -> { + HashMap map = (HashMap) item; + allMap.put(map.get("id").toString(), map); + }); + + while (iterator.hasNext()) { + Map map = (HashMap) iterator.next(); + String pid = map.get("pid").toString(); + if (!"0".equals(pid)) { + for (; ; ) { + Map pMap = (HashMap) allMap.get(pid); + if (pMap != null && !menuMap.contains(pMap) && !parentList.contains(pMap)) { + parentList.add(pMap); + pid = pMap.get("pid").toString(); + } else { + break; + } + } + } + } + menuMap.addAll(parentList); + TreeMapUtil treeMapUtil = new TreeMapUtil(); + treeMapUtil.tree(menuMap); + //转换为集合对象 + JSONArray jsonArray = new JSONArray(); + jsonArray.addAll(menuMap); + List menuList = jsonArray.toList(Menu.class); + return menuList; + } + return null; + } + /** * 获取菜单 * diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 4cd374e..7fedec1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -43,6 +43,8 @@ spring: use-global-data-source-stat: true # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + hikari: + auto-commit: true # 配置监控服务器 stat-view-servlet: login-username: admin @@ -62,6 +64,10 @@ spring: thymeleaf: prefix: classpath:/html/ suffix: .html + jackson: + default-property-inclusion: non_null + main: + allow-circular-references: true mybatis-plus: global-config: