Merge branch 'dev' of gitee.com:dromara/RuoYi-Vue-Plus into dev-oss3

Signed-off-by: AprilWind <2100166581@qq.com>
This commit is contained in:
AprilWind 2024-05-13 01:25:13 +00:00 committed by Gitee
commit a180271d0b
98 changed files with 1236 additions and 763 deletions

24
pom.xml
View File

@ -14,23 +14,23 @@
<properties>
<revision>5.2.0-SNAPSHOT</revision>
<spring-boot.version>3.2.4</spring-boot.version>
<spring-boot.version>3.2.5</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<spring-boot.mybatis>3.0.3</spring-boot.mybatis>
<springdoc.version>2.4.0</springdoc.version>
<mybatis.version>3.5.16</mybatis.version>
<springdoc.version>2.5.0</springdoc.version>
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<poi.version>5.2.3</poi.version>
<easyexcel.version>3.3.3</easyexcel.version>
<easyexcel.version>3.3.4</easyexcel.version>
<velocity.version>2.3</velocity.version>
<satoken.version>1.37.0</satoken.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<mybatis-plus.version>3.5.6</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version>
<hutool.version>5.8.26</hutool.version>
<hutool.version>5.8.27</hutool.version>
<okhttp.version>4.10.0</okhttp.version>
<spring-boot-admin.version>3.2.3</spring-boot-admin.version>
<redisson.version>3.27.2</redisson.version>
<redisson.version>3.29.0</redisson.version>
<lock4j.version>2.2.7</lock4j.version>
<dynamic-ds.version>4.3.0</dynamic-ds.version>
<alibaba-ttl.version>2.14.4</alibaba-ttl.version>
@ -38,7 +38,7 @@
<easyretry.version>3.2.0</easyretry.version>
<mapstruct-plus.version>1.3.6</mapstruct-plus.version>
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
<lombok.version>1.18.30</lombok.version>
<lombok.version>1.18.32</lombok.version>
<bouncycastle.version>1.76</bouncycastle.version>
<justauth.version>1.16.6</justauth.version>
<!-- 离线IP地址定位库 -->
@ -48,7 +48,7 @@
<aws.sdk.version>2.25.15</aws.sdk.version>
<aws.crt.version>0.29.13</aws.crt.version>
<!-- SMS 配置 -->
<sms4j.version>3.2.0</sms4j.version>
<sms4j.version>3.2.1</sms4j.version>
<!-- 限制框架中的fastjson版本 -->
<fastjson.version>1.2.83</fastjson.version>
@ -218,9 +218,9 @@
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${spring-boot.mybatis}</version>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>

View File

@ -19,6 +19,6 @@ ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_P
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
#-Dskywalking.agent.service_name=ruoyi-server \
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
-jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
-jar app.jar

View File

@ -5,6 +5,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.lock.annotation.Lock4j;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
@ -64,20 +65,24 @@ public class SysLoginService {
* 绑定第三方用户
*
* @param authUserData 授权响应实体
* @return 统一响应实体
*/
@Lock4j
public void socialRegister(AuthUser authUserData) {
String authId = authUserData.getSource() + authUserData.getUuid();
// 第三方用户信息
SysSocialBo bo = BeanUtil.toBean(authUserData, SysSocialBo.class);
BeanUtil.copyProperties(authUserData.getToken(), bo);
bo.setUserId(LoginHelper.getUserId());
Long userId = LoginHelper.getUserId();
bo.setUserId(userId);
bo.setAuthId(authId);
bo.setOpenId(authUserData.getUuid());
bo.setUserName(authUserData.getUsername());
bo.setNickName(authUserData.getNickname());
// 查询是否已经绑定用户
List<SysSocialVo> list = sysSocialService.selectByAuthId(authId);
SysSocialBo params = new SysSocialBo();
params.setUserId(userId);
params.setSource(bo.getSource());
List<SysSocialVo> list = sysSocialService.queryList(params);
if (CollUtil.isEmpty(list)) {
// 没有绑定用户, 新增用户信息
sysSocialService.insertByBo(bo);
@ -85,6 +90,8 @@ public class SysLoginService {
// 更新用户信息
bo.setId(list.get(0).getId());
sysSocialService.updateByBo(bo);
// 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
// throw new ServiceException("此平台账号已经被绑定!");
}
}

View File

@ -1,7 +1,6 @@
package org.dromara.web.service;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.Constants;
@ -61,8 +60,7 @@ public class SysRegisterService {
boolean exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, sysUser.getUserName())
.ne(ObjectUtil.isNotNull(sysUser.getUserId()), SysUser::getUserId, sysUser.getUserId()));
.eq(SysUser::getUserName, sysUser.getUserName()));
});
if (exist) {
throw new UserException("user.register.save.error", username);

View File

@ -20,7 +20,7 @@ import org.dromara.web.service.SysLoginService;
import org.springframework.stereotype.Service;
/**
* 邮件认证策略
* 小程序认证策略
*
* @author Michelle.Chung
*/

View File

@ -80,6 +80,8 @@ spring:
# 设置总上传的文件大小
max-request-size: 20MB
mvc:
# 设置静态资源路径 防止所有请求都去查静态资源
static-path-pattern: /static/**
format:
date-time: yyyy-MM-dd HH:mm:ss
jackson:

View File

@ -0,0 +1,46 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* OSS对象
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class OssDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 对象存储主键
*/
private Long ossId;
/**
* 文件名
*/
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
}

View File

@ -3,6 +3,7 @@ package org.dromara.common.core.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
@ -15,6 +16,9 @@ import java.io.Serializable;
@NoArgsConstructor
public class RoleDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 角色ID
*/

View File

@ -0,0 +1,73 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 用户
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
public class UserDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private Long deptId;
/**
* 用户账号
*/
private String userName;
/**
* 用户昵称
*/
private String nickName;
/**
* 用户类型sys_user系统用户
*/
private String userType;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String phonenumber;
/**
* 用户性别0男 1女 2未知
*/
private String sex;
/**
* 帐号状态0正常 1停用
*/
private String status;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -1,5 +1,9 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.OssDTO;
import java.util.List;
/**
* 通用 OSS服务
*
@ -15,4 +19,11 @@ public interface OssService {
*/
String selectUrlByIds(String ossIds);
/**
* 通过ossId查询列表
*
* @param ossIds ossId串逗号分隔
* @return 列表
*/
List<OssDTO> selectByIds(String ossIds);
}

View File

@ -1,5 +1,9 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.UserDTO;
import java.util.List;
/**
* 通用 用户服务
*
@ -19,10 +23,18 @@ public interface UserService {
* 通过用户ID查询用户账户
*
* @param userId 用户ID
* @return 用户账户
* @return 用户名称
*/
String selectNicknameById(Long userId);
/**
* 通过用户ID查询用户账户
*
* @param userIds 用户ID 多个用逗号隔开
* @return 用户名称
*/
String selectNicknameByIds(String userIds);
/**
* 通过用户ID查询用户手机号
*
@ -39,4 +51,19 @@ public interface UserService {
*/
String selectEmailById(Long userId);
/**
* 通过用户ID查询用户列表
*
* @param userIds 用户ids
* @return 用户列表
*/
List<UserDTO> selectListByIds(List<Long> userIds);
/**
* 通过角色ID查询用户ID
*
* @param roleIds 角色ids
* @return 用户ids
*/
List<Long> selectUserIdsByRoleIds(List<Long> roleIds);
}

View File

@ -11,7 +11,6 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.encrypt.properties.ApiDecryptProperties;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerExecutionChain;
@ -43,27 +42,25 @@ public class CryptoFilter implements Filter {
ServletResponse responseWrapper = null;
EncryptResponseBodyWrapper responseBodyWrapper = null;
// 是否为 json 请求
if (StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
// 是否为 put 或者 post 请求
if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) {
// 是否存在加密标头
String headerValue = servletRequest.getHeader(properties.getHeaderFlag());
if (StringUtils.isNotBlank(headerValue)) {
// 请求解密
requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPrivateKey(), properties.getHeaderFlag());
} else {
// 是否有注解有就报错没有放行
if (ObjectUtil.isNotNull(apiEncrypt)) {
HandlerExceptionResolver exceptionResolver = SpringUtils.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
exceptionResolver.resolveException(
servletRequest, servletResponse, null,
new ServiceException("没有访问权限,请联系管理员授权", HttpStatus.FORBIDDEN));
return;
}
// 是否为 put 或者 post 请求
if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) {
// 是否存在加密标头
String headerValue = servletRequest.getHeader(properties.getHeaderFlag());
if (StringUtils.isNotBlank(headerValue)) {
// 请求解密
requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPrivateKey(), properties.getHeaderFlag());
} else {
// 是否有注解有就报错没有放行
if (ObjectUtil.isNotNull(apiEncrypt)) {
HandlerExceptionResolver exceptionResolver = SpringUtils.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
exceptionResolver.resolveException(
servletRequest, servletResponse, null,
new ServiceException("没有访问权限,请联系管理员授权", HttpStatus.FORBIDDEN));
return;
}
}
}
// 判断是否响应加密
if (responseFlag) {
responseBodyWrapper = new EncryptResponseBodyWrapper(servletResponse);

View File

@ -76,6 +76,7 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
// 设置响应头
servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag);
servletResponse.setHeader(headerFlag, encryptPassword);
servletResponse.setHeader("Access-Control-Allow-Origin", "*");
servletResponse.setHeader("Access-Control-Allow-Methods", "*");

View File

@ -32,20 +32,9 @@
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- sql性能分析插件 -->

View File

@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerIntercept
import org.dromara.common.core.factory.YmlPropertySourceFactory;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler;
import org.dromara.common.mybatis.handler.MybatisExceptionHandler;
import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.BeansException;
@ -58,8 +59,6 @@ public class MybatisPlusConfig {
*/
public PaginationInnerInterceptor paginationInnerInterceptor() {
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
// 设置最大单页限制数量默认 500 -1 不受限制
paginationInnerInterceptor.setMaxLimit(-1L);
// 分页合理化
paginationInnerInterceptor.setOverflow(true);
return paginationInnerInterceptor;
@ -89,6 +88,14 @@ public class MybatisPlusConfig {
return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
}
/**
* 异常处理器
*/
@Bean
public MybatisExceptionHandler mybatisExceptionHandler() {
return new MybatisExceptionHandler();
}
/**
* PaginationInnerInterceptor 分页插件自动识别数据库类型
* https://baomidou.com/pages/97710a/

View File

@ -2,14 +2,15 @@ package org.dromara.common.mybatis.interceptor;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.ibatis.executor.Executor;
@ -32,7 +33,7 @@ import java.util.List;
* @version 3.5.0
*/
@Slf4j
public class PlusDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
public class PlusDataPermissionInterceptor extends BaseMultiTableInnerInterceptor implements InnerInterceptor {
private final PlusDataPermissionHandler dataPermissionHandler;
@ -75,11 +76,10 @@ public class PlusDataPermissionInterceptor extends JsqlParserSupport implements
@Override
protected void processSelect(Select select, int index, String sql, Object obj) {
SelectBody selectBody = select.getSelectBody();
if (selectBody instanceof PlainSelect plainSelect) {
this.setWhere(plainSelect, (String) obj);
} else if (selectBody instanceof SetOperationList setOperationList) {
List<SelectBody> selectBodyList = setOperationList.getSelects();
if (select instanceof PlainSelect) {
this.setWhere((PlainSelect) select, (String) obj);
} else if (select instanceof SetOperationList setOperationList) {
List<Select> selectBodyList = setOperationList.getSelects();
selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
}
}
@ -113,5 +113,11 @@ public class PlusDataPermissionInterceptor extends JsqlParserSupport implements
}
}
@Override
public Expression buildTableExpression(Table table, Expression where, String whereSegment) {
// 只有新版数据权限处理器才会执行到这里
final MultiDataPermissionHandler handler = (MultiDataPermissionHandler) dataPermissionHandler;
return handler.getSqlSegment(table, where, whereSegment);
}
}

View File

@ -16,12 +16,15 @@ import org.dromara.common.oss.exception.OssException;
import org.dromara.common.oss.properties.OssProperties;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.CompletedPart;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
import software.amazon.awssdk.services.s3.model.Part;
import software.amazon.awssdk.services.s3.model.S3Exception;
@ -30,10 +33,7 @@ import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.*;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
@ -89,6 +89,9 @@ public class OssClient {
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey()));
//MinIO 使用 HTTPS 限制使用域名访问站点填域名需要启用路径样式访问
boolean isStyle = !StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE);
//创建AWS基于 CRT S3 客户端
this.client = S3AsyncClient.crtBuilder()
.credentialsProvider(credentialsProvider)
@ -97,15 +100,15 @@ public class OssClient {
.targetThroughputInGbps(20.0)
.minimumPartSizeInBytes(10 * 1025 * 1024L)
.checksumValidationEnabled(false)
.forcePathStyle(isStyle)
.build();
//AWS基于 CRT S3 AsyncClient 实例用作 S3 传输管理器的底层客户端
this.transferManager = S3TransferManager.builder().s3Client(this.client).build();
// 检查是否连接到 MinIOMinIO 使用 HTTPS 限制使用域名访问需要启用路径样式访问
// 创建 S3 配置对象
S3Configuration config = S3Configuration.builder().chunkedEncodingEnabled(false)
// minio 使用https限制使用域名访问 需要此配置 站点填域名
.pathStyleAccessEnabled(!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)).build();
.pathStyleAccessEnabled(isStyle).build();
// 创建 预签名 URL 的生成器 实例用于生成 S3 预签名 URL
this.presigner = S3Presigner.builder()
@ -263,6 +266,37 @@ public class OssClient {
return tempFilePath;
}
/**
* 下载文件从 Amazon S3 输出流
*
* @param key 文件在 Amazon S3 中的对象键
* @param out 输出流
* @return 输出流中写入的字节数长度
* @throws OssException 如果下载失败抛出自定义异常
*/
public long download(String key, OutputStream out) {
try {
// 构建下载请求
DownloadRequest<ResponseInputStream<GetObjectResponse>> downloadRequest = DownloadRequest.builder()
// 文件对象
.getObjectRequest(y -> y.bucket(properties.getBucketName())
.key(key)
.build())
.addTransferListener(LoggingTransferListener.create())
// 使用订阅转换器
.responseTransformer(AsyncResponseTransformer.toBlockingInputStream())
.build();
// 使用 S3TransferManager 下载文件
Download<ResponseInputStream<GetObjectResponse>> responseFuture = transferManager.download(downloadRequest);
// 输出到流中
try (ResponseInputStream<GetObjectResponse> responseStream = responseFuture.completionFuture().join().result()) { // auto-closeable stream
return responseStream.transferTo(out); // 阻塞调用线程 blocks the calling thread
}
} catch (Exception e) {
throw new OssException("文件下载失败,错误信息:[" + e.getMessage() + "]");
}
}
/**
* 删除云存储服务中指定路径下文件
*

View File

@ -37,6 +37,11 @@
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -5,10 +5,14 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.redis.config.properties.RedissonProperties;
import org.dromara.common.redis.handler.KeyPrefixHandler;
import org.dromara.common.redis.handler.RedisExceptionHandler;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.CompositeCodec;
import org.redisson.codec.TypedJsonJacksonCodec;
@ -19,6 +23,10 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.VirtualThreadTaskExecutor;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
/**
* redis配置
*
@ -32,13 +40,16 @@ public class RedisConfig {
@Autowired
private RedissonProperties redissonProperties;
@Autowired
private ObjectMapper objectMapper;
@Bean
public RedissonAutoConfigurationCustomizer redissonCustomizer() {
return config -> {
ObjectMapper om = objectMapper.copy();
JavaTimeModule javaTimeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
ObjectMapper om = new ObjectMapper();
om.registerModule(javaTimeModule);
om.setTimeZone(TimeZone.getDefault());
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型类必须是非final修饰的序列化时将对象全类名一起保存下来
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
@ -87,6 +98,14 @@ public class RedisConfig {
};
}
/**
* 异常处理器
*/
@Bean
public RedisExceptionHandler redisExceptionHandler() {
return new RedisExceptionHandler();
}
/**
* redis集群配置 yml
*

View File

@ -0,0 +1,30 @@
package org.dromara.common.redis.handler;
import cn.hutool.http.HttpStatus;
import com.baomidou.lock.exception.LockFailureException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* Redis异常处理器
*
* @author AprilWind
*/
@Slf4j
@RestControllerAdvice
public class RedisExceptionHandler {
/**
* 分布式锁Lock4j异常
*/
@ExceptionHandler(LockFailureException.class)
public R<Void> handleLockFailureException(LockFailureException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("获取锁失败了'{}',发生Lock4j异常." + requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_UNAVAILABLE, "业务处理中,请稍后再试...");
}
}

View File

@ -107,7 +107,11 @@ public class RedisUtils {
bucket.setAndKeepTTL(value);
} catch (Exception e) {
long timeToLive = bucket.remainTimeToLive();
setCacheObject(key, value, Duration.ofMillis(timeToLive));
if (timeToLive == -1) {
setCacheObject(key, value);
} else {
setCacheObject(key, value, Duration.ofMillis(timeToLive));
}
}
} else {
bucket.set(value);

View File

@ -7,6 +7,7 @@ import cn.dev33.satoken.stp.StpLogic;
import org.dromara.common.core.factory.YmlPropertySourceFactory;
import org.dromara.common.satoken.core.dao.PlusSaTokenDao;
import org.dromara.common.satoken.core.service.SaPermissionImpl;
import org.dromara.common.satoken.handler.SaTokenExceptionHandler;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
@ -42,4 +43,12 @@ public class SaTokenConfig {
return new PlusSaTokenDao();
}
/**
* 异常处理器
*/
@Bean
public SaTokenExceptionHandler saTokenExceptionHandler() {
return new SaTokenExceptionHandler();
}
}

View File

@ -0,0 +1,52 @@
package org.dromara.common.satoken.handler;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.http.HttpStatus;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* SaToken异常处理器
*
* @author Lion Li
*/
@Slf4j
@RestControllerAdvice
public class SaTokenExceptionHandler {
/**
* 权限码异常
*/
@ExceptionHandler(NotPermissionException.class)
public R<Void> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
* 角色权限异常
*/
@ExceptionHandler(NotRoleException.class)
public R<Void> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
* 认证失败
*/
@ExceptionHandler(NotLoginException.class)
public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源");
}
}

View File

@ -1,3 +1,2 @@
org.dromara.common.security.handler.GlobalExceptionHandler
org.dromara.common.security.handler.AllUrlHandler
org.dromara.common.security.config.SecurityConfig

View File

@ -16,6 +16,7 @@ import org.redisson.config.ClusterServersConfig;
import org.redisson.config.SingleServerConfig;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
@ -28,16 +29,22 @@ import org.springframework.context.annotation.Primary;
* @author Lion Li
*/
@EnableConfigurationProperties(TenantProperties.class)
@AutoConfiguration(after = {RedisConfig.class, MybatisPlusConfig.class})
@AutoConfiguration(after = {RedisConfig.class})
@ConditionalOnProperty(value = "tenant.enable", havingValue = "true")
public class TenantConfig {
/**
* 多租户插件
*/
@Bean
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) {
return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties));
@ConditionalOnBean(MybatisPlusConfig.class)
@AutoConfiguration(after = {MybatisPlusConfig.class})
static class MybatisPlusConfigation {
/**
* 多租户插件
*/
@Bean
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) {
return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties));
}
}
@Bean

View File

@ -20,7 +20,9 @@ public class NicknameTranslationImpl implements TranslationInterface<String> {
@Override
public String translation(Object key, String other) {
if (key instanceof Long id) {
return userService.selectNicknameById(id);
return userService.selectNicknameByIds(id.toString());
} else if (key instanceof String ids) {
return userService.selectNicknameByIds(ids);
}
return null;
}

View File

@ -1,5 +1,6 @@
package org.dromara.common.web.config;
import org.dromara.common.web.handler.GlobalExceptionHandler;
import org.dromara.common.web.interceptor.PlusWebInvokeTimeInterceptor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@ -49,4 +50,12 @@ public class ResourcesConfig implements WebMvcConfigurer {
// 返回新的CorsFilter
return new CorsFilter(source);
}
/**
* 全局异常处理器
*/
@Bean
public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler();
}
}

View File

@ -1,8 +1,5 @@
package org.dromara.common.security.handler;
package org.dromara.common.web.handler;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import jakarta.servlet.http.HttpServletRequest;
@ -21,6 +18,7 @@ import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
/**
* 全局异常处理器
@ -31,36 +29,6 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchExcep
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 权限码异常
*/
@ExceptionHandler(NotPermissionException.class)
public R<Void> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
* 角色权限异常
*/
@ExceptionHandler(NotRoleException.class)
public R<Void> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
* 认证失败
*/
@ExceptionHandler(NotLoginException.class)
public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源");
}
/**
* 请求方式不支持
*/
@ -69,7 +37,7 @@ public class GlobalExceptionHandler {
HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return R.fail(e.getMessage());
return R.fail(HttpStatus.HTTP_BAD_METHOD, e.getMessage());
}
/**
@ -111,6 +79,16 @@ public class GlobalExceptionHandler {
return R.fail(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
}
/**
* 找不到路由
*/
@ExceptionHandler(NoHandlerFoundException.class)
public R<Void> handleNoHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}'不存在.", requestURI);
return R.fail(HttpStatus.HTTP_NOT_FOUND, e.getMessage());
}
/**
* 拦截未知的运行时异常
*/

View File

@ -14,5 +14,6 @@ EXPOSE 1788
ADD ./target/ruoyi-easyretry-server.jar ./app.jar
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
-jar app.jar

View File

@ -13,5 +13,6 @@ EXPOSE 9090
ADD ./target/ruoyi-monitor-admin.jar ./app.jar
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
-jar app.jar

View File

@ -14,4 +14,4 @@ EXPOSE 7700
ADD ./target/ruoyi-powerjob-server.jar ./app.jar
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar app.jar \
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS}

View File

@ -20,6 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
from information_schema.tables
where table_schema = (select database())
AND table_name NOT LIKE 'pj_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%'
<if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0">
AND table_name NOT IN
<foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item">
@ -40,7 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where dt.table_name = dtc.table_name
and dt.table_name = uo.object_name
and uo.object_type = 'TABLE'
AND dt.table_name NOT LIKE 'pj_%' AND dt.table_name NOT LIKE 'GEN_%'
AND dt.table_name NOT LIKE 'PJ_%' AND dt.table_name NOT LIKE 'GEN_%'
AND dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%'
<if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0">
AND lower(dt.table_name) NOT IN
<foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item">
@ -70,6 +72,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND n.nspname <![CDATA[ <> ]]> ''::name
) list_table
where table_name NOT LIKE 'pj_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%'
<if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0">
AND table_name NOT IN
<foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item">
@ -93,6 +96,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
AND D.NAME NOT LIKE 'pj_%' AND D.NAME NOT LIKE 'gen_%'
AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%'
<if test="genTable.params.genTableNames != null and genTable.params.genTableNames.size > 0">
AND D.NAME NOT IN
<foreach collection="genTable.params.genTableNames" open="(" close=")" separator="," item="item">
@ -112,7 +116,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectDbTableListByNames" resultMap="GenTableResult">
<if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
where table_schema = (select database())
and table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%'
and table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%'
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
@ -124,7 +130,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where dt.table_name = dtc.table_name
and dt.table_name = uo.object_name
and uo.object_type = 'TABLE'
AND dt.table_name NOT LIKE 'pj_%' AND dt.table_name NOT LIKE 'GEN_%'
and dt.table_name NOT LIKE 'PJ_%' AND dt.table_name NOT LIKE 'GEN_%'
and dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%'
and lower(dt.table_name) in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
@ -145,6 +152,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND n.nspname <![CDATA[ <> ]]> ''::name
) list_table
where table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%'
and table_name NOT LIKE 'act_%' and table_name NOT LIKE 'flw_%'
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
@ -159,6 +167,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
AND D.NAME NOT LIKE 'pj_%' AND D.NAME NOT LIKE 'gen_%'
AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%'
AND D.NAME in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
@ -169,7 +178,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
<if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
where table_schema = (select database())
and table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%'
and table_name NOT LIKE 'act_%' AND table_name NOT LIKE 'flw_%'
and table_name = #{tableName}
</if>
<if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isOracle()">
@ -178,7 +189,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where dt.table_name = dtc.table_name
and dt.table_name = uo.object_name
and uo.object_type = 'TABLE'
AND dt.table_name NOT LIKE 'pj_%' AND dt.table_name NOT LIKE 'GEN_%'
AND dt.table_name NOT LIKE 'PJ_%' AND dt.table_name NOT LIKE 'GEN_%'
AND dt.table_name NOT LIKE 'ACT_%' AND dt.table_name NOT LIKE 'FLW_%'
AND dt.table_name NOT IN (select table_name from gen_table)
and lower(dt.table_name) = #{tableName}
</if>
@ -197,6 +209,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND n.nspname <![CDATA[ <> ]]> ''::name
) list_table
where table_name NOT LIKE 'pj_%' and table_name NOT LIKE 'gen_%'
and table_name NOT LIKE 'act_%' and table_name NOT LIKE 'flw_%'
and table_name = #{tableName}
</if>
<if test="@org.dromara.common.mybatis.helper.DataBaseHelper@isSqlServer()">
@ -208,6 +221,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
AND D.NAME NOT LIKE 'pj_%' AND D.NAME NOT LIKE 'gen_%'
AND D.NAME NOT LIKE 'act_%' AND D.NAME NOT LIKE 'flw_%'
AND D.NAME = #{tableName}
</if>
</select>

View File

@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* 在线用户监控
@ -87,4 +88,43 @@ public class SysUserOnlineController extends BaseController {
}
return R.ok();
}
/**
* 获取当前用户登录在线设备
*/
@GetMapping()
public TableDataInfo<SysUserOnline> getInfo() {
// 获取指定账号 id token 集合
List<String> tokenIds = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString());
List<UserOnlineDTO> userOnlineDTOList = tokenIds.stream()
.filter(token -> StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) >= -1)
.map(token -> (UserOnlineDTO) RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token))
.collect(Collectors.toList());
//复制和处理 SysUserOnline 对象列表
Collections.reverse(userOnlineDTOList);
userOnlineDTOList.removeAll(Collections.singleton(null));
List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
return TableDataInfo.build(userOnlineList);
}
/**
* 强退当前在线设备
*
* @param tokenId token值
*/
@Log(title = "在线设备", businessType = BusinessType.FORCE)
@PostMapping("/{tokenId}")
public R<Void> remove(@PathVariable("tokenId") String tokenId) {
try {
// 获取指定账号 id token 集合
List<String> keys = StpUtil.getTokenValueListByLoginId(StpUtil.getLoginIdAsString());
keys.stream()
.filter(key -> key.equals(tokenId))
.findFirst()
.ifPresent(key -> StpUtil.kickoutByTokenValue(tokenId));
} catch (NotLoginException ignored) {
}
return R.ok();
}
}

View File

@ -87,6 +87,9 @@ public class SysDictDataController extends BaseController {
@Log(title = "字典数据", businessType = BusinessType.INSERT)
@PostMapping
public R<Void> add(@Validated @RequestBody SysDictDataBo dict) {
if (!dictDataService.checkDictDataUnique(dict)) {
return R.fail("新增字典数据'" + dict.getDictValue() + "'失败,字典键值已存在");
}
dictDataService.insertDictData(dict);
return R.ok();
}
@ -98,6 +101,9 @@ public class SysDictDataController extends BaseController {
@Log(title = "字典数据", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> edit(@Validated @RequestBody SysDictDataBo dict) {
if (!dictDataService.checkDictDataUnique(dict)) {
return R.fail("修改字典数据'" + dict.getDictValue() + "'失败,字典键值已存在");
}
dictDataService.updateDictData(dict);
return R.ok();
}

View File

@ -1,6 +1,7 @@
package org.dromara.system.controller.system;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ObjectUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.UserConstants;
@ -17,6 +18,7 @@ import org.dromara.system.service.ISysPostService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
@ -112,11 +114,20 @@ public class SysPostController extends BaseController {
* 获取岗位选择框列表
*
* @param postIds 岗位ID串
* @param deptId 部门id
*/
@SaCheckPermission("system:post:query")
@GetMapping("/optionselect")
public R<List<SysPostVo>> optionselect(@RequestParam(required = false) Long[] postIds) {
return R.ok(postService.selectPostByIds(postIds == null ? null : List.of(postIds)));
public R<List<SysPostVo>> optionselect(@RequestParam(required = false) Long[] postIds, @RequestParam(required = false) Long deptId) {
List<SysPostVo> list = new ArrayList<>();
if (ObjectUtil.isNotNull(deptId)) {
SysPostBo post = new SysPostBo();
post.setDeptId(deptId);
list = postService.selectPostList(post);
} else if (postIds != null) {
list = postService.selectPostByIds(List.of(postIds));
}
return R.ok(list);
}
}

View File

@ -132,16 +132,19 @@ public class SysUserController extends BaseController {
SysUserInfoVo userInfoVo = new SysUserInfoVo();
SysRoleBo roleBo = new SysRoleBo();
roleBo.setStatus(UserConstants.ROLE_NORMAL);
SysPostBo postBo = new SysPostBo();
postBo.setStatus(UserConstants.POST_NORMAL);
List<SysRoleVo> roles = roleService.selectRoleList(roleBo);
userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin()));
userInfoVo.setPosts(postService.selectPostList(postBo));
if (ObjectUtil.isNotNull(userId)) {
SysUserVo sysUser = userService.selectUserById(userId);
userInfoVo.setUser(sysUser);
userInfoVo.setRoleIds(roleService.selectRoleListByUserId(userId));
userInfoVo.setPostIds(postService.selectPostListByUserId(userId));
Long deptId = sysUser.getDeptId();
if (ObjectUtil.isNotNull(deptId)) {
SysPostBo postBo = new SysPostBo();
postBo.setDeptId(deptId);
userInfoVo.setPosts(postService.selectPostList(postBo));
userInfoVo.setPostIds(postService.selectPostListByUserId(userId));
}
}
return R.ok(userInfoVo);
}
@ -293,4 +296,5 @@ public class SysUserController extends BaseController {
public R<List<SysUserVo>> listByDept(@PathVariable @NotNull Long deptId) {
return R.ok(userService.selectUserListByDept(deptId));
}
}

View File

@ -3,9 +3,9 @@ package org.dromara.system.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
@ -39,6 +39,11 @@ public class SysDept extends TenantEntity {
*/
private String deptName;
/**
* 部门类别编码
*/
private String deptCategory;
/**
* 显示顺序
*/

View File

@ -17,7 +17,7 @@ import org.dromara.common.mybatis.core.domain.BaseEntity;
public class SysOssConfig extends BaseEntity {
/**
*
*
*/
@TableId(value = "oss_config_id")
private Long ossConfigId;

View File

@ -23,6 +23,11 @@ public class SysPost extends TenantEntity {
@TableId(value = "post_id")
private Long postId;
/**
* 部门id
*/
private Long deptId;
/**
* 岗位编码
*/
@ -33,6 +38,11 @@ public class SysPost extends TenantEntity {
*/
private String postName;
/**
* 岗位类别编码
*/
private String postCategory;
/**
* 岗位排序
*/

View File

@ -7,7 +7,6 @@ import lombok.Data;
*
* @author Lion Li
*/
@Data
public class SysUserOnline {

View File

@ -38,6 +38,12 @@ public class SysDeptBo extends BaseEntity {
@Size(min = 0, max = 30, message = "部门名称长度不能超过{max}个字符")
private String deptName;
/**
* 部门类别编码
*/
@Size(min = 0, max = 100, message = "部门类别编码长度不能超过{max}个字符")
private String deptCategory;
/**
* 显示顺序
*/

View File

@ -25,9 +25,9 @@ import lombok.EqualsAndHashCode;
public class SysOssConfigBo extends BaseEntity {
/**
*
*
*/
@NotNull(message = "不能为空", groups = {EditGroup.class})
@NotNull(message = "不能为空", groups = {EditGroup.class})
private Long ossConfigId;
/**

View File

@ -25,6 +25,17 @@ public class SysPostBo extends BaseEntity {
*/
private Long postId;
/**
* 部门id单部门
*/
@NotNull(message = "部门id不能为空")
private Long deptId;
/**
* 归属部门id部门树
*/
private Long belongDeptId;
/**
* 岗位编码
*/
@ -39,6 +50,12 @@ public class SysPostBo extends BaseEntity {
@Size(min = 0, max = 50, message = "岗位名称长度不能超过{max}个字符")
private String postName;
/**
* 岗位类别编码
*/
@Size(min = 0, max = 100, message = "类别编码长度不能超过{max}个字符")
private String postCategory;
/**
* 显示顺序
*/
@ -55,5 +72,4 @@ public class SysPostBo extends BaseEntity {
*/
private String remark;
}

View File

@ -29,9 +29,9 @@ public class SysSocialBo extends TenantEntity {
private Long id;
/**
* 唯一ID
* 认证唯一ID
*/
@NotBlank(message = "唯一ID不能为空", groups = { AddGroup.class, EditGroup.class })
@NotBlank(message = "认证唯一ID不能为空", groups = { AddGroup.class, EditGroup.class })
private String authId;
/**
@ -64,7 +64,7 @@ public class SysSocialBo extends TenantEntity {
/**
* 用户的 ID
*/
@NotBlank(message = "用户的 ID不能为空", groups = { AddGroup.class, EditGroup.class })
@NotBlank(message = "用户的ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long userId;
/**

View File

@ -103,6 +103,11 @@ public class SysUserBo extends BaseEntity {
*/
private Long roleId;
/**
* 排除不查询的用户(工作流用)
*/
private String excludeUserIds;
public SysUserBo(Long userId) {
this.userId = userId;
}

View File

@ -52,6 +52,12 @@ public class SysDeptVo implements Serializable {
@ExcelProperty(value = "部门名称")
private String deptName;
/**
* 部门类别编码
*/
@ExcelProperty(value = "部门类别编码")
private String deptCategory;
/**
* 显示顺序
*/

View File

@ -25,7 +25,7 @@ public class SysOssConfigVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*
*/
private Long ossConfigId;

View File

@ -2,18 +2,18 @@ package org.dromara.system.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.system.domain.SysPost;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.system.domain.SysPost;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 岗位信息视图对象 sys_post
*
@ -33,6 +33,12 @@ public class SysPostVo implements Serializable {
@ExcelProperty(value = "岗位序号")
private Long postId;
/**
* 部门id
*/
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 岗位编码
*/
@ -45,6 +51,12 @@ public class SysPostVo implements Serializable {
@ExcelProperty(value = "岗位名称")
private String postName;
/**
* 岗位类别编码
*/
@ExcelProperty(value = "类别编码")
private String postCategory;
/**
* 显示顺序
*/
@ -70,4 +82,10 @@ public class SysPostVo implements Serializable {
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 部门名
*/
@Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "deptId")
private String deptName;
}

View File

@ -1,5 +1,11 @@
package org.dromara.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.system.domain.SysPost;
import org.dromara.system.domain.vo.SysPostVo;
@ -13,6 +19,12 @@ import java.util.List;
*/
public interface SysPostMapper extends BaseMapperPlus<SysPost, SysPostVo> {
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "create_by")
})
Page<SysPostVo> selectPagePostList(@Param("page") Page<SysPostVo> page, @Param(Constants.WRAPPER) Wrapper<SysPost> queryWrapper);
/**
* 查询用户所属岗位组
*

View File

@ -64,4 +64,13 @@ public interface ISysDictDataService {
* @return 结果
*/
List<SysDictDataVo> updateDictData(SysDictDataBo bo);
/**
* 校验字典键值是否唯一
*
* @param dict 字典数据
* @return 结果
*/
boolean checkDictDataUnique(SysDictDataBo dict);
}

View File

@ -21,7 +21,7 @@ public interface ISysSocialService {
/**
* 查询社会化关系列表
*/
List<SysSocialVo> queryList();
List<SysSocialVo> queryList(SysSocialBo bo);
/**
* 查询社会化关系列表
@ -45,9 +45,7 @@ public interface ISysSocialService {
/**
* 根据 authId 查询 SysSocial 表和 SysUser 返回 SysSocialAuthResult 映射的对象
* @param authId 认证ID
* @return SysSocial
* 根据 authId 查询
*/
List<SysSocialVo> selectByAuthId(String authId);

View File

@ -82,6 +82,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId());
lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId());
lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName());
lqw.like(StringUtils.isNotBlank(bo.getDeptCategory()), SysDept::getDeptCategory, bo.getDeptCategory());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysDept::getStatus, bo.getStatus());
lqw.orderByAsc(SysDept::getAncestors);
lqw.orderByAsc(SysDept::getParentId);

View File

@ -1,5 +1,6 @@
package org.dromara.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -135,4 +136,21 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
throw new ServiceException("操作失败");
}
/**
* 校验字典键值是否唯一
*
* @param dict 字典数据
* @return 结果
*/
@Override
public boolean checkDictDataUnique(SysDictDataBo dict) {
Long dictCode = ObjectUtil.isNull(dict.getDictCode()) ? -1L : dict.getDictCode();
SysDictData entity = baseMapper.selectOne(new LambdaQueryWrapper<SysDictData>()
.eq(SysDictData::getDictType, dict.getDictType()).eq(SysDictData::getDictValue, dict.getDictValue()));
if (ObjectUtil.isNotNull(entity) && !dictCode.equals(entity.getDictCode())) {
return false;
}
return true;
}
}

View File

@ -1,7 +1,7 @@
package org.dromara.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.domain.dto.OssDTO;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.MapstructUtils;
@ -122,6 +123,24 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
return String.join(StringUtils.SEPARATOR, list);
}
@Override
public List<OssDTO> selectByIds(String ossIds) {
List<OssDTO> list = new ArrayList<>();
for (Long id : StringUtils.splitTo(ossIds, Convert::toLong)) {
SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
if (ObjectUtil.isNotNull(vo)) {
try {
vo.setUrl(this.matchingUrl(vo).getUrl());
list.add(BeanUtil.toBean(vo, OssDTO.class));
} catch (Exception ignored) {
// 如果oss异常无法连接则将数据直接返回
list.add(BeanUtil.toBean(vo, OssDTO.class));
}
}
}
return list;
}
private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();
@ -165,13 +184,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
OssClient storage = OssFactory.instance(sysOss.getService());
try (InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
int available = inputStream.available();
IoUtil.copy(inputStream, response.getOutputStream(), available);
response.setContentLength(available);
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
long contentLength = storage.download(sysOss.getFileName(), response.getOutputStream());
response.setContentLengthLong(contentLength);
}
/**

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.UserConstants;
@ -14,10 +13,13 @@ import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.SysPost;
import org.dromara.system.domain.SysUserPost;
import org.dromara.system.domain.bo.SysPostBo;
import org.dromara.system.domain.vo.SysPostVo;
import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysPostMapper;
import org.dromara.system.mapper.SysUserPostMapper;
import org.dromara.system.service.ISysPostService;
@ -25,6 +27,7 @@ import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 岗位信息 服务层处理
@ -36,12 +39,12 @@ import java.util.List;
public class SysPostServiceImpl implements ISysPostService {
private final SysPostMapper baseMapper;
private final SysDeptMapper deptMapper;
private final SysUserPostMapper userPostMapper;
@Override
public TableDataInfo<SysPostVo> selectPagePostList(SysPostBo post, PageQuery pageQuery) {
LambdaQueryWrapper<SysPost> lqw = buildQueryWrapper(post);
Page<SysPostVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
Page<SysPostVo> page = baseMapper.selectPagePostList(pageQuery.build(), buildQueryWrapper(post));
return TableDataInfo.build(page);
}
@ -53,17 +56,39 @@ public class SysPostServiceImpl implements ISysPostService {
*/
@Override
public List<SysPostVo> selectPostList(SysPostBo post) {
LambdaQueryWrapper<SysPost> lqw = buildQueryWrapper(post);
return baseMapper.selectVoList(lqw);
return baseMapper.selectVoList(buildQueryWrapper(post));
}
/**
* 根据查询条件构建查询包装器
*
* @param bo 查询条件对象
* @return 构建好的查询包装器
*/
private LambdaQueryWrapper<SysPost> buildQueryWrapper(SysPostBo bo) {
LambdaQueryWrapper<SysPost> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getPostCode()), SysPost::getPostCode, bo.getPostCode());
lqw.like(StringUtils.isNotBlank(bo.getPostName()), SysPost::getPostName, bo.getPostName());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysPost::getStatus, bo.getStatus());
lqw.orderByAsc(SysPost::getPostSort);
return lqw;
LambdaQueryWrapper<SysPost> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(bo.getPostCode()), SysPost::getPostCode, bo.getPostCode())
.like(StringUtils.isNotBlank(bo.getPostCategory()), SysPost::getPostCategory, bo.getPostCategory())
.like(StringUtils.isNotBlank(bo.getPostName()), SysPost::getPostName, bo.getPostName())
.eq(StringUtils.isNotBlank(bo.getStatus()), SysPost::getStatus, bo.getStatus())
.orderByAsc(SysPost::getPostSort);
if (ObjectUtil.isNotNull(bo.getDeptId())) {
//优先单部门搜索
wrapper.eq(SysPost::getDeptId, bo.getDeptId());
} else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) {
//部门树搜索
wrapper.and(x -> {
List<Long> deptIds = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
.select(SysDept::getDeptId)
.apply(DataBaseHelper.findInSet(bo.getBelongDeptId(), "ancestors")))
.stream()
.map(SysDept::getDeptId)
.collect(Collectors.toList());
deptIds.add(bo.getBelongDeptId());
x.in(SysPost::getDeptId, deptIds);
});
}
return wrapper;
}
/**

View File

@ -1,8 +1,10 @@
package org.dromara.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.system.domain.SysSocial;
import org.dromara.system.domain.bo.SysSocialBo;
import org.dromara.system.domain.vo.SysSocialVo;
@ -37,8 +39,12 @@ public class SysSocialServiceImpl implements ISysSocialService {
* 授权列表
*/
@Override
public List<SysSocialVo> queryList() {
return baseMapper.selectVoList();
public List<SysSocialVo> queryList(SysSocialBo bo) {
LambdaQueryWrapper<SysSocial> lqw = new LambdaQueryWrapper<SysSocial>()
.eq(ObjectUtil.isNotNull(bo.getUserId()), SysSocial::getUserId, bo.getUserId())
.eq(StringUtils.isNotBlank(bo.getAuthId()), SysSocial::getAuthId, bo.getAuthId())
.eq(StringUtils.isNotBlank(bo.getSource()), SysSocial::getSource, bo.getSource());
return baseMapper.selectVoList(lqw);
}
@Override

View File

@ -1,6 +1,8 @@
package org.dromara.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
@ -13,9 +15,11 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -37,6 +41,7 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -92,6 +97,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
ids.add(user.getDeptId());
w.in("u.dept_id", ids);
}).orderByAsc("u.user_id");
if (StringUtils.isNotBlank(user.getExcludeUserIds())) {
wrapper.notIn("u.user_id", StringUtils.splitList(user.getExcludeUserIds()));
}
return wrapper;
}
@ -316,8 +324,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
*/
@Override
public boolean registerUser(SysUserBo user, String tenantId) {
user.setCreateBy(user.getUserId());
user.setUpdateBy(user.getUserId());
user.setCreateBy(0L);
user.setUpdateBy(0L);
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
sysUser.setTenantId(tenantId);
return baseMapper.insert(sysUser) > 0;
@ -579,6 +587,24 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
return ObjectUtil.isNull(sysUser) ? null : sysUser.getNickName();
}
/**
* 通过用户ID查询用户账户
*
* @param userIds 用户ID 多个用逗号隔开
* @return 用户账户
*/
@Override
public String selectNicknameByIds(String userIds) {
List<String> list = new ArrayList<>();
for (Long id : StringUtils.splitTo(userIds, Convert::toLong)) {
String nickname = SpringUtils.getAopProxy(this).selectNicknameById(id);
if (StringUtils.isNotBlank(nickname)) {
list.add(nickname);
}
}
return String.join(StringUtils.SEPARATOR, list);
}
/**
* 通过用户ID查询用户手机号
*
@ -605,4 +631,20 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
return ObjectUtil.isNull(sysUser) ? null : sysUser.getEmail();
}
@Override
public List<UserDTO> selectListByIds(List<Long> userIds) {
if (CollUtil.isEmpty(userIds)) {
return List.of();
}
List<SysUserVo> list = this.selectUserByIds(userIds, null);
return BeanUtil.copyToList(list, UserDTO.class);
}
@Override
public List<Long> selectUserIdsByRoleIds(List<Long> roleIds) {
List<SysUserRole> userRoles = userRoleMapper.selectList(
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
return StreamUtils.toList(userRoles, SysUserRole::getUserId);
}
}

View File

@ -7,8 +7,19 @@
<resultMap type="org.dromara.system.domain.vo.SysPostVo" id="SysPostResult">
</resultMap>
<select id="selectPagePostList" resultMap="SysPostResult">
select
<if test="ew.getSqlSelect != null">
${ew.getSqlSelect}
</if>
<if test="ew.getSqlSelect == null">
*
</if>
from sys_post ${ew.getCustomSqlSegment}
</select>
<select id="selectPostsByUserId" parameterType="Long" resultMap="SysPostResult">
select p.post_id, p.post_name, p.post_code
select p.post_id, p.dept_id, p.post_name, p.post_code, p.post_category
from sys_post p
left join sys_user_post up on up.post_id = p.post_id
left join sys_user u on u.user_id = up.user_id

View File

@ -66,12 +66,6 @@
</exclusions>
</dependency>
<!--系统模块-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-websocket</artifactId>
@ -87,6 +81,35 @@
<artifactId>ruoyi-common-sms</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -42,7 +42,7 @@ public class ActTaskController extends BaseController {
private final TaskService taskService;
private final IWfTaskBackNodeService iWfTaskBackNodeService;
private final IWfTaskBackNodeService wfTaskBackNodeService;
/**
@ -269,6 +269,27 @@ public class ActTaskController extends BaseController {
*/
@GetMapping("/getTaskNodeList/{processInstanceId}")
public R<List<WfTaskBackNode>> getNodeList(@PathVariable String processInstanceId) {
return R.ok(CollUtil.reverse(iWfTaskBackNodeService.getListByInstanceId(processInstanceId)));
return R.ok(CollUtil.reverse(wfTaskBackNodeService.getListByInstanceId(processInstanceId)));
}
/**
* 查询工作流任务用户选择加签人员
*
* @param taskId 任务id
*/
@GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}")
public R<String> getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) {
return R.ok(actTaskService.getTaskUserIdsByAddMultiInstance(taskId));
}
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id
*/
@GetMapping("/getListByDeleteMultiInstance/{taskId}")
public R<List<TaskVo>> getListByDeleteMultiInstance(@PathVariable String taskId) {
return R.ok(actTaskService.getListByDeleteMultiInstance(taskId));
}
}

View File

@ -15,7 +15,6 @@ import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.domain.TestLeave;
import org.dromara.workflow.domain.bo.TestLeaveBo;
import org.dromara.workflow.domain.vo.TestLeaveVo;
import org.dromara.workflow.service.ITestLeaveService;

View File

@ -1,72 +0,0 @@
package org.dromara.workflow.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.workflow.domain.bo.SysUserMultiBo;
import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.service.IWorkflowUserService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 工作流用户选人管理 控制层
*
* @author may
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/user")
public class WorkflowUserController extends BaseController {
private final IWorkflowUserService workflowUserService;
/**
* 分页查询工作流选择加签人员
*
* @param bo 参数
*/
@GetMapping("/getPageByAddMultiInstance")
public TableDataInfo<SysUserVo> getPageByAddMultiInstance(SysUserMultiBo bo, PageQuery pageQuery) {
return workflowUserService.getPageByAddMultiInstance(bo, pageQuery);
}
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id
*/
@GetMapping("/getListByDeleteMultiInstance/{taskId}")
public R<List<TaskVo>> getListByDeleteMultiInstance(@PathVariable String taskId) {
return R.ok(workflowUserService.getListByDeleteMultiInstance(taskId));
}
/**
* 按照用户id查询用户
*
* @param userIds 用户id
*/
@GetMapping("/getUserListByIds/{userIds}")
public R<List<SysUserVo>> getUserListByIds(@PathVariable List<Long> userIds) {
return R.ok(workflowUserService.getUserListByIds(userIds));
}
/**
* 分页查询用户
*
* @param sysUserBo 参数
* @param pageQuery 分页
*/
@GetMapping("/getPageByUserList")
public TableDataInfo<SysUserVo> getPageByUserList(SysUserBo sysUserBo, PageQuery pageQuery) {
return workflowUserService.getPageByUserList(sysUserBo, pageQuery);
}
}

View File

@ -59,7 +59,7 @@ public class ActHistoryInfoVo implements Serializable {
/**
* 办理人id
*/
private Long assignee;
private String assignee;
/**
* 办理人名称

View File

@ -1,20 +1,17 @@
package org.dromara.workflow.flowable.cmd;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.domain.dto.OssDTO;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.AttachmentEntity;
import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@ -41,20 +38,19 @@ public class AttachmentCmd implements Command<Boolean> {
public Boolean execute(CommandContext commandContext) {
try {
if (StringUtils.isNotBlank(fileId)) {
List<Long> fileIds = StreamUtils.toList(Arrays.asList(fileId.split(StrUtil.COMMA)), Long::valueOf);
List<SysOssVo> sysOssVos = SpringUtils.getBean(ISysOssService.class).listByIds(fileIds);
if (CollUtil.isNotEmpty(sysOssVos)) {
for (SysOssVo sysOssVo : sysOssVos) {
List<OssDTO> ossList = SpringUtils.getBean(OssService.class).selectByIds(fileId);
if (CollUtil.isNotEmpty(ossList)) {
for (OssDTO oss : ossList) {
AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager();
AttachmentEntity attachmentEntity = attachmentEntityManager.create();
attachmentEntity.setRevision(1);
attachmentEntity.setUserId(LoginHelper.getUserId().toString());
attachmentEntity.setName(sysOssVo.getOriginalName());
attachmentEntity.setDescription(sysOssVo.getOriginalName());
attachmentEntity.setType(sysOssVo.getFileSuffix());
attachmentEntity.setName(oss.getOriginalName());
attachmentEntity.setDescription(oss.getOriginalName());
attachmentEntity.setType(oss.getFileSuffix());
attachmentEntity.setTaskId(taskId);
attachmentEntity.setProcessInstanceId(processInstanceId);
attachmentEntity.setContentId(sysOssVo.getOssId().toString());
attachmentEntity.setContentId(oss.getOssId().toString());
attachmentEntity.setTime(new Date());
attachmentEntityManager.insert(attachmentEntity);
}

View File

@ -23,6 +23,7 @@ import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@ -50,6 +51,9 @@ public class GlobalFlowableListener implements FlowableEventListener {
@Lazy
private RepositoryService repositoryService;
@Value("${flowable.async-executor-activate}")
private boolean asyncExecutorActivate;
@Override
public void onEvent(FlowableEvent flowableEvent) {
if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) {
@ -60,7 +64,7 @@ public class GlobalFlowableListener implements FlowableEventListener {
FlowableEntityEvent flowableEntityEvent = (FlowableEntityEvent) flowableEngineEvent;
Object entityObject = flowableEntityEvent.getEntity();
TaskEntity task = (TaskEntity) entityObject;
if (task.getDueDate() != null && task.getDueDate().after(new Date())) {
if (asyncExecutorActivate && task.getDueDate() != null && task.getDueDate().after(new Date())) {
//删除之前已经存在的定时任务
TimerJobService timerJobService = CommandContextUtil.getTimerJobService();
List<TimerJobEntity> timerJobEntityList = timerJobService.findTimerJobsByProcessInstanceId(task.getProcessInstanceId());

View File

@ -142,4 +142,20 @@ public interface IActTaskService {
* @return 结果
*/
List<VariableVo> getInstanceVariable(String taskId);
/**
* 查询工作流任务用户选择加签人员
*
* @param taskId 任务id
* @return 结果
*/
String getTaskUserIdsByAddMultiInstance(String taskId);
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id
* @return 结果
*/
List<TaskVo> getListByDeleteMultiInstance(String taskId);
}

View File

@ -1,61 +0,0 @@
package org.dromara.workflow.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.workflow.domain.bo.SysUserMultiBo;
import org.dromara.workflow.domain.vo.TaskVo;
import java.util.List;
/**
* 工作流用户选人管理 服务层
*
* @author may
*/
public interface IWorkflowUserService {
/**
* 分页查询工作流选择加签人员
*
* @param sysUserMultiBo 参数
* @param pageQuery 分页
* @return 结果
*/
TableDataInfo<SysUserVo> getPageByAddMultiInstance(SysUserMultiBo sysUserMultiBo, PageQuery pageQuery);
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id
* @return 结果
*/
List<TaskVo> getListByDeleteMultiInstance(String taskId);
/**
* 按照用户id查询用户
*
* @param userIds 用户id
* @return 结果
*/
List<SysUserVo> getUserListByIds(List<Long> userIds);
/**
* 按照角色id查询关联用户id
*
* @param roleIds 角色id
* @return 结果
*/
List<SysUserRole> getUserRoleListByRoleIds(List<Long> roleIds);
/**
* 分页查询用户
*
* @param sysUserBo 参数
* @param pageQuery 分页
* @return 结果
*/
TableDataInfo<SysUserVo> getPageByUserList(SysUserBo sysUserBo, PageQuery pageQuery);
}

View File

@ -13,7 +13,6 @@ import lombok.RequiredArgsConstructor;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.io.IOUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -34,7 +33,10 @@ import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.validation.ValidationError;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -46,7 +48,6 @@ import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -63,8 +64,8 @@ import java.util.zip.ZipOutputStream;
public class ActModelServiceImpl implements IActModelService {
private final RepositoryService repositoryService;
private final IWfNodeConfigService iWfNodeConfigService;
private final IWfDefinitionConfigService iWfDefinitionConfigService;
private final IWfNodeConfigService wfNodeConfigService;
private final IWfDefinitionConfigService wfDefinitionConfigService;
/**
* 分页查询模型
@ -249,7 +250,7 @@ public class ActModelServiceImpl implements IActModelService {
if (ArrayUtil.isEmpty(xmlBytes)) {
throw new ServiceException("模型数据为空,请先设计流程定义模型,再进行部署!");
}
if (JSONUtil.isTypeJSON(IOUtils.toString(xmlBytes, StandardCharsets.UTF_8.toString()))) {
if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8))) {
byte[] bytes = ModelUtils.bpmnJsonToXmlBytes(xmlBytes);
if (ArrayUtil.isEmpty(bytes)) {
throw new ServiceException("模型不能为空,请至少设计一条主线流程!");
@ -290,16 +291,16 @@ public class ActModelServiceImpl implements IActModelService {
repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory());
//更新流程定义配置
if (processDefinition != null) {
WfDefinitionConfigVo definitionVo = iWfDefinitionConfigService.getByDefId(processDefinition.getId());
WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(processDefinition.getId());
if (definitionVo != null) {
iWfDefinitionConfigService.deleteByDefIds(Collections.singletonList(processDefinition.getId()));
wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(processDefinition.getId()));
WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo();
wfFormDefinition.setDefinitionId(definition.getId());
wfFormDefinition.setProcessKey(definition.getKey());
wfFormDefinition.setTableName(definitionVo.getTableName());
wfFormDefinition.setVersion(definition.getVersion());
wfFormDefinition.setRemark(definitionVo.getRemark());
iWfDefinitionConfigService.saveOrUpdate(wfFormDefinition);
wfDefinitionConfigService.saveOrUpdate(wfFormDefinition);
}
}
//更新流程节点配置表单
@ -320,7 +321,7 @@ public class ActModelServiceImpl implements IActModelService {
}
}
if (CollUtil.isNotEmpty(wfNodeConfigList)) {
iWfNodeConfigService.saveOrUpdate(wfNodeConfigList);
wfNodeConfigService.saveOrUpdate(wfNodeConfigList);
}
return true;
} catch (Exception e) {
@ -337,9 +338,7 @@ public class ActModelServiceImpl implements IActModelService {
*/
@Override
public void exportZip(List<String> modelIds, HttpServletResponse response) {
ZipOutputStream zos = null;
try {
zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8);
try (ZipOutputStream zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
// 压缩包文件名
String zipName = "模型不存在";
// 查询模型基本信息
@ -347,7 +346,7 @@ public class ActModelServiceImpl implements IActModelService {
Model model = repositoryService.getModel(modelId);
byte[] xmlBytes = repositoryService.getModelEditorSource(modelId);
if (ObjectUtil.isNotNull(model)) {
if (JSONUtil.isTypeJSON(IOUtils.toString(xmlBytes, StandardCharsets.UTF_8.toString())) && ArrayUtil.isEmpty(ModelUtils.bpmnJsonToXmlBytes(xmlBytes))) {
if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8)) && ArrayUtil.isEmpty(ModelUtils.bpmnJsonToXmlBytes(xmlBytes))) {
zipName = "模型不能为空,请至少设计一条主线流程!";
zos.putNextEntry(new ZipEntry(zipName + ".txt"));
zos.write(zipName.getBytes(StandardCharsets.UTF_8));
@ -367,19 +366,11 @@ public class ActModelServiceImpl implements IActModelService {
}
response.setHeader("Content-Disposition",
"attachment; filename=" + URLEncoder.encode(zipName, StandardCharsets.UTF_8) + ".zip");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 刷出响应流
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (zos != null) {
try {
zos.closeEntry();
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -3,14 +3,12 @@ package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@ -38,7 +36,6 @@ import org.flowable.engine.RepositoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.flowable.engine.repository.*;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -46,7 +43,10 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -62,9 +62,9 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
private final RepositoryService repositoryService;
private final ProcessMigrationService processMigrationService;
private final IWfCategoryService wfCategoryService;
private final IWfDefinitionConfigService iWfDefinitionConfigService;
private final IWfDefinitionConfigService wfDefinitionConfigService;
private final WfDefinitionConfigMapper wfDefinitionConfigMapper;
private final IWfNodeConfigService iWfNodeConfigService;
private final IWfNodeConfigService wfNodeConfigService;
/**
* 分页查询
@ -95,7 +95,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
}
if (CollUtil.isNotEmpty(definitionList)) {
List<String> ids = StreamUtils.toList(definitionList, ProcessDefinition::getId);
List<WfDefinitionConfigVo> wfDefinitionConfigVos = iWfDefinitionConfigService.queryList(ids);
List<WfDefinitionConfigVo> wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids);
for (ProcessDefinition processDefinition : definitionList) {
ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class);
if (CollUtil.isNotEmpty(deploymentList)) {
@ -135,7 +135,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
}
if (CollUtil.isNotEmpty(definitionList)) {
List<String> ids = StreamUtils.toList(definitionList, ProcessDefinition::getId);
List<WfDefinitionConfigVo> wfDefinitionConfigVos = iWfDefinitionConfigService.queryList(ids);
List<WfDefinitionConfigVo> wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids);
for (ProcessDefinition processDefinition : definitionList) {
ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class);
if (CollUtil.isNotEmpty(deploymentList)) {
@ -150,7 +150,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
processDefinitionVoList.add(processDefinitionVo);
}
}
return CollectionUtil.reverse(processDefinitionVoList);
return CollUtil.reverse(processDefinitionVoList);
}
/**
@ -162,7 +162,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
@Override
public String definitionImage(String processDefinitionId) {
InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
return Base64.encode(IOUtils.toByteArray(inputStream));
return Base64.encode(IoUtil.readBytes(inputStream));
}
/**
@ -174,13 +174,8 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
public String definitionXml(String processDefinitionId) {
StringBuilder xml = new StringBuilder();
ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
InputStream inputStream;
try {
inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
xml.append(IOUtils.toString(inputStream, StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
return xml.toString();
}
@ -195,7 +190,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
public boolean deleteDeployment(List<String> deploymentIds, List<String> processDefinitionIds) {
try {
List<HistoricProcessInstance> historicProcessInstances = QueryUtils.hisInstanceQuery().deploymentIdIn(deploymentIds).list();
if (CollectionUtil.isNotEmpty(historicProcessInstances)) {
if (CollUtil.isNotEmpty(historicProcessInstances)) {
Set<String> defIds = StreamUtils.toSet(historicProcessInstances, HistoricProcessInstance::getProcessDefinitionId);
List<ProcessDefinition> processDefinitions = QueryUtils.definitionQuery().processDefinitionIds(defIds).list();
if (CollUtil.isNotEmpty(processDefinitions)) {
@ -208,9 +203,9 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
repositoryService.deleteDeployment(deploymentId);
}
//删除流程定义配置
iWfDefinitionConfigService.deleteByDefIds(processDefinitionIds);
wfDefinitionConfigService.deleteByDefIds(processDefinitionIds);
//删除节点配置
iWfNodeConfigService.deleteByDefIds(processDefinitionIds);
wfNodeConfigService.deleteByDefIds(processDefinitionIds);
return true;
} catch (Exception e) {
e.printStackTrace();
@ -387,12 +382,12 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
if (CollUtil.isEmpty(wfDefinitionConfigs)) {
ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey("leave1").latestVersion().singleResult();
if (processDefinition != null) {
WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo();
wfFormDefinition.setDefinitionId(processDefinition.getId());
wfFormDefinition.setProcessKey(processDefinition.getKey());
wfFormDefinition.setTableName("test_leave");
wfFormDefinition.setVersion(processDefinition.getVersion());
iWfDefinitionConfigService.saveOrUpdate(wfFormDefinition);
WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo();
wfDefinitionConfigBo.setDefinitionId(processDefinition.getId());
wfDefinitionConfigBo.setProcessKey(processDefinition.getKey());
wfDefinitionConfigBo.setTableName("test_leave");
wfDefinitionConfigBo.setVersion(processDefinition.getVersion());
wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo);
}
}
@ -407,16 +402,16 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
private void setWfConfig(ProcessDefinition oldProcessDefinition, ProcessDefinition definition) {
//更新流程定义表单
if (oldProcessDefinition != null) {
WfDefinitionConfigVo definitionVo = iWfDefinitionConfigService.getByDefId(oldProcessDefinition.getId());
WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(oldProcessDefinition.getId());
if (definitionVo != null) {
iWfDefinitionConfigService.deleteByDefIds(Collections.singletonList(oldProcessDefinition.getId()));
WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo();
wfFormDefinition.setDefinitionId(definition.getId());
wfFormDefinition.setProcessKey(definition.getKey());
wfFormDefinition.setTableName(definitionVo.getTableName());
wfFormDefinition.setVersion(definition.getVersion());
wfFormDefinition.setRemark(definitionVo.getRemark());
iWfDefinitionConfigService.saveOrUpdate(wfFormDefinition);
wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(oldProcessDefinition.getId()));
WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo();
wfDefinitionConfigBo.setDefinitionId(definition.getId());
wfDefinitionConfigBo.setProcessKey(definition.getKey());
wfDefinitionConfigBo.setTableName(definitionVo.getTableName());
wfDefinitionConfigBo.setVersion(definition.getVersion());
wfDefinitionConfigBo.setRemark(definitionVo.getRemark());
wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo);
}
}
//更新流程节点配置表单
@ -437,7 +432,7 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
}
}
if (CollUtil.isNotEmpty(wfNodeConfigList)) {
iWfNodeConfigService.saveOrUpdate(wfNodeConfigList);
wfNodeConfigService.saveOrUpdate(wfNodeConfigList);
}
}
}

View File

@ -3,11 +3,12 @@ package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@ -52,7 +53,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
@ -76,8 +76,8 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
private final IActHiProcinstService actHiProcinstService;
private final ManagementService managementService;
private final FlowEventStrategy flowEventStrategy;
private final IWfTaskBackNodeService iWfTaskBackNodeService;
private final IWfNodeConfigService iWfNodeConfigService;
private final IWfTaskBackNodeService wfTaskBackNodeService;
private final IWfNodeConfigService wfNodeConfigService;
@Value("${flowable.activity-font-name}")
private String activityFontName;
@ -122,7 +122,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
}
if (CollUtil.isNotEmpty(list)) {
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (ProcessInstanceVo processInstanceVo : list) {
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
@ -169,7 +169,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
}
if (CollUtil.isNotEmpty(list)) {
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (ProcessInstanceVo processInstanceVo : list) {
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);
@ -236,7 +236,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
CustomDefaultProcessDiagramGenerator diagramGenerator = new CustomDefaultProcessDiagramGenerator();
InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodeList, highLightedFlows, activityFontName, labelFontName, annotationFontName, null, 1.0, true);
return Base64.encode(IOUtils.toByteArray(inputStream));
return Base64.encode(IoUtil.readBytes(inputStream));
}
/**
@ -282,14 +282,9 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
map.put("taskList", taskList);
List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId);
map.put("historyList", historyTaskList);
InputStream inputStream;
try {
inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
xml.append(IOUtils.toString(inputStream, String.valueOf(StandardCharsets.UTF_8)));
map.put("xml", xml.toString());
} catch (IOException e) {
e.printStackTrace();
}
InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8));
map.put("xml", xml.toString());
return map;
}
@ -306,7 +301,6 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
for (HistoricTaskInstance historicTaskInstance : list) {
ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo();
BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo);
actHistoryInfoVo.setAssignee(StringUtils.isNotBlank(historicTaskInstance.getAssignee()) ? Long.valueOf(historicTaskInstance.getAssignee()) : null);
actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "待处理" : "已处理");
if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
@ -324,6 +318,12 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
historyInfoVo.setStartTime(e.getStartTime());
historyInfoVo.setEndTime(null);
historyInfoVo.setRunDuration(null);
if (ObjectUtil.isEmpty(e.getAssignee())) {
ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId());
if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
}
}
});
historyInfoVoList.add(historyInfoVo);
}
@ -362,11 +362,6 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
}
try {
actHistoryInfoVo.setAssignee(StringUtils.isNotBlank(historicTaskInstance.getAssignee()) ? Long.valueOf(historicTaskInstance.getAssignee()) : null);
} catch (NumberFormatException ignored) {
log.warn("当前任务【{}】,办理人转换人员ID【{}】异常!", historicTaskInstance.getName(), historicTaskInstance.getAssignee());
}
//附件
if (CollUtil.isNotEmpty(attachmentList)) {
List<Attachment> attachments = attachmentList.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).collect(Collectors.toList());
@ -374,6 +369,13 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
actHistoryInfoVo.setAttachmentList(attachments);
}
}
//设置人员id
if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) {
ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId());
if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
}
}
actHistoryInfoVoList.add(actHistoryInfoVo);
}
List<ActHistoryInfoVo> collect = new ArrayList<>();
@ -389,10 +391,6 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
ActHistoryInfoVo actHistoryInfoVo = BeanUtil.toBean(entry.getValue().get(0), ActHistoryInfoVo.class);
String nickName = entry.getValue().stream().filter(e -> StringUtils.isNotBlank(e.getNickName()) && e.getEndTime() == null).map(ActHistoryInfoVo::getNickName).toList().stream().distinct().collect(Collectors.joining(StringUtils.SEPARATOR));
if (StringUtils.isNotBlank(nickName)) {
actHistoryInfoVo.setNickName(nickName);
}
actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst()
.ifPresent(e -> {
actHistoryInfoVo.setStatus("已处理");
@ -525,7 +523,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
}
iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
return true;
} catch (Exception e) {
e.printStackTrace();
@ -560,7 +558,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) {
historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
}
iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
return true;
} catch (Exception e) {
e.printStackTrace();
@ -578,7 +576,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
public boolean deleteFinishAndHisInstance(List<String> processInstanceIds) {
try {
historyService.bulkDeleteHistoricProcessInstances(processInstanceIds);
iWfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
return true;
} catch (Exception e) {
e.printStackTrace();
@ -679,7 +677,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
}
if (CollUtil.isNotEmpty(list)) {
List<String> processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (ProcessInstanceVo processInstanceVo : list) {
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo);

View File

@ -2,14 +2,15 @@ package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -76,10 +77,11 @@ public class ActTaskServiceImpl implements IActTaskService {
private final ManagementService managementService;
private final FlowEventStrategy flowEventStrategy;
private final ActTaskMapper actTaskMapper;
private final IWfTaskBackNodeService iWfTaskBackNodeService;
private final IWfTaskBackNodeService wfTaskBackNodeService;
private final ActHiTaskinstMapper actHiTaskinstMapper;
private final IWfNodeConfigService iWfNodeConfigService;
private final IWfDefinitionConfigService iWfDefinitionConfigService;
private final IWfNodeConfigService wfNodeConfigService;
private final IWfDefinitionConfigService wfDefinitionConfigService;
private final UserService userService;
/**
* 启动任务
@ -108,7 +110,7 @@ public class ActTaskServiceImpl implements IActTaskService {
map.put("taskId", taskResult.get(0).getId());
return map;
}
WfDefinitionConfigVo wfDefinitionConfigVo = iWfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName());
WfDefinitionConfigVo wfDefinitionConfigVo = wfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName());
if (wfDefinitionConfigVo == null) {
throw new ServiceException("请到流程定义绑定业务表名与流程KEY");
}
@ -207,7 +209,7 @@ public class ActTaskServiceImpl implements IActTaskService {
taskService.complete(completeTaskBo.getTaskId());
}
//记录执行过的流程任务节点
iWfTaskBackNodeService.recordExecuteNode(task);
wfTaskBackNodeService.recordExecuteNode(task);
ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
if (pi == null) {
UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
@ -282,7 +284,7 @@ public class ActTaskServiceImpl implements IActTaskService {
List<TaskVo> taskList = page.getRecords();
if (CollUtil.isNotEmpty(taskList)) {
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (TaskVo task : taskList) {
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
@ -336,7 +338,7 @@ public class ActTaskServiceImpl implements IActTaskService {
List<TaskVo> list = new ArrayList<>();
if (CollUtil.isNotEmpty(taskList)) {
List<String> processDefinitionIds = StreamUtils.toList(taskList, Task::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (Task task : taskList) {
TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
if (CollUtil.isNotEmpty(processInstanceList)) {
@ -384,7 +386,7 @@ public class ActTaskServiceImpl implements IActTaskService {
List<TaskVo> taskList = page.getRecords();
if (CollUtil.isNotEmpty(taskList)) {
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (TaskVo task : taskList) {
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
@ -420,7 +422,7 @@ public class ActTaskServiceImpl implements IActTaskService {
List<TaskVo> taskList = page.getRecords();
if (CollUtil.isNotEmpty(taskList)) {
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (TaskVo task : taskList) {
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
@ -448,7 +450,7 @@ public class ActTaskServiceImpl implements IActTaskService {
List<TaskVo> taskList = page.getRecords();
if (CollUtil.isNotEmpty(taskList)) {
List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
List<WfNodeConfigVo> wfNodeConfigVoList = iWfNodeConfigService.selectByDefIds(processDefinitionIds);
List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
for (TaskVo task : taskList) {
task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
@ -517,9 +519,9 @@ public class ActTaskServiceImpl implements IActTaskService {
}
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TERMINATION.getStatus(), terminationBo.getComment());
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
if (CollectionUtil.isNotEmpty(list)) {
if (CollUtil.isNotEmpty(list)) {
List<Task> subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId()));
if (CollectionUtil.isNotEmpty(subTasks)) {
if (CollUtil.isNotEmpty(subTasks)) {
subTasks.forEach(e -> taskService.deleteTask(e.getId()));
}
runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus());
@ -723,7 +725,7 @@ public class ActTaskServiceImpl implements IActTaskService {
managementService.executeCommand(deleteExecutionCmd);
}
WfTaskBackNode wfTaskBackNode = iWfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId());
WfTaskBackNode wfTaskBackNode = wfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId());
if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) {
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
@ -732,7 +734,7 @@ public class ActTaskServiceImpl implements IActTaskService {
}
}
//删除驳回后的流程节点
iWfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());
wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
@ -768,7 +770,7 @@ public class ActTaskServiceImpl implements IActTaskService {
public List<VariableVo> getInstanceVariable(String taskId) {
List<VariableVo> variableVoList = new ArrayList<>();
Map<String, VariableInstance> variableInstances = taskService.getVariableInstances(taskId);
if (CollectionUtil.isNotEmpty(variableInstances)) {
if (CollUtil.isNotEmpty(variableInstances)) {
for (Map.Entry<String, VariableInstance> entry : variableInstances.entrySet()) {
VariableVo variableVo = new VariableVo();
variableVo.setKey(entry.getKey());
@ -778,4 +780,93 @@ public class ActTaskServiceImpl implements IActTaskService {
}
return variableVoList;
}
/**
* 查询工作流任务用户选择加签人员
*
* @param taskId 任务id
* @return
*/
@Override
@SuppressWarnings("unchecked")
public String getTaskUserIdsByAddMultiInstance(String taskId) {
Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new ServiceException("任务不存在");
}
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
if (multiInstance == null) {
return "";
}
List<Long> userIds;
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
userIds = (List<Long>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
} else {
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
userIds = StreamUtils.toList(list, e -> Long.valueOf(e.getAssignee()));
}
return StringUtils.join(userIds, StringUtils.SEPARATOR);
}
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id 任务id
*/
@Override
@SuppressWarnings("unchecked")
public List<TaskVo> getListByDeleteMultiInstance(String taskId) {
Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
List<TaskVo> taskListVo = new ArrayList<>();
if (multiInstance == null) {
return List.of();
}
List<Long> assigneeList = new ArrayList<>();
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
List<Object> variable = (List<Object>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
for (Object o : variable) {
assigneeList.add(Long.valueOf(o.toString()));
}
}
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
List<Long> userIds = StreamUtils.filter(assigneeList, e -> !String.valueOf(e).equals(task.getAssignee()));
List<UserDTO> userList = userService.selectListByIds(userIds);
for (Long userId : userIds) {
TaskVo taskVo = new TaskVo();
taskVo.setId("串行会签");
taskVo.setExecutionId("串行会签");
taskVo.setProcessInstanceId(task.getProcessInstanceId());
taskVo.setName(task.getName());
taskVo.setAssignee(userId);
if (CollUtil.isNotEmpty(userList)) {
userList.stream().filter(u -> u.getUserId().toString().equals(userId.toString())).findFirst().ifPresent(u -> taskVo.setAssigneeName(u.getNickName()));
}
taskListVo.add(taskVo);
}
return taskListVo;
} else if (multiInstance.getType() instanceof ParallelMultiInstanceBehavior) {
List<Task> tasks = StreamUtils.filter(taskList, e -> StringUtils.isBlank(e.getParentTaskId()) && !e.getExecutionId().equals(task.getExecutionId()) && e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
if (CollUtil.isNotEmpty(tasks)) {
List<Long> userIds = StreamUtils.toList(tasks, e -> Long.valueOf(e.getAssignee()));
List<UserDTO> userList = userService.selectListByIds(userIds);
for (Task t : tasks) {
TaskVo taskVo = new TaskVo();
taskVo.setId(t.getId());
taskVo.setExecutionId(t.getExecutionId());
taskVo.setProcessInstanceId(t.getProcessInstanceId());
taskVo.setName(t.getName());
taskVo.setAssignee(Long.valueOf(t.getAssignee()));
if (CollUtil.isNotEmpty(userList)) {
userList.stream().filter(u -> u.getUserId().toString().equals(t.getAssignee())).findFirst().ifPresent(e -> taskVo.setAssigneeName(e.getNickName()));
}
taskListVo.add(taskVo);
}
return taskListVo;
}
}
return List.of();
}
}

View File

@ -35,7 +35,7 @@ import java.util.List;
public class TestLeaveServiceImpl implements ITestLeaveService {
private final TestLeaveMapper baseMapper;
private final IActProcessInstanceService iActProcessInstanceService;
private final IActProcessInstanceService actProcessInstanceService;
/**
* 查询请假
@ -115,7 +115,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids) {
List<String> idList = StreamUtils.toList(ids, String::valueOf);
iActProcessInstanceService.deleteRunAndHisInstanceByBusinessKeys(idList);
actProcessInstanceService.deleteRunAndHisInstanceByBusinessKeys(idList);
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@ -27,7 +27,7 @@ import java.util.List;
public class WfNodeConfigServiceImpl implements IWfNodeConfigService {
private final WfNodeConfigMapper baseMapper;
private final IWfFormManageService iWfFormManageService;
private final IWfFormManageService wfFormManageService;
/**
* 查询节点配置
@ -65,7 +65,7 @@ public class WfNodeConfigServiceImpl implements IWfNodeConfigService {
List<WfNodeConfigVo> wfNodeConfigVos = baseMapper.selectVoList(new LambdaQueryWrapper<WfNodeConfig>().in(WfNodeConfig::getDefinitionId, ids));
if (CollUtil.isNotEmpty(wfNodeConfigVos)) {
List<Long> formIds = StreamUtils.toList(wfNodeConfigVos, WfNodeConfigVo::getFormId);
List<WfFormManageVo> wfFormManageVos = iWfFormManageService.queryByIds(formIds);
List<WfFormManageVo> wfFormManageVos = wfFormManageService.queryByIds(formIds);
for (WfNodeConfigVo wfNodeConfigVo : wfNodeConfigVos) {
wfFormManageVos.stream().filter(e -> ObjectUtil.equals(e.getId(), wfNodeConfigVo.getFormId())).findFirst().ifPresent(wfNodeConfigVo::setWfFormManageVo);
}

View File

@ -1,6 +1,6 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
@ -50,7 +50,7 @@ public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService {
} else {
wfTaskBackNode.setTaskType(USER_TASK);
}
if (CollectionUtil.isEmpty(list)) {
if (CollUtil.isEmpty(list)) {
wfTaskBackNode.setOrderNo(0);
wfTaskBackNodeMapper.insert(wfTaskBackNode);
} else {
@ -96,14 +96,14 @@ public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService {
Integer orderNo = actTaskNode.getOrderNo();
List<WfTaskBackNode> taskNodeList = getListByInstanceId(processInstanceId);
List<Long> ids = new ArrayList<>();
if (CollectionUtil.isNotEmpty(taskNodeList)) {
if (CollUtil.isNotEmpty(taskNodeList)) {
for (WfTaskBackNode taskNode : taskNodeList) {
if (taskNode.getOrderNo() >= orderNo) {
ids.add(taskNode.getId());
}
}
}
if (CollectionUtil.isNotEmpty(ids)) {
if (CollUtil.isNotEmpty(ids)) {
wfTaskBackNodeMapper.deleteBatchIds(ids);
}
}

View File

@ -1,215 +0,0 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.enums.UserStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.mapper.SysUserRoleMapper;
import org.dromara.workflow.domain.bo.SysUserMultiBo;
import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.service.IWorkflowUserService;
import org.dromara.workflow.utils.QueryUtils;
import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 工作流用户选人管理 业务处理层
*
* @author may
*/
@RequiredArgsConstructor
@Service
public class WorkflowUserServiceImpl implements IWorkflowUserService {
private final SysUserMapper sysUserMapper;
private final SysUserRoleMapper sysUserRoleMapper;
private final RuntimeService runtimeService;
/**
* 分页查询工作流选择加签人员
*
* @param bo 参数
* @param pageQuery 分页
*/
@Override
@SuppressWarnings("unchecked")
public TableDataInfo<SysUserVo> getPageByAddMultiInstance(SysUserMultiBo bo, PageQuery pageQuery) {
Task task = QueryUtils.taskQuery().taskId(bo.getTaskId()).singleResult();
if (task == null) {
throw new ServiceException("任务不存在");
}
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
if (multiInstance == null) {
return TableDataInfo.build();
}
LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
//检索条件
queryWrapper.eq(StringUtils.isNotEmpty(bo.getDeptId()), SysUser::getDeptId, bo.getDeptId());
queryWrapper.eq(SysUser::getStatus, UserStatus.OK.getCode());
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
List<Long> assigneeList = (List<Long>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
queryWrapper.notIn(CollectionUtil.isNotEmpty(assigneeList), SysUser::getUserId, assigneeList);
} else {
List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
List<Long> userIds = StreamUtils.toList(list, e -> Long.valueOf(e.getAssignee()));
queryWrapper.notIn(CollectionUtil.isNotEmpty(userIds), SysUser::getUserId, userIds);
}
queryWrapper.like(StringUtils.isNotEmpty(bo.getUserName()), SysUser::getUserName, bo.getUserName());
queryWrapper.like(StringUtils.isNotEmpty(bo.getNickName()), SysUser::getNickName, bo.getNickName());
Page<SysUser> page = new Page<>(pageQuery.getFirstNum(), pageQuery.getPageSize());
Page<SysUserVo> userPage = sysUserMapper.selectVoPage(page, queryWrapper);
return TableDataInfo.build(recordPage(userPage));
}
/**
* 查询工作流选择减签人员
*
* @param taskId 任务id 任务id
*/
@Override
@SuppressWarnings("unchecked")
public List<TaskVo> getListByDeleteMultiInstance(String taskId) {
Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
List<TaskVo> taskListVo = new ArrayList<>();
if (multiInstance == null) {
return Collections.emptyList();
}
List<Long> assigneeList = new ArrayList<>();
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
List<Object> variable = (List<Object>) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList());
for (Object o : variable) {
assigneeList.add(Long.valueOf(o.toString()));
}
}
if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) {
List<Long> userIds = StreamUtils.filter(assigneeList, e -> !String.valueOf(e).equals(task.getAssignee()));
List<SysUserVo> sysUsers = null;
if (CollectionUtil.isNotEmpty(userIds)) {
sysUsers = sysUserMapper.selectVoBatchIds(userIds);
}
for (Long userId : userIds) {
TaskVo taskVo = new TaskVo();
taskVo.setId("串行会签");
taskVo.setExecutionId("串行会签");
taskVo.setProcessInstanceId(task.getProcessInstanceId());
taskVo.setName(task.getName());
taskVo.setAssignee(userId);
if (CollectionUtil.isNotEmpty(sysUsers)) {
sysUsers.stream().filter(u -> u.getUserId().toString().equals(userId.toString())).findFirst().ifPresent(u -> taskVo.setAssigneeName(u.getNickName()));
}
taskListVo.add(taskVo);
}
return taskListVo;
} else if (multiInstance.getType() instanceof ParallelMultiInstanceBehavior) {
List<Task> tasks = StreamUtils.filter(taskList, e -> StringUtils.isBlank(e.getParentTaskId()) && !e.getExecutionId().equals(task.getExecutionId()) && e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
if (CollectionUtil.isNotEmpty(tasks)) {
List<Long> userIds = StreamUtils.toList(tasks, e -> Long.valueOf(e.getAssignee()));
List<SysUserVo> sysUsers = null;
if (CollectionUtil.isNotEmpty(userIds)) {
sysUsers = sysUserMapper.selectVoBatchIds(userIds);
}
for (Task t : tasks) {
TaskVo taskVo = new TaskVo();
taskVo.setId(t.getId());
taskVo.setExecutionId(t.getExecutionId());
taskVo.setProcessInstanceId(t.getProcessInstanceId());
taskVo.setName(t.getName());
taskVo.setAssignee(Long.valueOf(t.getAssignee()));
if (CollectionUtil.isNotEmpty(sysUsers)) {
sysUsers.stream().filter(u -> u.getUserId().toString().equals(t.getAssignee())).findFirst().ifPresent(e -> taskVo.setAssigneeName(e.getNickName()));
}
taskListVo.add(taskVo);
}
return taskListVo;
}
}
return Collections.emptyList();
}
/**
* 翻译部门
*
* @param page 用户分页数据
*/
private Page<SysUserVo> recordPage(Page<SysUserVo> page) {
List<SysUserVo> records = page.getRecords();
if (CollUtil.isEmpty(records)) {
return page;
}
List<Long> collectDeptId = StreamUtils.toList(records, SysUserVo::getDeptId);
if (CollUtil.isEmpty(collectDeptId)) {
return page;
}
page.setRecords(records);
return page;
}
/**
* 按照用户id查询用户
*
* @param userIds 用户id
*/
@Override
public List<SysUserVo> getUserListByIds(List<Long> userIds) {
if (CollUtil.isEmpty(userIds)) {
return Collections.emptyList();
}
LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
// 检索条件
queryWrapper.eq(SysUser::getStatus, UserStatus.OK.getCode());
queryWrapper.in(SysUser::getUserId, userIds);
return sysUserMapper.selectVoList(queryWrapper);
}
/**
* 按照角色id查询关联用户id
*
* @param roleIds 角色id
*/
@Override
public List<SysUserRole> getUserRoleListByRoleIds(List<Long> roleIds) {
return sysUserRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
}
/**
* 分页查询用户
*
* @param sysUserBo 参数
* @param pageQuery 分页
*/
@Override
public TableDataInfo<SysUserVo> getPageByUserList(SysUserBo sysUserBo, PageQuery pageQuery) {
LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(sysUserBo.getDeptId() != null, SysUser::getDeptId, sysUserBo.getDeptId());
queryWrapper.eq(SysUser::getStatus, UserStatus.OK.getCode());
queryWrapper.like(StringUtils.isNotEmpty(sysUserBo.getUserName()), SysUser::getUserName, sysUserBo.getUserName());
queryWrapper.like(StringUtils.isNotEmpty(sysUserBo.getNickName()), SysUser::getNickName, sysUserBo.getNickName());
Page<SysUserVo> userPage = sysUserMapper.selectVoPage(pageQuery.build(), queryWrapper);
return TableDataInfo.build(recordPage(userPage));
}
}

View File

@ -7,6 +7,8 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@ -15,18 +17,18 @@ import org.dromara.common.mail.utils.MailUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.common.enums.BusinessStatusEnum;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.workflow.domain.ActHiTaskinst;
import org.dromara.workflow.domain.vo.*;
import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.ParticipantVo;
import org.dromara.workflow.domain.vo.ProcessInstanceVo;
import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd;
import org.dromara.workflow.mapper.ActHiTaskinstMapper;
import org.dromara.workflow.service.*;
import org.dromara.workflow.service.IActHiProcinstService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.common.engine.api.delegate.Expression;
@ -41,7 +43,7 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import java.util.*;
import static org.dromara.workflow.common.constant.FlowConstant.*;
import static org.dromara.workflow.common.constant.FlowConstant.PROCESS_INSTANCE_VO;
/**
* 工作流工具
@ -52,7 +54,7 @@ import static org.dromara.workflow.common.constant.FlowConstant.*;
public class WorkflowUtils {
private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class);
private static final IWorkflowUserService WORKFLOW_USER_SERVICE = SpringUtils.getBean(IWorkflowUserService.class);
private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class);
private static final IActHiProcinstService ACT_HI_PROCINST_SERVICE = SpringUtils.getBean(IActHiProcinstService.class);
private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class);
@ -138,15 +140,14 @@ public class WorkflowUtils {
List<HistoricIdentityLink> groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId()));
if (CollUtil.isNotEmpty(groupList)) {
List<Long> groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId()));
List<SysUserRole> sysUserRoles = WORKFLOW_USER_SERVICE.getUserRoleListByRoleIds(groupIds);
if (CollUtil.isNotEmpty(sysUserRoles)) {
List<Long> userIds = USER_SERVICE.selectUserIdsByRoleIds(groupIds);
if (CollUtil.isNotEmpty(userIds)) {
participantVo.setGroupIds(groupIds);
List<Long> userIdList = StreamUtils.toList(sysUserRoles, SysUserRole::getUserId);
List<SysUserVo> sysUsers = WORKFLOW_USER_SERVICE.getUserListByIds(userIdList);
if (CollUtil.isNotEmpty(sysUsers)) {
List<Long> userIds = StreamUtils.toList(sysUsers, SysUserVo::getUserId);
List<String> nickNames = StreamUtils.toList(sysUsers, SysUserVo::getNickName);
participantVo.setCandidate(userIds);
List<UserDTO> userList = USER_SERVICE.selectListByIds(userIds);
if (CollUtil.isNotEmpty(userList)) {
List<Long> userIdList = StreamUtils.toList(userList, UserDTO::getUserId);
List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
participantVo.setCandidate(userIdList);
participantVo.setCandidateName(nickNames);
participantVo.setClaim(!StringUtils.isBlank(task.getAssignee()));
}
@ -161,10 +162,10 @@ public class WorkflowUtils {
}
}
List<SysUserVo> sysUsers = WORKFLOW_USER_SERVICE.getUserListByIds(userIdList);
if (CollUtil.isNotEmpty(sysUsers)) {
List<Long> userIds = StreamUtils.toList(sysUsers, SysUserVo::getUserId);
List<String> nickNames = StreamUtils.toList(sysUsers, SysUserVo::getNickName);
List<UserDTO> userList = USER_SERVICE.selectListByIds(userIdList);
if (CollUtil.isNotEmpty(userList)) {
List<Long> userIds = StreamUtils.toList(userList, UserDTO::getUserId);
List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
participantVo.setCandidate(userIds);
participantVo.setCandidateName(nickNames);
// 判断当前任务是否具有多个办理人
@ -306,9 +307,9 @@ public class WorkflowUtils {
for (Task t : list) {
ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId());
if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
List<SysUserRole> sysUserRoles = WORKFLOW_USER_SERVICE.getUserRoleListByRoleIds(taskParticipant.getGroupIds());
if (CollUtil.isNotEmpty(sysUserRoles)) {
userIds.addAll(StreamUtils.toList(sysUserRoles, SysUserRole::getUserId));
List<Long> userIdList = USER_SERVICE.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
if (CollUtil.isNotEmpty(userIdList)) {
userIds.addAll(userIdList);
}
}
List<Long> candidate = taskParticipant.getCandidate();
@ -317,7 +318,7 @@ public class WorkflowUtils {
}
}
if (CollUtil.isNotEmpty(userIds)) {
List<SysUserVo> sysUserVoList = WORKFLOW_USER_SERVICE.getUserListByIds(new ArrayList<>(userIds));
List<UserDTO> userList = USER_SERVICE.selectListByIds(new ArrayList<>(userIds));
for (String code : messageType) {
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
@ -329,7 +330,7 @@ public class WorkflowUtils {
WebSocketUtils.publishMessage(dto);
break;
case EMAIL_MESSAGE:
MailUtils.sendText(StreamUtils.join(sysUserVoList, SysUserVo::getEmail), "单据审批提醒", message);
MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message);
break;
case SMS_MESSAGE:
//todo 短信发送

View File

@ -5,7 +5,7 @@ rem jar平级目录
set AppName=ruoyi-admin.jar
rem JVM参数
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC"
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC"
ECHO.

View File

@ -3,7 +3,7 @@
AppName=ruoyi-admin.jar
# JVM参数
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC"
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC"
APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log

Binary file not shown.

View File

@ -310,6 +310,8 @@ CREATE TABLE `er_job`
AUTO_INCREMENT = 0
DEFAULT CHARSET = utf8mb4 COMMENT ='任务信息';
INSERT INTO `er_job` VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', now(), now(), 0);
CREATE TABLE `er_job_log_message`
(
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',

View File

@ -474,8 +474,11 @@ COMMENT ON COLUMN er_job.resident IS '是否是常驻任务';
COMMENT ON COLUMN er_job.description IS '描述';
COMMENT ON COLUMN er_job.ext_attrs IS '扩展字段';
COMMENT ON COLUMN er_job.create_dt IS '创建时间';
COMMENT ON COLUMN er_job.deleted IS '逻辑删除 1、删除';
COMMENT ON COLUMN er_job.update_dt IS '更新时间';
COMMENT ON COLUMN er_job.deleted IS '逻辑删除 1、删除';
INSERT INTO er_job (namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, description, ext_attrs, create_dt, update_dt, deleted)
VALUES ('dev', 'ruoyi_group', 'demo-job', NULL, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', SYSDATE, SYSDATE, 0);
-- er_job_log_message
CREATE TABLE er_job_log_message

View File

@ -165,6 +165,7 @@ create table sys_dept (
parent_id number(20) default 0,
ancestors varchar2(500) default '',
dept_name varchar2(30) default '',
dept_category varchar2(100) default null,
order_num number(4) default 0,
leader number(20) default null,
phone varchar2(11) default null,
@ -186,6 +187,7 @@ comment on column sys_dept.tenant_id is '租户编号';
comment on column sys_dept.parent_id is '父部门id';
comment on column sys_dept.ancestors is '祖级列表';
comment on column sys_dept.dept_name is '部门名称';
comment on column sys_dept.dept_category is '部门类别编码';
comment on column sys_dept.order_num is '显示顺序';
comment on column sys_dept.leader is '负责人';
comment on column sys_dept.phone is '联系电话';
@ -201,16 +203,17 @@ comment on column sys_dept.update_time is '更新时间';
-- ----------------------------
-- 初始化-部门表数据
-- ----------------------------
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', 0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', 1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', 3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', 4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', 5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', null,0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', null,1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', null,3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', null,4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', null,5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate, null, null);
-- ----------------------------
@ -278,7 +281,9 @@ insert into sys_user values(4, '000000', 102, 'test1', '仅本人 密码666666',
create table sys_post (
post_id number(20) not null,
tenant_id varchar2(20) default '000000',
dept_id number(20) not null,
post_code varchar2(64) not null,
post_category varchar2(64) default null,
post_name varchar2(50) not null,
post_sort number(4) not null,
status char(1) not null,
@ -295,7 +300,9 @@ alter table sys_post add constraint pk_sys_post primary key (post_id);
comment on table sys_post is '岗位信息表';
comment on column sys_post.post_id is '岗位ID';
comment on column sys_post.tenant_id is '租户编号';
comment on column sys_post.dept_id is '部门id';
comment on column sys_post.post_code is '岗位编码';
comment on column sys_post.post_category is '岗位类别编码';
comment on column sys_post.post_name is '岗位名称';
comment on column sys_post.post_sort is '显示顺序';
comment on column sys_post.status is '状态0正常 1停用';
@ -309,10 +316,10 @@ comment on column sys_post.remark is '备注';
-- ----------------------------
-- 初始化-岗位信息表数据
-- ----------------------------
insert into sys_post values(1, '000000', 'ceo', '董事长', 1, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(2, '000000', 'se', '项目经理', 2, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(3, '000000', 'hr', '人力资源', 3, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(4, '000000', 'user', '普通员工', 4, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(1, '000000', 103, 'ceo', null, '董事长', 1, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(2, '000000', 100, 'se', null, '项目经理', 2, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(3, '000000', 100, 'hr', null, '人力资源', 3, '0', 103, 1, sysdate, null, null, '');
insert into sys_post values(4, '000000', 100, 'user', null, '普通员工', 4, '0', 103, 1, sysdate, null, null, '');
-- ----------------------------
@ -1179,7 +1186,7 @@ create table sys_oss_config (
alter table sys_oss_config add constraint pk_sys_oss_config primary key (oss_config_id);
comment on table sys_oss_config is '对象存储配置表';
comment on column sys_oss_config.oss_config_id is '';
comment on column sys_oss_config.oss_config_id is '';
comment on column sys_oss_config.tenant_id is '租户编码';
comment on column sys_oss_config.config_key is '配置key';
comment on column sys_oss_config.access_key is 'accesskey';
@ -1230,7 +1237,7 @@ create table sys_client (
alter table sys_client add constraint pk_sys_client primary key (id);
comment on table sys_client is '系统授权表';
comment on column sys_client.id is '';
comment on column sys_client.id is '';
comment on column sys_client.client_id is '客户端id';
comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';

View File

@ -463,6 +463,8 @@ COMMENT ON COLUMN er_job.deleted IS '逻辑删除 1、删除';
COMMENT ON COLUMN er_job.update_dt IS '更新时间';
COMMENT ON TABLE er_job IS '任务信息';
INSERT INTO er_job VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', now(), now(), 0);
CREATE TABLE er_job_log_message
(
id BIGSERIAL PRIMARY KEY,

View File

@ -169,6 +169,7 @@ create table if not exists sys_dept
parent_id int8 default 0,
ancestors varchar(500)default ''::varchar,
dept_name varchar(30) default ''::varchar,
dept_category varchar(100) default null::varchar,
order_num int4 default 0,
leader int8 default null,
phone varchar(11) default null::varchar,
@ -189,6 +190,7 @@ comment on column sys_dept.tenant_id is '租户编号';
comment on column sys_dept.parent_id is '父部门ID';
comment on column sys_dept.ancestors is '祖级列表';
comment on column sys_dept.dept_name is '部门名称';
comment on column sys_dept.dept_category is '部门类别编码';
comment on column sys_dept.order_num is '显示顺序';
comment on column sys_dept.leader is '负责人';
comment on column sys_dept.phone is '联系电话';
@ -204,16 +206,16 @@ comment on column sys_dept.update_time is '更新时间';
-- ----------------------------
-- 初始化-部门表数据
-- ----------------------------
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', 0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', 1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', 3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', 4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', 5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', null,0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', null,1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', null,3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', null,4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', null,5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, now(), null, null);
-- ----------------------------
-- 2、用户信息表
@ -282,7 +284,9 @@ create table if not exists sys_post
(
post_id int8,
tenant_id varchar(20) default '000000'::varchar,
dept_id int8,
post_code varchar(64) not null,
post_category varchar(100) default null,
post_name varchar(50) not null,
post_sort int4 not null,
status char not null,
@ -298,7 +302,9 @@ create table if not exists sys_post
comment on table sys_post is '岗位信息表';
comment on column sys_post.post_id is '岗位ID';
comment on column sys_post.tenant_id is '租户编号';
comment on column sys_post.dept_id is '部门id';
comment on column sys_post.post_code is '岗位编码';
comment on column sys_post.post_category is '岗位类别编码';
comment on column sys_post.post_name is '岗位名称';
comment on column sys_post.post_sort is '显示顺序';
comment on column sys_post.status is '状态0正常 1停用';
@ -312,10 +318,10 @@ comment on column sys_post.remark is '备注';
-- ----------------------------
-- 初始化-岗位信息表数据
-- ----------------------------
insert into sys_post values(1, '000000', 'ceo', '董事长', 1, '0', 103, 1, now(), null, null, '');
insert into sys_post values(2, '000000', 'se', '项目经理', 2, '0', 103, 1, now(), null, null, '');
insert into sys_post values(3, '000000', 'hr', '人力资源', 3, '0', 103, 1, now(), null, null, '');
insert into sys_post values(4, '000000', 'user', '普通员工', 4, '0', 103, 1, now(), null, null, '');
insert into sys_post values(1, '000000', 103, 'ceo', null, '董事长', 1, '0', 103, 1, now(), null, null, '');
insert into sys_post values(2, '000000', 100, 'se', null, '项目经理', 2, '0', 103, 1, now(), null, null, '');
insert into sys_post values(3, '000000', 100, 'hr', null, '人力资源', 3, '0', 103, 1, now(), null, null, '');
insert into sys_post values(4, '000000', 100, 'user', null, '普通员工', 4, '0', 103, 1, now(), null, null, '');
-- ----------------------------
-- 4、角色信息表
@ -425,7 +431,7 @@ insert into sys_menu values('6', '系统管理', '0', '2', 'tenant', n
insert into sys_menu values('2', '系统监控', '0', '3', 'monitor', null, '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, now(), null, null, '系统监控目录');
insert into sys_menu values('3', '系统工具', '0', '4', 'tool', null, '', '1', '0', 'M', '0', '0', '', 'tool', 103, 1, now(), null, null, '系统工具目录');
insert into sys_menu values('4', 'PLUS官网', '0', '5', 'https://gitee.com/dromara/RuoYi-Vue-Plus', null, '', '0', '0', 'M', '0', '0', '', 'guide', 103, 1, now(), null, null, 'RuoYi-Vue-Plus官网地址');
insert into sys_menu VALUES('5', '测试菜单', '0', '5', 'demo', null, '1', '0', 'M', '0', '0', null, 'star', 103, 1, now(), null, null, '测试菜单');
insert into sys_menu VALUES('5', '测试菜单', '0', '5', 'demo', null, '', '1', '0', 'M', '0', '0', null, 'star', 103, 1, now(), null, null, '测试菜单');
-- 二级菜单
insert into sys_menu values('100', '用户管理', '1', '1', 'user', 'system/user/index', '', '1', '0', 'C', '0', '0', 'system:user:list', 'user', 103, 1, now(), null, null, '用户管理菜单');
insert into sys_menu values('101', '角色管理', '1', '2', 'role', 'system/role/index', '', '1', '0', 'C', '0', '0', 'system:role:list', 'peoples', 103, 1, now(), null, null, '角色管理菜单');
@ -553,8 +559,8 @@ insert into sys_menu values('1065', '客户端管理导出', '123', '5', '#', '
-- 测试菜单
INSERT INTO sys_menu VALUES('1500', '测试单表', '5', '1', 'demo', 'demo/demo/index', '', '1', '0', 'C', '0', '0', 'demo:demo:list', '#', 103, 1, now(), NULL, NULL, '测试单表菜单');
INSERT INTO sys_menu VALUES('1501', '测试单表查询', '1500', '1', '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:query', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1502', '测试单表新增', '1500', '2,' '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:add', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1503', '测试单表修改', '1500', '3', '#', '', '', '1', '0,' 'F', '0', '0', 'demo:demo:edit', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1502', '测试单表新增', '1500', '2', '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:add', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1503', '测试单表修改', '1500', '3', '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:edit', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1504', '测试单表删除', '1500', '4', '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:remove', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1505', '测试单表导出', '1500', '5', '#', '', '', '1', '0', 'F', '0', '0', 'demo:demo:export', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES('1506', '测试树表', '5', '1', 'tree', 'demo/tree/index', '', '1', '0', 'C', '0', '0', 'demo:tree:list', '#', 103, 1, now(), NULL, NULL, '测试树表菜单');
@ -1182,7 +1188,7 @@ create table if not exists sys_oss_config
);
comment on table sys_oss_config is '对象存储配置表';
comment on column sys_oss_config.oss_config_id is '';
comment on column sys_oss_config.oss_config_id is '';
comment on column sys_oss_config.tenant_id is '租户编码';
comment on column sys_oss_config.config_key is '配置key';
comment on column sys_oss_config.access_key is 'accessKey';
@ -1232,7 +1238,7 @@ create table sys_client (
);
comment on table sys_client is '系统授权表';
comment on column sys_client.id is '';
comment on column sys_client.id is '';
comment on column sys_client.client_id is '客户端id';
comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';
@ -1261,8 +1267,8 @@ create table if not exists test_demo
test_key varchar(255),
value varchar(255),
version int4 default 0,
create_time timestamp,
create_dept int8,
create_time timestamp,
create_by int8,
update_time timestamp,
update_by int8,
@ -1294,8 +1300,8 @@ create table if not exists test_tree
user_id int8,
tree_name varchar(255),
version int4 default 0,
create_time timestamp,
create_dept int8,
create_time timestamp,
create_by int8,
update_time timestamp,
update_by int8,

View File

@ -101,6 +101,7 @@ create table sys_dept (
parent_id bigint(20) default 0 comment '父部门id',
ancestors varchar(500) default '' comment '祖级列表',
dept_name varchar(30) default '' comment '部门名称',
dept_category varchar(100) default null comment '部门类别编码',
order_num int(4) default 0 comment '显示顺序',
leader bigint(20) default null comment '负责人',
phone varchar(11) default null comment '联系电话',
@ -120,16 +121,16 @@ create table sys_dept (
-- ----------------------------
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', 0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', 1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', 3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', 4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', 5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', 1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', 2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(100, '000000', 0, '0', 'XXX科技', null,0, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(101, '000000', 100, '0,100', '深圳总公司', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(102, '000000', 100, '0,100', '长沙分公司', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(103, '000000', 101, '0,100,101', '研发部门', null,1, 1, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(104, '000000', 101, '0,100,101', '市场部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(105, '000000', 101, '0,100,101', '测试部门', null,3, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(106, '000000', 101, '0,100,101', '财务部门', null,4, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(107, '000000', 101, '0,100,101', '运维部门', null,5, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(108, '000000', 102, '0,100,102', '市场部门', null,1, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
insert into sys_dept values(109, '000000', 102, '0,100,102', '财务部门', null,2, null, '15888888888', 'xxx@qq.com', '0', '0', 103, 1, sysdate(), null, null);
-- ----------------------------
@ -174,7 +175,9 @@ create table sys_post
(
post_id bigint(20) not null comment '岗位ID',
tenant_id varchar(20) default '000000' comment '租户编号',
dept_id bigint(20) not null comment '部门id',
post_code varchar(64) not null comment '岗位编码',
post_category varchar(100) default null comment '岗位类别编码',
post_name varchar(50) not null comment '岗位名称',
post_sort int(4) not null comment '显示顺序',
status char(1) not null comment '状态0正常 1停用',
@ -190,10 +193,10 @@ create table sys_post
-- ----------------------------
-- 初始化-岗位信息表数据
-- ----------------------------
insert into sys_post values(1, '000000', 'ceo', '董事长', 1, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(2, '000000', 'se', '项目经理', 2, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(3, '000000', 'hr', '人力资源', 3, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(4, '000000', 'user', '普通员工', 4, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(1, '000000', 103, 'ceo', null, '董事长', 1, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(2, '000000', 100, 'se', null, '项目经理', 2, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(3, '000000', 100, 'hr', null, '人力资源', 3, '0', 103, 1, sysdate(), null, null, '');
insert into sys_post values(4, '000000', 100, 'user', null, '普通员工', 4, '0', 103, 1, sysdate(), null, null, '');
-- ----------------------------
@ -814,7 +817,7 @@ create table sys_oss (
-- OSS对象存储动态配置表
-- ----------------------------
create table sys_oss_config (
oss_config_id bigint(20) not null comment '',
oss_config_id bigint(20) not null comment '',
tenant_id varchar(20) default '000000'comment '租户编号',
config_key varchar(20) not null default '' comment '配置key',
access_key varchar(255) default '' comment 'accessKey',

View File

@ -418,6 +418,8 @@ EXEC sp_addextendedproperty
'TABLE', N'er_job'
GO
INSERT INTO `er_job` VALUES (1, N'dev', N'ruoyi_group', N'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, N'testJobExecutor', 2, N'60', 1, 60, 3, 1, 1, 116, 0, N'', N'', getdate(), getdate(), 0);
GO
-- er_job_log_message
CREATE TABLE er_job_log_message

View File

@ -926,7 +926,8 @@ CREATE TABLE sys_dept
tenant_id nvarchar(20) DEFAULT ('000000') NULL,
parent_id bigint DEFAULT ((0)) NULL,
ancestors nvarchar(500)DEFAULT '' NULL,
dept_name nvarchar(30) DEFAULT '' NULL,
dept_name nvarchar(30) NULL,
dept_category nvarchar(100) DEFAULT '' NULL,
order_num int DEFAULT ((0)) NULL,
leader bigint NULL,
phone nvarchar(11) NULL,
@ -975,6 +976,12 @@ EXEC sys.sp_addextendedproperty
'TABLE', N'sys_dept',
'COLUMN', N'dept_name'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'部门类别编码' ,
'SCHEMA', N'dbo',
'TABLE', N'sys_dept',
'COLUMN', N'dept_category'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'显示顺序' ,
'SCHEMA', N'dbo',
@ -1047,25 +1054,25 @@ EXEC sys.sp_addextendedproperty
'TABLE', N'sys_dept'
GO
INSERT sys_dept VALUES (100, N'000000', 0, N'0', N'XXX科技', 0, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (100, N'000000', 0, N'0', N'XXX科技', NULL, 0, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (101, N'000000', 100, N'0,100', N'深圳总公司', 1, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (101, N'000000', 100, N'0,100', N'深圳总公司', NULL, 1, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (102, N'000000', 100, N'0,100', N'长沙分公司', 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (102, N'000000', 100, N'0,100', N'长沙分公司', NULL, 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (103, N'000000', 101, N'0,100,101', N'研发部门', 1, 1, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (103, N'000000', 101, N'0,100,101', N'研发部门', NULL, 1, 1, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (104, N'000000', 101, N'0,100,101', N'市场部门', 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (104, N'000000', 101, N'0,100,101', N'市场部门', NULL, 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (105, N'000000', 101, N'0,100,101', N'测试部门', 3, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (105, N'000000', 101, N'0,100,101', N'测试部门', NULL, 3, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (106, N'000000', 101, N'0,100,101', N'财务部门', 4, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (106, N'000000', 101, N'0,100,101', N'财务部门', NULL, 4, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (107, N'000000', 101, N'0,100,101', N'运维部门', 5, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (107, N'000000', 101, N'0,100,101', N'运维部门', NULL, 5, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (108, N'000000', 102, N'0,100,102', N'市场部门', 1, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (108, N'000000', 102, N'0,100,102', N'市场部门', NULL, 1, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
INSERT sys_dept VALUES (109, N'000000', 102, N'0,100,102', N'财务部门', 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
INSERT sys_dept VALUES (109, N'000000', 102, N'0,100,102', N'财务部门', NULL, 2, NULL, N'15888888888', N'xxx@qq.com', N'0', N'0', 103, 1, getdate(), NULL, NULL)
GO
CREATE TABLE sys_dict_data
@ -2135,7 +2142,9 @@ CREATE TABLE sys_post
(
post_id bigint NOT NULL,
tenant_id nvarchar(20) DEFAULT ('000000') NULL,
dept_id bigint NOT NULL,
post_code nvarchar(64) NOT NULL,
post_category nvarchar(100) NULL,
post_name nvarchar(50) NOT NULL,
post_sort int NOT NULL,
status nchar(1) NOT NULL,
@ -2164,12 +2173,24 @@ EXEC sys.sp_addextendedproperty
'TABLE', N'sys_post',
'COLUMN', N'tenant_id'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'部门id' ,
'SCHEMA', N'dbo',
'TABLE', N'sys_post',
'COLUMN', N'dept_id'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'岗位编码' ,
'SCHEMA', N'dbo',
'TABLE', N'sys_post',
'COLUMN', N'post_code'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'岗位类别编码' ,
'SCHEMA', N'dbo',
'TABLE', N'sys_post',
'COLUMN', N'post_category'
GO
EXEC sys.sp_addextendedproperty
'MS_Description', N'岗位名称' ,
'SCHEMA', N'dbo',
@ -2230,13 +2251,13 @@ EXEC sys.sp_addextendedproperty
'TABLE', N'sys_post'
GO
INSERT sys_post VALUES (1, N'000000', N'ceo', N'董事长', 1, N'0', 103, 1, getdate(), NULL, NULL, N'')
INSERT sys_post VALUES (1, N'000000', 103, N'ceo', NULL, N'董事长', 1, N'0', 103, 1, getdate(), NULL, NULL, N'')
GO
INSERT sys_post VALUES (2, N'000000', N'se', N'项目经理', 2, N'0', 103, 1, getdate(), NULL, NULL, N'')
INSERT sys_post VALUES (2, N'000000', 100, N'se', NULL, N'项目经理', 2, N'0', 103, 1, getdate(), NULL, NULL, N'')
GO
INSERT sys_post VALUES (3, N'000000', N'hr', N'人力资源', 3, N'0', 103, 1, getdate(), NULL, NULL, N'')
INSERT sys_post VALUES (3, N'000000', 100, N'hr', NULL, N'人力资源', 3, N'0', 103, 1, getdate(), NULL, NULL, N'')
GO
INSERT sys_post VALUES (4, N'000000', N'user', N'普通员工', 4, N'0', 103, 1, getdate(), NULL, NULL, N'')
INSERT sys_post VALUES (4, N'000000', 100, N'user', NULL, N'普通员工', 4, N'0', 103, 1, getdate(), NULL, NULL, N'')
GO
CREATE TABLE sys_role
@ -2967,7 +2988,7 @@ ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'',
'MS_Description', N'',
'SCHEMA', N'dbo',
'TABLE', N'sys_oss_config',
'COLUMN', N'oss_config_id'
@ -3129,7 +3150,7 @@ ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'',
'MS_Description', N'',
'SCHEMA', N'dbo',
'TABLE', N'sys_client',
'COLUMN', N'id'

View File

@ -98,7 +98,7 @@ create table sys_client (
alter table sys_client add constraint pk_sys_client primary key (id);
comment on table sys_client is '系统授权表';
comment on column sys_client.id is '';
comment on column sys_client.id is '';
comment on column sys_client.client_id is '客户端id';
comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';

View File

@ -1,5 +1,5 @@
ALTER TABLE sys_logininfor ADD (client_key VARCHAR(32) DEFAULT '');
ALTER TABLE sys_logininfor ADD (client_key varchar2(32) DEFAULT '');
COMMENT ON COLUMN sys_logininfor.client_key IS '客户端';
ALTER TABLE sys_logininfor ADD (device_type VARCHAR(32) DEFAULT '');
ALTER TABLE sys_logininfor ADD (device_type varchar2(32) DEFAULT '');
COMMENT ON COLUMN sys_logininfor.device_type IS '设备类型';

View File

@ -3,3 +3,4 @@ insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1,
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate, null, null, '');

View File

@ -0,0 +1,8 @@
ALTER TABLE sys_dept ADD (dept_category varchar2(100) DEFAULT NULL) COMMENT '部门类别编码';
COMMENT ON COLUMN sys_dept.dept_category IS '部门类别编码';
ALTER TABLE sys_post ADD (dept_id number(20) NOT NULL) COMMENT '部门id';
COMMENT ON COLUMN sys_post.dept_id IS '部门id';
ALTER TABLE sys_post ADD (post_category VARCHAR2(100) DEFAULT NULL) COMMENT '岗位类别编码';
COMMENT ON COLUMN sys_post.post_category IS '岗位类别编码';
UPDATE sys_post SET dept_id = 100;
UPDATE sys_post SET dept_id = 103 where post_id = 1;

View File

@ -97,7 +97,7 @@ create table sys_client (
);
comment on table sys_client is '系统授权表';
comment on column sys_client.id is '';
comment on column sys_client.id is '';
comment on column sys_client.client_id is '客户端id';
comment on column sys_client.client_key is '客户端key';
comment on column sys_client.client_secret is '客户端秘钥';

View File

@ -3,4 +3,3 @@ insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', '1'
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, now(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', '1', '0', 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, now(), null, null, '');

View File

@ -0,0 +1,8 @@
ALTER TABLE sys_dept ADD COLUMN dept_category varchar(100) default null::varchar;
COMMENT ON COLUMN sys_dept.dept_category IS '客户端';
ALTER TABLE sys_post ADD COLUMN dept_id int8 NOT NULL;
COMMENT ON COLUMN sys_post.dept_id IS '部门id';
ALTER TABLE sys_post ADD COLUMN post_category varchar(100) default null::varchar;
COMMENT ON COLUMN sys_post.post_category IS '岗位类别编码';
UPDATE sys_post SET dept_id = 100;
UPDATE sys_post SET dept_id = 103 where post_id = 1;

View File

@ -250,7 +250,7 @@ ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'',
'MS_Description', N'',
'SCHEMA', N'dbo',
'TABLE', N'sys_client',
'COLUMN', N'id'

View File

@ -0,0 +1,27 @@
ALTER TABLE sys_dept ADD dept_category nvarchar(100) DEFAULT NULL;
EXEC sp_addextendedproperty
'MS_Description', N'部门类别编码',
'SCHEMA', N'dbo',
'TABLE', N'sys_dept',
'COLUMN', N'dept_category';
GO
ALTER TABLE sys_post ADD dept_id bigint NOT NULL;
GO
ALTER TABLE sys_post ADD post_category nvarchar(100) DEFAULT NULL;
GO
EXEC sp_addextendedproperty
'MS_Description', N'部门id',
'SCHEMA', N'dbo',
'TABLE', N'sys_post',
'COLUMN', N'dept_id';
GO
EXEC sp_addextendedproperty
'MS_Description', N'岗位类别编码',
'SCHEMA', N'dbo',
'TABLE', N'sys_post',
'COLUMN', N'post_category';
GO
UPDATE sys_post SET dept_id = 100;
GO
UPDATE sys_post SET dept_id = 103 where post_id = 1;
GO

View File

@ -3,4 +3,3 @@ insert into sys_menu values('1620', '配置列表', '118', '5', '#', '', '', 1,
insert into sys_menu values('1621', '配置添加', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1622', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values('1623', '配置删除', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, sysdate(), null, null, '');

View File

@ -0,0 +1,4 @@
ALTER TABLE sys_dept ADD dept_category VARCHAR(100) DEFAULT NULL COMMENT '部门类别编码';
ALTER TABLE sys_post ADD dept_id BIGINT(20) NOT NULL COMMENT '部门id', ADD post_category VARCHAR(100) DEFAULT NULL COMMENT '岗位类别编码';
UPDATE sys_post SET dept_id = 100;
UPDATE sys_post SET dept_id = 103 where post_id = 1;