diff --git a/1-sql/2026-03-09/simulation_work.sql b/1-sql/2026-03-09/simulation_work.sql new file mode 100644 index 00000000..dae560cd --- /dev/null +++ b/1-sql/2026-03-09/simulation_work.sql @@ -0,0 +1,3 @@ +ALTER TABLE spdm_baseline.simulation_work ADD approveStatus varchar(100) NULL COMMENT 'EP审批状态'; +ALTER TABLE spdm_baseline.simulation_work ADD planBeginTime datetime NULL COMMENT '任务计划开始时间'; +ALTER TABLE spdm_baseline.simulation_work ADD planFinishTime datetime NULL COMMENT '任务计划完成时间'; diff --git a/common/src/main/java/com/sdm/common/service/TaskProgressService.java b/common/src/main/java/com/sdm/common/service/TaskProgressService.java index 6dd02a6e..ac11b797 100644 --- a/common/src/main/java/com/sdm/common/service/TaskProgressService.java +++ b/common/src/main/java/com/sdm/common/service/TaskProgressService.java @@ -32,4 +32,13 @@ public class TaskProgressService { } return taskProgressStatusList.getData().stream().collect(Collectors.toMap(DataDictionary::getDictName, DataDictionary::getDictValue)); } + + public Map getNameByValueMap() { + SdmResponse> taskProgressStatusList = sysConfigFeignClient.getDictionaryData(SUBMITTER_TASK_PROGRESS_STATUS); + if (!taskProgressStatusList.isSuccess() || ObjectUtils.isEmpty(taskProgressStatusList.getData())) { + log.error("字典信息查询失败"); + return emptyMap(); + } + return taskProgressStatusList.getData().stream().collect(Collectors.toMap(DataDictionary::getDictValue, DataDictionary::getDictName)); + } } diff --git a/data/src/main/java/com/sdm/data/controller/DataFileController.java b/data/src/main/java/com/sdm/data/controller/DataFileController.java index 124cd782..d4854724 100644 --- a/data/src/main/java/com/sdm/data/controller/DataFileController.java +++ b/data/src/main/java/com/sdm/data/controller/DataFileController.java @@ -558,7 +558,6 @@ public class DataFileController implements IDataFeignClient { * 文件信息入库准备发起评审 */ @AutoFillDictTags - @SysLog("新增文件") @PostMapping("/batchAddFileInfo") @Operation(summary = "文件信息入库准备发起评审") public SdmResponse> batchAddFileInfo(@RequestBody UploadFilesReq req) { diff --git a/project/src/main/java/com/sdm/project/controller/SimulationWorkController.java b/project/src/main/java/com/sdm/project/controller/SimulationWorkController.java index 9ab909f1..745ab5a8 100644 --- a/project/src/main/java/com/sdm/project/controller/SimulationWorkController.java +++ b/project/src/main/java/com/sdm/project/controller/SimulationWorkController.java @@ -49,4 +49,6 @@ public class SimulationWorkController { return simulationWorkService.deleteWork(req); } + + } diff --git a/project/src/main/java/com/sdm/project/model/entity/SimulationWork.java b/project/src/main/java/com/sdm/project/model/entity/SimulationWork.java index 7a4c26c0..0793f5c6 100644 --- a/project/src/main/java/com/sdm/project/model/entity/SimulationWork.java +++ b/project/src/main/java/com/sdm/project/model/entity/SimulationWork.java @@ -1,12 +1,10 @@ package com.sdm.project.model.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import com.sdm.common.entity.resp.system.CIDUserResp; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -99,4 +97,25 @@ public class SimulationWork implements Serializable { @TableField("taskId") private String taskId; + @ApiModelProperty(value = "EP审批状态") + @TableField("approveStatus") + private String approveStatus; + + @ApiModelProperty(value = "任务计划开始时间") + @TableField("planBeginTime") + private String planBeginTime; + + @ApiModelProperty(value = "任务计划完成时间") + @TableField("planFinishTime") + private String planFinishTime; + + + @Schema(description= "项目编号,列表展示使用") + @TableField(value = "projectCode", insertStrategy = FieldStrategy.NEVER,select = false,updateStrategy = FieldStrategy.NEVER) + private String projectCode; + + @Schema(description= "工位编号,列表展示使用") + @TableField(value = "workSpaceCode", insertStrategy = FieldStrategy.NEVER,select = false,updateStrategy = FieldStrategy.NEVER) + private String workSpaceCode; + } diff --git a/project/src/main/java/com/sdm/project/model/req/SpdmTaskListReq.java b/project/src/main/java/com/sdm/project/model/req/SpdmTaskListReq.java index 13e791c7..649dfc62 100644 --- a/project/src/main/java/com/sdm/project/model/req/SpdmTaskListReq.java +++ b/project/src/main/java/com/sdm/project/model/req/SpdmTaskListReq.java @@ -143,4 +143,6 @@ public class SpdmTaskListReq { private List filterDiscipline; + private String taskId; + } diff --git a/project/src/main/java/com/sdm/project/model/req/SpdmWorkListReq.java b/project/src/main/java/com/sdm/project/model/req/SpdmWorkListReq.java index 0f6b429f..44a4364f 100644 --- a/project/src/main/java/com/sdm/project/model/req/SpdmWorkListReq.java +++ b/project/src/main/java/com/sdm/project/model/req/SpdmWorkListReq.java @@ -1,19 +1,44 @@ + package com.sdm.project.model.req; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import jakarta.validation.constraints.NotNull; -import lombok.Data; + import com.sdm.project.model.bo.TaskNodeTag; + import io.swagger.v3.oas.annotations.media.Schema; + import jakarta.validation.constraints.NotNull; + import lombok.Data; -@JsonIgnoreProperties(ignoreUnknown = true) + import java.util.List; + + +/** + * 查询报工列表请求参数 + */ @Data public class SpdmWorkListReq { + /** 项目uuid */ + @Schema(description = "项目uuid") + private String projectId; - @NotNull(message = "current不能为空") + /** 工位uuid */ + @Schema(description = "工位uuid") + private String workSpaceId; + + /** 审批状态:0:未审批,1:已审批 */ + @Schema(description = "审批状态") + private Integer approveStatus; + + /** 类型 0:我确认的,1:我执行的 */ + @Schema(description = "类型") + private Integer type; + + @Schema(description = "任务id") + private String taskId; + + private List nodeTypeMap; + + /** 分页参数 */ + @NotNull(message = "分页参数不能为空") private Integer current; - @NotNull(message = "size不能为空") + @NotNull(message = "每页数量不能为空") private Integer size; - - @NotNull(message = "taskId不能为空") - private String taskId; -} +} \ No newline at end of file diff --git a/project/src/main/java/com/sdm/project/model/req/SpdmWorkReq.java b/project/src/main/java/com/sdm/project/model/req/SpdmWorkReq.java index 58470768..ef29ed9b 100644 --- a/project/src/main/java/com/sdm/project/model/req/SpdmWorkReq.java +++ b/project/src/main/java/com/sdm/project/model/req/SpdmWorkReq.java @@ -2,6 +2,7 @@ package com.sdm.project.model.req; import com.baomidou.mybatisplus.annotation.TableField; import com.sdm.common.entity.pojo.BaseEntity; +import com.sdm.project.model.bo.TaskNodeTag; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -41,4 +42,12 @@ public class SpdmWorkReq { private List delIdList; + private List idMap; + + private List nodeTypeMap; + /** + * 计划开始和结束时间 + */ + private String[] planTime; + } diff --git a/project/src/main/java/com/sdm/project/service/impl/SimulationWorkServiceImpl.java b/project/src/main/java/com/sdm/project/service/impl/SimulationWorkServiceImpl.java index 1fa89415..a075f29f 100644 --- a/project/src/main/java/com/sdm/project/service/impl/SimulationWorkServiceImpl.java +++ b/project/src/main/java/com/sdm/project/service/impl/SimulationWorkServiceImpl.java @@ -1,6 +1,8 @@ package com.sdm.project.service.impl; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ArrayUtil; +import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -11,22 +13,31 @@ import com.sdm.common.common.ThreadLocalContext; import com.sdm.common.entity.req.system.UserQueryReq; import com.sdm.common.entity.resp.system.CIDUserResp; import com.sdm.common.feign.impl.system.SysUserFeignClientImpl; +import com.sdm.common.service.TaskProgressService; import com.sdm.common.utils.PageUtils; import com.sdm.common.utils.TimeCalculator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.sdm.outbridge.entity.LyricVProjectBatchToDM; import com.sdm.outbridge.service.lyric.LyricVProjectBatchToDmService; import com.sdm.outbridge.service.lyric.LyricVProjectToDmService; import com.sdm.project.common.MemberTypeEnum; +import com.sdm.project.common.TaskQryTypeEnum; +import com.sdm.project.dao.SimulationNodeMapper; import com.sdm.project.dao.SimulationTaskMapper; import com.sdm.project.dao.SimulationWorkMapper; +import com.sdm.project.model.bo.TaskNodeTag; +import com.sdm.project.model.entity.SimulationNode; import com.sdm.project.model.entity.SimulationTask; import com.sdm.project.model.entity.SimulationTaskExtra; import com.sdm.project.model.entity.SimulationWork; +import com.sdm.project.model.req.SpdmTaskListReq; import com.sdm.project.model.req.SpdmWorkListReq; import com.sdm.project.model.req.SpdmWorkReq; +import com.sdm.project.model.vo.SpdmNewTaskVo; import com.sdm.project.model.vo.SpdmTaskMemberVo; import com.sdm.common.entity.resp.project.SpdmTaskVo; import com.sdm.project.service.ISimulationWorkService; +import com.sdm.project.service.ITaskService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -36,6 +47,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.util.*; import java.util.function.Function; @@ -62,6 +74,18 @@ public class SimulationWorkServiceImpl extends ServiceImpl taskVoList = (List) dataObj.get("data"); + if (CollectionUtils.isNotEmpty(taskVoList)) { + SpdmNewTaskVo taskVo = taskVoList.get(0); + // 构造EP创建任务参数 + // 项目号 + + // 机台号 + + // 工位号 + + String projectCode = getNodeCodeByType(taskVo, req.getIdMap(), "project"); + String machineCode = getNodeCodeByType(taskVo, req.getIdMap(), "machine"); + String workspaceCode = getNodeCodeByType(taskVo, req.getIdMap(), "workspace"); + + // 工序 任务名称-学科 +// taskVo.getTaskName() + "-" + taskVo.getDiscipline(); + + // 任务详情 报工名称-应完成阶段 + Map taskProgressMap = taskProgressService.getNameByValueMap(); +// simulationWork.getWorkName() + "-" + taskProgressMap.get(simulationWork.getShouldProgress()); + + // 创建时间 + + // 计划开始时间 + simulationWork.getPlanBeginTime(); + + // 计划完成时间 + simulationWork.getPlanFinishTime(); + + // 实际开始时间 + + // 报工日期 当天 + + // 计划工时 + simulationWork.getPlanWorkHour(); + + // 标准工时 + simulationWork.getPlanWorkHour(); + + // 责任人工号 + // 根据userId查询工号 + UserQueryReq userReq = new UserQueryReq(); + userReq.setUserId(Long.valueOf(simulationWork.getOwner())); + userReq.setTenantId(ThreadLocalContext.getTenantId()); + SdmResponse sdmResponse = sysUserFeignClient.queryUserDetail(userReq); + if (sdmResponse.getData() != null) { + sdmResponse.getData().getUsername(); + } + + // 确认人工号 + userReq.setUserId(Long.valueOf(simulationWork.getCreator())); + SdmResponse sdmResponse2 = sysUserFeignClient.queryUserDetail(userReq); + if (sdmResponse2.getData() != null) { + sdmResponse2.getData().getUsername(); + } + + // SAP工序ID 固定为2C + + // 工时属性 固定为研发 + + } + } + + + return this.lambdaUpdate() .set(SimulationWork::getBeginTime, curDateStr) .eq(SimulationWork::getId, workId) @@ -192,6 +300,12 @@ public class SimulationWorkServiceImpl extends ServiceImpl workList = this.lambdaQuery().eq(SimulationWork::getTaskId, req.getTaskId()).list(); - if (CollectionUtils.isEmpty(workList)) { - PageInfo page = new PageInfo<>(workList); - return PageUtils.getJsonObjectSdmResponse(workList, page); - } - // 当前用户需要是报工条目的创建人或负责人 Long userId = ThreadLocalContext.getUserId(); - workList = workList.stream().filter(work -> userId.equals(work.getOwner()) || userId.equals(work.getCreator())).collect(Collectors.toList()); + List workList; + + // 工位筛选:获取符合条件的taskId列表 + List filteredTaskIds = null; + if (StringUtils.isNotBlank(req.getWorkSpaceId())) { + filteredTaskIds = getTaskIdsByNodeId(req, "workspace", req.getWorkSpaceId()); + if (CollectionUtils.isEmpty(filteredTaskIds)) { + // 没有匹配的任务,返回空结果 + PageInfo page = new PageInfo<>(new ArrayList<>()); + return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), page); + } + } + + // 项目筛选:获取符合条件的taskId列表 + if (StringUtils.isNotBlank(req.getProjectId())) { + List projectTaskIds = getTaskIdsByNodeId(req, "project", req.getProjectId()); + if (CollectionUtils.isEmpty(projectTaskIds)) { + // 没有匹配的任务,返回空结果 + PageInfo page = new PageInfo<>(new ArrayList<>()); + return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), page); + } + // 如果已有工位筛选,取交集 + if (filteredTaskIds != null) { + filteredTaskIds = filteredTaskIds.stream() + .filter(projectTaskIds::contains) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(filteredTaskIds)) { + PageInfo page = new PageInfo<>(new ArrayList<>()); + return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), page); + } + } else { + filteredTaskIds = projectTaskIds; + } + } + + // 判断是否传了taskId + if (StringUtils.isNotBlank(req.getTaskId())) { + // 传了taskId,按原逻辑查询 + PageHelper.startPage(req.getCurrent(), req.getSize()); + workList = this.lambdaQuery().eq(SimulationWork::getTaskId, req.getTaskId()).list(); + if (CollectionUtils.isEmpty(workList)) { + PageInfo page = new PageInfo<>(workList); + return PageUtils.getJsonObjectSdmResponse(workList, page); + } + // 当前用户需要是报工条目的创建人或负责人 + workList = workList.stream().filter(work -> userId.equals(work.getOwner()) || userId.equals(work.getCreator())).collect(Collectors.toList()); + } else { + // 不传taskId,根据type查询 + PageHelper.startPage(req.getCurrent(), req.getSize()); + if (req.getType() != null && req.getType() == 0) { + // type=0:查询当前登录人为creator(我确认的) + workList = this.lambdaQuery().eq(SimulationWork::getCreator, userId).list(); + } else if (req.getType() != null && req.getType() == 1) { + // type=1:查询当前登录人为owner(我执行的) + workList = this.lambdaQuery().eq(SimulationWork::getOwner, userId).list(); + } else { + // type为空或其他值,查询全部 + workList = this.lambdaQuery().list(); + } + + // 如果有筛选条件,过滤workList + if (filteredTaskIds != null && CollectionUtils.isNotEmpty(workList)) { + List finalFilteredTaskIds = filteredTaskIds; + workList = workList.stream() + .filter(work -> finalFilteredTaskIds.contains(work.getTaskId())) + .collect(Collectors.toList()); + } + } + if (CollectionUtils.isEmpty(workList)) { PageInfo page = new PageInfo<>(workList); return PageUtils.getJsonObjectSdmResponse(workList, page); } + + // 填充projectCode和workSpaceCode + fillProjectAndWorkSpaceCode(workList, req.getNodeTypeMap()); + SdmResponse> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(workList.stream().map(SimulationWork::getOwner).filter(ObjectUtils::isNotEmpty).toList()).build()); if (CollectionUtils.isEmpty(cidUserResp.getData())) { PageInfo page = new PageInfo<>(workList); @@ -364,6 +543,182 @@ public class SimulationWorkServiceImpl extends ServiceImpl workList, List nodeTypeMap) { + if (CollectionUtils.isEmpty(nodeTypeMap) || CollectionUtils.isEmpty(workList)) { + return; + } + + // 1. 获取所有taskId,批量查询simulation_task + List taskIds = workList.stream() + .map(SimulationWork::getTaskId) + .filter(StringUtils::isNotBlank) + .distinct() + .toList(); + if (CollectionUtils.isEmpty(taskIds)) { + return; + } + + List tasks = simulationTaskMapper.selectList( + new QueryWrapper().in("uuid", taskIds) + ); + if (CollectionUtils.isEmpty(tasks)) { + return; + } + Map taskMap = tasks.stream() + .collect(Collectors.toMap(SimulationTask::getUuid, Function.identity())); + + // 2. 从nodeTypeMap获取project和workspace对应的tag字段名 + String projectTagField = nodeTypeMap.stream() + .filter(tag -> "project".equals(tag.getKey())) + .map(TaskNodeTag::getValue) + .findFirst() + .orElse(null); + String workspaceTagField = nodeTypeMap.stream() + .filter(tag -> "workspace".equals(tag.getKey())) + .map(TaskNodeTag::getValue) + .findFirst() + .orElse(null); + + // 3. 收集所有需要查询的nodeId + Set nodeIds = new HashSet<>(); + Map taskProjectNodeIdMap = new HashMap<>(); + Map taskWorkspaceNodeIdMap = new HashMap<>(); + + for (SimulationWork work : workList) { + SimulationTask task = taskMap.get(work.getTaskId()); + if (task == null) continue; + + // 通过反射获取tag字段值 + if (StringUtils.isNotBlank(projectTagField)) { + String projectNodeId = getTagValue(task, projectTagField); + if (StringUtils.isNotBlank(projectNodeId)) { + nodeIds.add(projectNodeId); + taskProjectNodeIdMap.put(work.getTaskId(), projectNodeId); + } + } + if (StringUtils.isNotBlank(workspaceTagField)) { + String workspaceNodeId = getTagValue(task, workspaceTagField); + if (StringUtils.isNotBlank(workspaceNodeId)) { + nodeIds.add(workspaceNodeId); + taskWorkspaceNodeIdMap.put(work.getTaskId(), workspaceNodeId); + } + } + } + + if (CollectionUtils.isEmpty(nodeIds)) { + return; + } + + // 4. 批量查询simulation_node + List nodes = simulationNodeMapper.selectList( + new QueryWrapper().in("uuid", nodeIds) + ); + if (CollectionUtils.isEmpty(nodes)) { + return; + } + Map nodeCodeMap = nodes.stream() + .collect(Collectors.toMap(SimulationNode::getUuid, SimulationNode::getNodeCode)); + + // 5. 设置projectCode和workSpaceCode + for (SimulationWork work : workList) { + String projectNodeId = taskProjectNodeIdMap.get(work.getTaskId()); + if (StringUtils.isNotBlank(projectNodeId)) { + work.setProjectCode(nodeCodeMap.get(projectNodeId)); + } + String workspaceNodeId = taskWorkspaceNodeIdMap.get(work.getTaskId()); + if (StringUtils.isNotBlank(workspaceNodeId)) { + work.setWorkSpaceCode(nodeCodeMap.get(workspaceNodeId)); + } + } + } + + /** + * 通过反射获取SimulationTask的tag字段值 + */ + private String getTagValue(SimulationTask task, String tagField) { + try { + java.lang.reflect.Field field = SimulationTask.class.getDeclaredField(tagField); + field.setAccessible(true); + return (String) field.get(task); + } catch (Exception e) { + log.warn("获取SimulationTask的tag字段值失败,字段名:{}", tagField, e); + return null; + } + } + + /** + * 根据节点uuid获取符合条件的taskId列表 + * @param req 请求参数 + * @param nodeTypeKey nodeTypeMap中的key(如workspace、project) + * @param nodeId 节点uuid + * @return taskId列表 + */ + private List getTaskIdsByNodeId(SpdmWorkListReq req, String nodeTypeKey, String nodeId) { + // 1. 从nodeTypeMap中获取对应的tag字段 + String tagField = null; + if (CollectionUtils.isNotEmpty(req.getNodeTypeMap())) { + tagField = req.getNodeTypeMap().stream() + .filter(tag -> nodeTypeKey.equals(tag.getKey())) + .map(TaskNodeTag::getValue) + .findFirst() + .orElse(null); + } + + if (StringUtils.isBlank(tagField)) { + return null; + } + + // 2. 直接用nodeId查询simulation_task表 + QueryWrapper taskWrapper = new QueryWrapper<>(); + taskWrapper.eq(tagField, nodeId); + List tasks = simulationTaskMapper.selectList(taskWrapper); + + if (CollectionUtils.isEmpty(tasks)) { + return Collections.emptyList(); + } + return tasks.stream().map(SimulationTask::getUuid).toList(); + } + + /** + * 根据nodeTypeKey从SpdmNewTaskVo中获取对应的Code值 + * @param taskVo 任务VO + * @param nodeTypeMap 标签映射关系 + * @param nodeTypeKey 类型key(project、machine、workspace) + * @return 对应的Code值 + */ + private String getNodeCodeByType(SpdmNewTaskVo taskVo, List nodeTypeMap, String nodeTypeKey) { + if (taskVo == null || CollectionUtils.isEmpty(nodeTypeMap)) { + return null; + } + // 1. 从nodeTypeMap获取对应的tag字段名(如tag1、tag4、tag5) + String tagField = nodeTypeMap.stream() + .filter(tag -> nodeTypeKey.equals(tag.getKey())) + .map(TaskNodeTag::getValue) + .findFirst() + .orElse(null); + if (StringUtils.isBlank(tagField)) { + return null; + } + // 2. 构造对应的Code字段名(如tag1 -> tag1Code) + String codeField = tagField + "Code"; + // 3. 通过反射获取值 + try { + java.lang.reflect.Field field = SpdmNewTaskVo.class.getDeclaredField(codeField); + field.setAccessible(true); + return (String) field.get(taskVo); + } catch (Exception e) { + log.warn("获取SpdmNewTaskVo的{}字段值失败", codeField, e); + return null; + } + } + @Override public SdmResponse deleteWork(SpdmWorkReq req) { List delIdList = req.getDelIdList(); diff --git a/project/src/main/resources/mapper/SimulationTaskMapper.xml b/project/src/main/resources/mapper/SimulationTaskMapper.xml index 052884d1..adff1f5f 100644 --- a/project/src/main/resources/mapper/SimulationTaskMapper.xml +++ b/project/src/main/resources/mapper/SimulationTaskMapper.xml @@ -763,6 +763,9 @@ and demand_id = #{req.demandId} + + and st.uuid = #{req.taskId} + and task_name like #{searchKey1} @@ -880,6 +883,9 @@ and demand_id = #{req.demandId} + + and st.uuid = #{req.taskId} + and task_name like #{searchKey2}