fix(缺陷管理): 关联文件失败报错问题

--bug=1036477 --user=宋昌昌 【缺陷管理】缺陷详情-附件-关联文件失败报错 https://www.tapd.cn/55049933/s/1466558
This commit is contained in:
song-cc-rock 2024-02-28 19:29:14 +08:00 committed by 刘瑞斌
parent e592811b76
commit ce37c4c194
8 changed files with 44 additions and 58 deletions

View File

@ -22,25 +22,10 @@ public class BugUploadFileRequest implements Serializable {
@NotBlank(message = "{bug.project_id.not_blank}")
private String projectId;
@Schema(description = "不勾选的ID")
private List<String> excludeIds;
@Schema(description = "勾选的ID")
@Valid
private List<
@NotBlank(message = "{id must not be blank}", groups = {Created.class, Updated.class})
String
> selectIds = new ArrayList<>();
@Schema(description = "是否全选", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean selectAll;
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<String> moduleIds;
@Schema(description = "文件类型")
private String fileType;
@Schema(description = "关键字")
private String keyword;
}

View File

@ -33,6 +33,9 @@ public class BugFileDTO {
@Schema(description = "创建人")
private String createUser;
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "是否本地文件")
private Boolean local;
}

View File

@ -22,8 +22,6 @@ import io.metersphere.project.domain.FileMetadata;
import io.metersphere.project.domain.FileMetadataExample;
import io.metersphere.project.dto.filemanagement.FileAssociationDTO;
import io.metersphere.project.dto.filemanagement.FileLogRecord;
import io.metersphere.project.dto.filemanagement.request.FileMetadataTableRequest;
import io.metersphere.project.dto.filemanagement.response.FileInformationResponse;
import io.metersphere.project.mapper.FileAssociationMapper;
import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.project.service.FileAssociationService;
@ -35,11 +33,12 @@ import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.file.FileCenter;
import io.metersphere.sdk.file.FileRequest;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.FileAssociationSourceUtil;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.mapper.BaseUserMapper;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.io.FileUtils;
@ -70,6 +69,8 @@ public class BugAttachmentService {
@Resource
private FileService fileService;
@Resource
private BaseUserMapper baseUserMapper;
@Resource
private FileMetadataMapper fileMetadataMapper;
@Resource
private FileMetadataService fileMetadataService;
@ -116,7 +117,13 @@ public class BugAttachmentService {
bugFiles.add(associatedFileDTO);
});
}
return bugFiles;
if (CollectionUtils.isEmpty(bugFiles)) {
return bugFiles;
}
List<String> userIds = bugFiles.stream().map(BugFileDTO::getCreateUser).distinct().toList();
List<OptionDTO> userOptions = baseUserMapper.selectUserOptionByIds(userIds);
Map<String, String> userMap = userOptions.stream().collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName));
return bugFiles.stream().peek(file -> file.setCreateUserName(userMap.get(file.getCreateUser()))).toList();
}
/**
@ -131,26 +138,11 @@ public class BugAttachmentService {
+ File.separator);
List<SyncAttachmentToPlatformRequest> platformAttachments = new ArrayList<>();
if (file == null) {
// 关联文件
List<String> relateFileIds;
if (request.isSelectAll()) {
// 全选
FileMetadataTableRequest metadataTableRequest = new FileMetadataTableRequest();
BeanUtils.copyBean(metadataTableRequest, request);
List<FileInformationResponse> relateAllFiles = fileMetadataService.list(metadataTableRequest);
if (!CollectionUtils.isEmpty(request.getExcludeIds())) {
relateAllFiles.removeIf(relateFile -> request.getExcludeIds().contains(relateFile.getId()));
}
relateFileIds = relateAllFiles.stream().map(FileInformationResponse::getId).collect(Collectors.toList());
} else {
// 非全选
relateFileIds= request.getSelectIds();
}
// 缺陷与文件库关联
if (CollectionUtils.isEmpty(relateFileIds)) {
if (CollectionUtils.isEmpty(request.getSelectIds())) {
return;
}
List<SyncAttachmentToPlatformRequest> syncLinkFiles = uploadLinkFile(bug.getId(), bug.getPlatformBugId(), request.getProjectId(), tempFileDir, relateFileIds, currentUser, bug.getPlatform(), false);
List<SyncAttachmentToPlatformRequest> syncLinkFiles = uploadLinkFile(bug.getId(), bug.getPlatformBugId(), request.getProjectId(), tempFileDir, request.getSelectIds(), currentUser, bug.getPlatform(), false);
platformAttachments.addAll(syncLinkFiles);
} else {
// 上传文件

View File

@ -97,26 +97,15 @@ public class BugAttachmentControllerTests extends BaseTest {
BugUploadFileRequest request = new BugUploadFileRequest();
request.setBugId("default-attachment-bug-id");
request.setProjectId("default-project-for-attachment");
request.setSelectAll(false);
request.setSelectIds(List.of(unRelatedFiles.get(0).getId()));
MultiValueMap<String, Object> paramMap1 = getDefaultMultiPartParam(request, null);
this.requestMultipartWithOk(BUG_ATTACHMENT_UPLOAD, paramMap1);
// 全选关联
request.setSelectAll(true);
request.setExcludeIds(List.of(unRelatedFiles.get(0).getId(), unRelatedFiles.get(1).getId()));
MultiValueMap<String, Object> paramMap2 = getDefaultMultiPartParam(request, null);
this.requestMultipartWithOk(BUG_ATTACHMENT_UPLOAD, paramMap2);
request.setSelectAll(true);
request.setExcludeIds(null);
MultiValueMap<String, Object> paramMap3 = getDefaultMultiPartParam(request, null);
this.requestMultipartWithOk(BUG_ATTACHMENT_UPLOAD, paramMap3);
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.xlsx")).getPath();
File file = new File(filePath);
MultiValueMap<String, Object> paramMapWithFile = getDefaultMultiPartParam(request, file);
this.requestMultipartWithOk(BUG_ATTACHMENT_UPLOAD, paramMapWithFile);
// 第三方平台的缺陷关联文件
request.setBugId("default-bug-id-tapd");
request.setSelectAll(false);
request.setSelectIds(List.of("not-exist-file-id"));
MultiValueMap<String, Object> paramMap4 = getDefaultMultiPartParam(request, null);
this.requestMultipart(BUG_ATTACHMENT_UPLOAD, paramMap4).andExpect(status().is5xxServerError());

View File

@ -35,6 +35,7 @@ export default {
'common.editFailed': 'Edit failed',
'common.saveSuccess': 'Save success',
'common.saveFailed': 'Save failed',
'common.linkSuccess': 'Link success',
'common.confirmEnable': 'Confirm enable',
'common.confirmEnd': 'Confirm end',
'common.confirmStart': 'Confirm start',

View File

@ -37,6 +37,7 @@ export default {
'common.editFailed': '编辑失败',
'common.saveSuccess': '保存成功',
'common.saveFailed': '保存失败',
'common.linkSuccess': '关联成功',
'common.confirmEnable': '确认启用',
'common.confirmDisable': '确认禁用',
'common.confirmClose': '确认关闭',

View File

@ -177,10 +177,11 @@
downloadFileRequest,
editorUploadFile,
getAssociatedFileList,
getAttachmentList,
previewFile,
transferFileRequest,
updateFile,
uploadOrAssociationFile,
uploadOrAssociationFile
} from '@/api/modules/bug-management';
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
import { useI18n } from '@/hooks/useI18n';
@ -256,6 +257,8 @@
.map((fileInfo: any) => {
return convertToFileByBug(fileInfo);
}) || [];
} else {
fileList.value = [];
}
};
@ -285,7 +288,8 @@
Message.success(
item.local ? t('caseManagement.featureCase.deleteSuccess') : t('caseManagement.featureCase.cancelLinkSuccess')
);
emit('updateSuccess');
const attachments = await getAttachmentList(bugId.value);
handleFileFunc(attachments);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
@ -432,7 +436,6 @@
templateId: props.detailInfo.templateId,
customFields,
};
console.log(tmpObj);
//
const res = await createOrUpdateBug({ request: tmpObj, fileList: fileList.value as unknown as File[] });
if (res) {
@ -448,11 +451,21 @@
}
}
//
function saveSelectAssociatedFile(fileData: AssociatedList[]) {
//
async function saveSelectAssociatedFile(fileData: AssociatedList[]) {
const fileResultList = fileData.map(convertToFileByDetail);
fileList.value.push(...fileResultList);
handleSave();
const params = {
request: {
bugId: bugId.value as string,
projectId: currentProjectId.value,
selectIds: fileResultList.map((item: any) => item.uid)
}
};
await uploadOrAssociationFile(params);
const attachments = await getAttachmentList(bugId.value);
handleFileFunc(attachments);
Message.success(t('common.linkSuccess'));
}
watchEffect(() => {

View File

@ -10,13 +10,13 @@ import { AssociatedList } from '@/models/caseManagement/featureCase';
export function convertToFileByBug(fileInfo: AssociatedList): MsFileItem {
const gatewayAddress = `${window.location.protocol}//${window.location.hostname}:${window.location.port}`;
const fileName = fileInfo.fileType ? `${fileInfo.name}.${fileInfo.fileType || ''}` : `${fileInfo.name}`;
const type = fileName.split('.')[1];
const fileName = `${fileInfo.name}`;
const type = `${fileInfo.fileType}`;
const file = new File([new Blob()], `${fileName}`, {
type: `application/${type}`,
});
Object.defineProperty(file, 'size', { value: fileInfo.fileSize });
const { fileId, associated, isUpdateFlag, refId } = fileInfo;
const { fileId, local, isUpdateFlag, refId, createUserName, createTime } = fileInfo;
return {
enable: fileInfo.enable || false,
file,
@ -25,10 +25,12 @@ export function convertToFileByBug(fileInfo: AssociatedList): MsFileItem {
status: 'done',
uid: fileId,
url: `${gatewayAddress}/${fileInfo.filePath || ''}`,
local: !associated,
deleteContent: associated ? 'caseManagement.featureCase.cancelLink' : '',
local,
deleteContent: !local ? 'caseManagement.featureCase.cancelLink' : '',
isUpdateFlag,
associateId: refId,
createUserName,
uploadedTime: createTime
};
}
/** *