feat:仿真策划审批

This commit is contained in:
2026-01-27 18:02:24 +08:00
parent e4c8a2c16b
commit 779c42bdac
14 changed files with 381 additions and 16 deletions

View File

@@ -7,7 +7,8 @@ public enum ApproveTypeEnum {
FLOW_TEMPLATE_APPROVE(3, "流程模板评审"),
DELIVERABLE_APPROVE(4, "交付物评审"),
PARAM_APPROVE(5, "仿真参数库评审"),
REPORT_TEMPLATE_APPROVE(6, "报告模板评审")
REPORT_TEMPLATE_APPROVE(6, "报告模板评审"),
DESIGN_APPROVE(7, "仿真策划评审")
;
private final int code;

View File

@@ -0,0 +1,31 @@
package com.sdm.common.feign.impl.project;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.feign.inter.project.ISimulationProjectFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SimulationProjectFeignClientImpl implements ISimulationProjectFeignClient {
@Autowired
ISimulationProjectFeignClient simulationProjectFeignClient;
@Override
public SdmResponse receiveApproveNotice(LaunchApproveReq req) {
try {
SdmResponse response = simulationProjectFeignClient.receiveApproveNotice(req);
if (!response.isSuccess()){
return SdmResponse.failed("仿真策划评审回调失败");
}
return response;
} catch (Exception e) {
log.error("仿真策划评审回调失败", e);
return SdmResponse.failed("仿真策划评审回调失败");
}
}
}

View File

@@ -0,0 +1,16 @@
package com.sdm.common.feign.inter.project;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "project",contextId = "projectFeignClient")
public interface ISimulationProjectFeignClient {
@PostMapping(value = "/project/approveHandleNotice")
SdmResponse receiveApproveNotice(@RequestBody LaunchApproveReq req);
}

View File

@@ -1,8 +1,10 @@
package com.sdm.project.controller;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.entity.req.task.TaskExportExcelFormat;
import com.sdm.common.entity.req.task.TaskTreeExportExcelFormat;
import com.sdm.common.feign.inter.project.ISimulationProjectFeignClient;
import com.sdm.common.log.annotation.SysLog;
import com.sdm.project.model.bo.ModifyProjectNode;
import com.sdm.project.model.req.ProjectTreeListReq;
@@ -23,7 +25,7 @@ import javax.annotation.Resource;
@RestController
@RequestMapping(value = "/project")
@Tag(name = "仿真任务策划管理", description = "仿真任务策划管理管理相关接口")
public class SimulationProjectController {
public class SimulationProjectController implements ISimulationProjectFeignClient {
@Resource
private IProjectService projectService;
@@ -45,6 +47,12 @@ public class SimulationProjectController {
return projectService.modify(req);
}
@PostMapping(value = "/approveHandleNotice")
@Operation(summary = "仿真策划审批结果回调", description = "仿真策划审批结果回调")
public SdmResponse receiveApproveNotice(@RequestBody LaunchApproveReq req) {
return projectService.handleApproveNotice(req);
}
/**
* 任务分析项树
*

View File

@@ -0,0 +1,8 @@
package com.sdm.project.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sdm.project.model.entity.SimulationDesignVersions;
public interface SimulationDesignVersionsMapper extends BaseMapper<SimulationDesignVersions> {
}

View File

@@ -25,4 +25,37 @@ public class ModifyProjectNode extends BaseEntity {
List<TaskEditNodeReq> editNodeList;
List<SpdmDeleteProjectDetailReq> deleteNodeList;
/**
* 是否需要评审
*/
public boolean bApprove = false;
/**
* 是否需要升版
*/
public boolean bNewVersion = false;
/**
* 0生成小版本 1生成大版本
*/
public int versionType = 0;
/**
* 评审模板id
*/
public String approveTemplateId;
/**
* 评审模板名称
*/
public String approveTemplateName;
/**
* 项目uuid
*/
public String projectNodeId;
/**
* 阶段uuid
*/
public String phaseNodeId;
/**
* 当前版本
*/
public String currentVersion;
}

View File

@@ -1,10 +1,14 @@
package com.sdm.project.model.bo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TaskNodeTag {
String key;
String value;

View File

@@ -0,0 +1,56 @@
package com.sdm.project.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("simulation_design_versions")
@ApiModel(value = "SimulationDesignVersions对象", description = "仿真策划版本表")
public class SimulationDesignVersions implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "项目UUID")
@TableField("projectId")
private String projectId;
@ApiModelProperty(value = "当前策划版本号")
@TableField("currentVersion")
private String currentVersion;
@ApiModelProperty(value = "所属父版本版本号")
@TableField("parentVersion")
private String parentVersion;
@ApiModelProperty(value = "所属子版本版本号")
@TableField("childVersion")
private String childVersion;
@ApiModelProperty(value = "版本内容JSON字符串")
@TableField("versionContents")
private String versionContents;
@ApiModelProperty(value = "创建者")
@TableField("creator")
private Long creator;
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField(value = "createTime", insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
private LocalDateTime createTime;
}

View File

@@ -3,6 +3,8 @@ package com.sdm.project.model.req;
import com.sdm.project.model.bo.TaskNodeTag;
import lombok.Data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -15,4 +17,33 @@ public class ProjectTreeTagReq {
private String projectNodeId;
/**
* 根据projectNodeId和phaseNodeId构建
*/
public static ProjectTreeTagReq buildForProjectAndPhase(String projectNodeId, String phaseNodeId) {
ProjectTreeTagReq req = new ProjectTreeTagReq();
req.setProjectNodeId(projectNodeId);
// 构建idMap第一个是projectNodeId第二个是phaseNodeId后面8个key为null
List<TaskNodeTag> idMap = new ArrayList<>();
idMap.add(new TaskNodeTag(projectNodeId, "tag1"));
idMap.add(new TaskNodeTag(phaseNodeId, "tag2"));
for (int i = 3; i <= 10; i++) {
idMap.add(new TaskNodeTag(null, "tag" + i));
}
req.setIdMap(idMap);
// 构建tagMap完全固定
req.setTagMap(Arrays.asList(
new TaskNodeTag("project", "tag1"),
new TaskNodeTag("phase", "tag2"),
new TaskNodeTag("machine", "tag4"),
new TaskNodeTag("workspace", "tag5"),
new TaskNodeTag("discipline", "tag6")
));
return req;
}
}

View File

@@ -2,6 +2,7 @@ package com.sdm.project.service;
import com.alibaba.fastjson2.JSONObject;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.entity.req.task.TaskTreeExportExcelFormat;
import com.sdm.project.model.bo.ModifyProjectNode;
import com.sdm.project.model.req.*;
@@ -24,8 +25,12 @@ public interface IProjectService {
SdmResponse taskHandle(String taskId, Integer handleType);
SdmResponse modifyWithApprove(ModifyProjectNode req);
SdmResponse modify(ModifyProjectNode req);
SdmResponse handleApproveNotice(LaunchApproveReq req);
SdmResponse exportTaskTree(TaskTreeExportExcelFormat taskTreeExportExcelFormat, HttpServletResponse httpservletResponse);
SdmResponse getTaskTreeList(ProjectTreeListReq req);

View File

@@ -0,0 +1,8 @@
package com.sdm.project.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdm.project.model.entity.SimulationDesignVersions;
public interface ISimulationDesignVersionsService extends IService<SimulationDesignVersions> {
}

View File

@@ -11,6 +11,7 @@ import com.sdm.common.entity.ExportExcelFormat;
import com.sdm.common.entity.enums.*;
import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.project.SimulationPerformance;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.entity.req.system.SendMsgReq;
import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.req.task.TaskTreeExportExcelFormat;
@@ -22,14 +23,13 @@ import com.sdm.common.entity.resp.project.TaskNodeExtraPo;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.feign.impl.capability.SimulationFlowFeignClientImpl;
import com.sdm.common.feign.impl.data.DataClientFeignClientImpl;
import com.sdm.common.feign.impl.system.ApproveFeignClientImpl;
import com.sdm.common.feign.impl.system.MessageFeignClientImpl;
import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
import com.sdm.common.service.BaseService;
import com.sdm.common.utils.RandomUtil;
import com.sdm.common.utils.SystemOperate;
import com.sdm.common.utils.excel.ExcelUtil;
import com.sdm.outbridge.entity.LyricVProjectStationPlanToDM;
import com.sdm.outbridge.service.lyric.LyricVProjectStationPlanToDmService;
import com.sdm.project.bo.ExportOperate;
import com.sdm.project.common.MemberTypeEnum;
import com.sdm.project.common.TaskExeStatusEnum;
@@ -38,19 +38,13 @@ import com.sdm.project.dao.SimulationNodeMapper;
import com.sdm.project.dao.SimulationProjectMapper;
import com.sdm.project.dao.SimulationTaskMapper;
import com.sdm.project.model.bo.*;
import com.sdm.project.model.entity.SimulationNode;
import com.sdm.project.model.entity.SimulationPerformanceExtra;
import com.sdm.project.model.entity.SimulationTask;
import com.sdm.project.model.entity.SimulationTaskMember;
import com.sdm.project.model.entity.*;
import com.sdm.project.model.po.*;
import com.sdm.project.model.req.*;
import com.sdm.project.model.vo.SpdmNodeExtraVo;
import com.sdm.project.model.vo.SpdmNodeMemberVo;
import com.sdm.project.model.vo.SpdmNodeVo;
import com.sdm.project.service.IProjectService;
import com.sdm.project.service.ISimulationPerformanceExtraService;
import com.sdm.project.service.ISimulationPerformanceService;
import com.sdm.project.service.ISimulationTaskMemberService;
import com.sdm.project.service.*;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@@ -66,9 +60,6 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@@ -111,11 +102,14 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
private ExportOperate exportOperate;
@Autowired
private LyricVProjectStationPlanToDmService lyricVProjectStationPlanToDmService;
private ISimulationDesignVersionsService simulationDesignVersionsService;
@Autowired
private SimulationFlowFeignClientImpl flowFeignClient;
@Autowired
private ApproveFeignClientImpl approveFeignClient;
@Value("${commitmentDeadlineStatusTask.schedule.calculationInterval:5}")
private int calculationInterval;
@@ -2349,6 +2343,86 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
return SdmResponse.success();
}
@Override
public SdmResponse modifyWithApprove(ModifyProjectNode req) {
Long tenantId = ThreadLocalContext.getTenantId();
Long userId = ThreadLocalContext.getUserId();
// 如果需要评审 发起评审
if (req.isBApprove()) {
String approveContents = JSONObject.toJSONString(req);
int approveAction = 2;
// 发起评审
if(launchTaskPoolApprove(req.approveTemplateId,req.approveTemplateName,approveContents,approveAction)) {
return SdmResponse.success();
} else {
return SdmResponse.failed("发起评审失败");
}
}
// 不需要评审 直接升版 or 不升
if (req.isBNewVersion()) {
SdmResponse response = modify(req);
if (!response.isSuccess()) {
return response;
} else {
ProjectTreeTagReq getTaskTreeReq = ProjectTreeTagReq.buildForProjectAndPhase(req.getProjectNodeId(), req.getPhaseNodeId());
SdmResponse treeRespond = getTaskTree(getTaskTreeReq);
if (treeRespond.getData() != null) {
String viewContents = JSONObject.toJSONString(treeRespond.getData());
List<SimulationDesignVersions> designVersions = simulationDesignVersionsService.lambdaQuery().eq(SimulationDesignVersions::getProjectId, req.getProjectNodeId()).list();
if (CollectionUtils.isNotEmpty(designVersions)) {
// 根据最新版本升版
SimulationDesignVersions latestVersion = designVersions.stream().sorted(Comparator.comparing(SimulationDesignVersions::getCreateTime).reversed()).collect(Collectors.toList()).get(0);
String newVersion = generateVersion(latestVersion.getCurrentVersion(), req.versionType);
SimulationDesignVersions newDesignVersion = new SimulationDesignVersions();
newDesignVersion.setProjectId(req.getProjectNodeId());
newDesignVersion.setCurrentVersion(newVersion);
newDesignVersion.setParentVersion(latestVersion.getCurrentVersion());
newDesignVersion.setCreator(userId);
newDesignVersion.setVersionContents(viewContents);
simulationDesignVersionsService.save(newDesignVersion);
} else {
addNewVersion(req.getProjectNodeId(), "V1.0", viewContents, userId);
}
} else {
return SdmResponse.failed("获取不到任务树");
}
}
} else {
// 直接修改当前策划版本
SdmResponse response = modify(req);
if (!response.isSuccess()) {
return response;
} else {
ProjectTreeTagReq getTaskTreeReq = ProjectTreeTagReq.buildForProjectAndPhase(req.getProjectNodeId(), req.getPhaseNodeId());
SdmResponse treeRespond = getTaskTree(getTaskTreeReq);
if (treeRespond.getData() != null) {
String viewContents = JSONObject.toJSONString(treeRespond.getData());
if (StringUtils.isNotEmpty(req.getCurrentVersion())) {
simulationDesignVersionsService.lambdaUpdate()
.eq(SimulationDesignVersions::getProjectId, req.getProjectNodeId())
.eq(SimulationDesignVersions::getCurrentVersion, req.getCurrentVersion())
.set(SimulationDesignVersions::getVersionContents, viewContents)
.update();
} else {
addNewVersion(req.getProjectNodeId(), "V1.0", viewContents, userId);
}
}
}
}
return SdmResponse.success();
}
private void addNewVersion(String projectId, String version, String viewContents, Long userId) {
SimulationDesignVersions designVersions = new SimulationDesignVersions();
designVersions.setProjectId(projectId);
designVersions.setCurrentVersion(version);
designVersions.setVersionContents(viewContents);
designVersions.setCreator(userId);
simulationDesignVersionsService.save(designVersions);
}
@Transactional
@Override
public SdmResponse modify(ModifyProjectNode req) {
@@ -2472,6 +2546,56 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
return SdmResponse.success();
}
/**
* 发起仿真策划评审
*/
private boolean launchTaskPoolApprove(String templateId, String templateName,String approveContents,int approveAction)
{
LaunchApproveReq req = new LaunchApproveReq();
req.templateId = templateId;
req.templateName = templateName;
req.approveContents = approveContents;
req.approveAction = approveAction;
req.approveStatus = 1;
req.approveType = ApproveTypeEnum.DESIGN_APPROVE.getCode();
req.approveTitle = ApproveTypeEnum.DESIGN_APPROVE.getDescription();
req.tenantId = ThreadLocalContext.getTenantId();
req.userId = ThreadLocalContext.getUserId();
req.creator = ThreadLocalContext.getUserId();
SdmResponse response = approveFeignClient.launchApproval(req);
return response.isSuccess();
}
/**
* 评审回调处理
*/
@Override
public SdmResponse handleApproveNotice(LaunchApproveReq approveReq) {
SdmResponse response = SdmResponse.success();
String contents = approveReq.approveContents;
int status = approveReq.approveStatus;
long tenantId = approveReq.tenantId;
long userId = approveReq.userId;
ThreadLocalContext.setTenantId(tenantId);
ThreadLocalContext.setUserId(userId);
// 评审成功
if(status == ApproveStatusEnum.PASSED.getCode() && contents != null) {
ObjectMapper objectMapper = new ObjectMapper();
try {
ModifyProjectNode req = objectMapper.readValue(contents, ModifyProjectNode.class);
if(req != null) {
// 清除上次评审标记
req.setBApprove(false);
modify(req);
}
} catch (Exception e) {
log.error("convert modify req error:{}", e.getMessage());
e.printStackTrace();
}
}
return response;
}
@Override
public SdmResponse exportTaskTree(TaskTreeExportExcelFormat taskTreeExportExcelFormat, HttpServletResponse httpServletResponse) {
// 补充表头

View File

@@ -0,0 +1,12 @@
package com.sdm.project.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sdm.project.dao.SimulationDesignVersionsMapper;
import com.sdm.project.model.entity.SimulationDesignVersions;
import com.sdm.project.service.ISimulationDesignVersionsService;
import org.springframework.stereotype.Service;
@Service
public class SimulationDesignVersionsServiceImpl extends ServiceImpl<SimulationDesignVersionsMapper, SimulationDesignVersions> implements ISimulationDesignVersionsService {
}

View File

@@ -0,0 +1,28 @@
package com.sdm.system.service.impl.approvalNotice;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.enums.ApproveTypeEnum;
import com.sdm.common.entity.req.system.LaunchApproveReq;
import com.sdm.common.feign.impl.project.SimulationProjectFeignClientImpl;
import com.sdm.common.feign.inter.project.ISimulationRunFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SimulationDesignStrategy extends ApproveAbstractNoticeStrategy {
@Autowired
private SimulationProjectFeignClientImpl projectFeignClient;
// 这个回调场景值和 LaunchApproveReq 类里的 approveType 对应
// 审批类型 0.http回调的replyUrl必须传递相当于是跨系统的,调用的时候可以不传replyUrl必须传递 1仿真地图审批spdm内部feign 2知识库审批spdm内部feign 4交付物审批spdm内部feign
@Override
protected int getNoticeType() {
return ApproveTypeEnum.DESIGN_APPROVE.getCode();
}
@Override
public SdmResponse noticeResult(LaunchApproveReq req) {
return projectFeignClient.receiveApproveNotice(req);
}
}