diff --git a/.gitignore b/.gitignore index e345e9b..efead51 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,8 @@ localDocs ## backend **/target **/logs -**/yml **/.claude +*.bundle ## front **/*.lock diff --git a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/client/KsimApiClient.java b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/client/KsimApiClient.java index 1188172..56ba2e5 100644 --- a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/client/KsimApiClient.java +++ b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/client/KsimApiClient.java @@ -1,7 +1,7 @@ package org.jeecg.modules.ksim.client; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.util.RestUtil; import org.jeecg.modules.ksim.config.KsimProperties; diff --git a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/dto/KsimApiResult.java b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/dto/KsimApiResult.java index c86723d..56aec86 100644 --- a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/dto/KsimApiResult.java +++ b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/dto/KsimApiResult.java @@ -1,6 +1,6 @@ package org.jeecg.modules.ksim.dto; -import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson2.annotation.JSONField; /** * 即时通 API 通用响应体 diff --git a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/service/impl/KsimMessageServiceImpl.java b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/service/impl/KsimMessageServiceImpl.java index 06065da..7fe3d6c 100644 --- a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/service/impl/KsimMessageServiceImpl.java +++ b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/service/impl/KsimMessageServiceImpl.java @@ -1,6 +1,6 @@ package org.jeecg.modules.ksim.service.impl; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.api.vo.Result; import org.jeecg.modules.ksim.client.KsimApiClient; diff --git a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/token/KsimTokenManager.java b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/token/KsimTokenManager.java index 0a6cc77..4b607a2 100644 --- a/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/token/KsimTokenManager.java +++ b/jeecg-boot-module/jeecg-module-im/src/main/java/org/jeecg/modules/ksim/token/KsimTokenManager.java @@ -1,6 +1,6 @@ package org.jeecg.modules.ksim.token; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.modules.ksim.client.KsimApiClient; diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/pom.xml b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/pom.xml index 4498b9c..284a9ad 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/pom.xml +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/pom.xml @@ -47,7 +47,13 @@ org.jeecgframework.boot jeecg-system-local-api - + + + org.jeecgframework.boot + jeecg-module-im + ${jeecgProjectVersion} + + org.flowable diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/controller/TaskApprovalOpinionController.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/controller/TaskApprovalOpinionController.java index 96fc998..fceaea0 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/controller/TaskApprovalOpinionController.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/controller/TaskApprovalOpinionController.java @@ -105,9 +105,9 @@ public class TaskApprovalOpinionController extends JeecgController supplement(@RequestBody SupplementApprovalOpinionDTO supplementDTO) { - taskApprovalOpinionService.saveSupplementOpinion(supplementDTO); - return Result.OK("提交成功!"); + public Result> supplement(@RequestBody SupplementApprovalOpinionDTO supplementDTO) { + Map pushResult = taskApprovalOpinionService.saveSupplementOpinion(supplementDTO); + return Result.OK(pushResult); } /** diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/dto/SupplementApprovalOpinionDTO.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/dto/SupplementApprovalOpinionDTO.java index 44bb6d3..2f50af4 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/dto/SupplementApprovalOpinionDTO.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/dto/SupplementApprovalOpinionDTO.java @@ -5,9 +5,6 @@ import lombok.Data; import java.io.Serializable; -/** - * 增补审批意见提交参数。 - */ @Data @Schema(description = "增补审批意见提交参数") public class SupplementApprovalOpinionDTO implements Serializable { @@ -15,22 +12,18 @@ public class SupplementApprovalOpinionDTO implements Serializable { @Schema(description = "流程实例ID") private String processInstId; - @Schema(description = "Flowable任务ID") private String flowTaskId; - @Schema(description = "流程节点Key") private String taskDefKey; - - @Schema(description = "事项任务ID,对应task_task.id") + @Schema(description = "事项任务ID") private String taskTaskId; - @Schema(description = "关联业务ID") private String businessId; - @Schema(description = "流程编码") private String flowCode; - + @Schema(description = "业务标题") + private String bizTitle; @Schema(description = "增补审批意见") private String opinion; } diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/ITaskApprovalOpinionService.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/ITaskApprovalOpinionService.java index c337926..f817a49 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/ITaskApprovalOpinionService.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/ITaskApprovalOpinionService.java @@ -1,15 +1,10 @@ package org.jeecg.modules.taskapprovalopinion.service; +import java.util.Map; import org.jeecg.modules.taskapprovalopinion.entity.TaskApprovalOpinion; import org.jeecg.modules.taskapprovalopinion.dto.SupplementApprovalOpinionDTO; import com.baomidou.mybatisplus.extension.service.IService; -/** - * 审批意见快照 Service。 - */ public interface ITaskApprovalOpinionService extends IService { - /** - * 保存增补审批意见,仅写入 task_approval_opinion。 - */ - void saveSupplementOpinion(SupplementApprovalOpinionDTO supplementDTO); + Map saveSupplementOpinion(SupplementApprovalOpinionDTO supplementDTO); } diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/impl/TaskApprovalOpinionServiceImpl.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/impl/TaskApprovalOpinionServiceImpl.java index f286a51..dfe5e9e 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/impl/TaskApprovalOpinionServiceImpl.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/taskapprovalopinion/service/impl/TaskApprovalOpinionServiceImpl.java @@ -5,12 +5,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.system.api.ISysBaseAPI; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.extbpm.process.entity.ExtActFlowData; import org.jeecg.modules.extbpm.process.mapper.ExtActFlowDataMapper; +import org.jeecg.modules.ksim.service.IKsimMessageService; import org.jeecg.modules.taskapprovalopinion.dto.SupplementApprovalOpinionDTO; import org.jeecg.modules.taskapprovalopinion.entity.TaskApprovalOpinion; import org.jeecg.modules.taskapprovalopinion.mapper.TaskApprovalOpinionMapper; @@ -21,9 +23,14 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** * 审批意见快照 Service 实现。 @@ -43,13 +50,12 @@ public class TaskApprovalOpinionServiceImpl extends ServiceImpl saveSupplementOpinion(SupplementApprovalOpinionDTO supplementDTO) { if (supplementDTO == null || oConvertUtils.isEmpty(supplementDTO.getProcessInstId())) { throw new JeecgBootException("流程实例ID不能为空"); } @@ -88,6 +94,42 @@ public class TaskApprovalOpinionServiceImpl extends ServiceImpl pushResult = new HashMap<>(); + try { + if (isSuoLeader(loginUser, deptInfo.id)) { + String bizTitle = oConvertUtils.isNotEmpty(supplementDTO.getBizTitle()) + ? supplementDTO.getBizTitle() + : getBizTitle(opinion.getTaskTaskId(), opinion.getProcessInstId()); + String content = "所领导" + (oConvertUtils.isNotEmpty(loginUser.getRealname()) ? loginUser.getRealname() : loginUser.getUsername()) + + "增补意见:" + opinionText; + List handlerNames = getDistinctHandlerNames(opinion.getProcessInstId(), loginUser.getUsername()); + pushResult.put("pushed", !handlerNames.isEmpty()); + pushResult.put("toUsers", handlerNames); + pushResult.put("content", content); + pushResult.put("title", bizTitle); + if (!handlerNames.isEmpty()) { + Result sendResult = ksimMessageService.sendBatch("Account", handlerNames, bizTitle, content, + null, null, null, null, null); + if (sendResult != null && sendResult.isSuccess()) { + log.info("【增补意见-即时通推送】已发送, processInstId: {}, toUserCount: {}, toUsers: {}, title: {}, content: {}", + opinion.getProcessInstId(), handlerNames.size(), handlerNames, bizTitle, content); + } else { + log.warn("【增补意见-即时通推送】发送失败, reason: {}", + sendResult != null ? sendResult.getMessage() : "null"); + pushResult.put("pushed", false); + } + } + } else { + pushResult.put("pushed", false); + } + } catch (Exception e) { + log.warn("【增补意见-即时通推送】失败,不影响增补意见保存, error: {}", e.getMessage()); + pushResult.put("pushed", false); + pushResult.put("error", e.getMessage()); + } + return pushResult; } private LoginUser getCurrentLoginUser() { @@ -98,9 +140,6 @@ public class TaskApprovalOpinionServiceImpl extends ServiceImpl> rows = jdbcTemplate.queryForList( + "select depart_type from sys_depart where id = ?", deptId); + if (!rows.isEmpty()) { + Object val = rows.get(0).get("depart_type"); + return val != null && "1".equals(String.valueOf(val)); + } + } catch (Exception e) { + log.debug("查询部门类型失败, deptId={}", deptId, e); + } + return false; + } + + private String getBizTitle(String taskTaskId, String processInstId) { + if (jdbcTemplate != null && oConvertUtils.isNotEmpty(taskTaskId)) { + try { + List> rows = jdbcTemplate.queryForList( + "select title from task_task where id = ?", taskTaskId); + if (!rows.isEmpty()) { + Object val = rows.get(0).get("title"); + if (val != null && !String.valueOf(val).trim().isEmpty()) { + return String.valueOf(val).trim(); + } + } + } catch (Exception e) { + log.debug("查询 task_task.title 失败, taskTaskId={}", taskTaskId, e); + } + } + if (oConvertUtils.isNotEmpty(processInstId)) { + try { + ExtActFlowData flowData = queryFlowData(processInstId); + if (flowData != null && oConvertUtils.isNotEmpty(flowData.getProcessExpTitle())) { + return flowData.getProcessExpTitle().trim(); + } + } catch (Exception e) { + log.debug("查询 flow title 失败, processInstId={}", processInstId, e); + } + } + return ""; + } + + private List getDistinctHandlerNames(String processInstId, String excludeUserName) { + if (jdbcTemplate == null || oConvertUtils.isEmpty(processInstId)) { + return Collections.emptyList(); + } + try { + List> rows = jdbcTemplate.queryForList( + "select distinct op_user_id, op_user_name from task_approval_opinion where process_inst_id = ?", + processInstId); + Set names = new LinkedHashSet<>(); + for (Map row : rows) { + Object nameVal = row.get("op_user_name"); + Object idVal = row.get("op_user_id"); + if (nameVal != null) { + String name = String.valueOf(nameVal).trim(); + String userId = idVal != null ? String.valueOf(idVal).trim() : ""; + if (!name.isEmpty() && !userId.equals(excludeUserName)) { + names.add(name); + } + } + } + return names.stream().collect(Collectors.toList()); + } catch (Exception e) { + log.debug("查询经办人失败, processInstId={}", processInstId, e); + return Collections.emptyList(); + } + } + private static class ApprovalDeptInfo { private final String id; private final String name;