fix:查询工位所有结构细化完成时间、工位升级时间、清单下发时间

This commit is contained in:
2026-01-27 09:48:44 +08:00
parent 9ded8a078b
commit 81de41f7f7
11 changed files with 435 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState"> <component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
<option name="chatAppRouterInfo" value="builder/697475c803c032e49caec283" /> <option name="chatAppRouterInfo" value="builder/697757ee83e9f2b0bd667524" />
<option name="progress" value="1.0" /> <option name="progress" value="1.0" />
</component> </component>
</project> </project>

View File

@@ -0,0 +1,24 @@
package com.sdm.common.entity.req.project;
import com.sdm.common.entity.BaseReq;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* 获取专用时间请求参数
*/
@Data
@Schema(description = "获取专用时间请求参数")
public class GetDedicatedTimeReq extends BaseReq {
@Schema(description = "项目UUID,用于获取项目信息")
@NotBlank(message = "projectUuid不能为空")
private String projectUuid;
/**
* 节点UUID()
*/
@Schema(description = "节点UUID可以传阶段uuid用于获取阶段下的所有工位")
@NotBlank(message = "nodeUuid不能为空")
private String nodeUuid;
}

View File

@@ -8,4 +8,21 @@ public class PageDataResp<T> {
Integer currentPage; Integer currentPage;
Integer pageSize; Integer pageSize;
T data; T data;
/**
* 构建分页响应对象
* @param data 数据列表
* @param total 总记录数
* @param currentPage 当前页码
* @param pageSize 每页大小
* @return 分页响应对象
*/
public static <T> PageDataResp<T> of(T data, Long total, Integer currentPage, Integer pageSize) {
PageDataResp<T> resp = new PageDataResp<>();
resp.setData(data);
resp.setTotal(total);
resp.setCurrentPage(currentPage);
resp.setPageSize(pageSize);
return resp;
}
} }

View File

@@ -10,6 +10,7 @@ import com.sdm.common.entity.resp.project.SimulationNodeResp;
import com.sdm.common.entity.resp.project.SimulationRunResp; import com.sdm.common.entity.resp.project.SimulationRunResp;
import com.sdm.common.feign.inter.project.ISimulationNodeFeignClient; import com.sdm.common.feign.inter.project.ISimulationNodeFeignClient;
import com.sdm.common.log.annotation.SysLog; import com.sdm.common.log.annotation.SysLog;
import com.sdm.project.model.po.ProjectNodePo;
import com.sdm.project.model.req.*; import com.sdm.project.model.req.*;
import com.sdm.project.service.INodeService; import com.sdm.project.service.INodeService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -120,13 +121,23 @@ public class SimulationNodeController implements ISimulationNodeFeignClient {
*/ */
@GetMapping("/getChildrenNodeList") @GetMapping("/getChildrenNodeList")
@Operation(summary = "根据项目查询子节点列表", description = "根据项目查询子节点列表") @Operation(summary = "根据项目查询子节点列表", description = "根据项目查询子节点列表")
public SdmResponse getChildrenNodeList(@RequestParam(value = "nodeId") String nodeId, @RequestParam(value = "nodeType") String nodeType) { public SdmResponse<List<ProjectNodePo>> getChildrenNodeList(@RequestParam(value = "nodeId") String nodeId, @RequestParam(value = "nodeType") String nodeType) {
if (StringUtils.isBlank(nodeId) || StringUtils.isBlank(nodeType)) { if (StringUtils.isBlank(nodeId) || StringUtils.isBlank(nodeType)) {
return SdmResponse.failed("节点id和类型都不能为空"); return SdmResponse.failed("节点id和类型都不能为空");
} }
return nodeService.getChildrenNodeList(Collections.singletonList(nodeId), nodeType); return nodeService.getChildrenNodeList(Collections.singletonList(nodeId), nodeType);
} }
/**
* 获取项目专项时间
* @param req
* @return
*/
@PostMapping("/getDedicatedTime")
@Operation(summary = "获取专项时间", description = "获取专项时间")
public SdmResponse getDedicatedTime(@RequestBody GetDedicatedTimeReq req) {
return nodeService.getDedicatedTime(req);
}
/** /**
* 根据节点类型获取所有节点 * 根据节点类型获取所有节点

View File

@@ -0,0 +1,12 @@
package com.sdm.project.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sdm.project.model.entity.SimulationNodeExtra;
import org.apache.ibatis.annotations.Mapper;
/**
* SimulationNodeExtra 数据访问层
*/
@Mapper
public interface SimulationNodeExtraMapper extends BaseMapper<SimulationNodeExtra> {
}

View File

@@ -0,0 +1,76 @@
package com.sdm.project.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
/**
* simulation_node_extra 表对应的实体类
* 用于存储仿真节点的扩展属性信息
*/
@Data
@TableName("simulation_node_extra") // 映射数据库表名
public class SimulationNodeExtra implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(type = IdType.AUTO) // 自增主键
private Integer id;
/**
* 节点ID
*/
@TableField("nodeId") // 映射数据库字段名如果数据库是nodeid可省略这里按表中列名写
private String nodeId;
/**
* 属性名称
*/
@TableField("propertyName")
private String propertyName;
/**
* 属性值
*/
@TableField("propertyValue")
private String propertyValue;
/**
* 值类型
*/
@TableField("valueType")
private String valueType;
/**
* 属性分类
*/
@TableField("propertyClass")
private String propertyClass;
/**
* 创作者ID
*/
@TableField("creator")
private Long creator;
/**
* 创建时间
*/
@TableField("create_time")
private String createTime;
/**
* 更新者ID
*/
@TableField("updater")
private Long updater;
/**
* 更新时间
*/
@TableField("update_time")
private String updateTime;
}

View File

@@ -187,4 +187,14 @@ public class ProjectNodePo extends NodeAllBase {
private String discipline; private String discipline;
private Integer expStatus; private Integer expStatus;
/**
* 所属项目名称
*/
private String projectName;
/**
* 所属项目编码
*/
private String projectCode;
} }

View File

@@ -8,6 +8,7 @@ import com.sdm.common.entity.resp.AllNodeByProjectIdAndTypeResp;
import com.sdm.common.entity.resp.project.SimulationNodeResp; import com.sdm.common.entity.resp.project.SimulationNodeResp;
import com.sdm.common.entity.resp.project.SimulationRunResp; import com.sdm.common.entity.resp.project.SimulationRunResp;
import com.sdm.project.model.entity.SimulationNode; import com.sdm.project.model.entity.SimulationNode;
import com.sdm.project.model.po.ProjectNodePo;
import com.sdm.project.model.req.*; import com.sdm.project.model.req.*;
import com.sdm.project.model.req.YA.SyncCidProjectReq; import com.sdm.project.model.req.YA.SyncCidProjectReq;
import com.sdm.project.model.resp.YA.BosimSaveProjectTaskRsp; import com.sdm.project.model.resp.YA.BosimSaveProjectTaskRsp;
@@ -31,7 +32,9 @@ public interface INodeService extends IService<SimulationNode> {
SdmResponse getProjectMemberList(GetProjectListReq req); SdmResponse getProjectMemberList(GetProjectListReq req);
SdmResponse getChildrenNodeList(List<String> projectNodeIdList, String nodeType); SdmResponse<List<ProjectNodePo>> getChildrenNodeList(List<String> projectNodeIdList, String nodeType);
SdmResponse getDedicatedTime(GetDedicatedTimeReq req);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> getAllNodeByBodeType(String nodeType, Long nodeId); SdmResponse<List<AllNodeByProjectIdAndTypeResp>> getAllNodeByBodeType(String nodeType, Long nodeId);

View File

@@ -0,0 +1,28 @@
package com.sdm.project.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdm.project.model.entity.SimulationNodeExtra;
import java.util.List;
import java.util.Map;
/**
* SimulationNodeExtra 业务层接口
*/
public interface SimulationNodeExtraService extends IService<SimulationNodeExtra> {
/**
* 基于 nodeId、propertyName 查询节点扩展属性
* @param nodeId 节点ID
* @param propertyName 属性名称
* @return 节点扩展属性列表
*/
List<SimulationNodeExtra> getSimulationNodeExtraByNodeIdAndPropertyName(String nodeId, String propertyName);
/**
* 批量查询节点扩展属性
* @param nodeIds 节点ID数组
* @param propertyNames 属性名称数组
* @return 节点扩展属性Map外层key为nodeId内层key为propertyName
*/
Map<String, Map<String, SimulationNodeExtra>> batchGetNodeExtraMap(List<String> nodeIds, List<String> propertyNames);
}

View File

@@ -41,10 +41,7 @@ import com.sdm.project.dao.SimulationProjectMapper;
import com.sdm.project.model.bo.TaskExtraNode; import com.sdm.project.model.bo.TaskExtraNode;
import com.sdm.project.model.bo.TaskNode; import com.sdm.project.model.bo.TaskNode;
import com.sdm.project.model.bo.TaskNodeTag; import com.sdm.project.model.bo.TaskNodeTag;
import com.sdm.project.model.entity.SimulationNode; import com.sdm.project.model.entity.*;
import com.sdm.project.model.entity.SimulationRun;
import com.sdm.project.model.entity.SimulationTask;
import com.sdm.project.model.entity.SimulationTaskMember;
import com.sdm.project.model.po.PerformanceNodePo; import com.sdm.project.model.po.PerformanceNodePo;
import com.sdm.project.model.po.ProjectNodePo; import com.sdm.project.model.po.ProjectNodePo;
import com.sdm.project.model.po.TaskNodePo; import com.sdm.project.model.po.TaskNodePo;
@@ -63,7 +60,6 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.transaction.interceptor.TransactionAspectSupport;
@@ -78,6 +74,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@@ -127,6 +124,15 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
@Autowired @Autowired
private SimulationProjectMapper projectMapper; private SimulationProjectMapper projectMapper;
/**
* 扩展属性名称常量
*/
private static final String PROPERTY_PROJECT_UNDERTAKER = "projectUndertaker";
private static final String PROPERTY_STRUCTURE_REFINEMENT_TIME = "structureRefinementCompletionTime";
private static final String PROPERTY_STATION_UPGRADE_TIME = "stationUpgradeTime";
private static final String PROPERTY_LIST_RELEASE_TIME = "listReleaseTime";
public static final String SYNC_PROJECT_SOURCE = "EP"; public static final String SYNC_PROJECT_SOURCE = "EP";
@Autowired @Autowired
@@ -135,6 +141,9 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
@Autowired @Autowired
private LyricVTodoInfoService lyricVTodoInfoService; private LyricVTodoInfoService lyricVTodoInfoService;
@Autowired
private SimulationNodeExtraService simulationNodeExtraService;
private static final String[] FIELD_NAMES = { private static final String[] FIELD_NAMES = {
"projectNodeId", "projectNodeId",
"phaseNodeId", "phaseNodeId",
@@ -1217,7 +1226,7 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
} }
@Override @Override
public SdmResponse getChildrenNodeList(List<String> nodeIdList, String nodeType) { public SdmResponse<List<ProjectNodePo>> getChildrenNodeList(List<String> nodeIdList, String nodeType) {
log.info("getChildrenNodeListnodeIdList{}nodeType{}", nodeIdList, nodeType); log.info("getChildrenNodeListnodeIdList{}nodeType{}", nodeIdList, nodeType);
List<ProjectNodePo> projectNodePoList = mapper.queryNodeListByParentNodeId(nodeIdList); List<ProjectNodePo> projectNodePoList = mapper.queryNodeListByParentNodeId(nodeIdList);
if (CollectionUtils.isEmpty(projectNodePoList)) { if (CollectionUtils.isEmpty(projectNodePoList)) {
@@ -1258,6 +1267,182 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
return response; return response;
} }
@Override
public SdmResponse getDedicatedTime(GetDedicatedTimeReq req) {
String projectUuid = req.getProjectUuid();
// 验证项目存在性
SimulationNode project = getProjectOrThrow(projectUuid);
// 获取项目扩展属性
List<SimulationNodeExtra> projectExtras = simulationNodeExtraService
.getSimulationNodeExtraByNodeIdAndPropertyName(projectUuid, PROPERTY_PROJECT_UNDERTAKER);
// 获取工位列表并分页
List<ProjectNodePo> allWorkspaces = getWorkspaceListOrThrow(req.getNodeUuid());
PageSlice<ProjectNodePo> pageSlice = sliceWorkspaces(allWorkspaces, req.getCurrent(), req.getSize());
// 批量查询当前页工位的扩展属性
Map<String, Map<String, SimulationNodeExtra>> workspaceExtrasMap = batchQueryWorkspaceExtras(pageSlice.getData());
// 组装工位数据(项目信息 + 扩展属性)
pageSlice.getData().forEach(workspace ->
enrichWorkspaceWithProjectData(workspace, project, projectExtras, workspaceExtrasMap)
);
// 构建分页响应
return SdmResponse.success(PageDataResp.of(
pageSlice.getData(),
pageSlice.getTotal(),
req.getCurrent(),
req.getSize()
));
}
/**
* 获取项目信息,不存在则抛异常
*/
private SimulationNode getProjectOrThrow(String projectUuid) {
SimulationNode project = this.lambdaQuery()
.eq(SimulationNode::getUuid, projectUuid)
.one();
if (ObjectUtils.isEmpty(project)) {
log.error("[getDedicatedTime] 项目不存在 projectUuid={}", projectUuid);
throw new IllegalArgumentException("项目不存在");
}
return project;
}
/**
* 获取项目下所有工位,不存在则抛异常
*/
private List<ProjectNodePo> getWorkspaceListOrThrow(String nodeUuid) {
SdmResponse<List<ProjectNodePo>> response = getChildrenNodeList(
Collections.singletonList(nodeUuid),
NodeTypeEnum.WORKSPACE.getValue()
);
if (!response.isSuccess() || ObjectUtils.isEmpty(response.getData())) {
log.error("[getDedicatedTime] 未查询到项目工位信息 projectUuid={}", nodeUuid);
throw new IllegalStateException("未查询到项目工位信息");
}
return response.getData();
}
/**
* 对工位列表进行内存分页
*/
private PageSlice<ProjectNodePo> sliceWorkspaces(List<ProjectNodePo> allWorkspaces, int pageNum, int pageSize) {
int total = allWorkspaces.size();
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, total);
if (startIndex >= total) {
log.warn("[getDedicatedTime] 分页参数超出范围 pageNum={} pageSize={} total={}", pageNum, pageSize, total);
return new PageSlice<>(Collections.emptyList(), 0L);
}
List<ProjectNodePo> pageData = allWorkspaces.subList(startIndex, endIndex);
return new PageSlice<>(pageData, (long) total);
}
/**
* 批量查询工位扩展属性
*/
private Map<String, Map<String, SimulationNodeExtra>> batchQueryWorkspaceExtras(List<ProjectNodePo> workspaces) {
List<String> workspaceUuids = workspaces.stream()
.map(ProjectNodePo::getUuid)
.collect(Collectors.toList());
List<String> propertyNames = Arrays.asList(
PROPERTY_STRUCTURE_REFINEMENT_TIME,
PROPERTY_STATION_UPGRADE_TIME,
PROPERTY_LIST_RELEASE_TIME
);
return simulationNodeExtraService.batchGetNodeExtraMap(workspaceUuids, propertyNames);
}
/**
* 为工位设置项目信息和扩展属性
*/
private void enrichWorkspaceWithProjectData(
ProjectNodePo workspace,
SimulationNode project,
List<SimulationNodeExtra> projectExtras,
Map<String, Map<String, SimulationNodeExtra>> workspaceExtrasMap
) {
// 设置项目基本信息
workspace.setProjectName(project.getNodeName());
workspace.setProjectCode(project.getNodeCode());
// 构建并设置扩展属性列表
List<SpdmNodeExtraVo> extras = buildExtrasForWorkspace(
projectExtras,
workspaceExtrasMap.getOrDefault(workspace.getUuid(), Collections.emptyMap())
);
workspace.setExtras(extras);
}
/**
* 构建工位的扩展属性列表(项目扩展 + 工位扩展)
*/
private List<SpdmNodeExtraVo> buildExtrasForWorkspace(
List<SimulationNodeExtra> projectExtras,
Map<String, SimulationNodeExtra> workspaceExtrasMap
) {
List<SpdmNodeExtraVo> extras = new ArrayList<>();
// 添加项目扩展属性
projectExtras.stream()
.map(this::convertToExtraVo)
.forEach(vo -> extras.add(vo));
// 添加工位扩展属性
Stream.of(
PROPERTY_STRUCTURE_REFINEMENT_TIME,
PROPERTY_STATION_UPGRADE_TIME,
PROPERTY_LIST_RELEASE_TIME
).map(workspaceExtrasMap::get)
.filter(ObjectUtils::isNotEmpty)
.map(this::convertToExtraVo)
.forEach(vo -> extras.add(vo));
return extras;
}
/**
* 将 SimulationNodeExtra 转换为 SpdmNodeExtraVo
*/
private SpdmNodeExtraVo convertToExtraVo(SimulationNodeExtra extra) {
SpdmNodeExtraVo vo = new SpdmNodeExtraVo();
BeanUtils.copyProperties(extra, vo);
return vo;
}
/**
* 分页数据切片内部类
*/
private static class PageSlice<T> {
private final List<T> data;
private final Long total;
public PageSlice(List<T> data, Long total) {
this.data = data;
this.total = total;
}
public List<T> getData() {
return data;
}
public Long getTotal() {
return total;
}
}
@Override @Override
public SdmResponse<List<AllNodeByProjectIdAndTypeResp>> getAllNodeByBodeType(String nodeType, Long nodeId) { public SdmResponse<List<AllNodeByProjectIdAndTypeResp>> getAllNodeByBodeType(String nodeType, Long nodeId) {
@@ -2929,4 +3114,4 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
return SdmResponse.success(resultResponse); return SdmResponse.success(resultResponse);
} }
} }

View File

@@ -0,0 +1,59 @@
package com.sdm.project.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sdm.project.dao.SimulationNodeExtraMapper;
import com.sdm.project.model.entity.SimulationNodeExtra;
import com.sdm.project.service.SimulationNodeExtraService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* SimulationNodeExtra 业务层实现
*/
@Service
public class SimulationNodeExtraServiceImpl extends ServiceImpl<SimulationNodeExtraMapper, SimulationNodeExtra>
implements SimulationNodeExtraService {
//基于 nodeId、propertyName 查询节点扩展属性
public List<SimulationNodeExtra> getSimulationNodeExtraByNodeIdAndPropertyName(String nodeId, String propertyName) {
return this.lambdaQuery().eq(SimulationNodeExtra::getNodeId, nodeId)
.eq(ObjectUtils.isNotEmpty(propertyName), SimulationNodeExtra::getPropertyName, propertyName).list();
}
/**
* 批量查询节点扩展属性
* @param nodeIds 节点ID数组
* @param propertyNames 属性名称数组
* @return 节点扩展属性Map外层key为nodeId内层key为propertyName
*/
@Override
public Map<String, Map<String, SimulationNodeExtra>> batchGetNodeExtraMap(List<String> nodeIds, List<String> propertyNames) {
// 参数校验
if (CollectionUtils.isEmpty(nodeIds) || CollectionUtils.isEmpty(propertyNames)) {
return new HashMap<>();
}
// 批量查询
List<SimulationNodeExtra> extraList = this.lambdaQuery()
.in(SimulationNodeExtra::getNodeId, nodeIds)
.in(SimulationNodeExtra::getPropertyName, propertyNames)
.list();
// 转换为Map结构: nodeId -> (propertyName -> SimulationNodeExtra)
return extraList.stream()
.collect(Collectors.groupingBy(
SimulationNodeExtra::getNodeId,
Collectors.toMap(
SimulationNodeExtra::getPropertyName,
extra -> extra,
(existing, replacement) -> existing // 如果有重复key保留第一个
)
));
}
}