OA板块整合与实现
This commit is contained in:
parent
8a9252d227
commit
172e3520e0
|
@ -1,5 +1,6 @@
|
|||
package com.ydool;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> {
|
||||
|
||||
|
@ -36,7 +35,7 @@ public class BaseService<M extends BaseMapper<T>, 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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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<T> 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> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> data(T data) {
|
||||
return data(data, DEFAULT_SUCCESS_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param data 数据
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> data(T data, String msg) {
|
||||
return data(HttpServletResponse.SC_OK, data, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param data 数据
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> data(int code, T data, String msg) {
|
||||
return new Result<>(code, data, data == null ? DEFAULT_NULL_MESSAGE : msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> data(int code,int count, T data, String msg) {
|
||||
return new Result<>(code,count, data, data == null ? DEFAULT_NULL_MESSAGE : msg);
|
||||
}
|
||||
|
||||
public static <T> Result<List<T>> page(PageResult<T> pageResult) {
|
||||
return data(HttpServletResponse.SC_OK,pageResult.getCount(),pageResult.getRows(),null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success() {
|
||||
return new Result<>(ResultCode.SUCCESS, DEFAULT_SUCCESS_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success(String msg) {
|
||||
return new Result<>(ResultCode.SUCCESS, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param resultCode 业务代码
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success(IResultCode resultCode) {
|
||||
return new Result<>(resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param resultCode 业务代码
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> success(IResultCode resultCode, String msg) {
|
||||
return new Result<>(resultCode, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> fail(String msg) {
|
||||
return new Result<>(ResultCode.FAILURE, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> fail(int code, String msg) {
|
||||
return new Result<>(code, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param resultCode 业务代码
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> fail(IResultCode resultCode) {
|
||||
return new Result<>(resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param resultCode 业务代码
|
||||
* @param msg 消息
|
||||
* @param <T> T 泛型标记
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> fail(IResultCode resultCode, String msg) {
|
||||
return new Result<>(resultCode, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Result
|
||||
*
|
||||
* @param flag 成功状态
|
||||
* @return Result
|
||||
*/
|
||||
public static <T> Result<T> status(boolean flag) {
|
||||
return flag ? success(DEFAULT_SUCCESS_MESSAGE) : fail(DEFAULT_FAILURE_MESSAGE);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
this.result = Result.success();
|
||||
}
|
||||
|
||||
public ResultException(String msg) {
|
||||
this.ajaxResult = AjaxResult.fail(msg);
|
||||
this.result = Result.fail(msg);
|
||||
}
|
||||
|
||||
public ResultException(AjaxResult ajaxResult){
|
||||
this.ajaxResult = ajaxResult;
|
||||
public ResultException(Result result){
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public AjaxResult getResult() {
|
||||
return ajaxResult;
|
||||
public Result getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String> 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<String, Cookie> 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<String, Cookie> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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<ProcessVo> 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<PageResult<FlowVo>> queryCreate() {
|
||||
return Result.data(FlowWrapper.build().toVo(flowService.getCreateList()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 我待处理
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("query_todo")
|
||||
public Result<PageResult<FlowStepVo>> queryTodo() {
|
||||
return Result.data(FlowStepWrapper.build().toVo(flowStepService.getFlowTodoList(false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 已完成的
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("query_done")
|
||||
public Result<PageResult<FlowStepVo>> queryDone() {
|
||||
return Result.data(FlowStepWrapper.build().toVo(flowStepService.getFlowTodoList(true)));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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<UserDept> users;
|
||||
|
||||
private List<FlowStepLogVo> logs;
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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<FlowStepVo> steps;
|
||||
|
||||
}
|
|
@ -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<T, V> {
|
||||
|
||||
/**
|
||||
* 单个实体类包装
|
||||
*
|
||||
* @param entity 实体类
|
||||
* @return V
|
||||
*/
|
||||
public abstract V toVo(T entity);
|
||||
|
||||
/**
|
||||
* 实体类集合包装
|
||||
*
|
||||
* @param list 实体类集合
|
||||
* @return List<V>
|
||||
*/
|
||||
public List<V> toVo(List<T> list) {
|
||||
return list.stream().map(this::toVo).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页实体类集合包装
|
||||
*
|
||||
* @param t 分页对象
|
||||
* @return IPage<V>
|
||||
*/
|
||||
public PageResult<V> toVo(PageResult<T> t) {
|
||||
List<T> list = t.getRows();
|
||||
List<V> dtoList = toVo(list);
|
||||
PageResult<V> pageResult = new PageResult<>();
|
||||
BeanUtil.copyProperties(t, pageResult);
|
||||
pageResult.setRows(dtoList);
|
||||
return pageResult;
|
||||
}
|
||||
}
|
|
@ -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<FlowStepLog, FlowStepLogVo> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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<FlowStep, FlowStepVo> {
|
||||
|
||||
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<FlowStepLog> logs = flowStepLogService.getFlowStepLogListByStepId(entity.getId());
|
||||
vo.setLogs(FlowStepLogWrapper.build().toVo(logs));
|
||||
return vo;
|
||||
}
|
||||
|
||||
public List<FlowStepVo> toLogVo(List<FlowStep> list) {
|
||||
return list.stream().map(this::toLogVo).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<Flow, FlowVo> {
|
||||
|
||||
public static FlowWrapper build() {
|
||||
return new FlowWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowVo toVo(Flow entity) {
|
||||
FlowVo flowVo = Objects.requireNonNull(BeanUtil.copyProperties(entity, FlowVo.class));
|
||||
return flowVo;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<FlowStep> flowStepList = flowStepService.getFlowStepListByFlowId(flow.getId());
|
||||
vo.setSteps(FlowStepWrapper.build().toLogVo(flowStepList));
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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<UserDept> assignedUser;
|
||||
}
|
|
@ -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<UserDept> assignedUser;
|
||||
|
||||
private List<UserDept> assignedDept;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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<ContextRefreshedEvent> {
|
||||
|
||||
private Map<String, IProcessType> 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<String, IProcessType> beansOfType = applicationContext.getBeansOfType(IProcessType.class);
|
||||
beansOfType.values().forEach(source -> processTypeMap.put(source.getName(), source));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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<UserDept> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Flow> {
|
||||
}
|
|
@ -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<FlowStepLog> {
|
||||
}
|
|
@ -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<FlowStep> {
|
||||
}
|
|
@ -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<FlowMapper, Flow> {
|
||||
|
||||
@Resource
|
||||
private IUserDeptService userDeptService;
|
||||
@Resource
|
||||
private FormilyService formilyService;
|
||||
|
||||
@Resource
|
||||
private FlowStepService flowStepService;
|
||||
|
||||
|
||||
/**
|
||||
* 我发起的
|
||||
* @return
|
||||
*/
|
||||
public PageResult<Flow> getCreateList() {
|
||||
UserDept currentUser = userDeptService.getCurrentUser();
|
||||
LambdaQueryWrapper<Flow> qw = new LambdaQueryWrapper<>(Flow.class).eq(Flow::getUserId, currentUser.getId()).orderByDesc(Flow::getCreatedAt);
|
||||
PageResult<Flow> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<FlowStepLogMapper, FlowStepLog> {
|
||||
|
||||
/**
|
||||
* 判断是否已全部审批
|
||||
* @param flowStep 审批节点
|
||||
* @param userIds 需要审批的用户id
|
||||
* @return
|
||||
*/
|
||||
public Boolean isAllApproval(FlowStep flowStep, List<String> userIds) {
|
||||
List<FlowStepLog> flowStepLogList = getFlowStepLogListByStepId(flowStep.getId());
|
||||
List<String> idList = CollUtil.getFieldValues(flowStepLogList, "userId", String.class);
|
||||
List<String> reduceId = userIds.stream().filter(item -> !idList.contains(item)).collect(Collectors.toList());
|
||||
return reduceId.isEmpty();
|
||||
}
|
||||
|
||||
public List<FlowStepLog> getFlowStepLogListByStepId(String stepId) {
|
||||
LambdaQueryWrapper<FlowStepLog> qw = new LambdaQueryWrapper<>();
|
||||
qw.eq(FlowStepLog::getStepId, stepId).orderByDesc(FlowStepLog::getCreatedAt);
|
||||
return list(qw);
|
||||
}
|
||||
}
|
|
@ -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<FlowStepMapper, FlowStep> {
|
||||
|
||||
@Resource
|
||||
private ProcessTypeFactory processTypeFactory;
|
||||
|
||||
@Resource
|
||||
private IUserDeptService userDeptService;
|
||||
|
||||
@Resource
|
||||
private FlowService flowService;
|
||||
|
||||
/**
|
||||
* 我待处理
|
||||
* @param isDone true: 返回 PASS 和 REFUSE false: 返回 ACTIVE
|
||||
* @return
|
||||
*/
|
||||
public PageResult<FlowStep> getFlowTodoList(Boolean isDone) {
|
||||
UserDept currentUser = userDeptService.getCurrentUser();
|
||||
LambdaQueryWrapper<FlowStep> 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<FlowStep> 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<FlowStep> 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<FlowStep> getFlowStepListByFlowId(String flowId) {
|
||||
LambdaQueryWrapper<FlowStep> qw = new LambdaQueryWrapper<>();
|
||||
qw.eq(FlowStep::getFlowId, flowId).orderByAsc(FlowStep::getCreatedAt);
|
||||
return list(qw);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.ydool.oa.formily.constant;
|
||||
|
||||
public interface GrapeConst {
|
||||
|
||||
String API = "/api";
|
||||
|
||||
}
|
|
@ -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<FormilyStartVo> 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("上传失败"));
|
||||
}
|
||||
}
|
|
@ -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<Group> list = groupService.list(new LambdaQueryWrapper<>(Group.class).orderByAsc(Group::getSortNo));
|
||||
List<GroupVo> 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<Group> uw = new LambdaUpdateWrapper();
|
||||
uw.set(Group::getSortNo, i + 1).eq(Group::getId, id.toString());
|
||||
groupService.update(uw);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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<UserDept> result = userDeptService.getTree(type, deptId);
|
||||
return Result.data(result);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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<FormilyVo> formilies;
|
||||
|
||||
public GroupVo(Group group) {
|
||||
this.id = group.getId();
|
||||
this.name = group.getName();
|
||||
}
|
||||
}
|
|
@ -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<Formily> {
|
||||
}
|
|
@ -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<Group> {
|
||||
}
|
|
@ -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<FormilyMapper, Formily> {
|
||||
|
||||
public List<Formily> getFormilyByGroup(String groupId) {
|
||||
return list(new LambdaQueryWrapper<>(Formily.class).eq(Formily::getGroupId, groupId));
|
||||
}
|
||||
|
||||
}
|
|
@ -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<GroupMapper, Group> {
|
||||
}
|
|
@ -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<UserDept> getTree(String type, String deptId);
|
||||
|
||||
/**
|
||||
* 根据用户ID, 返回用户所在部门的领导
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
UserDept getUserDeptLeader(String userId);
|
||||
|
||||
/**
|
||||
* 根据部门ID,返回该部门负责人
|
||||
* @param deptIds
|
||||
* @return
|
||||
*/
|
||||
List<UserDept> getUserListByDeptId(List<String> deptIds) ;
|
||||
|
||||
/**
|
||||
* 根据部门ID,返回该部门负责人
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
List<UserDept> getUserListByUserId(List<String> userIds);
|
||||
|
||||
/**
|
||||
* 当审批人员为空时,转交给管理员审批
|
||||
* @return
|
||||
*/
|
||||
UserDept getAdminUserDepot();
|
||||
|
||||
/**
|
||||
* 根据ID 返回用户
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
UserDept getUserById(String userId);
|
||||
|
||||
/**
|
||||
* 返回当前登录的用户
|
||||
* @return
|
||||
*/
|
||||
UserDept getCurrentUser();
|
||||
|
||||
/**
|
||||
* 返回当前登录用户的菜单列表
|
||||
* @return
|
||||
*/
|
||||
Object getUserMenuList();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<UserDept> getTree(String type, String deptId) {
|
||||
List<UserDept> result = new ArrayList<UserDept>();
|
||||
|
||||
List<Dept> depts = deptService.list(new QueryWrapper<Dept>().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<User> users = userService.list(new QueryWrapper<User>().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<User>().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<User>().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<UserDept> getUserListByDeptId(List<String> deptIds) {
|
||||
if (CollUtil.isEmpty(deptIds)) return null;
|
||||
|
||||
List<User> userList = userService.list(new QueryWrapper<User>().lambda()
|
||||
.in(User::getDept, deptIds)
|
||||
.eq(User::getJob, getLeaderJobId())
|
||||
.eq(User::getStatus, true)
|
||||
);
|
||||
|
||||
|
||||
List<UserDept> userDeptList = new ArrayList<UserDept>();
|
||||
if (CollUtil.isNotEmpty(userList)) {
|
||||
userList.forEach(user -> {
|
||||
userDeptList.add(new UserDept(user.getId(), user.getUserName(), "user", "", isLeader(user.getJob())));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return userDeptList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserDept> getUserListByUserId(List<String> userIds) {
|
||||
if (CollUtil.isEmpty(userIds)) return null;
|
||||
List<User> userList = userService.list(new QueryWrapper<User>().lambda()
|
||||
.in(User::getId, userIds)
|
||||
.eq(User::getStatus, true)
|
||||
);
|
||||
if (CollUtil.isEmpty(userList)) return null;
|
||||
List<String> deptIds = userList.stream().map(User::getDept).collect(Collectors.toList());
|
||||
|
||||
return getUserListByDeptId(deptIds);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDept getAdminUserDepot() {
|
||||
User user = userService.getOne(new QueryWrapper<User>().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<User>().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<User>().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<Job>().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<Job>().lambda()
|
||||
.eq(Job::getName, "负责人")
|
||||
.eq(Job::getStatus, true)
|
||||
.last("limit 1")
|
||||
);
|
||||
String jobId = "";
|
||||
if (ObjectUtil.isNotNull(job)) {
|
||||
jobId = job.getId();
|
||||
}
|
||||
return jobId;
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
|
|
@ -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("接口文档系统")
|
||||
|
|
|
@ -112,6 +112,13 @@ public interface IUserService {
|
|||
*/
|
||||
List<Menu> menuTreesByUser(String id);
|
||||
|
||||
/**
|
||||
* 获取菜单树
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
List<Menu> menuTreesByUserId(String id);
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
* @param id
|
||||
|
|
|
@ -315,6 +315,71 @@ public class UserServiceImpl extends BaseService<UserMapper, User> implements IU
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取菜单树
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Menu> menuTreesByUserId(String id) {
|
||||
List<Role> roles = roleListByUser(id);
|
||||
if (CollUtil.isNotEmpty(roles)) {
|
||||
String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(","));
|
||||
|
||||
List<Map<String, Object>> menuMap = menuService.listMaps(new QueryWrapper<Menu>().lambda()
|
||||
.in(Menu::getId, Arrays.asList(menus.split(
|
||||
",")))
|
||||
.eq(Menu::getStatus, true)
|
||||
.eq(Menu::getVisible, false)
|
||||
.ne(Menu::getMenuType, "F")
|
||||
.orderByAsc(Menu::getSortNo)
|
||||
);
|
||||
|
||||
//树结构下搜索,如果子级符合条件,就把父级也放进去,确保其能显示
|
||||
Iterator<Map<String, Object>> iterator = menuMap.iterator();
|
||||
List<Map<String, Object>> parentList = new ArrayList<>();
|
||||
|
||||
QueryWrapper<Menu> wrapper = new QueryWrapper<Menu>();
|
||||
wrapper.lambda().eq(Menu::getStatus, true)
|
||||
.eq(Menu::getVisible, false).orderByAsc(Menu::getSortNo);
|
||||
|
||||
//获取所有菜单
|
||||
List<Map<String, Object>> allMenuMap = menuService.listMaps(wrapper);
|
||||
Map<String, Object> allMap = new HashMap<String, Object>();
|
||||
|
||||
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<Menu> menuList = jsonArray.toList(Menu.class);
|
||||
return menuList;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
*
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue