feat(功能用例): 附件接口
This commit is contained in:
parent
e6f1fcb7ab
commit
a90a8a0865
|
@ -1,6 +1,8 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import io.metersphere.functional.domain.FunctionalCaseAttachment;
|
||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
||||
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
||||
|
@ -22,6 +24,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
|||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -124,4 +127,21 @@ public class FunctionalCaseAttachmentController {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/upload/file")
|
||||
@Operation(summary = "用例管理-功能用例-上传文件并关联用例")
|
||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
|
||||
public void uploadFile(@Validated @RequestPart("request") FunctionalCaseAssociationFileRequest request, @RequestPart(value = "file", required = false) MultipartFile file) {
|
||||
String userId = SessionUtils.getUserId();
|
||||
functionalCaseAttachmentService.uploadOrAssociationFile(request, file, userId);
|
||||
}
|
||||
|
||||
@PostMapping("/delete/file")
|
||||
@Operation(summary = "用例管理-功能用例-删除文件并取消关联用例")
|
||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
|
||||
public void deleteFile(@Validated @RequestBody FunctionalCaseDeleteFileRequest request) {
|
||||
String userId = SessionUtils.getUserId();
|
||||
functionalCaseAttachmentService.deleteFile(request, userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.functional.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wx
|
||||
*/
|
||||
@Data
|
||||
public class FunctionalCaseAssociationFileRequest implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "文件id列表")
|
||||
private List<String> fileIds;
|
||||
|
||||
@Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String caseId;
|
||||
|
||||
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String projectId;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.functional.request;
|
||||
|
||||
import io.metersphere.functional.dto.FunctionalCaseAttachmentDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author wx
|
||||
*/
|
||||
@Data
|
||||
public class FunctionalCaseDeleteFileRequest implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "附件信息", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private FunctionalCaseAttachmentDTO attachment;
|
||||
|
||||
@Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String caseId;
|
||||
|
||||
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String projectId;
|
||||
}
|
|
@ -7,7 +7,8 @@ import io.metersphere.functional.domain.FunctionalCaseAttachmentExample;
|
|||
import io.metersphere.functional.dto.FunctionalCaseAttachmentDTO;
|
||||
import io.metersphere.functional.dto.FunctionalCaseDetailDTO;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
|
||||
import io.metersphere.functional.request.FunctionalCaseAddRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
||||
import io.metersphere.project.domain.FileAssociation;
|
||||
import io.metersphere.project.dto.filemanagement.FileInfo;
|
||||
|
@ -24,6 +25,7 @@ import io.metersphere.system.log.constants.OperationLogModule;
|
|||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
@ -52,6 +54,9 @@ public class FunctionalCaseAttachmentService {
|
|||
@Resource
|
||||
private FileAssociationService fileAssociationService;
|
||||
|
||||
private static final String UPLOAD_FILE = "/attachment/upload/file";
|
||||
private static final String DELETED_FILE = "/attachment/delete/file";
|
||||
|
||||
/**
|
||||
* 保存本地上传文件和用例关联关系
|
||||
*
|
||||
|
@ -70,16 +75,16 @@ public class FunctionalCaseAttachmentService {
|
|||
/**
|
||||
* 功能用例上传附件
|
||||
*
|
||||
* @param request request
|
||||
* @param projectId projectId
|
||||
* @param files files
|
||||
*/
|
||||
public void uploadFile(FunctionalCaseAddRequest request, String caseId, List<MultipartFile> files, Boolean isLocal, String userId) {
|
||||
public void uploadFile(String projectId, String caseId, List<MultipartFile> files, Boolean isLocal, String userId) {
|
||||
if (CollectionUtils.isNotEmpty(files)) {
|
||||
files.forEach(file -> {
|
||||
String fileId = IDGenerator.nextStr();
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(file.getOriginalFilename());
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(request.getProjectId(), caseId) + "/" + fileId);
|
||||
fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(projectId, caseId) + "/" + fileId);
|
||||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
try {
|
||||
fileService.upload(file, fileRequest);
|
||||
|
@ -289,4 +294,21 @@ public class FunctionalCaseAttachmentService {
|
|||
}
|
||||
return fileAssociationMap;
|
||||
}
|
||||
|
||||
public void uploadOrAssociationFile(FunctionalCaseAssociationFileRequest request, MultipartFile file, String userId) {
|
||||
Optional.ofNullable(file).ifPresent(item -> this.uploadFile(request.getProjectId(), request.getCaseId(), Arrays.asList(file), Boolean.TRUE, userId));
|
||||
|
||||
if (CollectionUtils.isNotEmpty(request.getFileIds())) {
|
||||
this.association(request.getFileIds(), request.getCaseId(), userId, UPLOAD_FILE, request.getProjectId());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFile(FunctionalCaseDeleteFileRequest request, String userId) {
|
||||
if (BooleanUtils.isTrue(request.getAttachment().getLocal())) {
|
||||
this.deleteCaseAttachment(Arrays.asList(request.getAttachment().getId()), request.getCaseId(), userId);
|
||||
}
|
||||
if (BooleanUtils.isFalse(request.getAttachment().getLocal())) {
|
||||
this.unAssociation(Arrays.asList(request.getAttachment().getId()), DELETED_FILE, userId, request.getProjectId());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,7 +95,7 @@ public class FunctionalCaseService {
|
|||
FunctionalCase functionalCase = addCase(caseId, request, userId);
|
||||
|
||||
//上传文件
|
||||
functionalCaseAttachmentService.uploadFile(request, caseId, files, true, userId);
|
||||
functionalCaseAttachmentService.uploadFile(request.getProjectId(), caseId, files, true, userId);
|
||||
|
||||
//关联附件
|
||||
if (CollectionUtils.isNotEmpty(request.getRelateFileMetaIds())) {
|
||||
|
@ -275,7 +275,7 @@ public class FunctionalCaseService {
|
|||
}
|
||||
|
||||
//上传新文件
|
||||
functionalCaseAttachmentService.uploadFile(request, request.getId(), files, true, userId);
|
||||
functionalCaseAttachmentService.uploadFile(request.getProjectId(), request.getId(), files, true, userId);
|
||||
|
||||
//关联新附件
|
||||
if (CollectionUtils.isNotEmpty(request.getRelateFileMetaIds())) {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import io.metersphere.functional.dto.FunctionalCaseAttachmentDTO;
|
||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
||||
import io.metersphere.functional.utils.FileBaseUtils;
|
||||
import io.metersphere.project.dto.filemanagement.request.FileMetadataTableRequest;
|
||||
|
@ -23,6 +26,7 @@ import org.springframework.mock.web.MockMultipartFile;
|
|||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlConfig;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
@ -50,6 +54,9 @@ public class FunctionalCaseAttachmentControllerTests extends BaseTest {
|
|||
public static final String ATTACHMENT_CHECK_UPDATE_URL = "/attachment/check-update";
|
||||
public static final String ATTACHMENT_UPDATE_URL = "/attachment/update/";
|
||||
public static final String ATTACHMENT_TRANSFER_URL = "/attachment/transfer";
|
||||
public static final String UPLOAD_FILE_URL = "/attachment/upload/file";
|
||||
public static final String DELETE_FILE_URL = "/attachment/delete/file";
|
||||
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
|
@ -171,4 +178,49 @@ public class FunctionalCaseAttachmentControllerTests extends BaseTest {
|
|||
this.requestPost(ATTACHMENT_TRANSFER_URL, request);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
public void testUploadFile() throws Exception {
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.JPG")).getPath();
|
||||
MockMultipartFile file = new MockMultipartFile("file", "file_re-upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, FileBaseUtils.getFileBytes(filePath));
|
||||
LinkedMultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
FunctionalCaseAssociationFileRequest request = new FunctionalCaseAssociationFileRequest();
|
||||
request.setCaseId("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1");
|
||||
request.setProjectId("WX_TEST_PROJECT_ID");
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
paramMap.add("file", file);
|
||||
this.requestMultipart(UPLOAD_FILE_URL, paramMap);
|
||||
|
||||
request.setFileIds(Arrays.asList("wx_test_file_association_1"));
|
||||
paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
paramMap.add("file", file);
|
||||
this.requestMultipart(UPLOAD_FILE_URL, paramMap);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
public void testDeleteFile() throws Exception {
|
||||
FunctionalCaseDeleteFileRequest request = new FunctionalCaseDeleteFileRequest();
|
||||
FunctionalCaseAttachmentDTO attachmentDTO = new FunctionalCaseAttachmentDTO();
|
||||
//覆盖率
|
||||
request.setCaseId("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1");
|
||||
request.setProjectId("WX_TEST_PROJECT_ID");
|
||||
request.setAttachment(attachmentDTO);
|
||||
this.requestPost(DELETE_FILE_URL, request);
|
||||
|
||||
|
||||
attachmentDTO.setId("wx_test_file_association_1");
|
||||
attachmentDTO.setLocal(false);
|
||||
this.requestPost(DELETE_FILE_URL, request);
|
||||
|
||||
attachmentDTO.setId("TEST_ATTACHMENT_ID");
|
||||
attachmentDTO.setLocal(true);
|
||||
this.requestPost(DELETE_FILE_URL, request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -19,3 +19,7 @@ INSERT INTO functional_case_attachment(id, case_id, file_id, file_name, size, lo
|
|||
|
||||
INSERT INTO file_association(id, source_type, source_id, file_id, file_ref_id, file_version, create_time, update_user, update_time, create_user) VALUES ('wx_test_file_association', 'functional_case', 'WX_TEST_FUNCTIONAL_CASE_ID', 'wx_file_id', '1', '1', 1698983271536, 'admin', 1698983271536, 'admin');
|
||||
INSERT INTO file_metadata(id, name, type, size, create_time, update_time, project_id, storage, create_user, update_user, tags, description, module_id, path, latest, ref_id, file_version) VALUES ('wx_file_id', 'formItem', 'ts', 2502, 1698058347559, 1698058347559, '100001100001', 'MINIO', 'admin', 'admin', NULL, NULL, 'root', '100001100001/1127016598347779', b'1', '1127016598347779', '1127016598347779');
|
||||
|
||||
|
||||
INSERT INTO file_association(id, source_type, source_id, file_id, file_ref_id, file_version, create_time, update_user, update_time, create_user) VALUES ('wx_test_file_association_1', 'functional_case', 'WX_TEST_FUNCTIONAL_CASE_ID', 'wx_file_id_1', '1', '1', 1698983271536, 'admin', 1698983271536, 'admin');
|
||||
INSERT INTO file_metadata(id, name, type, size, create_time, update_time, project_id, storage, create_user, update_user, tags, description, module_id, path, latest, ref_id, file_version) VALUES ('wx_file_id_1', 'formItem', 'ts', 2502, 1698058347559, 1698058347559, '100001100001', 'MINIO', 'admin', 'admin', NULL, NULL, 'root', '100001100001/1127016598347779', b'1', '1127016598347779', '1127016598347779');
|
||||
|
|
Loading…
Reference in New Issue