Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -4,10 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "从回收站彻底删除请求")
|
||||
public class PermanentDeleteFromRecycleReq {
|
||||
@Schema(description = "要彻底删除的文件/目录ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件/目录ID不能为空")
|
||||
private Long id;
|
||||
@Schema(description = "要彻底删除的文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件/目录ID列表不能为空")
|
||||
private List<Long> ids;
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "从回收站还原请求")
|
||||
public class RestoreFromRecycleReq {
|
||||
@Schema(description = "要还原的文件/目录ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件/目录ID不能为空")
|
||||
private Long id;
|
||||
@Schema(description = "要还原的文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件/目录ID列表不能为空")
|
||||
private List<Long> ids;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.sdm.common.entity.req.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "批量更新回收站过期时间请求")
|
||||
public class UpdateRecycleExpireReq {
|
||||
@Schema(description = "文件/目录ID列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "文件/目录ID列表不能为空")
|
||||
private List<Long> ids;
|
||||
|
||||
@Schema(description = "保留天数(从删除时间开始计算)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "保留天数不能为空")
|
||||
@Min(value = 0, message = "保留天数不能小于0")
|
||||
private Integer days;
|
||||
}
|
||||
@@ -146,31 +146,44 @@ public class DataFileController implements IDataFeignClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从回收站还原
|
||||
* 批量从回收站还原
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@SysLog("从回收站还原")
|
||||
@PostMapping("/restoreFromRecycle")
|
||||
@Operation(summary = "从回收站还原", description = "将文件/目录从回收站还原到原位置")
|
||||
@Operation(summary = "从回收站还原", description = "将文件/目录从回收站还原到原位置(支持批量)")
|
||||
public SdmResponse restoreFromRecycle(@RequestBody @Validated RestoreFromRecycleReq req) {
|
||||
return IDataFileService.restoreFromRecycle(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从回收站彻底删除
|
||||
* 批量从回收站彻底删除
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@SysLog("从回收站彻底删除")
|
||||
@PostMapping("/permanentDeleteFromRecycle")
|
||||
@Operation(summary = "从回收站彻底删除", description = "从回收站彻底删除文件/目录(物理删除,不可恢复)")
|
||||
@Operation(summary = "从回收站彻底删除", description = "从回收站彻底删除文件/目录(物理删除,不可恢复,支持批量)")
|
||||
public SdmResponse permanentDeleteFromRecycle(@RequestBody @Validated PermanentDeleteFromRecycleReq req) {
|
||||
return IDataFileService.permanentDeleteFromRecycle(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新回收站过期时间
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@SysLog("更新回收站过期时间")
|
||||
@PostMapping("/updateRecycleExpire")
|
||||
@Operation(summary = "更新回收站过期时间", description = "批量更新回收站中文件/目录的过期时间")
|
||||
public SdmResponse updateRecycleExpire(@RequestBody @Validated UpdateRecycleExpireReq req) {
|
||||
return IDataFileService.updateRecycleExpire(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索文件
|
||||
*
|
||||
|
||||
@@ -140,25 +140,34 @@ public interface IDataFileService {
|
||||
* @param req 回收站列表查询请求参数
|
||||
* @return 回收站列表响应
|
||||
*/
|
||||
default SdmResponse listRecycleBin(com.sdm.common.entity.req.data.ListRecycleBinReq req) {
|
||||
default SdmResponse listRecycleBin(ListRecycleBinReq req) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从回收站还原文件/目录
|
||||
* 批量从回收站还原文件/目录
|
||||
* @param req 还原请求参数
|
||||
* @return 还原结果响应
|
||||
*/
|
||||
default SdmResponse restoreFromRecycle(com.sdm.common.entity.req.data.RestoreFromRecycleReq req) {
|
||||
default SdmResponse restoreFromRecycle(RestoreFromRecycleReq req) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从回收站彻底删除文件/目录
|
||||
* 批量从回收站彻底删除文件/目录
|
||||
* @param req 彻底删除请求参数
|
||||
* @return 删除结果响应
|
||||
*/
|
||||
default SdmResponse permanentDeleteFromRecycle(com.sdm.common.entity.req.data.PermanentDeleteFromRecycleReq req) {
|
||||
default SdmResponse permanentDeleteFromRecycle(PermanentDeleteFromRecycleReq req) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新回收站过期时间
|
||||
* @param req 更新过期时间请求参数
|
||||
* @return 更新结果响应
|
||||
*/
|
||||
default SdmResponse updateRecycleExpire(com.sdm.common.entity.req.data.UpdateRecycleExpireReq req) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
private static final String FLOWABLE_SIMULATION_BASEDIR = "/home/simulation/";
|
||||
|
||||
@Value("${data.recycle.retention-days:7}")
|
||||
|
||||
|
||||
|
||||
|
||||
private Integer recycleRetentionDays;
|
||||
|
||||
@Autowired
|
||||
@@ -4686,8 +4690,30 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SdmResponse restoreFromRecycle(RestoreFromRecycleReq req) {
|
||||
if (ObjectUtils.isEmpty(req.getIds())) {
|
||||
return SdmResponse.failed("未选择要还原的文件");
|
||||
}
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (Long id : req.getIds()) {
|
||||
SdmResponse resp = restoreSingleFile(id);
|
||||
if (!resp.isSuccess()) {
|
||||
throw new RuntimeException("还原文件(ID:" + id + ")失败: " + resp.getMessage());
|
||||
}
|
||||
if (resp.getData() != null && !Objects.equals(resp.getData(), "还原成功")) {
|
||||
messages.add(resp.getData().toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!messages.isEmpty()) {
|
||||
return SdmResponse.success("还原成功,部分文件已重命名: " + String.join("; ", messages));
|
||||
}
|
||||
return SdmResponse.success("批量还原成功");
|
||||
}
|
||||
|
||||
private SdmResponse restoreSingleFile(Long id) {
|
||||
FileMetadataInfo metadata = fileMetadataInfoService.lambdaQuery()
|
||||
.eq(FileMetadataInfo::getId, req.getId())
|
||||
.eq(FileMetadataInfo::getId, id)
|
||||
.isNotNull(FileMetadataInfo::getDeletedAt)
|
||||
.one();
|
||||
|
||||
@@ -4778,7 +4804,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
|
||||
log.info("成功从回收站还原: id={}, oldKey={}, newKey={}, newName={}", metadata.getId(), oldKey, restoreKey, restoreName);
|
||||
return SdmResponse.success(Objects.equals(restoreName, originalName) ? "还原成功" : "还原成功,原路径已存在,已重命名为: " + restoreName);
|
||||
return SdmResponse.success(Objects.equals(restoreName, originalName) ? "还原成功" : "已重命名为: " + restoreName);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("还原失败", e);
|
||||
@@ -4789,8 +4815,22 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SdmResponse permanentDeleteFromRecycle(PermanentDeleteFromRecycleReq req) {
|
||||
if (ObjectUtils.isEmpty(req.getIds())) {
|
||||
return SdmResponse.failed("未选择要删除的文件");
|
||||
}
|
||||
|
||||
for (Long id : req.getIds()) {
|
||||
SdmResponse resp = permanentDeleteSingleFile(id);
|
||||
if (!resp.isSuccess()) {
|
||||
throw new RuntimeException("删除文件(ID:" + id + ")失败: " + resp.getMessage());
|
||||
}
|
||||
}
|
||||
return SdmResponse.success("批量彻底删除成功");
|
||||
}
|
||||
|
||||
private SdmResponse permanentDeleteSingleFile(Long id) {
|
||||
FileMetadataInfo metadata = fileMetadataInfoService.lambdaQuery()
|
||||
.eq(FileMetadataInfo::getId, req.getId())
|
||||
.eq(FileMetadataInfo::getId, id)
|
||||
.isNotNull(FileMetadataInfo::getDeletedAt)
|
||||
.one();
|
||||
|
||||
@@ -4816,4 +4856,64 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SdmResponse updateRecycleExpire(UpdateRecycleExpireReq req) {
|
||||
if (ObjectUtils.isEmpty(req.getIds())) {
|
||||
return SdmResponse.failed("未选择要更新的文件");
|
||||
}
|
||||
|
||||
List<FileMetadataInfo> metadataList = fileMetadataInfoService.listByIds(req.getIds());
|
||||
if (CollectionUtils.isEmpty(metadataList)) {
|
||||
return SdmResponse.failed("文件不存在");
|
||||
}
|
||||
|
||||
int successCount = 0;
|
||||
for (FileMetadataInfo metadata : metadataList) {
|
||||
// 仅处理已删除的文件
|
||||
if (metadata.getDeletedAt() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算新的过期时间:基于 deletedAt + days
|
||||
LocalDateTime newExpireAt = metadata.getDeletedAt().plusDays(req.getDays());
|
||||
|
||||
// 如果是目录,递归更新子项
|
||||
if (Objects.equals(DataTypeEnum.DIRECTORY.getValue(), metadata.getDataType())) {
|
||||
updateDirectoryRecycleExpire(metadata, newExpireAt);
|
||||
} else {
|
||||
// 单文件更新
|
||||
metadata.setRecycleExpireAt(newExpireAt);
|
||||
metadata.setUpdateTime(LocalDateTime.now());
|
||||
fileMetadataInfoService.updateById(metadata);
|
||||
}
|
||||
successCount++;
|
||||
}
|
||||
|
||||
return SdmResponse.success("成功更新 " + successCount + " 个文件的回收站过期时间");
|
||||
}
|
||||
|
||||
private void updateDirectoryRecycleExpire(FileMetadataInfo rootDir, LocalDateTime newExpireAt) {
|
||||
// 1. 更新目录本身
|
||||
rootDir.setRecycleExpireAt(newExpireAt);
|
||||
rootDir.setUpdateTime(LocalDateTime.now());
|
||||
fileMetadataInfoService.updateById(rootDir);
|
||||
|
||||
// 2. 批量更新子项(包括子目录和文件)
|
||||
// 只要是该目录下的(objectKey以目录key为前缀),且已删除的,都更新
|
||||
String dirKey = rootDir.getObjectKey();
|
||||
if (!dirKey.endsWith("/")) {
|
||||
dirKey += "/";
|
||||
}
|
||||
|
||||
// 使用 LambdaUpdateWrapper 批量更新,效率更高
|
||||
fileMetadataInfoService.lambdaUpdate()
|
||||
.likeRight(FileMetadataInfo::getObjectKey, dirKey) // objectKey like 'dirKey%'
|
||||
.eq(FileMetadataInfo::getBucketName, rootDir.getBucketName())
|
||||
.isNotNull(FileMetadataInfo::getDeletedAt) // 必须是已删除的
|
||||
.set(FileMetadataInfo::getRecycleExpireAt, newExpireAt)
|
||||
.set(FileMetadataInfo::getUpdateTime, LocalDateTime.now())
|
||||
.update();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,7 +101,12 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
public SdmResponse addDemand(SpdmAddDemandReq req) {
|
||||
Long tenantId = ThreadLocalContext.getTenantId();
|
||||
Long jobNumber = ThreadLocalContext.getUserId();
|
||||
req.setCreator(jobNumber);
|
||||
String workNo = ThreadLocalContext.getJobNumber();
|
||||
if (isConvertibleToLong(workNo)) {
|
||||
req.setCreator(Long.valueOf(workNo));
|
||||
}else {
|
||||
req.setCreator(jobNumber);
|
||||
}
|
||||
log.info("新增需求时,当前租户id为:{},工号为:{}", tenantId, jobNumber);
|
||||
// 获取仿真负责人
|
||||
String pMemberList = req.getPMemberList();
|
||||
@@ -433,10 +438,19 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
return SdmResponse.success();
|
||||
}
|
||||
|
||||
public static String removeLeadingZeros(String jobNumber) {
|
||||
if (StringUtils.isNotBlank(jobNumber)) {
|
||||
return "";
|
||||
}
|
||||
String trimmed = jobNumber.replaceAll("^0+","");
|
||||
return trimmed.isEmpty() ? "0" : trimmed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SdmResponse list(SpdmDemandListReq req) {
|
||||
Long tenantId = ThreadLocalContext.getTenantId();
|
||||
Long jobNumber = ThreadLocalContext.getUserId();
|
||||
String jobNumber = removeLeadingZeros(ThreadLocalContext.getJobNumber());
|
||||
Long currentUserId = ThreadLocalContext.getUserId();
|
||||
if (ObjectUtils.isEmpty(tenantId) || ObjectUtils.isEmpty(jobNumber)) {
|
||||
log.error("公司和工号都不能为空");
|
||||
return SdmResponse.failed("公司和工号都不能为空");
|
||||
@@ -461,10 +475,10 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
}
|
||||
if (type == 0) {
|
||||
// 创建人是当前用户
|
||||
demandList = demandList.stream().filter(demand -> jobNumber.equals(demand.getCreator())).toList();
|
||||
demandList = demandList.stream().filter(demand -> jobNumber.equals(String.valueOf(demand.getCreator()))).toList();
|
||||
} else {
|
||||
// 仿真负责人是当前用户
|
||||
List<SpdmDemandMemberVo> pDemandMemberVoList = demandMemberVoList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && Long.valueOf(jobNumber).equals(member.getUserId())).toList();
|
||||
List<SpdmDemandMemberVo> pDemandMemberVoList = demandMemberVoList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && currentUserId.equals(member.getUserId())).toList();
|
||||
if (CollectionUtils.isNotEmpty(pDemandMemberVoList)) {
|
||||
List<String> myDemandIdList = pDemandMemberVoList.stream().map(SpdmDemandMemberVo::getDemandId).toList();
|
||||
demandList = demandList.stream().filter(demand -> myDemandIdList.contains(demand.getUuid())).toList();
|
||||
@@ -1208,12 +1222,46 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
return SdmResponse.success(demandVoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否可以安全转换为Long类型
|
||||
* @param str 待校验的字符串
|
||||
* @return true-可以转换,false-不可以转换
|
||||
*/
|
||||
public static boolean isConvertibleToLong(String str) {
|
||||
// 1. 处理null、空字符串、全空格字符串
|
||||
if (str == null || str.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String trimmedStr = str.trim();
|
||||
|
||||
// 2. 正则校验数字格式(支持正负号,纯数字)
|
||||
// 正则说明:^-? 匹配开头的负号(可选);\\d+ 匹配1个及以上数字;$ 匹配结尾
|
||||
if (!trimmedStr.matches("^-?\\d+$")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 校验数值范围,避免溢出
|
||||
try {
|
||||
// 直接调用Long.parseLong,利用其自带的范围校验
|
||||
Long.parseLong(trimmedStr);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
// 捕获数值超出Long范围的异常
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public SdmResponse addDemandNoPermission(SpdmAddDemandReq req) {
|
||||
Long tenantId = ThreadLocalContext.getTenantId();
|
||||
Long jobNumber = ThreadLocalContext.getUserId();
|
||||
req.setCreator(jobNumber);
|
||||
String workNo = ThreadLocalContext.getJobNumber();
|
||||
if (isConvertibleToLong(workNo)) {
|
||||
req.setCreator(Long.valueOf(workNo));
|
||||
}else {
|
||||
req.setCreator(jobNumber);
|
||||
}
|
||||
log.info("新增需求时(无权限校验),当前租户id为:{},工号为:{}", tenantId, jobNumber);
|
||||
// 获取仿真负责人
|
||||
String pMemberList = req.getPMemberList();
|
||||
|
||||
@@ -405,7 +405,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
try {
|
||||
String demandUuid = RandomUtil.generateString(UUID_LENGTH);
|
||||
// 1. 构建需求基础参数 + 成员 + 权限
|
||||
SpdmAddDemandReq demandReq = buildDemandReq(todo, demandUuid, curDateStr);
|
||||
SpdmAddDemandReq demandReq = buildDemandReq(todo, demandUuid, curDateStr,tenantId,usernameToUserIdMap);
|
||||
List<SpdmDemandRelateMemberReq> memberList = buildDemandMemberList(todo, demandUuid, jobNumber, curDateStr);
|
||||
List<SpdmDemandExtraReq> demandExtraList = buildDemandExtraList(todo, demandUuid, jobNumber, curDateStr);
|
||||
// 2. 构建权限更新参数
|
||||
@@ -478,7 +478,9 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
*/
|
||||
private SpdmAddDemandReq buildDemandReq(LyricVTodoEmulationInfoDM todo,
|
||||
String demandUuid,
|
||||
String curDateStr) {
|
||||
String curDateStr,
|
||||
Long tenantId,
|
||||
Map<String, Long> usernameToUserIdMap) {
|
||||
SpdmAddDemandReq req = new SpdmAddDemandReq();
|
||||
req.setUuid(demandUuid);
|
||||
req.setDemandName(todo.getSubject());
|
||||
@@ -492,7 +494,13 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
req.setEndTime(todo.getClosedTime());
|
||||
req.setCreateTime(curDateStr);
|
||||
req.setDemandSource(SYNC_PROJECT_SOURCE);
|
||||
req.setCreator(Long.valueOf(todo.getIntroduceBy()));
|
||||
if (isConvertibleToInt(todo.getIntroduceBy())) {
|
||||
req.setCreator(Long.valueOf(todo.getIntroduceBy()));
|
||||
}else {
|
||||
req.setCreator(usernameToUserIdMap.get(todo.getIntroduceBy()));
|
||||
}
|
||||
req.setTenantId(tenantId);
|
||||
|
||||
|
||||
// 补充项目/阶段/工位ID
|
||||
fillProjectPhaseWorkspaceId(req, todo);
|
||||
@@ -503,20 +511,18 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
* 填充需求的项目/阶段/工位ID
|
||||
*/
|
||||
private void fillProjectPhaseWorkspaceId(SpdmAddDemandReq req, LyricVTodoEmulationInfoDM todo) {
|
||||
List<SimulationNode> allNodeList = nodeService.lambdaQuery()
|
||||
SimulationNode projectNode = nodeService.lambdaQuery()
|
||||
.in(SimulationNode::getNodeCode, Arrays.asList(todo.getProject(), todo.getProjectStage(), todo.getStationNum()))
|
||||
.list();
|
||||
.one();
|
||||
|
||||
if (CollectionUtils.isEmpty(allNodeList)) {
|
||||
if (ObjectUtils.isEmpty(projectNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 填充需求的项目ID
|
||||
allNodeList.stream()
|
||||
.filter(node -> NodeTypeEnum.PROJECT.getValue().equals(node.getNodeType())
|
||||
&& node.getNodeCode().equals(todo.getProject()))
|
||||
.findFirst()
|
||||
.ifPresent(node -> req.setProjectId(node.getUuid()));
|
||||
req.setProjectId(projectNode.getUuid());
|
||||
|
||||
List<SimulationNode> allNodeList = nodeService.lambdaQuery().eq(SimulationNode::getTag1, projectNode.getUuid()).list();
|
||||
|
||||
// 填充需求的阶段ID
|
||||
allNodeList.stream()
|
||||
@@ -694,13 +700,17 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
try {
|
||||
demandMapper.addDemand(demandReq, tenantId, demandReq.getCreator());
|
||||
if (CollectionUtils.isNotEmpty(memberList)) {
|
||||
List<SpdmDemandRelateMemberReq> normalMemberList = new ArrayList<>();
|
||||
for (SpdmDemandRelateMemberReq member : memberList) {
|
||||
Long cidUserId = usernameToUserIdMap.get(String.valueOf(member.getUserId()));
|
||||
if (cidUserId != null) {
|
||||
member.setUserId(cidUserId);
|
||||
Long cidUserId = usernameToUserIdMap.get(member.getUserIdStr());
|
||||
if (cidUserId == null) {
|
||||
log.info("工号为:{}的用户未查询到用户id", member.getUserIdStr());
|
||||
continue;
|
||||
}
|
||||
member.setUserId(cidUserId);
|
||||
normalMemberList.add(member);
|
||||
}
|
||||
demandMapper.addDemandMember(memberList);
|
||||
demandMapper.addDemandMember(normalMemberList);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(demandExtraList)) {
|
||||
demandMapper.addDemandExtra(demandExtraList);
|
||||
@@ -2238,10 +2248,12 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
// 关联的项目未在系统
|
||||
// 取项目视图、工位相关视图构建项目树信息(只同步当前阶段)创建任务(不创建任务文件夹,等下发时进行创建)
|
||||
if (CollectionUtils.isNotEmpty(noRelatedProjectVTodoEmulationInfoDMList)) {
|
||||
SdmResponse response = httpSyncHandleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber);
|
||||
log.info("httpSyncHandleNoRelatedProjectTodo响应值为:{}",response);
|
||||
if (!response.isSuccess()) {
|
||||
return response;
|
||||
List<SpdmProjectNodeEditReq> spdmProjectNodeEditReqList = httpSyncHandleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber);
|
||||
log.info("httpSyncHandleNoRelatedProjectTodo响应值为:{}",spdmProjectNodeEditReqList);
|
||||
for (SpdmProjectNodeEditReq spdmProjectNodeEditReq : spdmProjectNodeEditReqList) {
|
||||
SimulationNode simulationNode = new SimulationNode();
|
||||
BeanUtils.copyProperties(spdmProjectNodeEditReq,simulationNode);
|
||||
projectNodeList.add(simulationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2252,57 +2264,61 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
return response;
|
||||
}
|
||||
|
||||
private SdmResponse httpSyncHandleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
|
||||
CompletableFuture<SdmResponse> syncHandleNoRelatedProjectTodoFeature = CompletableFuture.supplyAsync(() ->
|
||||
private List<SpdmProjectNodeEditReq> httpSyncHandleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
|
||||
CompletableFuture<List<SpdmProjectNodeEditReq>> syncHandleNoRelatedProjectTodoFeature = CompletableFuture.supplyAsync(() ->
|
||||
handleNoRelatedProjectTodo(noRelatedProjectVTodoEmulationInfoDMList, tenantId, jobNumber));
|
||||
try {
|
||||
SdmResponse sdmResponse = syncHandleNoRelatedProjectTodoFeature.get(syncProjectDataWaitSeconds, TimeUnit.SECONDS);
|
||||
return sdmResponse;
|
||||
List<SpdmProjectNodeEditReq> spdmProjectNodeEditReqList = syncHandleNoRelatedProjectTodoFeature.get(syncProjectDataWaitSeconds, TimeUnit.SECONDS);
|
||||
return spdmProjectNodeEditReqList;
|
||||
} catch (InterruptedException e) {
|
||||
log.error("同步项目信息异常终止:{}", e.getMessage());
|
||||
return SdmResponse.failed("同步项目信息异常终止");
|
||||
return new ArrayList<>();
|
||||
} catch (ExecutionException e) {
|
||||
log.error("同步项目信息执行错误:{}", e.getMessage());
|
||||
return SdmResponse.failed("同步项目信息执行出错误");
|
||||
return new ArrayList<>();
|
||||
} catch (TimeoutException e) {
|
||||
log.warn("同步项目信息执行超时:{}", e.getMessage());
|
||||
return SdmResponse.success("同步项目信息执行中,请稍后");
|
||||
return new ArrayList<>();
|
||||
} catch (Exception e) {
|
||||
log.error("同步项目信息未知错误:{}", e.getMessage());
|
||||
return SdmResponse.failed("同步项目信息未知错误");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private SdmResponse handleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
|
||||
private List<SpdmProjectNodeEditReq> handleNoRelatedProjectTodo(List<LyricVTodoEmulationInfoDM> noRelatedProjectVTodoEmulationInfoDMList, Long tenantId, Long jobNumber) {
|
||||
// 尝试获取锁(立即返回,不等待)
|
||||
if (!syncTodoInfoProjectLock.tryLock()) {
|
||||
return SdmResponse.success("有数据同步任务(同步项目信息)正在执行中,请稍后再试");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 取项目视图、工位相关视图构建项目树信息(只同步当前阶段)
|
||||
// 根据待办获取所有项目编号
|
||||
List<SpdmProjectNodeEditReq> spdmProjectNodeEditReqList = new ArrayList<>();
|
||||
try {
|
||||
List<String> projectNumList = noRelatedProjectVTodoEmulationInfoDMList.stream().map(LyricVTodoEmulationInfoDM::getProject)
|
||||
.filter(StringUtils::isNotBlank).distinct().toList();
|
||||
if (CollectionUtils.isEmpty(projectNumList)) {
|
||||
log.info("projectNumList为空");
|
||||
return SdmResponse.success("projectNumList为空");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
// 根据项目编号查询项目视图获取项目信息
|
||||
List<LyricVProjectToDM> lyricVProjectToDMList = lyricVProjectToDmService.lambdaQuery().in(LyricVProjectToDM::getProjectNum, projectNumList).list();
|
||||
if (CollectionUtils.isEmpty(lyricVProjectToDMList)) {
|
||||
log.info("lyricVProjectToDMList为空");
|
||||
return SdmResponse.success("lyricVProjectToDMList为空");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
for (LyricVProjectToDM lyricVProjectToDM : lyricVProjectToDMList) {
|
||||
buildProjectForTodoInfo(lyricVProjectToDM, tenantId, jobNumber);
|
||||
SpdmProjectNodeEditReq spdmProjectNodeEditReq = buildProjectForTodoInfo(lyricVProjectToDM, tenantId, jobNumber);
|
||||
if (spdmProjectNodeEditReq != null) {
|
||||
spdmProjectNodeEditReqList.add(spdmProjectNodeEditReq);
|
||||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error("handleNoRelatedProjectTodo 未知 error: {}", e.getMessage());
|
||||
return SdmResponse.failed();
|
||||
return new ArrayList<>();
|
||||
} finally {
|
||||
syncTodoInfoProjectLock.unlock();
|
||||
}
|
||||
return SdmResponse.success();
|
||||
return spdmProjectNodeEditReqList;
|
||||
}
|
||||
|
||||
public static String getTagProperty(Object obj, String propertyName) throws Exception {
|
||||
@@ -2570,7 +2586,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
log.info("创建节点时,调用批量创建文件夹的返回值为:{}", response);
|
||||
}
|
||||
|
||||
private void buildProjectForTodoInfo(LyricVProjectToDM lyricVProjectToDM, Long tenantId, Long jobNumber) {
|
||||
private SpdmProjectNodeEditReq buildProjectForTodoInfo(LyricVProjectToDM lyricVProjectToDM, Long tenantId, Long jobNumber) {
|
||||
String curDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||
List<SpdmProjectNodeEditReq> currentNodeList;
|
||||
List<SpdmProjectNodeEditReq> addNodeList = new ArrayList<>();
|
||||
@@ -2734,7 +2750,7 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
}
|
||||
|
||||
if (nodeMapper.addNodeBatch(addNodeList) <= 0) {
|
||||
return ;
|
||||
return null;
|
||||
}
|
||||
|
||||
// 保存拓展字段
|
||||
@@ -2874,6 +2890,8 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
|
||||
SdmResponse response = dataFeignClient.batchUpdatePermission(batchReq);
|
||||
log.info("同步待办拉取项目时,批量更新权限结果为:{}",response);
|
||||
}
|
||||
|
||||
return spdmProjectNodeEditReq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -393,8 +393,8 @@ public class NodeServiceImpl extends ServiceImpl<SimulationNodeMapper, Simulatio
|
||||
taskNodePoList = taskService.lambdaQuery().eq(SimulationTask::getTag2,nodeId).list();
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(taskNodePoList)) {
|
||||
nodeMapper.deleteTaskBatch(deleteNodeIdList);
|
||||
List<String> taskIdList = taskNodePoList.stream().map(SimulationTask::getUuid).toList();
|
||||
taskService.lambdaUpdate().in(SimulationTask::getUuid,taskIdList).remove();
|
||||
nodeMapper.deleteTaskExtraBatch(taskIdList);
|
||||
nodeMapper.deleteTaskMemberBatch(taskIdList);
|
||||
// 删除当前节点及子节点下的指标相关信息
|
||||
|
||||
@@ -253,13 +253,7 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
||||
}
|
||||
String realTag = realTagObj.getKey();
|
||||
String realTagId = realTagObj.getValue();
|
||||
Long userId = ThreadLocalContext.getUserId();
|
||||
SdmResponse<CIDUserResp> currentCidUserResp = sysUserFeignClient.queryUserDetail(UserQueryReq.builder().userId(userId).build());
|
||||
if (ObjectUtils.isEmpty(currentCidUserResp.getData())) {
|
||||
log.error("根据userId:{},未查询到用户", userId);
|
||||
return ;
|
||||
}
|
||||
Long curUserId = currentCidUserResp.getData().getUserId();
|
||||
Long curUserId = ThreadLocalContext.getUserId();
|
||||
// 查询当前节点下任务
|
||||
List<TaskNodePo> currentNodeAssociatedTaskList = new ArrayList<>();
|
||||
int currentNodeDepth = getCurrentNodeDepth(projectNodePo);
|
||||
@@ -313,19 +307,41 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
||||
}
|
||||
}
|
||||
}
|
||||
SdmResponse<List<CIDUserResp>> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(memberList.stream().map(SimulationTaskMember::getUserId).toList()).build());
|
||||
if (ObjectUtils.isEmpty(cidUserResp)) {
|
||||
return;
|
||||
}
|
||||
List<CIDUserResp> cidUserRespList = cidUserResp.getData();
|
||||
if (CollectionUtils.isEmpty(cidUserRespList)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, CIDUserResp> cidUserMap = cidUserRespList.stream().collect(Collectors.toMap(CIDUserResp::getUserId, Function.identity()));
|
||||
// 查询当前任务的负责人和执行人
|
||||
for (TaskNodePo taskNodePo : currentNodeAssociatedTaskList) {
|
||||
if (CollectionUtils.isNotEmpty(memberList)) {
|
||||
List<Long> eUserIdList = memberList.stream().filter(member -> MemberTypeEnum.EXECUTOR.getCode().equals(member.getType())).map(SimulationTaskMember::getUserId).distinct().toList();
|
||||
List<Long> pUserIdList = memberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType())).map(SimulationTaskMember::getUserId).distinct().toList();
|
||||
if (CollectionUtils.isNotEmpty(eUserIdList)) {
|
||||
SdmResponse<List<CIDUserResp>> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(eUserIdList).build());
|
||||
taskNodePo.setEMemberList(cidUserResp.getData());
|
||||
List<Long> eUserIdList = memberList.stream().filter(member -> MemberTypeEnum.EXECUTOR.getCode().equals(member.getType()) && taskNodePo.getUuid().equals(member.getTaskId())).map(SimulationTaskMember::getUserId).distinct().toList();
|
||||
List<Long> pUserIdList = memberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && taskNodePo.getUuid().equals(member.getTaskId())).map(SimulationTaskMember::getUserId).distinct().toList();
|
||||
if (CollectionUtils.isNotEmpty(eUserIdList)) {
|
||||
List<CIDUserResp> eUserList = new ArrayList<>();
|
||||
for (Long eUserId : eUserIdList) {
|
||||
CIDUserResp eCidUser = cidUserMap.get(eUserId);
|
||||
if (ObjectUtils.isEmpty(eCidUser)) {
|
||||
continue;
|
||||
}
|
||||
eUserList.add(eCidUser);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(pUserIdList)) {
|
||||
SdmResponse<List<CIDUserResp>> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(pUserIdList).build());
|
||||
taskNodePo.setPMemberList(cidUserResp.getData());
|
||||
taskNodePo.setEMemberList(eUserList);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(pUserIdList)) {
|
||||
List<CIDUserResp> pUserList = new ArrayList<>();
|
||||
for (Long eUserId : pUserIdList) {
|
||||
CIDUserResp pCidUser = cidUserMap.get(eUserId);
|
||||
if (ObjectUtils.isEmpty(pCidUser)) {
|
||||
continue;
|
||||
}
|
||||
pUserList.add(pCidUser);
|
||||
}
|
||||
taskNodePo.setPMemberList(pUserList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ public class TaskServiceImpl implements ITaskService {
|
||||
List<SpdmDemandVo> demandVoList = demandMapper.getDemandListById(demandIdList);
|
||||
demandMap = demandVoList.stream()
|
||||
.collect(Collectors.toMap(SpdmDemandVo::getUuid, Function.identity()));
|
||||
demandSubmitMap = demandVoList.stream()
|
||||
demandSubmitMap = demandVoList.stream().filter(spdmDemandVo -> ObjectUtils.isNotEmpty(spdmDemandVo.getCreator()))
|
||||
.collect(Collectors.toMap(SpdmDemandVo::getUuid, SpdmDemandVo::getCreator));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
insert into simulation_demand (uuid,demand_name,demand_code,demand_type,sim_type,demand_status,achieve_status,progress,approval_status,
|
||||
begin_time,end_time,finish_time,project_id,phase_id,workspace_id,tenant_id,creator,create_time,demandSource,description,machine_id) values
|
||||
(#{req.uuid},#{req.demandName},#{req.demandCode},#{req.demandType},#{req.simType},#{req.demandStatus},#{req.achieveStatus},#{req.progress},#{req.approvalStatus},
|
||||
#{req.beginTime},#{req.endTime},'',#{req.projectId},#{req.phaseId},#{req.workspaceId},#{tenantId},#{jobNumber},#{req.createTime},#{req.demandSource},#{req.description},#{req.machineId})
|
||||
#{req.beginTime},#{req.endTime},'',#{req.projectId},#{req.phaseId},#{req.workspaceId},#{req.creator},#{jobNumber},#{req.createTime},#{req.demandSource},#{req.description},#{req.machineId})
|
||||
</insert>
|
||||
|
||||
<insert id="addDemandMember">
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<insert id="saveBatchTaskExtra">
|
||||
insert into simulation_task_extra (task_id, property_name, property_value, value_type, property_class, creator, create_time) values
|
||||
<foreach collection='list' item='taskExtra' index='index' separator=','>
|
||||
(#{taskExtra.taskId}}, #{taskExtra.propertyName}, #{taskExtra.propertyValue}, #{taskExtra.valueType}, #{taskExtra.propertyClass}, #{taskExtra.creator}, #{taskExtra.createTime})
|
||||
(#{taskExtra.taskId}, #{taskExtra.propertyName}, #{taskExtra.propertyValue}, #{taskExtra.valueType}, #{taskExtra.propertyClass}, #{taskExtra.creator}, #{taskExtra.createTime})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user