Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-02-03 19:08:39 +08:00
13 changed files with 191 additions and 15 deletions

View File

@@ -0,0 +1,2 @@
ALTER TABLE simulation_task MODIFY COLUMN exe_status varchar(20) DEFAULT '1' NOT NULL COMMENT '执行状态';
ALTER TABLE simulation_task MODIFY COLUMN achieve_status varchar(20) DEFAULT '0' NULL;

View File

@@ -0,0 +1,30 @@
package com.sdm.common.entity.enums;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
@Schema(description = "附件文件夹名称枚举")
public enum AttachFileTypeEnum {
/**
* 项目附件文件夹名称
*/
PROJECT_FILE("项目文件"),
/**
* 需求附件文件夹名称
*/
DEMAND_FILE("需求附件");
String value;
AttachFileTypeEnum(String i) {
value = i;
}
public String getValue() {
return value;
}
}

View File

@@ -11,7 +11,6 @@ import java.util.List;
@Schema(description = "批量创建普通文件夹请求参数")
public class BatchCreateNormalDirReq {
@NotNull(message = "父节点UUID")
@Schema(description = "父节点UUID", requiredMode = Schema.RequiredMode.REQUIRED)
private String parentUUId;

View File

@@ -31,5 +31,6 @@ public class ProjectTreeReq {
@JsonProperty(value = "tag10")
private String tag10;
private String filterDiscipline;
}

View File

@@ -17,6 +17,8 @@ public class ProjectTreeTagReq {
private String projectNodeId;
private String filterDiscipline;
/**
* 根据projectNodeId和phaseNodeId构建

View File

@@ -143,4 +143,6 @@ public class SpdmTaskListReq {
private Long userId;
private String filterDiscipline;
}

View File

@@ -8,10 +8,7 @@ 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.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FilePermissionEnum;
import com.sdm.common.entity.enums.MessageTemplateEnum;
import com.sdm.common.entity.enums.ValueTypeEnum;
import com.sdm.common.entity.enums.*;
import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.system.SendMsgReq;
import com.sdm.common.entity.req.system.UserQueryReq;
@@ -200,8 +197,29 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
}
}
// 项目层级文件夹和需求文件夹中,新增一层【需求附件】文件夹
String projectNodeId = req.getProjectId();
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
batchCreateNormalDirReq.setParentUUId(req.getProjectId());
SdmResponse<FileMetadataInfoResp> fileMetadataInfoResp = dataFeignClient.queryFileMetadataInfo(projectNodeId, NodeTypeEnum.PROJECT.getValue(), 0L);
if (fileMetadataInfoResp.getData() == null) {
log.error("fileMetadataInfoResp为空,projectNodeId为{}",projectNodeId);
return SdmResponse.failed("新增需求失败!");
}
// 查询需求附件的uuid元数据表中【parentId是project的元数据主键id且originalName为需求附件】
FileMetadataInfoResp projectMetadataInfo = fileMetadataInfoResp.getData();
SdmResponse<List<FileMetadataInfoResp>> listSdmResponse = dataFeignClient.listDir(DirTypeEnum.PROJECT_NODE_DIR.getValue(), projectMetadataInfo.getId());
if (!listSdmResponse.isSuccess() || CollectionUtils.isEmpty(listSdmResponse.getData())) {
log.error("listSdmResponse为空,project的元数据主键id为{}",projectMetadataInfo.getId());
return SdmResponse.failed("新增需求失败!");
}
List<FileMetadataInfoResp> childrenMetadataInfoList = listSdmResponse.getData();
FileMetadataInfoResp demandAttachFileMetadataInfoResp = childrenMetadataInfoList.stream().filter(metadataInfo -> AttachFileTypeEnum.DEMAND_FILE.getValue().equals(metadataInfo.getOriginalName())).findFirst().orElse(null);
if (ObjectUtils.isEmpty(demandAttachFileMetadataInfoResp)) {
log.error("未查询到需求附件文件夹,当前项目下的子文件夹为:{}",childrenMetadataInfoList);
return SdmResponse.failed("新增需求失败!");
}
Long demandAttachFileMetadataInfoId = demandAttachFileMetadataInfoResp.getId();
batchCreateNormalDirReq.setParentId(demandAttachFileMetadataInfoId);
FolderItemReq folderItemReq = new FolderItemReq();
folderItemReq.setFolderName(req.getDemandName());
folderItemReq.setFolderUuid(req.getUuid());

View File

@@ -5,12 +5,14 @@ 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.entity.enums.AttachFileTypeEnum;
import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FilePermissionEnum;
import com.sdm.common.entity.enums.NodeTypeEnum;
import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.project.SpdmNodeListReq;
import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.feign.impl.data.DataClientFeignClientImpl;
import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
@@ -616,9 +618,35 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
List<UpdatePermissionReq> updatePermissionList) {
// 批量创建文件夹
if (CollectionUtils.isNotEmpty(createDirItemList)) {
// project的uuidcreateDirItemList中每一项project的uuid都一样取第一个即可
String projectNodeId = createDirItemList.get(0).getParentDirNodeInfo().getUuId();
if (StringUtils.isBlank(projectNodeId)) {
log.error("projectNodeId为空createDirItemList{}",createDirItemList);
return;
}
SdmResponse<FileMetadataInfoResp> fileMetadataInfoResp = dataFeignClient.queryFileMetadataInfo(projectNodeId, NodeTypeEnum.PROJECT.getValue(), 0L);
if (fileMetadataInfoResp.getData() == null) {
log.error("fileMetadataInfoResp为空,projectNodeId为{}",projectNodeId);
return;
}
// 查询需求附件的uuid元数据表中【parentId是project的元数据主键id且originalName为需求附件】
FileMetadataInfoResp projectMetadataInfo = fileMetadataInfoResp.getData();
SdmResponse<List<FileMetadataInfoResp>> listSdmResponse = dataFeignClient.listDir(DirTypeEnum.PROJECT_NODE_DIR.getValue(), projectMetadataInfo.getId());
if (!listSdmResponse.isSuccess() || CollectionUtils.isEmpty(listSdmResponse.getData())) {
log.error("listSdmResponse为空,project的元数据主键id为{}",projectMetadataInfo.getId());
return;
}
List<FileMetadataInfoResp> childrenMetadataInfoList = listSdmResponse.getData();
FileMetadataInfoResp demandAttachFileMetadataInfoResp = childrenMetadataInfoList.stream().filter(metadataInfo -> AttachFileTypeEnum.DEMAND_FILE.getValue().equals(metadataInfo.getOriginalName())).findFirst().orElse(null);
if (ObjectUtils.isEmpty(demandAttachFileMetadataInfoResp)) {
log.error("未查询到需求附件文件夹,当前项目下的子文件夹为:{}",childrenMetadataInfoList);
return;
}
Long demandAttachFileMetadataInfoId = demandAttachFileMetadataInfoResp.getId();
for (BatchCreateDirItem batchCreateDirItem : createDirItemList) {
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
batchCreateNormalDirReq.setParentUUId(batchCreateDirItem.getParentDirNodeInfo().getUuId());
// 2026-02-03 这里要挂在【需求附件】文件夹下了
batchCreateNormalDirReq.setParentId(demandAttachFileMetadataInfoId);
List<FolderItemReq> folderItemReqList = new ArrayList<>();
for (DirNodeInfo dirNodeInfo : batchCreateDirItem.getChildDirNodeInfos()) {
FolderItemReq folderItemReq = new FolderItemReq();

View File

@@ -9,6 +9,7 @@ import com.sdm.common.common.SdmResponse;
import com.sdm.common.common.ThreadLocalContext;
import com.sdm.common.entity.ExportExcelFormat;
import com.sdm.common.entity.constants.TagConstant;
import com.sdm.common.entity.enums.AttachFileTypeEnum;
import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FilePermissionEnum;
import com.sdm.common.entity.enums.NodeTypeEnum;
@@ -19,6 +20,7 @@ import com.sdm.common.entity.req.system.UserListReq;
import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.resp.AllNodeByProjectIdAndTypeResp;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.data.BatchCreateNormalDirResp;
import com.sdm.common.entity.resp.project.SimulationNodeResp;
import com.sdm.common.entity.resp.project.SimulationRunResp;
import com.sdm.common.entity.resp.system.CIDStaffResp;
@@ -218,7 +220,7 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
memberList = Arrays.stream(projectNode.getMemberList().split(",")).toList();
}
}else {
// 这里要兼容单独只创建阶段的逻辑,需要反查出项目经理并设置权限
// 这里要兼容单独只创建阶段的逻辑,需要反查出项目经理并设置权限
SpdmProjectNodeEditReq phaseNode = addNodeList.stream().filter(node -> NodeTypeEnum.PHASE.getValue().equals(node.getNodeType())).findFirst().orElse(null);
if (ObjectUtils.isNotEmpty(phaseNode)) {
List<SpdmNodeMemberVo> managerList = nodeMapper.getNodeMemberListByNodeIdList(Collections.singletonList(phaseNode.getParentId()));
@@ -1136,6 +1138,24 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
BatchCreateDirReq batchCreateDirReq = buildBatchCreateDirReq(filterResult);
// 4. 调用批量创建接口并记录日志
callBatchCreateDirApi(batchCreateDirReq);
// 项目下新增一层【项目文件】文件夹项目文件Tab上传的文件都放到这个文件夹里
// 5. 创建项目文件夹下【项目文件】层级文件夹
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
SpdmProjectNodeEditReq projectNode = filterResult.getProjectNode();
batchCreateNormalDirReq.setParentUUId(projectNode.getUuid());
List<FolderItemReq> folderItemReqList = new ArrayList<>();
FolderItemReq folderItemReq = new FolderItemReq();
folderItemReq.setFolderName(AttachFileTypeEnum.PROJECT_FILE.getValue());
folderItemReq.setFolderUuid(RandomUtil.generateString(32));
folderItemReqList.add(folderItemReq);
batchCreateNormalDirReq.setFolderItems(folderItemReqList);
log.info("创建【项目文件】文件夹请求参数:{}", batchCreateNormalDirReq);
try {
SdmResponse response = dataFeignClient.batchCreateNormalDirs(batchCreateNormalDirReq);
log.info("创建【项目文件】文件夹响应:{}", response);
} catch (Exception e) {
log.error("创建【项目文件】文件夹接口失败", e);
}
}
private void updatePermission(Long userId,String uuid) {
@@ -3328,6 +3348,18 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
permissionReqList.add(permissionReq);
}
/**
* 构建普通类型文件夹节点信息
*/
private DirNodeInfo buildDirNode(String nodeId, String nodeName, String parentNodeId) {
DirNodeInfo dirNodeInfo = new DirNodeInfo();
dirNodeInfo.setUuId(nodeId);
dirNodeInfo.setParentUuId(parentNodeId);
dirNodeInfo.setUuIdOwnType(NodeTypeEnum.NODE.getValue());
dirNodeInfo.setDirName(nodeName);
return dirNodeInfo;
}
/**
* 构建需求文件夹节点信息
*/
@@ -3375,8 +3407,43 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
log.info("无需求文件夹需要创建");
return SdmResponse.success();
}
// 项目层级文件夹和需求文件夹中,新增一层【需求附件】文件夹
List<FolderItemReq> demandAttachFolderItemReqList = new ArrayList<>();
BatchCreateNormalDirReq demandAttachBatchCreateNormalDirReq = new BatchCreateNormalDirReq();
demandAttachBatchCreateNormalDirReq.setParentUUId(projectNodeId);
FolderItemReq demandAttachFolderItemReq = new FolderItemReq();
demandAttachFolderItemReq.setFolderName(AttachFileTypeEnum.DEMAND_FILE.getValue());
demandAttachFolderItemReq.setFolderUuid(RandomUtil.generateString(32));
demandAttachFolderItemReqList.add(demandAttachFolderItemReq);
demandAttachBatchCreateNormalDirReq.setFolderItems(demandAttachFolderItemReqList);
log.info("批量创建需求附件文件夹请求参数:{}", demandAttachBatchCreateNormalDirReq);
BatchCreateNormalDirResp batchCreateNormalDirResp;
try {
SdmResponse<BatchCreateNormalDirResp> response = dataFeignClient.batchCreateNormalDirs(demandAttachBatchCreateNormalDirReq);
log.info("批量创建需求附件文件夹响应:{}", response);
if (!response.isSuccess() || ObjectUtils.isEmpty(response.getData())) {
log.error("调用批量创建需求附件文件夹接口失败,原因为:{}", response.getMessage());
return SdmResponse.failed("创建需求附件文件夹失败:,原因为:" + response.getMessage());
}
batchCreateNormalDirResp = response.getData();
} catch (Exception e) {
log.error("调用批量创建需求附件文件夹接口失败", e);
return SdmResponse.failed("创建需求附件文件夹失败:" + e.getMessage());
}
if (ObjectUtils.isEmpty(batchCreateNormalDirResp)) {
log.error("batchCreateNormalDirResp为空");
return SdmResponse.failed("创建需求附件文件夹失败");
}
List<BatchCreateNormalDirResp.DirInfo> successList = batchCreateNormalDirResp.getSuccessList();
if (CollectionUtils.isEmpty(successList)) {
log.error("successList为空");
return SdmResponse.failed("创建需求附件文件夹失败");
}
// 需求附件文件夹的元数据主键id
Long demandBatchMetadataInfoId = successList.get(0).getId();
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
batchCreateNormalDirReq.setParentUUId(projectNodeId);
batchCreateNormalDirReq.setParentId(demandBatchMetadataInfoId);
List<FolderItemReq> folderItemReqList = new ArrayList<>();
for (DirNodeInfo dirNodeInfo : demandDirNodeList) {
FolderItemReq folderItemReq = new FolderItemReq();

View File

@@ -458,6 +458,7 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
return SdmResponse.success(new ArrayList<>());
}
log.info("查询到的节点为:{}", taskTreeNodeList.stream().map(ProjectNodePo::getId).toList());
taskTreeReq.setFilterDiscipline(req.getFilterDiscipline());
taskTreeTaskList = mapper.getTaskListByTag(taskTreeReq);
if (CollectionUtils.isNotEmpty(taskTreeTaskList)) {
log.info("查询到的任务为:{}", taskTreeTaskList.stream().map(TaskNodePo::getId).toList());

View File

@@ -29,6 +29,7 @@ import com.sdm.common.entity.req.task.TaskExportExcelParam;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.project.SpdmTaskVo;
import com.sdm.common.entity.resp.project.TaskNodeExtraPo;
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;
@@ -2772,13 +2773,19 @@ public class TaskServiceImpl implements ITaskService {
log.info("项目成员为空");
return SdmResponse.success();
}
List<CIDUserResp> userList = (List<CIDUserResp>) ((JSONObject) sdmResponse.getData()).get("data");
List<CIDStaffResp> userList = (List<CIDStaffResp>) ((JSONObject) sdmResponse.getData()).get("data");
if (CollectionUtils.isEmpty(userList)) {
log.info("项目成员为空");
return SdmResponse.success();
}
List<Long> userIdList = userList.stream().map(CIDUserResp::getUserId).distinct().toList();
Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(CIDUserResp::getUserId, CIDUserResp::getNickname));
List<Long> userIdList = userList.stream().map(CIDStaffResp::getUserId).distinct().toList();
Map<Long, String> userMap = userList.stream()
.filter(resp -> Objects.nonNull(resp.getUserId()) && Objects.nonNull(resp.getUserInfo()))
.collect(Collectors.toMap(
CIDStaffResp::getUserId,
resp -> resp.getUserInfo().getNickname(),
(oldValue, newValue) -> newValue // 重复key处理保留新值
));
req.setUserIds(userIdList);
List<UserGroupTaskCompleteVo> userGroupTaskCompleteStatistics = mapper.getUserTaskCompleteStatistics(req);
// 按用户分组统计任务状态
@@ -2826,13 +2833,19 @@ public class TaskServiceImpl implements ITaskService {
log.info("项目成员为空");
return SdmResponse.success();
}
List<CIDUserResp> userList = (List<CIDUserResp>) ((JSONObject) sdmResponse.getData()).get("data");
List<CIDStaffResp> userList = (List<CIDStaffResp>) ((JSONObject) sdmResponse.getData()).get("data");
if (CollectionUtils.isEmpty(userList)) {
log.info("项目成员为空");
return SdmResponse.success();
}
List<Long> userIdList = userList.stream().map(CIDUserResp::getUserId).distinct().toList();
Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(CIDUserResp::getUserId, CIDUserResp::getNickname));
List<Long> userIdList = userList.stream().map(CIDStaffResp::getUserId).distinct().toList();
Map<Long, String> userMap = userList.stream()
.filter(resp -> Objects.nonNull(resp.getUserId()) && Objects.nonNull(resp.getUserInfo()))
.collect(Collectors.toMap(
CIDStaffResp::getUserId,
resp -> resp.getUserInfo().getNickname(),
(oldValue, newValue) -> newValue // 重复key处理保留新值
));
req.setUserIds(userIdList);
List<UserGroupDifficultyVo> userGroupDifficultyStatistics = mapper.getUserDifficultyStatistics(req);
// 按用户分组统计任务状态

View File

@@ -695,6 +695,9 @@
<bind name="searchKey10" value="'%' + req.tag10 + '%'"/>
and tag10 like #{searchKey10}
</if>
<if test="req.filterDiscipline != null and req.filterDiscipline != ''">
and (discipline = #{req.filterDiscipline} or discipline = '' or discipline = null)
</if>
</where>
</select>

View File

@@ -571,6 +571,11 @@
and STR_TO_DATE(finish_time,'%Y-%m-%d %H:%i:%s') <= #{req.finishETime}
]]>
</if>
<if test="req.filterDiscipline != null and req.filterDiscipline != ''">
and (discipline = #{req.filterDiscipline} or discipline = '' or discipline = null)
</if>
<!-- <if test='req.sortOrder != null and req.sortOrder == "0"'>-->
<!-- order by create_time-->
<!-- </if>-->
@@ -678,6 +683,11 @@
and STR_TO_DATE(finish_time,'%Y-%m-%d %H:%i:%s') <= #{req.finishETime}
]]>
</if>
<if test="req.filterDiscipline != null and req.filterDiscipline != ''">
and (discipline = #{req.filterDiscipline} or discipline = '' or discipline = null)
</if>
<!-- <if test='req.sortOrder != null and req.sortOrder == "0"'>-->
<!-- order by create_time-->
<!-- </if>-->