From 5125dc5af2b570dec5b6c624da25d778f85bbaf8 Mon Sep 17 00:00:00 2001 From: zhongmx Date: Fri, 2 Jun 2023 17:50:20 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90ADD=E3=80=91=E9=9B=86=E6=88=90?= =?UTF-8?q?=E5=8E=9F=E7=94=9FFlowable-ui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-extend/pom.xml | 1 + ruoyi-extend/ruoyi-flow-ui/.gitignore | 33 ++++ ruoyi-extend/ruoyi-flow-ui/Dockerfile | 16 ++ ruoyi-extend/ruoyi-flow-ui/HELP.md | 10 ++ ruoyi-extend/ruoyi-flow-ui/pom.xml | 137 +++++++++++++++ .../dromara/flow/ui/FlowUiApplication.java | 17 ++ .../flow/ui/config/FlowableIdmConfig.java | 83 +++++++++ .../ui/config/idm/CustomGroupDataManager.java | 165 ++++++++++++++++++ .../ui/config/idm/CustomPasswordEncoder.java | 50 ++++++ .../ui/config/idm/CustomUserDataManager.java | 154 ++++++++++++++++ .../flow/ui/domain/bo/GroupCodeBo.java | 120 +++++++++++++ .../flow/ui/domain/bo/GroupNameBo.java | 121 +++++++++++++ .../flow/ui/domain/bo/GroupQueryBo.java | 38 ++++ .../flow/ui/domain/bo/UserQueryBo.java | 55 ++++++ .../flow/ui/mapper/CustomMybatisMapper.java | 36 ++++ .../src/main/resources/application-dev.yml | 38 ++++ .../src/main/resources/application-prod.yml | 38 ++++ .../src/main/resources/application.yml | 38 ++++ .../src/main/resources/logback-plus.xml | 34 ++++ .../mappers/CustomMybatisXmlMapper.xml | 71 ++++++++ .../flow/ui/RuoyiFlowUiApplicationTests.java | 13 ++ 21 files changed, 1268 insertions(+) create mode 100644 ruoyi-extend/ruoyi-flow-ui/.gitignore create mode 100644 ruoyi-extend/ruoyi-flow-ui/Dockerfile create mode 100644 ruoyi-extend/ruoyi-flow-ui/HELP.md create mode 100644 ruoyi-extend/ruoyi-flow-ui/pom.xml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/FlowUiApplication.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/FlowableIdmConfig.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomGroupDataManager.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomPasswordEncoder.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomUserDataManager.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupCodeBo.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupNameBo.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupQueryBo.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/UserQueryBo.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/mapper/CustomMybatisMapper.java create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-dev.yml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-prod.yml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/resources/application.yml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/resources/logback-plus.xml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/main/resources/mappers/CustomMybatisXmlMapper.xml create mode 100644 ruoyi-extend/ruoyi-flow-ui/src/test/java/org/dromara/flow/ui/RuoyiFlowUiApplicationTests.java diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml index ee176e998..d6966e120 100644 --- a/ruoyi-extend/pom.xml +++ b/ruoyi-extend/pom.xml @@ -14,6 +14,7 @@ ruoyi-monitor-admin ruoyi-xxl-job-admin + ruoyi-flow-ui diff --git a/ruoyi-extend/ruoyi-flow-ui/.gitignore b/ruoyi-extend/ruoyi-flow-ui/.gitignore new file mode 100644 index 000000000..549e00a2a --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/ruoyi-extend/ruoyi-flow-ui/Dockerfile b/ruoyi-extend/ruoyi-flow-ui/Dockerfile new file mode 100644 index 000000000..448cda7e6 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/Dockerfile @@ -0,0 +1,16 @@ +FROM anapsix/alpine-java:8_server-jre_unlimited + +MAINTAINER zmx + +RUN mkdir -p /ruoyi/flow/ui/logs + +WORKDIR /ruoyi/flow/ui + +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +EXPOSE 9205 + +ADD ./target/ruoyi-flow-ui.jar ./app.jar + +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] diff --git a/ruoyi-extend/ruoyi-flow-ui/HELP.md b/ruoyi-extend/ruoyi-flow-ui/HELP.md new file mode 100644 index 000000000..5265b3d40 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/HELP.md @@ -0,0 +1,10 @@ +# Getting Started + +### Reference Documentation + +For further reference, please consider the following sections: + +* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) +* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.0/maven-plugin/reference/html/) +* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.0/maven-plugin/reference/html/#build-image) + diff --git a/ruoyi-extend/ruoyi-flow-ui/pom.xml b/ruoyi-extend/ruoyi-flow-ui/pom.xml new file mode 100644 index 000000000..1592a2bc6 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + ruoyi-extend + org.dromara + ${revision} + + ruoyi-flow-ui + ruoyi-flow-ui + ruoyi-flow-ui + + 2.7.12 + 2.7.10 + 2.2.2 + 6.8.0 + + + + + + org.springframework.boot + spring-boot-starter-parent + ${spring-boot.version} + pom + import + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + + + com.mysql + mysql-connector-j + + + + org.flowable + flowable-spring-boot-starter + ${flowable.version} + + + + org.flowable + flowable-spring-boot-starter-ui-idm + ${flowable.version} + + + + org.flowable + flowable-spring-boot-starter-ui-modeler + ${flowable.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + commons-collections + commons-collections + 3.2.2 + + + + + org.flowable + flowable-spring-boot-starter-ui-task + ${flowable.version} + + + + org.flowable + flowable-spring-boot-starter-ui-admin + ${flowable.version} + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + de.codecentric + spring-boot-admin-starter-client + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.projectlombok + lombok + + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + + + diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/FlowUiApplication.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/FlowUiApplication.java new file mode 100644 index 000000000..043ca78fc --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/FlowUiApplication.java @@ -0,0 +1,17 @@ +package com.dromara.flow.ui; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * flowable-ui启动类 + * Author: 土豆仙 + */ +@SpringBootApplication +public class FlowUiApplication { + + public static void main(String[] args) { + SpringApplication.run(com.dromara.flow.ui.FlowUiApplication.class, args); + } + +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/FlowableIdmConfig.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/FlowableIdmConfig.java new file mode 100644 index 000000000..a05178b7d --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/FlowableIdmConfig.java @@ -0,0 +1,83 @@ +package com.dromara.flow.ui.config; + + +import com.dromara.flow.ui.config.idm.CustomGroupDataManager; +import com.dromara.flow.ui.config.idm.CustomPasswordEncoder; +import com.dromara.flow.ui.config.idm.CustomUserDataManager; +import org.flowable.idm.engine.impl.persistence.entity.GroupEntityManager; +import org.flowable.idm.engine.impl.persistence.entity.GroupEntityManagerImpl; +import org.flowable.idm.engine.impl.persistence.entity.UserEntityManager; +import org.flowable.idm.engine.impl.persistence.entity.UserEntityManagerImpl; +import org.flowable.idm.spring.SpringIdmEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.flowable.spring.boot.idm.FlowableIdmProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * @Author: 土豆仙 + * @Date: 2021/9/28 19:30 + * @Description: 一旦使用视图效率不高,在这注入覆写类 + */ +@Configuration +public class FlowableIdmConfig implements EngineConfigurationConfigurer { + + @Autowired + private CustomUserDataManager customUserDataManager; + + @Autowired + private CustomGroupDataManager customGroupDataManager; + + @Override + public void configure(SpringIdmEngineConfiguration configuration) { + + //密码加密器和自建用户体系保持一致 + CustomPasswordEncoder bc = new CustomPasswordEncoder(); + configuration.setPasswordEncoder(bc); + + //用户 + configuration.setUserDataManager(customUserDataManager); + UserEntityManager userEntityManager = configuration.getUserEntityManager(); + if (userEntityManager != null) { + UserEntityManagerImpl userEntityManagerImpl = new UserEntityManagerImpl(configuration, customUserDataManager); + configuration.setUserEntityManager(userEntityManagerImpl); + } + + //用户-组关系 + /*configuration.setMembershipDataManager(customMembershipDataManager); + configuration.setMembershipEntityManager(customMembershipEntityManager);*/ + + + //组 + configuration.setGroupDataManager(customGroupDataManager); + GroupEntityManager groupEntityManager = configuration.getGroupEntityManager(); + if (groupEntityManager == null) { + GroupEntityManagerImpl groupEntityManagerImpl = new GroupEntityManagerImpl(configuration, customGroupDataManager); + configuration.setGroupEntityManager(groupEntityManagerImpl); + } + + + } + + + @Bean + public PasswordEncoder passwordEncoder(FlowableIdmProperties idmProperties) { + + PasswordEncoder encoder = new CustomPasswordEncoder(); + + return encoder; + } + + /* @Bean + public CustomGroupEntityManager customGroupEntityManager(IdmEngineConfiguration configuration) { + return new CustomGroupEntityManager(configuration, configuration.getGroupDataManager()); + }*/ + + + /* @Bean + public CustomUserEntityManager customUserEntityManager(IdmEngineConfiguration configuration) { + return new CustomUserEntityManager(configuration, new CustomUserDataManager(configuration)); + }*/ +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomGroupDataManager.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomGroupDataManager.java new file mode 100644 index 000000000..bff43b28d --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomGroupDataManager.java @@ -0,0 +1,165 @@ +package com.dromara.flow.ui.config.idm; + + +import com.dromara.flow.ui.domain.bo.GroupCodeBo; +import com.dromara.flow.ui.domain.bo.GroupNameBo; +import com.dromara.flow.ui.domain.bo.GroupQueryBo; +import com.dromara.flow.ui.mapper.CustomMybatisMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.ManagementService; +import org.flowable.engine.impl.cmd.AbstractCustomSqlExecution; +import org.flowable.idm.api.Group; +import org.flowable.idm.engine.IdmEngineConfiguration; +import org.flowable.idm.engine.impl.GroupQueryImpl; +import org.flowable.idm.engine.impl.persistence.entity.GroupEntity; +import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl; +import org.flowable.idm.engine.impl.persistence.entity.data.AbstractIdmDataManager; +import org.flowable.idm.engine.impl.persistence.entity.data.GroupDataManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + * @Author: 土豆仙 + * @Date: 2021/11/12 10:05 + * @Description: 覆写组查询 + */ +@Slf4j +@Component +public class CustomGroupDataManager extends AbstractIdmDataManager implements GroupDataManager { + + + public CustomGroupDataManager(IdmEngineConfiguration idmEngineConfiguration) { + super(idmEngineConfiguration); + } + + @Autowired + @Lazy + private ManagementService managementService; + + @Override + public Class getManagedEntityClass() { + return GroupEntityImpl.class; + } + + @Override + public GroupEntity create() { + return new GroupEntityImpl(); + } + + @SuppressWarnings("unchecked") + @Override + public List findGroupByQueryCriteria(GroupQueryImpl query) { + if (log.isDebugEnabled()) { + log.debug("已重写自定义组查询:findGroupByQueryCriteria"); + } + boolean isReturnList = true; + GroupQueryBo groupQueryBo = transformQueryParamToGroupDTO(query); + if (StringUtils.isNotBlank(query.getId())) { + groupQueryBo.setReturnList(false); + isReturnList = false; + } + + List groups = managementService.executeCustomSql(new AbstractCustomSqlExecution>(CustomMybatisMapper.class) { + @Override + public List execute(CustomMybatisMapper customMybatisMapper) { + return customMybatisMapper.findGroupList(groupQueryBo); + } + }); + + return groups; + //return getDbSqlSession().selectList("selectGroupByQueryCriteria", query, getManagedEntityClass()); + } + + private GroupQueryBo transformQueryParamToGroupDTO(GroupQueryImpl query) { + GroupQueryBo groupQueryBo = new GroupQueryBo(); + //约定 groupId 解析为 部门code.角色code + List groupIds = new ArrayList<>(); + if (StringUtils.isNotEmpty(query.getId())) { + groupIds.add(query.getId()); + } + if (CollectionUtils.isNotEmpty(query.getIds())) { + groupIds.addAll(query.getIds()); + } + List groupBoList = groupIds.stream() + .map(GroupCodeBo::new) + .collect(Collectors.toList()); + + groupQueryBo.setGroupCodeBos(groupBoList); + + //约定 groupName 解析为 区域name/部门name/角色name + groupQueryBo.setGroupNameBo(new GroupNameBo(query.getName())); + + + //userId + List userNames = new ArrayList<>(); + if (StringUtils.isNotEmpty(query.getUserId())) { + userNames.add(query.getUserId()); + } + + if (CollectionUtils.isNotEmpty(query.getIds())) { + userNames.addAll(query.getIds()); + } + + groupQueryBo.setUserNames(userNames); + + return groupQueryBo; + } + + @Override + public long findGroupCountByQueryCriteria(GroupQueryImpl query) { + if (log.isDebugEnabled()) { + log.debug("已重写自定义组查询:findGroupCountByQueryCriteria"); + } + //return (Long) getDbSqlSession().selectOne("selectGroupCountByQueryCriteria", query); + List groupByQueryCriteria = findGroupByQueryCriteria(query); + return groupByQueryCriteria.size(); + } + + @SuppressWarnings("unchecked") + @Override + public List findGroupsByUser(String userId) { + if (log.isDebugEnabled()) { + log.debug("已重写自定义组查询:findGroupsByUser"); + } + GroupQueryImpl groupQuery = new GroupQueryImpl(); + groupQuery.groupMember(userId); + List groupByQueryCriteria = findGroupByQueryCriteria(groupQuery); + return groupByQueryCriteria; + //return getDbSqlSession().selectList("selectGroupsByUserId", userId); + } + + @Override + @SuppressWarnings("unchecked") + public List findGroupsByPrivilegeId(String privilegeId) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findGroupsByPrivilegeId"); + } + return getDbSqlSession().selectList("selectGroupsWithPrivilegeId", privilegeId); + } + + @SuppressWarnings("unchecked") + @Override + public List findGroupsByNativeQuery(Map parameterMap) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findGroupsByNativeQuery"); + } + return getDbSqlSession().selectListWithRawParameter("selectGroupByNativeQuery", parameterMap); + } + + @Override + public long findGroupCountByNativeQuery(Map parameterMap) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findGroupCountByNativeQuery"); + } + return (Long) getDbSqlSession().selectOne("selectGroupCountByNativeQuery", parameterMap); + } +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomPasswordEncoder.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomPasswordEncoder.java new file mode 100644 index 000000000..477ee8058 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomPasswordEncoder.java @@ -0,0 +1,50 @@ +package com.dromara.flow.ui.config.idm; + +import org.flowable.idm.api.PasswordEncoder; +import org.flowable.idm.api.PasswordSalt; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** +* @Author: 土豆仙 +* @Date: 2021/11/12 10:04 +* @Description: 密码加密器 +*/ +public class CustomPasswordEncoder implements PasswordEncoder,org.springframework.security.crypto.password.PasswordEncoder { + @Override + public String encode(CharSequence rawPassword, PasswordSalt passwordSalt) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(rawPassword); + } + + /** + * 判断密码是否相同 + * + * @param rawPassword 真实密码 + * @param encodedPassword 加密后字符 + * @return 结果 + */ + @Override + public boolean isMatches(CharSequence rawPassword, String encodedPassword, PasswordSalt salt) { + /* BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();*/ + return true; + } + + + @Override + public String encode(CharSequence rawPassword) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(rawPassword); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + /*BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();*/ + return true; + } + + @Override + public boolean upgradeEncoding(String encodedPassword) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.upgradeEncoding(encodedPassword); + } +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomUserDataManager.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomUserDataManager.java new file mode 100644 index 000000000..3d9d3126e --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/config/idm/CustomUserDataManager.java @@ -0,0 +1,154 @@ +package com.dromara.flow.ui.config.idm; + + +import com.dromara.flow.ui.domain.bo.GroupCodeBo; +import com.dromara.flow.ui.domain.bo.UserQueryBo; +import com.dromara.flow.ui.mapper.CustomMybatisMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.ManagementService; +import org.flowable.engine.impl.cmd.AbstractCustomSqlExecution; +import org.flowable.idm.api.User; +import org.flowable.idm.engine.IdmEngineConfiguration; +import org.flowable.idm.engine.impl.UserQueryImpl; +import org.flowable.idm.engine.impl.persistence.entity.UserEntity; +import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl; +import org.flowable.idm.engine.impl.persistence.entity.data.AbstractIdmDataManager; +import org.flowable.idm.engine.impl.persistence.entity.data.UserDataManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + * @Author: 土豆仙 + * @Date: 2021/11/12 10:07 + * @Description: 覆写用户信息查询 + */ +@Slf4j +@Component +public class CustomUserDataManager extends AbstractIdmDataManager implements UserDataManager { + public CustomUserDataManager(IdmEngineConfiguration idmEngineConfiguration) { + super(idmEngineConfiguration); + } + + @Autowired + @Lazy + private ManagementService managementService; + + @Override + public Class getManagedEntityClass() { + return UserEntityImpl.class; + } + + @Override + public UserEntity create() { + return new UserEntityImpl(); + } + + /** + * + * @param query 流程引擎查询参数 + * @return 流程引擎展示视图 + */ + @SuppressWarnings("unchecked") + @Override + public List findUserByQueryCriteria(UserQueryImpl query) { + if (log.isDebugEnabled()) { + log.debug("已重写自定义组查询:findUserByQueryCriteria"); + } + UserQueryBo userQueryBo = transformQueryImplToUserQueryBo(query); + + List users = managementService.executeCustomSql(new AbstractCustomSqlExecution>(CustomMybatisMapper.class) { + @Override + public List execute(CustomMybatisMapper customMybatisMapper) { + return customMybatisMapper.selectUserList(userQueryBo); + } + }); + + return users; + } + + private UserQueryBo transformQueryImplToUserQueryBo(UserQueryImpl query) { + UserQueryBo userQueryBo = new UserQueryBo(); + + //设置userName + if (StringUtils.isNotBlank(query.getId())) { + userQueryBo.setUserName(query.getId()); + } else { + userQueryBo.setUserName(query.getIdIgnoreCase()); + } + + userQueryBo.setUserNames(query.getIds()); + + //设置nickName + if (StringUtils.isNotBlank(query.getFirstName()) || StringUtils.isNotBlank(query.getLastName())) { + String nickName = StringUtils.join(query.getFirstName(), query.getLastName()); + userQueryBo.setNickName(nickName); + } else { + userQueryBo.setNickName(query.getDisplayName()); + } + + //设置email + userQueryBo.setEmail(query.getEmail()); + userQueryBo.setEmailLike(query.getEmailLike()); + + + //处理组映射 + List groupBoList = new ArrayList<>(); + if (StringUtils.isNotEmpty(query.getGroupId())) { + groupBoList.add(new GroupCodeBo(query.getGroupId())); + } + if (!CollectionUtils.isEmpty(query.getGroupIds())) { + + List collect = query.getGroupIds().stream() + .map(GroupCodeBo::new) + .collect(Collectors.toList()); + + groupBoList.addAll(collect); + } + userQueryBo.setGroupBoList(groupBoList); + return userQueryBo; + } + + @Override + public long findUserCountByQueryCriteria(UserQueryImpl query) { + if (log.isDebugEnabled()) { + log.debug("已重写自定义组查询:findUserCountByQueryCriteria"); + } + // return (Long) getDbSqlSession().selectOne("selectUserCountByQueryCriteria", query); + return findUserByQueryCriteria(query).size(); + } + + @Override + @SuppressWarnings("unchecked") + public List findUsersByPrivilegeId(String privilegeId) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findUsersByPrivilegeId"); + } + return getDbSqlSession().selectList("selectUsersWithPrivilegeId", privilegeId); + } + + @SuppressWarnings("unchecked") + @Override + public List findUsersByNativeQuery(Map parameterMap) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findUsersByNativeQuery"); + } + return getDbSqlSession().selectListWithRawParameter("selectUserByNativeQuery", parameterMap); + } + + @Override + public long findUserCountByNativeQuery(Map parameterMap) { + if (log.isDebugEnabled()) { + log.debug("未重写自定义组查询:findUserCountByNativeQuery"); + } + return (Long) getDbSqlSession().selectOne("selectUserCountByNativeQuery", parameterMap); + } +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupCodeBo.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupCodeBo.java new file mode 100644 index 000000000..96fbaa3ca --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupCodeBo.java @@ -0,0 +1,120 @@ +package com.dromara.flow.ui.domain.bo; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import liquibase.repackaged.org.apache.commons.text.StringSubstitutor; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 业务组与流程组转换 + * Author: 土豆仙 + */ +@NoArgsConstructor +public class GroupCodeBo { + + /** + * 默认占位符号 代表所有 + */ + private static final String STAR = "*"; + + /** + * 分割符号 + */ + private static final String DOT = "."; + + /** + * 占位字符串定义 - 后期放入配置中,用于扩展 + */ + private static final String PLACEHOLDER_STRING = "${deptCode}.${roleCode}"; + + /** + * 取 定义中 ${}内的内容 + */ + private static final String pattern = "\\$\\{(.*?)}"; + + /** + * deptCode:* 、roleCode:* ... + */ + private Map codeMap = new HashMap<>(); + + /** + * deptCode:* 、roleCode:* ... + */ + private static final Map codeMapInit = new HashMap<>(); + + /** + * deptCode、roleCode ... + */ + private static final List codeList = new ArrayList<>(); + + //初始化 + static { + Pattern p = Pattern.compile(pattern); + Matcher m = p.matcher(PLACEHOLDER_STRING); + while (m.find()) { + // ${}和 里面的内容 + String code = m.group(1); + codeList.add(code); + codeMapInit.put(code, STAR); + } + } + + + public GroupCodeBo(String gourpCode) { + transferToBusiness(gourpCode); + } + + + /** + * @param gourpCode 流程引擎编码转换(约定) + */ + public void transferToBusiness(String gourpCode) { + + List split = StrUtil.split(gourpCode, DOT); + if (CollectionUtil.isNotEmpty(split) && split.size() == codeList.size()) { + + //遍历 + for (int i = 0; i < codeList.size(); i++) { + codeMap.put(codeList.get(i), split.get(i)); + } + } + } + + + /** + * @return 组编码 + */ + public String getGourpCode() { + + if (MapUtil.isEmpty(codeMap)) { + codeMap.putAll(codeMapInit); + } + StringSubstitutor strSubstitutor = new StringSubstitutor(codeMap); + + + return strSubstitutor.replace(PLACEHOLDER_STRING); + } + + + /** + * @return 编码-值 键值对 + */ + public Map getCodeMap() { + + if (MapUtil.isEmpty(codeMap)) { + codeMap.putAll(codeMapInit); + } + + return codeMap; + + } + +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupNameBo.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupNameBo.java new file mode 100644 index 000000000..42b6c6bf0 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupNameBo.java @@ -0,0 +1,121 @@ +package com.dromara.flow.ui.domain.bo; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import liquibase.repackaged.org.apache.commons.text.StringSubstitutor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 业务组名与流程组转换 + * Author: 土豆仙 + */ +@Data +@NoArgsConstructor +public class GroupNameBo { + + /** + * 默认占位符号 代表所有 + */ + private static final String STAR = "*"; + + /** + * 分割符号 + */ + private static final String DOT = "."; + + /** + * 占位字符串定义 - 后期放入配置中,用于扩展 + */ + private static final String PLACEHOLDER_STRING = "${deptName}.${roleName}"; + + /** + * 取 定义中 ${}内的内容 + */ + private static final String pattern = "\\$\\{(.*?)}"; + + /** + * deptName:* 、roleName:* ... + */ + private static final Map nameMapInit = new HashMap<>(); + + /** + * deptName:* 、roleName:* ... + */ + private Map nameMap = new HashMap<>(); + + /** + * deptName、roleName ... + */ + private static final List nameList = new ArrayList<>(); + + //初始化 + static { + Pattern p = Pattern.compile(pattern); + Matcher m = p.matcher(PLACEHOLDER_STRING); + while (m.find()) { + // ${}和 里面的内容 + String Name = m.group(1); + nameList.add(Name); + nameMapInit.put(Name, STAR); + } + } + + + public GroupNameBo(String gourpName) { + transferToBusiness(gourpName); + } + + + /** + * @param gourpName 流程引擎编码转换(约定) + */ + public void transferToBusiness(String gourpName) { + + List split = StrUtil.split(gourpName, DOT); + if (CollectionUtil.isNotEmpty(split) && split.size() <= nameList.size()) { + + //遍历 + for (int i = 0; i < split.size(); i++) { + nameMap.put(nameList.get(i), split.get(i)); + } + } + } + + /** + * @return 组名 + */ + public String getGourpname() { + + if (MapUtil.isEmpty(nameMap)) { + nameMap.putAll(nameMapInit); + } + StringSubstitutor strSubstitutor = new StringSubstitutor(nameMap); + + + return strSubstitutor.replace(PLACEHOLDER_STRING); + } + + + /** + * @return 名称编码-值 键值对 + */ + public Map getnameMap() { + + if (MapUtil.isEmpty(nameMap)) { + nameMap.putAll(nameMapInit); + } + + return nameMap; + + } + +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupQueryBo.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupQueryBo.java new file mode 100644 index 000000000..fb4d0ded0 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/GroupQueryBo.java @@ -0,0 +1,38 @@ +package com.dromara.flow.ui.domain.bo; + +import lombok.Data; + +import java.util.List; + +/** + * 自定义group查询条件 + * Author: 土豆仙 + */ +@Data +public class GroupQueryBo { + + + //约定 解析为 区域code/部门code/角色code + /* protected String id; + protected List ids;*/ + + private boolean isReturnList = true; + + // private DdrCodeDTO ddrCodeDTO; + + private List groupCodeBos; + + //约定 解析为 区域name/部门name/角色name + /* protected String name; + protected String nameLike; + protected String nameLikeIgnoreCase;*/ + + private GroupNameBo groupNameBo; + + /* + protected String type; + protected String userId; + protected List userIds;*/ + + protected List userNames; +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/UserQueryBo.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/UserQueryBo.java new file mode 100644 index 000000000..946263b83 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/domain/bo/UserQueryBo.java @@ -0,0 +1,55 @@ +package com.dromara.flow.ui.domain.bo; + +import lombok.Data; + +import java.util.List; + +/** + * 自定义user查询条件 + * Author: 土豆仙 + */ +@Data +public class UserQueryBo { + + //用户ID -对应账号 + /* protected String id; + protected List ids; + protected String idIgnoreCase;*/ + + private String userName; + + private List userNames; + + //用户名称 + /*protected String firstName; + protected String firstNameLike; + protected String firstNameLikeIgnoreCase; + protected String lastName; + protected String lastNameLike; + protected String lastNameLikeIgnoreCase; + protected String fullNameLike; + protected String fullNameLikeIgnoreCase; + protected String displayName; + protected String displayNameLike; + protected String displayNameLikeIgnoreCase;*/ + + private String nickName; + + //邮箱 + /*protected String email; + protected String emailLike;*/ + + private String email; + + private String emailLike; + + //用户组 + /*protected String groupId; + protected List groupIds;*/ + + //约定:用户组转换成 区化、部门、角色 最后使用稳定的code值 + private List groupBoList; + + //租户 + protected String tenantId; +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/mapper/CustomMybatisMapper.java b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/mapper/CustomMybatisMapper.java new file mode 100644 index 000000000..ea98b67e9 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/java/com/dromara/flow/ui/mapper/CustomMybatisMapper.java @@ -0,0 +1,36 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.dromara.flow.ui.mapper; + +import com.dromara.flow.ui.domain.bo.GroupQueryBo; +import com.dromara.flow.ui.domain.bo.UserQueryBo; +import org.flowable.idm.api.Group; +import org.flowable.idm.api.User; + +import java.util.List; + +/** + * 自定义mapperSQl + * Author: 土豆仙 + */ +public interface CustomMybatisMapper { + + + List selectUserList(UserQueryBo userQueryBo); + + /** + * @param groupQueryBo + * @return (id name) + */ + List findGroupList(GroupQueryBo groupQueryBo); +} diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-dev.yml new file mode 100644 index 000000000..431e8a8cc --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-dev.yml @@ -0,0 +1,38 @@ +--- # 监控配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + # 设置 Spring Boot Admin Server 地址 + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 +# Spring配置 +spring: + application: + name: flow-ui + main: + allow-bean-definition-overriding: true + liquibase: + enabled: false +# jackson: +# date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + # 资源信息 + messages: + # 国际化资源文件路径 + basename: i18n/messages + datasource: + url: jdbc:mysql://localhost:3306/ry-vue?zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true + username: root + password: 123456 +flowable: + databaseSchemaUpdate: true +# databaseSchema: + +# 日志配置 +logging: + level: + org.flowable.engine.impl.persistence.entity.*: DEBUG + org.flowable.task.service.impl.persistence.entity.*: DEBUG # 日志配置 diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-prod.yml new file mode 100644 index 000000000..431e8a8cc --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application-prod.yml @@ -0,0 +1,38 @@ +--- # 监控配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + # 设置 Spring Boot Admin Server 地址 + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 +# Spring配置 +spring: + application: + name: flow-ui + main: + allow-bean-definition-overriding: true + liquibase: + enabled: false +# jackson: +# date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + # 资源信息 + messages: + # 国际化资源文件路径 + basename: i18n/messages + datasource: + url: jdbc:mysql://localhost:3306/ry-vue?zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true + username: root + password: 123456 +flowable: + databaseSchemaUpdate: true +# databaseSchema: + +# 日志配置 +logging: + level: + org.flowable.engine.impl.persistence.entity.*: DEBUG + org.flowable.task.service.impl.persistence.entity.*: DEBUG # 日志配置 diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application.yml b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application.yml new file mode 100644 index 000000000..f86deaa7f --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/application.yml @@ -0,0 +1,38 @@ +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 9205 + servlet: + # 应用的访问路径 + context-path: /flowable-ui + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # tomcat最大线程数,默认为200 + #max-threads: 800 + # Tomcat启动初始化的线程数,默认值25 + #min-spare-threads: 30 +flowable: + customMybatisXMLMappers: + - mappers/CustomMybatisXmlMapper.xml + customMybatisMappers: + - com.dromara.flow.ui.mapper.CustomMybatisMapper +--- # Actuator 监控端点的配置项 +management: + health: + ldap: + enabled: false + mail: + enabled: false + endpoints: + web: + exposure: + include: '*' + endpoint: + health: + show-details: ALWAYS + logfile: + external-file: ./logs/ruoyi-flow-ui.log +spring: + profiles: + active: @profiles.active@ diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/resources/logback-plus.xml b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/logback-plus.xml new file mode 100644 index 000000000..589626fd1 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/logback-plus.xml @@ -0,0 +1,34 @@ + + + + logback + + + + + + + ${console.log.pattern} + utf-8 + + + + + ${log.path}.log + + ${log.path}.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + + + + + + diff --git a/ruoyi-extend/ruoyi-flow-ui/src/main/resources/mappers/CustomMybatisXmlMapper.xml b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/mappers/CustomMybatisXmlMapper.xml new file mode 100644 index 000000000..088545413 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/main/resources/mappers/CustomMybatisXmlMapper.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + diff --git a/ruoyi-extend/ruoyi-flow-ui/src/test/java/org/dromara/flow/ui/RuoyiFlowUiApplicationTests.java b/ruoyi-extend/ruoyi-flow-ui/src/test/java/org/dromara/flow/ui/RuoyiFlowUiApplicationTests.java new file mode 100644 index 000000000..cd4c0bcb7 --- /dev/null +++ b/ruoyi-extend/ruoyi-flow-ui/src/test/java/org/dromara/flow/ui/RuoyiFlowUiApplicationTests.java @@ -0,0 +1,13 @@ +package org.dromara.flow.ui; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RuoyiFlowUiApplicationTests { + + @Test + void contextLoads() { + } + +}