!551 ♥️发布 5.2.0 正式版本
Merge pull request !551 from 疯狂的狮子Li/dev
| | |
| | | [](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) |
| | | <br> |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | []() |
| | | []() |
| | | []() |
| | | []() |
| | | |
| | |
| | | <description>RuoYi-Vue-Plus多租户管理系统</description> |
| | | |
| | | <properties> |
| | | <revision>5.2.0-BETA2</revision> |
| | | <revision>5.2.0</revision> |
| | | <spring-boot.version>3.2.6</spring-boot.version> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | |
| | | <easyexcel.version>3.3.4</easyexcel.version> |
| | | <velocity.version>2.3</velocity.version> |
| | | <satoken.version>1.38.0</satoken.version> |
| | | <mybatis-plus.version>3.5.6</mybatis-plus.version> |
| | | <mybatis-plus.version>3.5.7</mybatis-plus.version> |
| | | <p6spy.version>3.9.1</p6spy.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.29.0</redisson.version> |
| | | <redisson.version>3.31.0</redisson.version> |
| | | <lock4j.version>2.2.7</lock4j.version> |
| | | <dynamic-ds.version>4.3.0</dynamic-ds.version> |
| | | <dynamic-ds.version>4.3.1</dynamic-ds.version> |
| | | <alibaba-ttl.version>2.14.4</alibaba-ttl.version> |
| | | <snailjob.version>1.0.0-beta3</snailjob.version> |
| | | <snailjob.version>1.0.1</snailjob.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.32</lombok.version> |
| | |
| | | package org.dromara.web.controller; |
| | | |
| | | import cn.dev33.satoken.annotation.SaIgnore; |
| | | import cn.hutool.core.codec.Base64; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.net.URL; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | |
| | | * @return 结果 |
| | | */ |
| | | @GetMapping("/binding/{source}") |
| | | public R<String> authBinding(@PathVariable("source") String source) { |
| | | public R<String> authBinding(@PathVariable("source") String source, |
| | | @RequestParam String tenantId, @RequestParam String domain) { |
| | | SocialLoginConfigProperties obj = socialProperties.getType().get(source); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return R.fail(source + "平台账号暂不支持"); |
| | | } |
| | | AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); |
| | | String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("tenantId", tenantId); |
| | | map.put("domain", domain); |
| | | map.put("state", AuthStateUtils.createState()); |
| | | String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8)); |
| | | return R.ok("操作成功", authorizeUrl); |
| | | } |
| | | |
| | |
| | | port: 1788 |
| | | # 详见 script/sql/snail_job.sql `sj_namespace` 表 |
| | | namespace: ${spring.profiles.active} |
| | | # 随主应用端口飘逸 |
| | | port: 2${server.port} |
| | | |
| | | --- # 数据源配置 |
| | | spring: |
| | |
| | | port: 1788 |
| | | # 详见 script/sql/snail_job.sql `sj_namespace` 表 |
| | | namespace: ${spring.profiles.active} |
| | | # 随主应用端口飘逸 |
| | | port: 2${server.port} |
| | | |
| | | --- # 数据源配置 |
| | | spring: |
| | |
| | | </description> |
| | | |
| | | <properties> |
| | | <revision>5.2.0-BETA2</revision> |
| | | <revision>5.2.0</revision> |
| | | </properties> |
| | | |
| | | <dependencyManagement> |
| | |
| | | * @author Lion Li |
| | | */ |
| | | @AutoConfiguration |
| | | // 表示通过aop框架暴露该代理对象,AopContext能够访问 |
| | | @EnableAspectJAutoProxy(exposeProxy = true) |
| | | @EnableAspectJAutoProxy |
| | | @EnableAsync(proxyTargetClass = true) |
| | | public class ApplicationConfig { |
| | | |
| | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 流程定义key与流程节点标识(拼接方式:流程定义key_流程节点) |
| | | * 流程定义key |
| | | */ |
| | | private String keyNode; |
| | | private String key; |
| | | |
| | | /** |
| | | * 审批节点key |
| | | */ |
| | | private String taskDefinitionKey; |
| | | |
| | | /** |
| | | * 任务id |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.extra.spring.SpringUtil; |
| | | import org.springframework.aop.framework.AopContext; |
| | | import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
| | | import org.springframework.boot.autoconfigure.thread.Threading; |
| | | import org.springframework.context.ApplicationContext; |
| | |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <T> T getAopProxy(T invoker) { |
| | | return (T) AopContext.currentProxy(); |
| | | return (T) getBean(invoker.getClass()); |
| | | } |
| | | |
| | | |
| | |
| | | * 处理请求前执行 |
| | | */ |
| | | @Before(value = "@annotation(controllerLog)") |
| | | public void boBefore(JoinPoint joinPoint, Log controllerLog) { |
| | | public void doBefore(JoinPoint joinPoint, Log controllerLog) { |
| | | StopWatch stopWatch = new StopWatch(); |
| | | KEY_CACHE.set(stopWatch); |
| | | stopWatch.start(); |
| | |
| | | * 批量插入 |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList) { |
| | | return Db.saveBatch(entityList); |
| | | Db.saveBatch(entityList); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 批量更新 |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList) { |
| | | return Db.updateBatchById(entityList); |
| | | Db.updateBatchById(entityList); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 批量插入或更新 |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList) { |
| | | return Db.saveOrUpdateBatch(entityList); |
| | | Db.saveOrUpdateBatch(entityList); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 批量插入(包含限制条数) |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveBatch(entityList, batchSize); |
| | | Db.saveBatch(entityList, batchSize); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 批量更新(包含限制条数) |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList, int batchSize) { |
| | | return Db.updateBatchById(entityList, batchSize); |
| | | Db.updateBatchById(entityList, batchSize); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 批量插入或更新(包含限制条数) |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveOrUpdateBatch(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * 插入或更新(包含限制条数) |
| | | */ |
| | | default boolean insertOrUpdate(T entity) { |
| | | return Db.saveOrUpdate(entity); |
| | | Db.saveOrUpdateBatch(entityList, batchSize); |
| | | // 临时解决 新版本 mp 插入状态判断错误问题 |
| | | return true; |
| | | } |
| | | |
| | | default V selectVoById(Serializable id) { |
| | |
| | | package org.dromara.common.websocket.handler; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.websocket.dto.WebSocketMessageDto; |
| | |
| | | import org.springframework.web.socket.*; |
| | | import org.springframework.web.socket.handler.AbstractWebSocketHandler; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | | import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; |
| | |
| | | * 连接成功后 |
| | | */ |
| | | @Override |
| | | public void afterConnectionEstablished(WebSocketSession session) { |
| | | public void afterConnectionEstablished(WebSocketSession session) throws IOException { |
| | | LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); |
| | | if (ObjectUtil.isNull(loginUser)) { |
| | | session.close(CloseStatus.BAD_DATA); |
| | | log.info("[connect] invalid token received. sessionId: {}", session.getId()); |
| | | return; |
| | | } |
| | | WebSocketSessionHolder.addSession(loginUser.getUserId(), session); |
| | | log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); |
| | | } |
| | |
| | | @Override |
| | | public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { |
| | | LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); |
| | | if (ObjectUtil.isNull(loginUser)) { |
| | | log.info("[disconnect] invalid token received. sessionId: {}", session.getId()); |
| | | return; |
| | | } |
| | | WebSocketSessionHolder.removeSession(loginUser.getUserId()); |
| | | log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); |
| | | } |
| | |
| | | package org.dromara.common.websocket.interceptor; |
| | | |
| | | import cn.dev33.satoken.exception.NotLoginException; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.springframework.http.server.ServerHttpRequest; |
| | | import org.springframework.http.server.ServerHttpResponse; |
| | |
| | | */ |
| | | @Override |
| | | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) { |
| | | // 检查是否登录 是否有token |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | |
| | | // 解决 ws 不走 mvc 拦截器问题(cloud 版本不受影响) |
| | | // 检查 header 与 param 里的 clientid 与 token 里的是否一致 |
| | | String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY); |
| | | String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY); |
| | | String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString(); |
| | | if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) { |
| | | // token 无效 |
| | | throw NotLoginException.newInstance(StpUtil.getLoginType(), |
| | | "-100", "客户端ID与Token不匹配", |
| | | StpUtil.getTokenValue()); |
| | | } |
| | | |
| | | attributes.put(LOGIN_USER_KEY, loginUser); |
| | | return true; |
| | | } |
| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | 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.StringUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.flowable.common.engine.impl.interceptor.Command; |
| | |
| | | |
| | | private final String processInstanceId; |
| | | |
| | | public AttachmentCmd(String fileId, String taskId, String processInstanceId) { |
| | | private final OssService ossService; |
| | | |
| | | public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) { |
| | | this.fileId = fileId; |
| | | this.taskId = taskId; |
| | | this.processInstanceId = processInstanceId; |
| | | this.ossService = ossService; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean execute(CommandContext commandContext) { |
| | | try { |
| | | if (StringUtils.isNotBlank(fileId)) { |
| | | List<OssDTO> ossList = SpringUtils.getBean(OssService.class).selectByIds(fileId); |
| | | List<OssDTO> ossList = ossService.selectByIds(fileId); |
| | | if (CollUtil.isNotEmpty(ossList)) { |
| | | for (OssDTO oss : ossList) { |
| | | AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager(); |
| | |
| | | /** |
| | | * 执行办理任务监听 |
| | | * |
| | | * @param keyNode 流程定义key与流程节点标识(拼接方式:流程定义key_流程节点) |
| | | * @param taskId 任务id |
| | | * @param businessKey 业务id |
| | | * @param key 流程key |
| | | * @param taskDefinitionKey 审批节点key |
| | | * @param taskId 任务id |
| | | * @param businessKey 业务id |
| | | */ |
| | | public void processTaskHandler(String keyNode, String taskId, String businessKey) { |
| | | public void processTaskHandler(String key, String taskDefinitionKey, String taskId, String businessKey) { |
| | | ProcessTaskEvent processTaskEvent = new ProcessTaskEvent(); |
| | | processTaskEvent.setKeyNode(keyNode); |
| | | processTaskEvent.setKey(key); |
| | | processTaskEvent.setTaskDefinitionKey(taskDefinitionKey); |
| | | processTaskEvent.setTaskId(taskId); |
| | | processTaskEvent.setBusinessKey(businessKey); |
| | | SpringUtils.context().publishEvent(processTaskEvent); |
| | |
| | | |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.workflow.domain.TestLeave; |
| | | import org.dromara.workflow.domain.bo.TestLeaveBo; |
| | | import org.dromara.workflow.domain.vo.TestLeaveVo; |
| | | |
| | |
| | | import com.alibaba.excel.util.StringUtils; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.batik.transcoder.TranscoderInput; |
| | | import org.apache.batik.transcoder.TranscoderOutput; |
| | | import org.apache.batik.transcoder.image.PNGTranscoder; |
| | |
| | | * |
| | | * @author may |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class ActModelServiceImpl implements IActModelService { |
| | |
| | | repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml)); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | modelVo.setDescription(model.getMetaInfo()); |
| | | return modelVo; |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | model.setMetaInfo(modelBo.getDescription()); |
| | | repositoryService.saveModel(model); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return true; |
| | |
| | | repositoryService.addModelEditorSourceExtra(model.getId(), result); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | // 刷出响应流 |
| | | response.flushBuffer(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return true; |
| | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | |
| | | * |
| | | * @author may |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService { |
| | |
| | | wfNodeConfigService.deleteByDefIds(processDefinitionIds); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException("操作失败:" + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | .migrateProcessInstances(fromProcessDefinitionId); |
| | | return true; |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | 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; |
| | |
| | | private final IWfTaskBackNodeService wfTaskBackNodeService; |
| | | private final IWfNodeConfigService wfNodeConfigService; |
| | | private final FlowProcessEventHandler flowProcessEventHandler; |
| | | private final UserService userService; |
| | | |
| | | @Value("${flowable.activity-font-name}") |
| | | private String activityFontName; |
| | |
| | | historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime()); |
| | | historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration()); |
| | | if (ObjectUtil.isEmpty(infoVo.getAssignee())) { |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId()); |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId(), userService); |
| | | if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { |
| | | historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); |
| | | } |
| | |
| | | historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime()); |
| | | historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration()); |
| | | if (ObjectUtil.isEmpty(e.getAssignee())) { |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId()); |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId(), userService); |
| | | if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { |
| | | historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); |
| | | } |
| | |
| | | } |
| | | //设置人员id |
| | | if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) { |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId()); |
| | | ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId(), userService); |
| | | if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { |
| | | actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); |
| | | } |
| | |
| | | historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("撤销失败:" + e.getMessage(), e); |
| | | throw new ServiceException("撤销失败:" + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | message = "您的【" + processInstance.getName() + "】单据还未审批,请您及时处理。"; |
| | | } |
| | | List<Task> list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list(); |
| | | WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message); |
| | | WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message, userService); |
| | | } catch (ServiceException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | 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.OssService; |
| | | import org.dromara.common.core.service.UserService; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | |
| | | * |
| | | * @author may |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class ActTaskServiceImpl implements IActTaskService { |
| | |
| | | private final ActHiTaskinstMapper actHiTaskinstMapper; |
| | | private final IWfNodeConfigService wfNodeConfigService; |
| | | private final IWfDefinitionConfigService wfDefinitionConfigService; |
| | | private final UserService userService; |
| | | private final FlowProcessEventHandler flowProcessEventHandler; |
| | | private final UserService userService; |
| | | private final OssService ossService; |
| | | |
| | | /** |
| | | * 启动任务 |
| | |
| | | return true; |
| | | } |
| | | //附件上传 |
| | | AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId()); |
| | | AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId(), ossService); |
| | | managementService.executeCommand(attachmentCmd); |
| | | String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey()); |
| | | //流程提交监听 |
| | |
| | | } |
| | | runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus()); |
| | | //办理监听 |
| | | String keyNode = processInstance.getProcessDefinitionKey() + "_" + task.getTaskDefinitionKey(); |
| | | flowProcessEventHandler.processTaskHandler(keyNode, task.getId(), processInstance.getBusinessKey()); |
| | | flowProcessEventHandler.processTaskHandler(processInstance.getProcessDefinitionKey(), task.getTaskDefinitionKey(), |
| | | task.getId(), processInstance.getBusinessKey()); |
| | | //办理意见 |
| | | taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage()); |
| | | //办理任务 |
| | |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | */ |
| | | @Async |
| | | public void sendMessage(List<Task> list, String name, List<String> messageType, String message) { |
| | | WorkflowUtils.sendMessage(list, name, messageType, message); |
| | | WorkflowUtils.sendMessage(list, name, messageType, message, userService); |
| | | } |
| | | |
| | | /** |
| | |
| | | List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); |
| | | for (TaskVo task : taskList) { |
| | | task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); |
| | | task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId())); |
| | | task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); |
| | | task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); |
| | | if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { |
| | | wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); |
| | |
| | | }); |
| | | } |
| | | taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null); |
| | | taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId())); |
| | | taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); |
| | | taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); |
| | | if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { |
| | | wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo); |
| | |
| | | taskService.complete(newTask.getId()); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | taskService.setAssignee(task.getId(), transmitBo.getUserId()); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | taskService.complete(newTask.getId()); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | taskService.complete(newTask.getId()); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | |
| | | //删除驳回后的流程节点 |
| | | wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId()); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return task.getProcessInstanceId(); |
| | |
| | | taskService.setAssignee(task.getId(), userId); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("修改失败:" + e.getMessage(), e); |
| | | throw new ServiceException("修改失败:" + e.getMessage()); |
| | | } |
| | | return true; |
| | |
| | | |
| | | /** |
| | | * 总体流程监听(例如: 提交 退回 撤销 终止 作废等) |
| | | * 正常使用只需#processEvent.key=='leave1' |
| | | * 示例为了方便则使用startsWith匹配了全部示例key |
| | | * |
| | | * @param processEvent 参数 |
| | | */ |
| | | @EventListener(condition = "#processEvent.key=='leave1'") |
| | | @EventListener(condition = "#processEvent.key.startsWith('leave')") |
| | | public void processHandler(ProcessEvent processEvent) { |
| | | log.info("当前任务执行了{}", processEvent.toString()); |
| | | TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey())); |
| | |
| | | |
| | | /** |
| | | * 执行办理任务监听 |
| | | * 示例:也可通过 @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断 |
| | | * 在方法中判断流程节点key |
| | | * if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) { |
| | | * //执行业务逻辑 |
| | | * } |
| | | * |
| | | * @param processTaskEvent 参数 |
| | | */ |
| | | @EventListener(condition = "#processTaskEvent.keyNode=='leave1_Activity_14633hx'") |
| | | @EventListener(condition = "#processTaskEvent.key=='leave1' && #processTaskEvent.taskDefinitionKey=='Activity_14633hx'") |
| | | public void processTaskHandler(ProcessTaskEvent processTaskEvent) { |
| | | log.info("当前任务执行了{}", processTaskEvent.toString()); |
| | | TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey())); |
| | | testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); |
| | | baseMapper.updateById(testLeave); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | |
| | | * @author may |
| | | * @date 2024-03-13 |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService { |
| | |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException("删除失败"); |
| | | } |
| | | } |
| | |
| | | * |
| | | * @param taskId 任务id |
| | | */ |
| | | public static ParticipantVo getCurrentTaskParticipant(String taskId) { |
| | | UserService userService = SpringUtils.getBean(UserService.class); |
| | | public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) { |
| | | ParticipantVo participantVo = new ParticipantVo(); |
| | | List<HistoricIdentityLink> linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId); |
| | | Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); |
| | |
| | | * @param messageType 消息类型 |
| | | * @param message 消息内容,为空则发送默认配置的消息内容 |
| | | */ |
| | | public static void sendMessage(List<Task> list, String name, List<String> messageType, String message) { |
| | | UserService userService = SpringUtils.getBean(UserService.class); |
| | | public static void sendMessage(List<Task> list, String name, List<String> messageType, String message, UserService userService) { |
| | | Set<Long> userIds = new HashSet<>(); |
| | | if (StringUtils.isBlank(message)) { |
| | | message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。"; |
| | | } |
| | | for (Task t : list) { |
| | | ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId()); |
| | | ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService); |
| | | if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) { |
| | | List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds()); |
| | | if (CollUtil.isNotEmpty(userIdList)) { |