+ * 监听Flowable流程引擎的全生命周期事件,实现算例状态的实时同步:
+ * - PROCESS_COMPLETED: 流程正常完成
+ * - PROCESS_CANCELLED: 流程被取消/终止
+ * - ENTITY_SUSPENDED: 实体挂起(需过滤流程实例)
+ * - ENTITY_ACTIVATED: 实体激活(需过滤流程实例)
+ * - JOB_MOVED_TO_DEADLETTER: 作业移入死信队列(ERROR状态)
+ *
+ *
+ * @author SDM
+ * @date 2026-01-23
+ */
+@Slf4j
+@Component
+public class GlobalStatusEventListener implements FlowableEventListener {
+
+ @Autowired
+ private ISimulationRunFeignClient simulationRunFeignClient;
+
+ @Override
+ public Set getTypes() {
+ return new HashSet<>(Arrays.asList(
+ FlowableEngineEventType.PROCESS_COMPLETED, // 流程完成
+ FlowableEngineEventType.PROCESS_CANCELLED, // 流程取消(精确匹配,不需要判断deleteReason)
+ FlowableEngineEventType.ENTITY_SUSPENDED, // 实体挂起(需过滤流程实例)
+ FlowableEngineEventType.ENTITY_ACTIVATED, // 实体激活(需过滤流程实例)
+ FlowableEngineEventType.JOB_MOVED_TO_DEADLETTER // 作业进入死信(ERROR状态)
+ ));
+ }
+
+ @Override
+ public void onEvent(FlowableEvent event) {
+ try {
+ FlowableEngineEventType eventType = (FlowableEngineEventType) event.getType();
+
+ // 1. 流程正常完成
+ if (eventType == FlowableEngineEventType.PROCESS_COMPLETED) {
+ handleProcessCompleted((FlowableEngineEntityEvent) event);
+ }
+ // 2. 流程被取消(Flowable 7.x有独立的CANCELLED事件)
+ else if (eventType == FlowableEngineEventType.PROCESS_CANCELLED) {
+ handleProcessCancelled((FlowableEngineEntityEvent) event);
+ }
+ // 3. 实体挂起/激活(需要过滤,只处理流程实例级别)
+ else if (eventType == FlowableEngineEventType.ENTITY_SUSPENDED ||
+ eventType == FlowableEngineEventType.ENTITY_ACTIVATED) {
+ handleSuspendOrActivate((FlowableEngineEntityEvent) event, eventType);
+ }
+ // 4. 作业进入死信队列(ERROR状态的金标准)
+ else if (eventType == FlowableEngineEventType.JOB_MOVED_TO_DEADLETTER) {
+ handleDeadLetter((FlowableEngineEntityEvent) event);
+ }
+ } catch (Exception e) {
+ log.error("处理Flowable事件异常: eventType={}", event.getType(), e);
+ }
+ }
+
+ // --- 内部逻辑方法 ---
+
+ /**
+ * 处理流程正常完成事件
+ * PROCESS_COMPLETED只表示流程走到EndEvent,不包括取消场景
+ */
+ private void handleProcessCompleted(FlowableEngineEntityEvent event) {
+ String processInstanceId = event.getProcessInstanceId();
+ log.info("流程正常完成: processInstanceId={}", processInstanceId);
+ doUpdate(processInstanceId, ProcessInstanceStateEnum.COMPLETED.getCode());
+ }
+
+ /**
+ * 处理流程取消事件
+ * Flowable 7.x提供了独立的PROCESS_CANCELLED事件,更精确
+ */
+ private void handleProcessCancelled(FlowableEngineEntityEvent event) {
+ String processInstanceId = event.getProcessInstanceId();
+ ExecutionEntity execution = (ExecutionEntity) event.getEntity();
+ log.info("流程被取消: processInstanceId={}, deleteReason={}",
+ processInstanceId, execution.getDeleteReason());
+ doUpdate(processInstanceId, ProcessInstanceStateEnum.CANCELLED.getCode());
+ }
+
+ /**
+ * 处理实体挂起/激活事件
+ * 关键:必须过滤,只处理流程实例级别的挂起/激活,忽略子流程或其他实体
+ */
+ private void handleSuspendOrActivate(FlowableEngineEntityEvent event, FlowableEngineEventType eventType) {
+ Object entity = event.getEntity();
+
+ // 只处理ExecutionEntity(流程执行实体)
+ if (entity instanceof ExecutionEntity) {
+ ExecutionEntity execution = (ExecutionEntity) entity;
+
+ // 关键判断:isProcessInstanceType()确保是流程实例本身,而非子分支
+ if (execution.isProcessInstanceType()) {
+ String processInstanceId = execution.getProcessInstanceId();
+ Integer status = (eventType == FlowableEngineEventType.ENTITY_SUSPENDED) ? ProcessInstanceStateEnum.SUSPENDED.getCode() : ProcessInstanceStateEnum.RUNNING.getCode();
+
+ log.info("流程实例{}状态变更: processInstanceId={}",
+ status.equals("SUSPENDED") ? "挂起" : "激活", processInstanceId);
+ doUpdate(processInstanceId, status);
+ } else {
+ log.debug("忽略非流程实例级别的挂起/激活事件: executionId={}", execution.getId());
+ }
+ }
+ }
+
+ /**
+ * 处理死信事件(ERROR状态的标准方式)
+ * JOB_MOVED_TO_DEADLETTER是最精确的ERROR信号:
+ * - 比JOB_EXECUTION_FAILURE准确(FAILURE只是重试中的失败)
+ * - 表示引擎已放弃重试,必须人工干预
+ *
+ * 前提条件:ServiceTask必须配置async="true"和R0/PT0S重试策略
+ */
+ private void handleDeadLetter(FlowableEngineEntityEvent event) {
+ Object entity = event.getEntity();
+
+ if (entity instanceof Job) {
+ Job job = (Job) entity;
+ String processInstanceId = job.getProcessInstanceId();
+ String exceptionMessage = job.getExceptionMessage();
+
+ log.error("❌ 作业进入死信队列,流程ERROR: processInstanceId={}, jobId={}, exception={}",
+ processInstanceId, job.getId(), exceptionMessage);
+
+ doUpdate(processInstanceId, ProcessInstanceStateEnum.ERROR.getCode());
+ }
+ }
+
+ /**
+ * 真正的更新数据库逻辑
+ * 通过Feign调用project服务更新算例状态
+ */
+ private void doUpdate(String processInstanceId, Integer statusCode) {
+ if (processInstanceId == null) {
+ log.warn("流程实例ID为空,跳过状态更新");
+ return;
+ }
+
+ log.info(">>> 更新算例状态 [{}] -> {}", processInstanceId, statusCode);
+ try {
+ simulationRunFeignClient.updateStatusByProcessInstanceId(processInstanceId, statusCode);
+ } catch (Exception e) {
+ log.error("更新算例状态失败: processInstanceId={}, status={}", processInstanceId, statusCode, e);
+ }
+ }
+
+ @Override
+ public boolean isFailOnException() {
+ // 返回false:即使监听器抛异常,也不影响流程继续执行
+ // 这是容错设计,保证业务流程的稳定性
+ return false;
+ }
+
+ @Override
+ public boolean isFireOnTransactionLifecycleEvent() {
+ // 返回false:在事务提交前触发,确保状态及时更新
+ // 如果返回true,监听器会在事务提交后触发,可能导致状态更新滞后
+ return false;
+ }
+
+ @Override
+ public String getOnTransaction() {
+ return null;
+ }
+}
diff --git a/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java b/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java
index e4834e87..0d814b3f 100644
--- a/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java
+++ b/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java
@@ -472,11 +472,11 @@ public class ProcessService implements Iprocess{
if (isRunning) {
// --- 运行中 ---
if (hasError) {
- status = ProcessInstanceStateEnum.ERROR.getCode(); // 有死信作业,视为异常
+ status = ProcessInstanceStateEnum.ERROR.getValue(); // 有死信作业,视为异常
} else if (isSuspended) {
- status = ProcessInstanceStateEnum.SUSPENDED.getCode(); // 被挂起
+ status = ProcessInstanceStateEnum.SUSPENDED.getValue(); // 被挂起
} else {
- status = ProcessInstanceStateEnum.RUNNING.getCode(); // 正常运行
+ status = ProcessInstanceStateEnum.RUNNING.getValue(); // 正常运行
}
} else {
// --- 已结束 (运行时查不到,历史表里有) ---
@@ -484,11 +484,11 @@ public class ProcessService implements Iprocess{
if (deleteReason == null) {
// 1. 正常走完结束节点,deleteReason 为空
- status = ProcessInstanceStateEnum.COMPLETED.getCode();
+ status = ProcessInstanceStateEnum.COMPLETED.getValue();
} else {
// 2. 有删除原因,说明是被取消或强制终止的
// 你可以根据 reason 的内容做更细的区分,或者统称为 cancelled
- status = ProcessInstanceStateEnum.CANCELLED.getCode();
+ status = ProcessInstanceStateEnum.CANCELLED.getValue();
}
}
info.setStatus(status);
diff --git a/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java b/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java
index fe7d40cc..71968877 100644
--- a/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java
+++ b/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java
@@ -1,13 +1,19 @@
package com.sdm.outbridge.config; //// common模块:com.xxx.common.config.CommonConfig
+import com.sdm.common.utils.AESUtil;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.MapPropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* 加载common模块的自定义配置文件
@@ -25,7 +31,48 @@ public class CommonConfig {
}
List> sources = new YamlPropertySourceLoader()
.load(resource.getResource().getFilename(), resource.getResource());
- return sources.get(0);
+ org.springframework.core.env.PropertySource> originalSource = sources.get(0);
+ org.springframework.core.env.PropertySource> decryptedSource =
+ decryptPropertySource(originalSource);
+ return decryptedSource;
}
}
+
+ private static org.springframework.core.env.PropertySource> decryptPropertySource(org.springframework.core.env.PropertySource> source) {
+ // 只处理可枚举的属性源(yml加载后的源都是EnumerablePropertySource)
+ if (!(source instanceof EnumerablePropertySource)) {
+ return source;
+ }
+
+ EnumerablePropertySource> enumerableSource = (EnumerablePropertySource>) source;
+ Map decryptedProperties = new HashMap<>();
+ // 遍历所有配置项
+ for (String propertyName : enumerableSource.getPropertyNames()) {
+ Object value = enumerableSource.getProperty(propertyName);
+ if (value != null && value instanceof String) {
+ String strValue = (String) value;
+ if (strValue.startsWith("ENC(") && strValue.endsWith(")")) {
+ // 解密并替换值
+ String spdmEnkey = StringUtils.isBlank(System.getProperty("spdm.enkey"))?
+ System.getenv("spdm.enkey"):System.getProperty("spdm.enkey");
+ String encryptedValue = strValue.substring(4, strValue.length() - 1);
+ try {
+ decryptedProperties.put(propertyName, AESUtil.decodeNew(encryptedValue, spdmEnkey));
+ } catch (Exception e) {
+ System.out.println("利元亨现场配置解密异常:"+e.getMessage());
+ throw new RuntimeException(e);
+ }
+ } else {
+ // 非加密值,直接保留
+ decryptedProperties.put(propertyName, strValue);
+ }
+ } else {
+ // 非字符串类型,直接保留
+ decryptedProperties.put(propertyName, value);
+ }
+ }
+ // 生成新的属性源(名称和原始源一致,确保覆盖)
+ return new MapPropertySource(source.getName(), decryptedProperties);
+ }
+
}
\ No newline at end of file
diff --git a/outbridge/src/main/resources/common.yml b/outbridge/src/main/resources/common.yml
index cb9cb324..67e3d02e 100644
--- a/outbridge/src/main/resources/common.yml
+++ b/outbridge/src/main/resources/common.yml
@@ -2,7 +2,7 @@ spring:
datasource:
second:
username: EP_DM
- password: ENC(c04rt9Z6Ygz024EU9eWvig==)
+ password: EP_DM@123.COM
# todo 生产地址
jdbc-url: jdbc:mysql://10.122.48.11:13306/easy_project?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
diff --git a/project/src/main/java/com/sdm/project/controller/SimulationNodeController.java b/project/src/main/java/com/sdm/project/controller/SimulationNodeController.java
index c25d7eba..3a1c6398 100644
--- a/project/src/main/java/com/sdm/project/controller/SimulationNodeController.java
+++ b/project/src/main/java/com/sdm/project/controller/SimulationNodeController.java
@@ -178,6 +178,7 @@ public class SimulationNodeController implements ISimulationNodeFeignClient {
@PostMapping("/getAllUserTaskCompleteStatistics")
@Operation(summary = "所有项目的人员任务完成情况统计", description = "所有项目的人员任务完成情况统计")
public SdmResponse getAllUserTaskCompleteStatistics(@RequestBody @Validated GetAllUserTaskCompleteStatisticsReq req) {
+ req.setTenantId(ThreadLocalContext.getTenantId());
return nodeService.getAllUserTaskCompleteStatistics(req);
}
@@ -188,7 +189,7 @@ public class SimulationNodeController implements ISimulationNodeFeignClient {
@GetMapping("/getUserGroupProjectStatistics")
@Operation(summary = "用户组项目统计", description = "用户组项目统计")
public SdmResponse getUserGroupProjectStatistics(@Parameter(description = "用户组ID")@RequestParam( value = "userGroupId" )@NotNull(message = "用户组ID(userGroupId)为必传参数,请补充后重试") Long userGroupId, @Parameter(description = "用户ID")@RequestParam( value = "userId", required = false) Long userId) {
- return nodeService.getUserGroupProjectStatistics(userGroupId,userId);
+ return nodeService.getUserGroupProjectStatistics(userGroupId,userId,ThreadLocalContext.getTenantId());
}
/**
@@ -201,6 +202,7 @@ public class SimulationNodeController implements ISimulationNodeFeignClient {
@PostMapping("/getUserGroupTaskCompleteStatistics")
@Operation(summary = "用户组任务完成情况统计", description = "用户组任务完成情况统计")
public SdmResponse getUserGroupTaskCompleteStatistics(@RequestBody @Validated GetUserGroupTaskCompleteStatisticsReq req) {
+ req.setTenantId(ThreadLocalContext.getTenantId());
return nodeService.getUserGroupTaskCompleteStatistics(req);
}
diff --git a/project/src/main/java/com/sdm/project/controller/SimulationRunController.java b/project/src/main/java/com/sdm/project/controller/SimulationRunController.java
index b3ad8f29..af96589c 100644
--- a/project/src/main/java/com/sdm/project/controller/SimulationRunController.java
+++ b/project/src/main/java/com/sdm/project/controller/SimulationRunController.java
@@ -240,8 +240,8 @@ public class SimulationRunController implements ISimulationRunFeignClient {
*/
@PostMapping("/editReport")
@Operation(summary = "编辑报告模板生成报告", description = "编辑报告模板生成报告")
- public void editReport(@RequestBody EditReportReq req) {
- runService.editReport(req);
+ public SdmResponse editReport(@RequestBody EditReportReq req) {
+ return runService.editReport(req);
}
/**
@@ -395,4 +395,13 @@ public class SimulationRunController implements ISimulationRunFeignClient {
return runService.syncKeyResultToTask(req);
}
+ /**
+ * 根据流程实例ID更新算例状态 (内部调用)
+ * 由Flowable全局事件监听器调用
+ */
+ @PostMapping("/updateStatusByProcessInstanceId")
+ public SdmResponse updateStatusByProcessInstanceId(@RequestParam String processInstanceId, @RequestParam Integer statusCode) {
+ return runService.updateStatusByProcessInstanceId(processInstanceId, statusCode);
+ }
+
}
\ No newline at end of file
diff --git a/project/src/main/java/com/sdm/project/dao/SimulationNodeMapper.java b/project/src/main/java/com/sdm/project/dao/SimulationNodeMapper.java
index 7553893f..b3bea795 100644
--- a/project/src/main/java/com/sdm/project/dao/SimulationNodeMapper.java
+++ b/project/src/main/java/com/sdm/project/dao/SimulationNodeMapper.java
@@ -74,7 +74,7 @@ public interface SimulationNodeMapper extends BaseMapper {
List getNodeListByIds(@Param("nodeIdList") List nodeIdList);
- List getUserGroupProjectStatistics(@Param("userIds")Set userIds );
+ List getUserGroupProjectStatistics(@Param("userIds")Set userIds, @Param("tenantId")Long tenantId);
List getUserGroupTaskCompleteStatistics(@Param("req") GetUserGroupTaskCompleteStatisticsReq req);
diff --git a/project/src/main/java/com/sdm/project/model/req/GetAllUserTaskCompleteStatisticsReq.java b/project/src/main/java/com/sdm/project/model/req/GetAllUserTaskCompleteStatisticsReq.java
index 8e1a58b6..cd6c31fe 100644
--- a/project/src/main/java/com/sdm/project/model/req/GetAllUserTaskCompleteStatisticsReq.java
+++ b/project/src/main/java/com/sdm/project/model/req/GetAllUserTaskCompleteStatisticsReq.java
@@ -11,6 +11,8 @@ import java.util.List;
@Data
@Schema(description = "所有项目的人员任务完成情况统计")
public class GetAllUserTaskCompleteStatisticsReq {
+ @Schema(description = "租户ID")
+ private Long tenantId;
@Schema(description = "用户列表")
private List userIds;
diff --git a/project/src/main/java/com/sdm/project/model/req/GetUserGroupTaskCompleteStatisticsReq.java b/project/src/main/java/com/sdm/project/model/req/GetUserGroupTaskCompleteStatisticsReq.java
index d51d5abf..05358692 100644
--- a/project/src/main/java/com/sdm/project/model/req/GetUserGroupTaskCompleteStatisticsReq.java
+++ b/project/src/main/java/com/sdm/project/model/req/GetUserGroupTaskCompleteStatisticsReq.java
@@ -20,6 +20,9 @@ public class GetUserGroupTaskCompleteStatisticsReq {
@Schema(description = "用户ID")
private Long userId;
+ @Schema(description = "租户ID")
+ private Long tenantId;
+
@Schema(description = "用户")
private Set userIds;
diff --git a/project/src/main/java/com/sdm/project/service/INodeService.java b/project/src/main/java/com/sdm/project/service/INodeService.java
index afbfa23a..b434f79f 100644
--- a/project/src/main/java/com/sdm/project/service/INodeService.java
+++ b/project/src/main/java/com/sdm/project/service/INodeService.java
@@ -41,7 +41,7 @@ public interface INodeService extends IService {
SdmResponse> getTaskRunList(List uuids);
- SdmResponse getUserGroupProjectStatistics(Long userGroupId, Long userId);
+ SdmResponse getUserGroupProjectStatistics(Long userGroupId, Long userId,Long tenantId);
SdmResponse getUserGroupTaskCompleteStatistics(GetUserGroupTaskCompleteStatisticsReq req);
diff --git a/project/src/main/java/com/sdm/project/service/ISimulationRunService.java b/project/src/main/java/com/sdm/project/service/ISimulationRunService.java
index 3aeaf650..22fc4ec2 100644
--- a/project/src/main/java/com/sdm/project/service/ISimulationRunService.java
+++ b/project/src/main/java/com/sdm/project/service/ISimulationRunService.java
@@ -71,7 +71,7 @@ public interface ISimulationRunService extends IService {
void generateNewReport(SpdmReportReq req, HttpServletResponse response);
- void editReport(EditReportReq req);
+ SdmResponse editReport(EditReportReq req);
void editReportAndDownload(EditReportReq req, HttpServletResponse response);
@@ -110,4 +110,12 @@ public interface ISimulationRunService extends IService {
SdmResponse syncKeyResultToTask(KeyResultReq req);
+ /**
+ * 根据流程实例ID更新算例状态
+ * @param processInstanceId 流程实例ID
+ * @param statusCode 状态值(RUNNING/SUSPENDED/COMPLETED/CANCELLED/ERROR)
+ * @return SdmResponse
+ */
+ SdmResponse updateStatusByProcessInstanceId(String processInstanceId, Integer statusCode);
+
}
\ No newline at end of file
diff --git a/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java
index a455f3ea..ae768997 100644
--- a/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java
+++ b/project/src/main/java/com/sdm/project/service/impl/NodeServiceImpl.java
@@ -8,7 +8,6 @@ import com.sdm.common.common.ResultCode;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.common.ThreadLocalContext;
import com.sdm.common.entity.ExportExcelFormat;
-import com.sdm.common.entity.bo.DataDictionary;
import com.sdm.common.entity.constants.TagConstant;
import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FilePermissionEnum;
@@ -22,7 +21,6 @@ import com.sdm.common.entity.resp.AllNodeByProjectIdAndTypeResp;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.project.SimulationNodeResp;
import com.sdm.common.entity.resp.project.SimulationRunResp;
-import com.sdm.common.entity.resp.system.CIDStaffResp;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.entity.resp.system.SysUserGroupDetailResp;
import com.sdm.common.feign.impl.data.DataClientFeignClientImpl;
@@ -1440,7 +1438,7 @@ public class NodeServiceImpl extends ServiceImpl userId2Nickname = getUserIdToNicknameMap(userGroupId);
if (MapUtils.isEmpty(userId2Nickname)) {
return SdmResponse.success();
@@ -1453,7 +1451,7 @@ public class NodeServiceImpl extends ServiceImpl userGroupProjectStatistics = this.baseMapper.getUserGroupProjectStatistics(userIds);
+ List userGroupProjectStatistics = this.baseMapper.getUserGroupProjectStatistics(userIds,tenantId );
if (CollectionUtils.isEmpty(userGroupProjectStatistics)) {
return SdmResponse.success(new ArrayList<>());
}
diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java
index 14b081e9..88474c1d 100644
--- a/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java
+++ b/project/src/main/java/com/sdm/project/service/impl/SimulationRunServiceImpl.java
@@ -12,12 +12,8 @@ import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.common.ThreadLocalContext;
-import com.sdm.common.config.FlowableConfig;
import com.sdm.common.entity.constants.NumberConstants;
-import com.sdm.common.entity.enums.ApproveTypeEnum;
-import com.sdm.common.entity.enums.DirTypeEnum;
-import com.sdm.common.entity.enums.FileBizTypeEnum;
-import com.sdm.common.entity.enums.NodeTypeEnum;
+import com.sdm.common.entity.enums.*;
import com.sdm.common.entity.flowable.dto.FlowElementDTO;
import com.sdm.common.entity.flowable.dto.ProcessDefinitionDTO;
import com.sdm.common.entity.req.capability.FlowNodeDto;
@@ -60,7 +56,6 @@ import com.sdm.project.model.resp.KeyResultAndTaskInfoResp;
import com.sdm.project.model.resp.RunVersionInfoResp;
import com.sdm.project.model.vo.SpdmNodeVo;
import com.sdm.common.entity.resp.project.SpdmTaskVo;
-import com.sdm.project.model.vo.SpdmTaskMemberVo;
import com.sdm.project.service.*;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@@ -84,7 +79,6 @@ import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
-import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import static com.sdm.common.service.BaseService.generateUuid;
@@ -629,7 +623,7 @@ public class SimulationRunServiceImpl extends ServiceImpl
#{userId}
@@ -354,6 +358,8 @@
from simulation_task task
left join simulation_task_member task_member on task.uuid = task_member.task_id
+ task.tenant_Id = #{req.tenantId}
+ and
task_member.user_id in
(
@@ -406,7 +412,8 @@
from simulation_task task
left join simulation_task_member task_member on task.uuid = task_member.task_id
- task_member.user_id in
+ task.tenant_Id = #{req.tenantId}
+ and task_member.user_id in
(
#{userId}
diff --git a/task/src/main/java/com/sdm/task/model/dto/TaskPerformanceDto.java b/task/src/main/java/com/sdm/task/model/dto/TaskPerformanceDto.java
index 952db88e..bf7ab008 100644
--- a/task/src/main/java/com/sdm/task/model/dto/TaskPerformanceDto.java
+++ b/task/src/main/java/com/sdm/task/model/dto/TaskPerformanceDto.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -66,6 +67,9 @@ public class TaskPerformanceDto {
@Schema(description = "标准")
private String standard;
+ @Schema(description = "计算及结果值")
+ private String resultValue;
+
@Schema(description = "租户ID")
private String tenantId;
diff --git a/task/src/main/java/com/sdm/task/model/entity/SimulationPerformance.java b/task/src/main/java/com/sdm/task/model/entity/SimulationPerformance.java
index a1cfbe09..6131271c 100644
--- a/task/src/main/java/com/sdm/task/model/entity/SimulationPerformance.java
+++ b/task/src/main/java/com/sdm/task/model/entity/SimulationPerformance.java
@@ -80,7 +80,7 @@ public class SimulationPerformance implements Serializable {
@TableField("method")
private String method;
- @ApiModelProperty(value = "指标完成情况 未完成 不合格 风险可控 未分析 合格")
+ @ApiModelProperty(value = "指标完成情况 未完成 不合格 风险可控 未分析 合格 ")
@TableField("completeStatus")
private String completeStatus;
diff --git a/task/src/main/java/com/sdm/task/service/impl/SimulationPerformanceServiceImpl.java b/task/src/main/java/com/sdm/task/service/impl/SimulationPerformanceServiceImpl.java
index 6d0be46b..cbc3d080 100644
--- a/task/src/main/java/com/sdm/task/service/impl/SimulationPerformanceServiceImpl.java
+++ b/task/src/main/java/com/sdm/task/service/impl/SimulationPerformanceServiceImpl.java
@@ -4,12 +4,14 @@ import com.alibaba.fastjson2.JSONArray;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.ExportExcelFormat;
import com.sdm.common.entity.enums.ApprovalFileDataStatusEnum;
+import com.sdm.common.entity.enums.PerformanceStatusEnum;
import com.sdm.common.entity.req.data.KnowledgeExportExcelParam;
import com.sdm.common.entity.req.performance.PerformanceExportExcelFormat;
import com.sdm.common.entity.req.performance.PerformanceExportExcelParam;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.task.PerformanceResp;
import com.sdm.common.service.BaseService;
+import com.sdm.common.utils.CommonUtils;
import com.sdm.common.utils.RandomUtil;
import com.sdm.common.utils.excel.ExcelUtil;
import com.sdm.task.model.dto.TaskPerformanceDto;
@@ -31,7 +33,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -131,9 +135,48 @@ public class SimulationPerformanceServiceImpl extends ServiceImpl comparison >= 0;
+ case ">" -> comparison > 0;
+ case "<" -> comparison < 0;
+ case "≤" -> comparison <= 0;
+ default -> throw new IllegalArgumentException("无效运算符: " + method);
+ };
+ simulationPerformance.setCompleteStatus(isPassed ? PerformanceStatusEnum.STARTED.getCode() : PerformanceStatusEnum.NOT_STARTED.getCode());
+ } catch (Exception e) {
+ log.error("数字格式异常:", e);
+ return SdmResponse.failed("请输入有效的目标值和分析值");
+ }
+ }
return SdmResponse.success(this.updateById(simulationPerformance));
}
+ private boolean validateNumber(String input) {
+ String trimmed = input.trim();
+ // 前置格式检查 - 验证是不是有效数字格式
+ if (!CommonUtils.isValidNumberFormat(trimmed)) {
+ return false;
+ }
+ return true;
+ }
+
@Override
public SdmResponse exportPerformance(PerformanceExportExcelFormat performanceExportExcelFormat, HttpServletResponse httpServletResponse) {
SdmResponse response = new SdmResponse();