From 475440ccd4900d5590040c4eba6ea31f3422ef98 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 16 Mar 2021 12:08:58 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(=E6=80=A7=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95):=20=E6=B5=8B=E8=AF=95=E6=96=87=E4=BB=B6=E5=85=B3?= =?UTF-8?q?=E8=81=94=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/service/APITestService.java | 14 +- .../metersphere/base/domain/FileMetadata.java | 5 +- .../base/domain/FileMetadataExample.java | 58 ++-- .../metersphere/base/domain/LoadTestFile.java | 5 +- .../base/domain/LoadTestFileExample.java | 60 ++++ .../base/mapper/FileMetadataMapper.xml | 28 +- .../base/mapper/LoadTestFileMapper.xml | 21 +- .../base/mapper/ext/ExtLoadTestMapper.java | 4 +- .../base/mapper/ext/ExtLoadTestMapper.xml | 8 +- .../controller/ProjectController.java | 10 + .../controller/PerformanceTestController.java | 10 +- .../performance/dto/LoadTestFileDTO.java | 12 - .../performance/engine/EngineFactory.java | 9 +- .../request/QueryProjectFileRequest.java | 8 + .../service/PerformanceTestService.java | 73 ++-- .../io/metersphere/service/FileService.java | 65 ++-- .../metersphere/service/ProjectService.java | 70 +++- .../track/service/TestCaseService.java | 4 +- .../db/migration/V78__v1.8_release.sql | 19 +- .../resources/i18n/messages_en_US.properties | 3 + .../resources/i18n/messages_zh_CN.properties | 3 + .../resources/i18n/messages_zh_TW.properties | 3 + .../test/components/ExistFiles.vue | 110 +++++- .../components/PerformanceBasicConfig.vue | 99 +----- .../test/components/ResourceFiles.vue | 154 +++++++++ .../components/settings/project/MsProject.vue | 318 +++++++++--------- frontend/src/i18n/en-US.js | 2 + frontend/src/i18n/zh-CN.js | 6 +- frontend/src/i18n/zh-TW.js | 6 +- 29 files changed, 768 insertions(+), 419 deletions(-) delete mode 100644 backend/src/main/java/io/metersphere/performance/dto/LoadTestFileDTO.java create mode 100644 backend/src/main/java/io/metersphere/performance/request/QueryProjectFileRequest.java create mode 100644 frontend/src/business/components/performance/test/components/ResourceFiles.vue diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index 659bcef3ba..ea7521209b 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -98,7 +98,7 @@ public class APITestService { checkQuota(); request.setBodyUploadIds(null); ApiTest test = createTest(request); - saveFile(test.getId(), file); + saveFile(test, file); return test; } @@ -112,7 +112,7 @@ public class APITestService { request.setBodyUploadIds(null); ApiTest test = updateTest(request); createBodyFiles(test, bodyUploadIds, bodyFiles); - saveFile(test.getId(), file); + saveFile(test, file); } private void createBodyFiles(ApiTest test, List bodyUploadIds, List bodyFiles) { @@ -292,10 +292,10 @@ public class APITestService { return test; } - private void saveFile(String testId, MultipartFile file) { - final FileMetadata fileMetadata = fileService.saveFile(file); + private void saveFile(ApiTest apiTest, MultipartFile file) { + final FileMetadata fileMetadata = fileService.saveFile(file, apiTest.getProjectId()); ApiTestFile apiTestFile = new ApiTestFile(); - apiTestFile.setTestId(testId); + apiTestFile.setTestId(apiTest.getId()); apiTestFile.setFileId(fileMetadata.getId()); apiTestFileMapper.insert(apiTestFile); } @@ -532,12 +532,12 @@ public class APITestService { //处理附件 Map attachmentFiles = new HashMap<>(); - int fileIndex = 0; + for (String filePath: attachmentFilePathList) { File file = new File(filePath); if(file.exists() && file.isFile()){ try{ - FileMetadata fileMetadata = fileService.saveFile(file,FileUtil.readAsByteArray(file),fileIndex++); + FileMetadata fileMetadata = fileService.saveFile(file,FileUtil.readAsByteArray(file)); attachmentFiles.put(fileMetadata.getId(),fileMetadata.getName()); }catch (Exception e){ e.printStackTrace(); diff --git a/backend/src/main/java/io/metersphere/base/domain/FileMetadata.java b/backend/src/main/java/io/metersphere/base/domain/FileMetadata.java index 4dd64f1051..8b07d2fbd5 100644 --- a/backend/src/main/java/io/metersphere/base/domain/FileMetadata.java +++ b/backend/src/main/java/io/metersphere/base/domain/FileMetadata.java @@ -1,8 +1,7 @@ package io.metersphere.base.domain; -import lombok.Data; - import java.io.Serializable; +import lombok.Data; @Data public class FileMetadata implements Serializable { @@ -18,7 +17,7 @@ public class FileMetadata implements Serializable { private Long size; - private Integer sort; + private String projectId; private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/FileMetadataExample.java b/backend/src/main/java/io/metersphere/base/domain/FileMetadataExample.java index c7a308d6a0..ca7c180f56 100644 --- a/backend/src/main/java/io/metersphere/base/domain/FileMetadataExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/FileMetadataExample.java @@ -494,63 +494,73 @@ public class FileMetadataExample { return (Criteria) this; } - public Criteria andSortIsNull() { - addCriterion("sort is null"); + public Criteria andProjectIdIsNull() { + addCriterion("project_id is null"); return (Criteria) this; } - public Criteria andSortIsNotNull() { - addCriterion("sort is not null"); + public Criteria andProjectIdIsNotNull() { + addCriterion("project_id is not null"); return (Criteria) this; } - public Criteria andSortEqualTo(Integer value) { - addCriterion("sort =", value, "sort"); + public Criteria andProjectIdEqualTo(String value) { + addCriterion("project_id =", value, "projectId"); return (Criteria) this; } - public Criteria andSortNotEqualTo(Integer value) { - addCriterion("sort <>", value, "sort"); + public Criteria andProjectIdNotEqualTo(String value) { + addCriterion("project_id <>", value, "projectId"); return (Criteria) this; } - public Criteria andSortGreaterThan(Integer value) { - addCriterion("sort >", value, "sort"); + public Criteria andProjectIdGreaterThan(String value) { + addCriterion("project_id >", value, "projectId"); return (Criteria) this; } - public Criteria andSortGreaterThanOrEqualTo(Integer value) { - addCriterion("sort >=", value, "sort"); + public Criteria andProjectIdGreaterThanOrEqualTo(String value) { + addCriterion("project_id >=", value, "projectId"); return (Criteria) this; } - public Criteria andSortLessThan(Integer value) { - addCriterion("sort <", value, "sort"); + public Criteria andProjectIdLessThan(String value) { + addCriterion("project_id <", value, "projectId"); return (Criteria) this; } - public Criteria andSortLessThanOrEqualTo(Integer value) { - addCriterion("sort <=", value, "sort"); + public Criteria andProjectIdLessThanOrEqualTo(String value) { + addCriterion("project_id <=", value, "projectId"); return (Criteria) this; } - public Criteria andSortIn(List values) { - addCriterion("sort in", values, "sort"); + public Criteria andProjectIdLike(String value) { + addCriterion("project_id like", value, "projectId"); return (Criteria) this; } - public Criteria andSortNotIn(List values) { - addCriterion("sort not in", values, "sort"); + public Criteria andProjectIdNotLike(String value) { + addCriterion("project_id not like", value, "projectId"); return (Criteria) this; } - public Criteria andSortBetween(Integer value1, Integer value2) { - addCriterion("sort between", value1, value2, "sort"); + public Criteria andProjectIdIn(List values) { + addCriterion("project_id in", values, "projectId"); return (Criteria) this; } - public Criteria andSortNotBetween(Integer value1, Integer value2) { - addCriterion("sort not between", value1, value2, "sort"); + public Criteria andProjectIdNotIn(List values) { + addCriterion("project_id not in", values, "projectId"); + return (Criteria) this; + } + + public Criteria andProjectIdBetween(String value1, String value2) { + addCriterion("project_id between", value1, value2, "projectId"); + return (Criteria) this; + } + + public Criteria andProjectIdNotBetween(String value1, String value2) { + addCriterion("project_id not between", value1, value2, "projectId"); return (Criteria) this; } } diff --git a/backend/src/main/java/io/metersphere/base/domain/LoadTestFile.java b/backend/src/main/java/io/metersphere/base/domain/LoadTestFile.java index 0fc212656e..98a8d47466 100644 --- a/backend/src/main/java/io/metersphere/base/domain/LoadTestFile.java +++ b/backend/src/main/java/io/metersphere/base/domain/LoadTestFile.java @@ -1,8 +1,7 @@ package io.metersphere.base.domain; -import lombok.Data; - import java.io.Serializable; +import lombok.Data; @Data public class LoadTestFile implements Serializable { @@ -10,5 +9,7 @@ public class LoadTestFile implements Serializable { private String fileId; + private Integer sort; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/LoadTestFileExample.java b/backend/src/main/java/io/metersphere/base/domain/LoadTestFileExample.java index 1386bb4661..38dca4c4c0 100644 --- a/backend/src/main/java/io/metersphere/base/domain/LoadTestFileExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/LoadTestFileExample.java @@ -243,6 +243,66 @@ public class LoadTestFileExample { addCriterion("file_id not between", value1, value2, "fileId"); return (Criteria) this; } + + public Criteria andSortIsNull() { + addCriterion("sort is null"); + return (Criteria) this; + } + + public Criteria andSortIsNotNull() { + addCriterion("sort is not null"); + return (Criteria) this; + } + + public Criteria andSortEqualTo(Integer value) { + addCriterion("sort =", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortNotEqualTo(Integer value) { + addCriterion("sort <>", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortGreaterThan(Integer value) { + addCriterion("sort >", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortGreaterThanOrEqualTo(Integer value) { + addCriterion("sort >=", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortLessThan(Integer value) { + addCriterion("sort <", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortLessThanOrEqualTo(Integer value) { + addCriterion("sort <=", value, "sort"); + return (Criteria) this; + } + + public Criteria andSortIn(List values) { + addCriterion("sort in", values, "sort"); + return (Criteria) this; + } + + public Criteria andSortNotIn(List values) { + addCriterion("sort not in", values, "sort"); + return (Criteria) this; + } + + public Criteria andSortBetween(Integer value1, Integer value2) { + addCriterion("sort between", value1, value2, "sort"); + return (Criteria) this; + } + + public Criteria andSortNotBetween(Integer value1, Integer value2) { + addCriterion("sort not between", value1, value2, "sort"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/metersphere/base/mapper/FileMetadataMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/FileMetadataMapper.xml index c123e5cc0a..e4624e049d 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/FileMetadataMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/FileMetadataMapper.xml @@ -8,7 +8,7 @@ - + @@ -69,7 +69,7 @@ - id, `name`, `type`, create_time, update_time, `size`, sort + id, `name`, `type`, create_time, update_time, `size`, project_id select @@ -87,8 +88,10 @@ - insert into load_test_file (test_id, file_id) - values (#{testId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}) + insert into load_test_file (test_id, file_id, sort + ) + values (#{testId,jdbcType=VARCHAR}, #{fileId,jdbcType=VARCHAR}, #{sort,jdbcType=INTEGER} + ) insert into load_test_file @@ -99,6 +102,9 @@ file_id, + + sort, + @@ -107,6 +113,9 @@ #{fileId,jdbcType=VARCHAR}, + + #{sort,jdbcType=INTEGER}, + - + SELECT file_metadata.* + FROM file_metadata WHERE file_metadata.type IN #{id} diff --git a/backend/src/main/java/io/metersphere/controller/ProjectController.java b/backend/src/main/java/io/metersphere/controller/ProjectController.java index edf0d20024..790bb76b50 100644 --- a/backend/src/main/java/io/metersphere/controller/ProjectController.java +++ b/backend/src/main/java/io/metersphere/controller/ProjectController.java @@ -14,6 +14,7 @@ import io.metersphere.service.ProjectService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.List; @@ -84,4 +85,13 @@ public class ProjectController { projectService.updateProject(Project); } + @PostMapping(value = "upload/files/{projectId}", consumes = {"multipart/form-data"}) + public void uploadFiles(@PathVariable String projectId, @RequestPart(value = "file") List files) { + projectService.uploadFiles(projectId, files); + } + + @GetMapping(value = "delete/file/{fileId}") + public void deleteFile(@PathVariable String fileId) { + projectService.deleteFile(fileId); + } } diff --git a/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java b/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java index 213f4b43d9..da19e2da3c 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java @@ -15,7 +15,6 @@ import io.metersphere.dto.DashboardTestDTO; import io.metersphere.dto.LoadTestDTO; import io.metersphere.dto.ScheduleDao; import io.metersphere.performance.dto.LoadTestExportJmx; -import io.metersphere.performance.dto.LoadTestFileDTO; import io.metersphere.performance.request.*; import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.service.CheckPermissionService; @@ -122,7 +121,7 @@ public class PerformanceTestController { } @GetMapping("/project/{loadType}/{projectId}/{goPage}/{pageSize}") - public Pager> getProjectFiles(@PathVariable String projectId, @PathVariable String loadType, + public Pager> getProjectFiles(@PathVariable String projectId, @PathVariable String loadType, @PathVariable int goPage, @PathVariable int pageSize) { checkPermissionService.checkProjectOwner(projectId); Page page = PageHelper.startPage(goPage, pageSize, true); @@ -148,7 +147,7 @@ public class PerformanceTestController { @GetMapping("/file/metadata/{testId}") public List getFileMetadata(@PathVariable String testId) { checkPermissionService.checkPerformanceTestOwner(testId); - return fileService.getFileMetadataByTestId(testId); + return performanceTestService.getFileMetadataByTestId(testId); } @GetMapping("/file/getMetadataById/{metadataId}") @@ -156,6 +155,11 @@ public class PerformanceTestController { return fileService.getFileMetadataById(metadataId); } + @PostMapping("/file/{projectId}/getMetadataByName") + public List getProjectMetadataByName(@PathVariable String projectId, @RequestBody QueryProjectFileRequest request) { + return fileService.getProjectFiles(projectId, request); + } + @PostMapping("/file/download") public ResponseEntity downloadJmx(@RequestBody FileOperationRequest fileOperationRequest) { byte[] bytes = fileService.loadFileAsBytes(fileOperationRequest.getId()); diff --git a/backend/src/main/java/io/metersphere/performance/dto/LoadTestFileDTO.java b/backend/src/main/java/io/metersphere/performance/dto/LoadTestFileDTO.java deleted file mode 100644 index 56b4f2c07e..0000000000 --- a/backend/src/main/java/io/metersphere/performance/dto/LoadTestFileDTO.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.metersphere.performance.dto; - -import io.metersphere.base.domain.FileMetadata; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class LoadTestFileDTO extends FileMetadata { - private String testId; - private String testName; -} diff --git a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java index bfc2d9461f..29edf085eb 100644 --- a/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java +++ b/backend/src/main/java/io/metersphere/performance/engine/EngineFactory.java @@ -15,6 +15,7 @@ import io.metersphere.i18n.Translator; import io.metersphere.performance.engine.docker.DockerTestEngine; import io.metersphere.performance.parse.EngineSourceParser; import io.metersphere.performance.parse.EngineSourceParserFactory; +import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.service.FileService; import io.metersphere.service.KubernetesTestEngine; import io.metersphere.service.TestResourcePoolService; @@ -46,6 +47,7 @@ import java.util.stream.Collectors; @Service public class EngineFactory { private static FileService fileService; + private static PerformanceTestService performanceTestService; private static TestResourcePoolService testResourcePoolService; private static Class kubernetesTestEngineClass; @@ -87,7 +89,7 @@ public class EngineFactory { } public static EngineContext createContext(LoadTestWithBLOBs loadTest, String resourceId, double ratio, long startTime, String reportId, int resourceIndex) { - final List fileMetadataList = fileService.getFileMetadataByTestId(loadTest.getId()); + final List fileMetadataList = performanceTestService.getFileMetadataByTestId(loadTest.getId()); if (org.springframework.util.CollectionUtils.isEmpty(fileMetadataList)) { MSException.throwException(Translator.get("run_load_test_file_not_found") + loadTest.getId()); } @@ -235,4 +237,9 @@ public class EngineFactory { public void setTestResourcePoolService(TestResourcePoolService testResourcePoolService) { EngineFactory.testResourcePoolService = testResourcePoolService; } + + @Resource + public void setPerformanceTestService(PerformanceTestService performanceTestService) { + EngineFactory.performanceTestService = performanceTestService; + } } diff --git a/backend/src/main/java/io/metersphere/performance/request/QueryProjectFileRequest.java b/backend/src/main/java/io/metersphere/performance/request/QueryProjectFileRequest.java new file mode 100644 index 0000000000..90c71dcb8a --- /dev/null +++ b/backend/src/main/java/io/metersphere/performance/request/QueryProjectFileRequest.java @@ -0,0 +1,8 @@ +package io.metersphere.performance.request; + +import lombok.Data; + +@Data +public class QueryProjectFileRequest { + private String filename; +} diff --git a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java index b5e2209e5c..1100f9dba3 100644 --- a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java +++ b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java @@ -21,7 +21,6 @@ import io.metersphere.dto.ScheduleDao; import io.metersphere.i18n.Translator; import io.metersphere.job.sechedule.PerformanceTestJob; import io.metersphere.performance.dto.LoadTestExportJmx; -import io.metersphere.performance.dto.LoadTestFileDTO; import io.metersphere.performance.engine.Engine; import io.metersphere.performance.engine.EngineFactory; import io.metersphere.performance.engine.producer.LoadTestProducer; @@ -124,8 +123,10 @@ public class PerformanceTestService { loadTestFileMapper.deleteByExample(loadTestFileExample); if (!CollectionUtils.isEmpty(loadTestFiles)) { - final List fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList()); - fileService.deleteFileByIds(fileIds); + List fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList()); + LoadTestFileExample example3 = new LoadTestFileExample(); + example3.createCriteria().andFileIdIn(fileIds); + loadTestFileMapper.deleteByExample(example3); } } @@ -138,15 +139,15 @@ public class PerformanceTestService { // 导入项目里其他的文件 this.importFiles(importFileIds, loadTest.getId(), request.getFileSorts()); // 保存上传的文件 - this.saveUploadFiles(files, loadTest.getId(), request.getFileSorts()); + this.saveUploadFiles(files, loadTest, request.getFileSorts()); //关联转化的文件 - this.conversionFiles(loadTest.getId(),request.getConversionFileIdList()); + this.conversionFiles(loadTest.getId(), request.getConversionFileIdList()); return loadTest.getId(); } private void conversionFiles(String id, List conversionFileIdList) { for (String metaFileId : conversionFileIdList) { - if(!this.loadTestFileExsits(id,metaFileId)){ + if (!this.loadTestFileExsits(id, metaFileId)) { LoadTestFile loadTestFile = new LoadTestFile(); loadTestFile.setTestId(id); loadTestFile.setFileId(metaFileId); @@ -161,21 +162,22 @@ public class PerformanceTestService { example.createCriteria().andTestIdEqualTo(testId).andFileIdEqualTo(metaFileId); long loadTestFiles = loadTestFileMapper.countByExample(example); - if(!fileExsits && loadTestFiles>0){ + if (!fileExsits && loadTestFiles > 0) { return false; - }else { - return true; + } else { + return true; } } - private void saveUploadFiles(List files, String testId, Map fileSorts) { + private void saveUploadFiles(List files, LoadTest loadTest, Map fileSorts) { if (files != null) { for (int i = 0; i < files.size(); i++) { MultipartFile file = files.get(i); - final FileMetadata fileMetadata = fileService.saveFile(file, fileSorts.getOrDefault(file.getOriginalFilename(), i)); + FileMetadata fileMetadata = fileService.saveFile(file, loadTest.getProjectId()); LoadTestFile loadTestFile = new LoadTestFile(); - loadTestFile.setTestId(testId); + loadTestFile.setTestId(loadTest.getId()); loadTestFile.setFileId(fileMetadata.getId()); + loadTestFile.setSort(fileSorts.getOrDefault(file.getOriginalFilename(), i)); loadTestFileMapper.insert(loadTestFile); } } @@ -184,12 +186,11 @@ public class PerformanceTestService { private void importFiles(List importFileIds, String testId, Map fileSorts) { for (int i = 0; i < importFileIds.size(); i++) { String fileId = importFileIds.get(i); - FileMetadata fileMetadata = fileService.copyFile(fileId); - fileMetadata.setSort(fileSorts.getOrDefault(fileMetadata.getName(), i)); - fileService.updateFileMetadata(fileMetadata); + FileMetadata fileMetadata = fileService.getFileMetadataById(fileId); LoadTestFile loadTestFile = new LoadTestFile(); loadTestFile.setTestId(testId); - loadTestFile.setFileId(fileMetadata.getId()); + loadTestFile.setFileId(fileId); + loadTestFile.setSort(fileSorts.getOrDefault(fileMetadata.getName(), i)); loadTestFileMapper.insert(loadTestFile); } } @@ -230,16 +231,23 @@ public class PerformanceTestService { } // 新选择了一个文件,删除原来的文件 List updatedFiles = request.getUpdatedFileList(); - List originFiles = fileService.getFileMetadataByTestId(request.getId()); + List originFiles = getFileMetadataByTestId(request.getId()); List updatedFileIds = updatedFiles.stream().map(FileMetadata::getId).collect(Collectors.toList()); List originFileIds = originFiles.stream().map(FileMetadata::getId).collect(Collectors.toList()); + // 相减 List deleteFileIds = ListUtils.subtract(originFileIds, updatedFileIds); - fileService.deleteFileByIds(deleteFileIds); + // 删除已经不相关的文件 + LoadTestFileExample example3 = new LoadTestFileExample(); + example3.createCriteria().andFileIdIn(deleteFileIds); + loadTestFileMapper.deleteByExample(example3); + // 导入项目里其他的文件 List addFileIds = ListUtils.subtract(updatedFileIds, originFileIds); this.importFiles(addFileIds, request.getId(), request.getFileSorts()); - this.saveUploadFiles(files, request.getId(), request.getFileSorts()); + + // 处理新上传的文件 + this.saveUploadFiles(files, loadTest, request.getFileSorts()); loadTest.setName(request.getName()); loadTest.setProjectId(request.getProjectId()); @@ -400,7 +408,7 @@ public class PerformanceTestService { } public List getJmxContent(String testId) { - List fileMetadataList = fileService.getFileMetadataByTestId(testId); + List fileMetadataList = getFileMetadataByTestId(testId); List results = new ArrayList<>(); for (FileMetadata metadata : fileMetadataList) { if (FileType.JMX.name().equals(metadata.getType())) { @@ -449,13 +457,7 @@ public class PerformanceTestService { List loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample); if (!CollectionUtils.isEmpty(loadTestFiles)) { loadTestFiles.forEach(loadTestFile -> { - FileMetadata fileMetadata = fileService.copyFile(loadTestFile.getFileId()); - if (fileMetadata == null) { - // 如果性能测试出现文件变更,这里会有 null - return; - } loadTestFile.setTestId(copy.getId()); - loadTestFile.setFileId(fileMetadata.getId()); loadTestFileMapper.insert(loadTestFile); }); } @@ -557,13 +559,18 @@ public class PerformanceTestService { } } - public List getProjectFiles(String projectId, String loadType) { + public List getProjectFiles(String projectId, String loadType) { List loadTypes = new ArrayList<>(); loadTypes.add(StringUtils.upperCase(loadType)); if (StringUtils.equalsIgnoreCase(loadType, "resource")) { loadTypes.add(FileType.CSV.name()); loadTypes.add(FileType.JAR.name()); } + if (StringUtils.equalsIgnoreCase(loadType, "all")) { + loadTypes.add(FileType.CSV.name()); + loadTypes.add(FileType.JAR.name()); + loadTypes.add(FileType.JMX.name()); + } return extLoadTestMapper.getProjectFiles(projectId, loadTypes); } @@ -580,4 +587,16 @@ public class PerformanceTestService { return results; } + + public List getFileMetadataByTestId(String testId) { + LoadTestFileExample loadTestFileExample = new LoadTestFileExample(); + loadTestFileExample.createCriteria().andTestIdEqualTo(testId); + loadTestFileExample.setOrderByClause("sort asc"); + List loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample); + + List fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList()); + FileMetadataExample example = new FileMetadataExample(); + example.createCriteria().andIdIn(fileIds); + return fileService.getFileMetadataByIds(fileIds); + } } diff --git a/backend/src/main/java/io/metersphere/service/FileService.java b/backend/src/main/java/io/metersphere/service/FileService.java index 328b427ee5..e1d7b3ffd1 100644 --- a/backend/src/main/java/io/metersphere/service/FileService.java +++ b/backend/src/main/java/io/metersphere/service/FileService.java @@ -7,8 +7,10 @@ import io.metersphere.base.mapper.LoadTestFileMapper; import io.metersphere.base.mapper.TestCaseFileMapper; import io.metersphere.commons.constants.FileType; import io.metersphere.commons.exception.MSException; +import io.metersphere.performance.request.QueryProjectFileRequest; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @@ -37,21 +39,6 @@ public class FileService { return fileContent.getFile(); } - public List getFileMetadataByTestId(String testId) { - LoadTestFileExample loadTestFileExample = new LoadTestFileExample(); - loadTestFileExample.createCriteria().andTestIdEqualTo(testId); - final List loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample); - - if (CollectionUtils.isEmpty(loadTestFiles)) { - return new ArrayList<>(); - } - List fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList()); - FileMetadataExample example = new FileMetadataExample(); - example.createCriteria().andIdIn(fileIds); - example.setOrderByClause("sort asc"); // 安装顺序排序 - return fileMetadataMapper.selectByExample(example); - } - public FileContent getFileContent(String fileId) { return fileContentMapper.selectByPrimaryKey(fileId); } @@ -86,20 +73,16 @@ public class FileService { fileContentMapper.deleteByExample(example2); } - public FileMetadata saveFile(MultipartFile file) { - return saveFile(file, 0); - } - - public FileMetadata saveFile(MultipartFile file, Integer sort) { + public FileMetadata saveFile(MultipartFile file, String projectId) { final FileMetadata fileMetadata = new FileMetadata(); fileMetadata.setId(UUID.randomUUID().toString()); fileMetadata.setName(file.getOriginalFilename()); fileMetadata.setSize(file.getSize()); + fileMetadata.setProjectId(projectId); fileMetadata.setCreateTime(System.currentTimeMillis()); fileMetadata.setUpdateTime(System.currentTimeMillis()); FileType fileType = getFileType(fileMetadata.getName()); fileMetadata.setType(fileType.name()); - fileMetadata.setSort(sort); fileMetadataMapper.insert(fileMetadata); FileContent fileContent = new FileContent(); @@ -114,7 +97,11 @@ public class FileService { return fileMetadata; } - public FileMetadata saveFile(File file, byte[] fileByte, Integer sort) { + public FileMetadata saveFile(MultipartFile file) { + return saveFile(file, null); + } + + public FileMetadata saveFile(File file, byte[] fileByte) { final FileMetadata fileMetadata = new FileMetadata(); fileMetadata.setId(UUID.randomUUID().toString()); fileMetadata.setName(file.getName()); @@ -123,7 +110,6 @@ public class FileService { fileMetadata.setUpdateTime(System.currentTimeMillis()); FileType fileType = getFileType(fileMetadata.getName()); fileMetadata.setType(fileType.name()); - fileMetadata.setSort(sort); fileMetadataMapper.insert(fileMetadata); FileContent fileContent = new FileContent(); @@ -197,12 +183,6 @@ public class FileService { return fileMetadataMapper.selectByPrimaryKey(fileId); } - public List getProjectJMXs(String projectId) { - FileMetadataExample example = new FileMetadataExample(); - fileMetadataMapper.selectByExample(example); - return null; - } - public void updateFileMetadata(FileMetadata fileMetadata) { fileMetadataMapper.updateByPrimaryKeySelective(fileMetadata); } @@ -211,10 +191,29 @@ public class FileService { FileMetadataExample example = new FileMetadataExample(); example.createCriteria().andIdEqualTo(fileId); long fileCount = fileMetadataMapper.countByExample(example); - if(fileCount>0){ - return true; - }else { - return false; + if (fileCount > 0) { + return true; + } else { + return false; } } + + public List getProjectFiles(String projectId, QueryProjectFileRequest request) { + FileMetadataExample example = new FileMetadataExample(); + FileMetadataExample.Criteria criteria = example.createCriteria(); + criteria.andProjectIdEqualTo(projectId); + if (!StringUtils.isEmpty(request.getFilename())) { + criteria.andNameEqualTo(request.getFilename()); + } + return fileMetadataMapper.selectByExample(example); + } + + public List getFileMetadataByIds(List fileIds) { + if (CollectionUtils.isEmpty(fileIds)) { + return new ArrayList<>(); + } + FileMetadataExample example = new FileMetadataExample(); + example.createCriteria().andIdIn(fileIds); + return fileMetadataMapper.selectByExample(example); + } } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/service/ProjectService.java b/backend/src/main/java/io/metersphere/service/ProjectService.java index 5dcf0d730c..77a218d37e 100644 --- a/backend/src/main/java/io/metersphere/service/ProjectService.java +++ b/backend/src/main/java/io/metersphere/service/ProjectService.java @@ -3,13 +3,12 @@ package io.metersphere.service; import io.metersphere.api.dto.DeleteAPITestRequest; import io.metersphere.api.dto.QueryAPITestRequest; import io.metersphere.api.service.APITestService; -import io.metersphere.base.domain.LoadTest; -import io.metersphere.base.domain.LoadTestExample; -import io.metersphere.base.domain.Project; -import io.metersphere.base.domain.ProjectExample; +import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiTestFileMapper; +import io.metersphere.base.mapper.LoadTestFileMapper; import io.metersphere.base.mapper.LoadTestMapper; import io.metersphere.base.mapper.ProjectMapper; -import io.metersphere.base.mapper.ext.*; +import io.metersphere.base.mapper.ext.ExtProjectMapper; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.SessionUtils; @@ -17,6 +16,7 @@ import io.metersphere.controller.request.ProjectRequest; import io.metersphere.dto.ProjectDTO; import io.metersphere.i18n.Translator; import io.metersphere.performance.request.DeleteTestPlanRequest; +import io.metersphere.performance.request.QueryProjectFileRequest; import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.track.service.TestCaseService; import io.metersphere.track.service.TestPlanProjectService; @@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.List; @@ -43,14 +44,6 @@ public class ProjectService { @Resource private LoadTestMapper loadTestMapper; @Resource - private ExtTestCaseMapper extTestCaseMapper; - @Resource - private ExtTestPlanMapper extTestPlanMapper; - @Resource - private ExtLoadTestMapper extLoadTestMapperMapper; - @Resource - private ExtApiTestMapper extApiTestMapper; - @Resource private TestPlanService testPlanService; @Resource private TestCaseService testCaseService; @@ -58,6 +51,12 @@ public class ProjectService { private APITestService apiTestService; @Resource private TestPlanProjectService testPlanProjectService; + @Resource + private FileService fileService; + @Resource + private LoadTestFileMapper loadTestFileMapper; + @Resource + private ApiTestFileMapper apiTestFileMapper; public Project addProject(Project project) { if (StringUtils.isBlank(project.getName())) { @@ -169,4 +168,49 @@ public class ProjectService { public Project getProjectById(String id) { return projectMapper.selectByPrimaryKey(id); } + + public void uploadFiles(String projectId, List files) { + if (files != null) { + for (MultipartFile file : files) { + QueryProjectFileRequest request = new QueryProjectFileRequest(); + request.setFilename(file.getOriginalFilename()); + if (CollectionUtils.isEmpty(fileService.getProjectFiles(projectId, request))) { + fileService.saveFile(file, projectId); + } else { + MSException.throwException(Translator.get("project_file_already_exists")); + } + } + } + } + + public void deleteFile(String fileId) { + LoadTestFileExample example1 = new LoadTestFileExample(); + example1.createCriteria().andFileIdEqualTo(fileId); + List loadTestFiles = loadTestFileMapper.selectByExample(example1); + String errorMessage = ""; + if (loadTestFiles.size() > 0) { + List testIds = loadTestFiles.stream().map(LoadTestFile::getTestId).distinct().collect(Collectors.toList()); + LoadTestExample example = new LoadTestExample(); + example.createCriteria().andIdIn(testIds); + List loadTests = loadTestMapper.selectByExample(example); + errorMessage += Translator.get("load_test") + ": " + StringUtils.join(loadTests.stream().map(LoadTest::getName).toArray(), ","); + errorMessage += "\n"; + } + ApiTestFileExample example2 = new ApiTestFileExample(); + example2.createCriteria().andFileIdEqualTo(fileId); + List apiTestFiles = apiTestFileMapper.selectByExample(example2); + if (apiTestFiles.size() > 0) { + List testIds = apiTestFiles.stream().map(ApiTestFile::getTestId).distinct().collect(Collectors.toList()); + LoadTestExample example = new LoadTestExample(); + example.createCriteria().andIdIn(testIds); + QueryAPITestRequest request = new QueryAPITestRequest(); + request.setIds(testIds); + List apiTests = apiTestService.listByIds(request); + errorMessage += Translator.get("api_test") + ": " + StringUtils.join(apiTests.stream().map(ApiTest::getName).toArray(), ","); + } + if (StringUtils.isNotBlank(errorMessage)) { + MSException.throwException(errorMessage + Translator.get("project_file_in_use")); + } + fileService.deleteFileById(fileId); + } } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java index 42db5f06e8..9deb78377d 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseService.java @@ -662,7 +662,7 @@ public class TestCaseService { } files.forEach(file -> { - final FileMetadata fileMetadata = fileService.saveFile(file); + final FileMetadata fileMetadata = fileService.saveFile(file, testCaseWithBLOBs.getProjectId()); TestCaseFile testCaseFile = new TestCaseFile(); testCaseFile.setCaseId(testCaseWithBLOBs.getId()); testCaseFile.setFileId(fileMetadata.getId()); @@ -695,7 +695,7 @@ public class TestCaseService { if (files != null) { files.forEach(file -> { - final FileMetadata fileMetadata = fileService.saveFile(file); + final FileMetadata fileMetadata = fileService.saveFile(file,testCaseWithBLOBs.getProjectId()); TestCaseFile testCaseFile = new TestCaseFile(); testCaseFile.setFileId(fileMetadata.getId()); testCaseFile.setCaseId(request.getId()); diff --git a/backend/src/main/resources/db/migration/V78__v1.8_release.sql b/backend/src/main/resources/db/migration/V78__v1.8_release.sql index 2b658eae4e..c1f35cfdab 100644 --- a/backend/src/main/resources/db/migration/V78__v1.8_release.sql +++ b/backend/src/main/resources/db/migration/V78__v1.8_release.sql @@ -88,10 +88,6 @@ ALTER TABLE test_case_review alter table test_plan_api_scenario change environment_id environment longtext null comment 'Relevance environment'; --- file add sort column -alter table file_metadata - add sort int default 0; - -- add Original state alter table api_definition add original_state varchar(64); alter table api_scenario add original_state varchar(64); @@ -140,4 +136,17 @@ update schedule sch inner join swagger_url_project sup on sup.id = sch.resource_id set sch.name = LEFT(SUBSTRING_INDEX(sup.swagger_url, '/', 3), 100); -- delete an unused colum -alter table schedule drop column custom_data; \ No newline at end of file +alter table schedule drop column custom_data; + +-- add sort column +alter table load_test_file add sort int default 0; + +UPDATE file_metadata JOIN (SELECT file_id, project_id + FROM load_test_file + JOIN load_test ON test_id = load_test.id) temp ON file_id = file_metadata.id +SET file_metadata.project_id = temp.project_id; + +UPDATE file_metadata JOIN (SELECT file_id, project_id + FROM api_test_file + JOIN api_test ON test_id = api_test.id) temp ON file_id = file_metadata.id +SET file_metadata.project_id = temp.project_id; \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index f6edc5e762..5c066f75fd 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -66,6 +66,8 @@ only_one_k8s=Only one K8S can be added #project project_name_is_null=Project name cannot be null project_name_already_exists=The project name already exists +project_file_already_exists=The file already exists +project_file_in_use=use this file and cannot be deleted. #organization organization_name_is_null=organization name cannot be null organization_name_already_exists=The organization name already exists @@ -75,6 +77,7 @@ organization_id_is_null=Organization ID cannot be null api_load_script_error=Load script error api_report_is_null="Report is null, can't update" api_test_environment_already_exists="Api test environment already exists" +api_test=API Test #test case test_case_node_level=level test_case_node_level_tip=The node tree maximum depth is diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index 3746f89597..e0f23126e3 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -66,6 +66,8 @@ only_one_k8s=只能添加一个 K8S #project project_name_is_null=项目名称不能为空 project_name_already_exists=项目名称已存在 +project_file_already_exists=项目下该文件已经存在 +project_file_in_use=占用文件,无法删除。 #organization organization_name_is_null=组织名不能为空 organization_name_already_exists=组织名已存在 @@ -75,6 +77,7 @@ organization_id_is_null=组织 ID 不能为空 api_load_script_error=读取脚本失败 api_report_is_null="测试报告是未生成,无法更新" api_test_environment_already_exists="已存在该名称的环境配置" +api_test=接口测试 #test case test_case_node_level=层 test_case_node_level_tip=模块树最大深度为 diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index 419afc2025..88ed5da387 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -66,6 +66,8 @@ only_one_k8s=只能添加一個 K8S #project project_name_is_null=項目名稱不能為空 project_name_already_exists=項目名稱已存在 +project_file_already_exists=項目下文件已存在 +project_file_in_use=佔用文件,無法刪除。 #organization organization_name_is_null=組織名不能為空 organization_name_already_exists=組織名已存在 @@ -75,6 +77,7 @@ organization_id_is_null=組織 ID 不能為空 api_load_script_error=讀取腳本失敗 api_report_is_null="測試報告是未生成,無法更新" api_test_environment_already_exists="已存在該名稱的環境配置" +api_test=接口測試 #test case test_case_node_level=層 test_case_node_level_tip=模塊樹最大深度為 diff --git a/frontend/src/business/components/performance/test/components/ExistFiles.vue b/frontend/src/business/components/performance/test/components/ExistFiles.vue index 5a8ea694be..1551584f95 100644 --- a/frontend/src/business/components/performance/test/components/ExistFiles.vue +++ b/frontend/src/business/components/performance/test/components/ExistFiles.vue @@ -3,6 +3,41 @@ :destroy-on-close="true" :title="$t('load_test.exist_jmx')" width="70%" :visible.sync="loadFileVisible"> + + + + + + + + + - - @@ -45,15 +76,18 @@ import MsDialogFooter from "@/business/components/common/components/MsDialogFoot import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import {getCurrentProjectID} from "@/common/js/utils"; import {findThreadGroup} from "@/business/components/performance/test/model/ThreadGroup"; +import MsTableButton from "@/business/components/common/components/MsTableButton"; +import axios from "axios"; export default { name: "ExistFiles", - components: {MsTablePagination, MsDialogFooter}, + components: {MsTableButton, MsTablePagination, MsDialogFooter}, props: { fileList: Array, tableData: Array, uploadList: Array, - scenarios: Array + scenarios: Array, + isReadOnly: Boolean, }, data() { return { @@ -65,6 +99,7 @@ export default { loadType: 'jmx', existFiles: [], selectIds: new Set, + fileNumLimit: 10, } }, methods: { @@ -106,6 +141,7 @@ export default { }, handleImport() { if (this.selectIds.size === 0) { + this.loadFileVisible = false; return; } @@ -163,6 +199,68 @@ export default { }); }, + beforeUploadFile(file) { + if (!this.fileValidator(file)) { + /// todo: 显示错误信息 + return false; + } + + if (this.tableData.filter(f => f.name === file.name).length > 0) { + this.$error(this.$t('load_test.delete_file')); + return false; + } + let valid = false; + + // 检查数据库是否存在同名文件 + async function f() { + return await axios.post('/performance/file/' + getCurrentProjectID() + '/getMetadataByName', {filename: file.name}) + } + f().then(res => { + let response = res.data; + if (response.data.length === 0) { + let type = file.name.substring(file.name.lastIndexOf(".") + 1); + + this.tableData.push({ + name: file.name, + size: (file.size / 1024).toFixed(2) + ' KB', + type: type.toUpperCase(), + updateTime: file.lastModified, + }); + valid = true; + } else { + this.$error(this.$t('load_test.project_file_exist')); + } + }); + + + return valid; + }, + handleUpload(uploadResources) { + let self = this; + let file = uploadResources.file; + self.uploadList.push(file); + let type = file.name.substring(file.name.lastIndexOf(".") + 1); + if (type.toLowerCase() !== 'jmx') { + return; + } + let jmxReader = new FileReader(); + jmxReader.onload = (event) => { + let threadGroups = findThreadGroup(event.target.result, file.name); + threadGroups.forEach(tg => { + tg.options = {}; + this.scenarios.push(tg); + }); + self.$emit('fileChange', self.scenarios); + }; + jmxReader.readAsText(file); + }, + handleExceed() { + this.$error(this.$t('load_test.file_size_limit')); + }, + fileValidator(file) { + /// todo: 是否需要对文件内容和大小做限制 + return file.size > 0; + }, } } diff --git a/frontend/src/business/components/performance/test/components/PerformanceBasicConfig.vue b/frontend/src/business/components/performance/test/components/PerformanceBasicConfig.vue index 44bcc186a9..9b45a65725 100644 --- a/frontend/src/business/components/performance/test/components/PerformanceBasicConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformanceBasicConfig.vue @@ -4,21 +4,6 @@

{{ $t('load_test.scenario_list') }}

- - - {{ $t('load_test.other_resource') }} - - - @@ -125,6 +95,7 @@ :file-list="fileList" :table-data="tableData" :upload-list="uploadList" + :is-read-only="isReadOnly" :scenarios="threadGroups"/> import {Message} from "element-ui"; -import {findThreadGroup} from "@/business/components/performance/test/model/ThreadGroup"; import MsTableButton from "@/business/components/common/components/MsTableButton"; import MsTablePagination from "@/business/components/common/pagination/TablePagination"; import MsTableOperatorButton from "@/business/components/common/components/MsTableOperatorButton"; @@ -229,64 +199,6 @@ export default { }); }) }, - - beforeUploadJmx(file) { - if (!this.fileValidator(file)) { - /// todo: 显示错误信息 - return false; - } - if (this.tableData.filter(f => f.name === file.name).length > 0) { - this.$error(this.$t('load_test.delete_file')); - return false; - } - - let type = file.name.substring(file.name.lastIndexOf(".") + 1); - - this.tableData.push({ - name: file.name, - size: (file.size / 1024).toFixed(2) + ' KB', - type: type.toUpperCase(), - updateTime: file.lastModified, - }); - - return true; - }, - beforeUploadFile(file) { - if (!this.fileValidator(file)) { - /// todo: 显示错误信息 - return false; - } - if (this.tableData.filter(f => f.name === file.name).length > 0) { - this.$error(this.$t('load_test.delete_file')); - return false; - } - - let type = file.name.substring(file.name.lastIndexOf(".") + 1); - - this.tableData.push({ - name: file.name, - size: (file.size / 1024).toFixed(2) + ' KB', - type: type.toUpperCase(), - updateTime: file.lastModified, - }); - - return true; - }, - handleUpload(uploadResources) { - let self = this; - let file = uploadResources.file; - self.uploadList.push(file); - let type = file.name.substring(file.name.lastIndexOf(".") + 1); - if (type.toLowerCase() !== 'jmx') { - return; - } - let jmxReader = new FileReader(); - jmxReader.onload = (event) => { - self.threadGroups = self.threadGroups.concat(findThreadGroup(event.target.result, file.name)); - self.$emit('fileChange', self.threadGroups); - }; - jmxReader.readAsText(file); - }, selectAttachFileById(metadataIdArr) { this.metadataIdList = metadataIdArr; for (let i = 0; i < metadataIdArr.length; i++) { @@ -380,13 +292,6 @@ export default { tgTypeChange(row) { this.$emit("tgTypeChange", row); }, - handleExceed() { - this.$error(this.$t('load_test.file_size_limit')); - }, - fileValidator(file) { - /// todo: 是否需要对文件内容和大小做限制 - return file.size > 0; - }, updatedFileList() { return this.fileList;// 表示修改了已经上传的文件列表 }, @@ -414,7 +319,7 @@ export default { }, validConfig() { if (this.uploadList.length + this.fileList.length > this.fileNumLimit) { - this.handleExceed(); + this.$refs.existFiles.handleExceed(); return false; } diff --git a/frontend/src/business/components/performance/test/components/ResourceFiles.vue b/frontend/src/business/components/performance/test/components/ResourceFiles.vue new file mode 100644 index 0000000000..a54952cfc5 --- /dev/null +++ b/frontend/src/business/components/performance/test/components/ResourceFiles.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/frontend/src/business/components/settings/project/MsProject.vue b/frontend/src/business/components/settings/project/MsProject.vue index 1f111a35cc..d07125ca22 100644 --- a/frontend/src/business/components/settings/project/MsProject.vue +++ b/frontend/src/business/components/settings/project/MsProject.vue @@ -7,6 +7,8 @@ @@ -88,6 +90,7 @@ + @@ -109,10 +112,12 @@ import {PROJECT_ID} from "@/common/js/constants"; import MsJarConfig from "../../api/test/components/jar/JarConfig"; import MsTableButton from "../../common/components/MsTableButton"; import {_sort} from "@/common/js/tableUtils"; +import MsResourceFiles from "@/business/components/performance/test/components/ResourceFiles"; export default { name: "MsProject", components: { + MsResourceFiles, MsTableButton, MsJarConfig, TemplateComponent, @@ -121,170 +126,173 @@ export default { MsDeleteConfirm, MsMainContainer, MsContainer, MsTableOperator, MsCreateBox, MsTablePagination, MsTableHeader, MsDialogFooter - }, - data() { - return { - createVisible: false, - result: {}, - btnTips: this.$t('project.create'), - title: this.$t('project.create'), - condition: {}, - items: [], - tapd: false, - jira: false, - zentao: false, - form: {}, - currentPage: 1, - pageSize: 10, - total: 0, - rules: { - name: [ - {required: true, message: this.$t('project.input_name'), trigger: 'blur'}, - {min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'} - ], - description: [ - {max: 250, message: this.$t('commons.input_limit', [0, 250]), trigger: 'blur'} - ], - }, + }, + data() { + return { + createVisible: false, + result: {}, + btnTips: this.$t('project.create'), + title: this.$t('project.create'), + condition: {}, + items: [], + tapd: false, + jira: false, + zentao: false, + form: {}, + currentPage: 1, + pageSize: 10, + total: 0, + rules: { + name: [ + {required: true, message: this.$t('project.input_name'), trigger: 'blur'}, + {min: 2, max: 50, message: this.$t('commons.input_limit', [2, 50]), trigger: 'blur'} + ], + description: [ + {max: 250, message: this.$t('commons.input_limit', [0, 250]), trigger: 'blur'} + ], + }, + } + }, + props: { + baseUrl: { + type: String + } + }, + mounted() { + if (this.$route.path.split('/')[2] === 'project' && + this.$route.path.split('/')[3] === 'create') { + this.create(); + this.$router.replace('/setting/project/all'); + } + this.list(); + }, + activated() { + this.list(); + }, + computed: { + currentUser: () => { + return getCurrentUser(); + } + }, + destroyed() { + this.createVisible = false; + }, + methods: { + create() { + let workspaceId = this.currentUser.lastWorkspaceId; + if (!workspaceId) { + this.$warning(this.$t('project.please_choose_workspace')); + return false; } + this.title = this.$t('project.create'); + // listenGoBack(this.handleClose); + this.createVisible = true; + this.form = {}; }, - props: { - baseUrl: { - type: String - } + edit(row) { + this.title = this.$t('project.edit'); + this.createVisible = true; + listenGoBack(this.handleClose); + this.form = Object.assign({}, row); + this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => { + let data = response.data; + let platforms = data.map(d => d.platform); + if (platforms.indexOf("Tapd") !== -1) { + this.tapd = true; + } + if (platforms.indexOf("Jira") !== -1) { + this.jira = true; + } + if (platforms.indexOf("Zentao") !== -1) { + this.zentao = true; + } + }); }, - mounted() { - if (this.$route.path.split('/')[2] === 'project' && - this.$route.path.split('/')[3] === 'create') { - this.create(); - this.$router.replace('/setting/project/all'); - } - this.list(); - }, - activated() { - this.list(); - }, - computed: { - currentUser: () => { - return getCurrentUser(); - } - }, - destroyed() { - this.createVisible = false; - }, - methods: { - create() { - let workspaceId = this.currentUser.lastWorkspaceId; - if (!workspaceId) { - this.$warning(this.$t('project.please_choose_workspace')); + submit(formName) { + this.$refs[formName].validate((valid) => { + if (valid) { + let saveType = "add"; + if (this.form.id) { + saveType = "update" + } + this.result = this.$post("/project/" + saveType, this.form, () => { + this.createVisible = false; + this.list(); + Message.success(this.$t('commons.save_success')); + }); + } else { return false; } - this.title = this.$t('project.create'); - // listenGoBack(this.handleClose); - this.createVisible = true; - this.form = {}; - }, - edit(row) { - this.title = this.$t('project.edit'); - this.createVisible = true; - listenGoBack(this.handleClose); - this.form = Object.assign({}, row); - this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => { - let data = response.data; - let platforms = data.map(d => d.platform); - if (platforms.indexOf("Tapd") !== -1) { - this.tapd = true; - } - if (platforms.indexOf("Jira") !== -1) { - this.jira = true; - } - if (platforms.indexOf("Zentao") !== -1) { - this.zentao = true; - } - }); - }, - submit(formName) { - this.$refs[formName].validate((valid) => { - if (valid) { - let saveType = "add"; - if (this.form.id) { - saveType = "update" - } - this.result = this.$post("/project/" + saveType, this.form, () => { - this.createVisible = false; - this.list(); - Message.success(this.$t('commons.save_success')); - }); - } else { - return false; - } - }); - }, - openJarConfig() { - this.$refs.jarConfig.open(); - }, - handleDelete(project) { - this.$refs.deleteConfirm.open(project); - }, - _handleDelete(project) { - this.$confirm(this.$t('project.delete_tip'), '', { - confirmButtonText: this.$t('commons.confirm'), - cancelButtonText: this.$t('commons.cancel'), - type: 'warning' - }).then(() => { - this.$get('/project/delete/' + project.id, () => { - if (project.id === getCurrentProjectID()) { - localStorage.removeItem(PROJECT_ID); - this.$post("/user/update/current", {id: getCurrentUser().id, lastProjectId: ''}); - } - Message.success(this.$t('commons.delete_success')); - this.list(); - }); - }).catch(() => { - this.$message({ - type: 'info', - message: this.$t('commons.delete_cancelled') - }); - }); - }, - handleClose() { - removeGoBackListener(this.handleClose); - this.createVisible = false; - this.tapd = false; - this.jira = false; - this.zentao = false; - }, - search() { - this.list(); - }, - list() { - let url = "/project/list/" + this.currentPage + '/' + this.pageSize; - this.result = this.$post(url, this.condition, (response) => { - let data = response.data; - this.items = data.listObject; - this.total = data.itemCount; - }) - }, - sort(column) { - _sort(column, this.condition); - this.list(); - }, - openEnvironmentConfig(project) { - this.$refs.environmentConfig.open(project.id); - }, + }); }, - created() { - document.addEventListener('keydown', this.handleEvent) + openJarConfig() { + this.$refs.jarConfig.open(); }, - beforeDestroy() { - document.removeEventListener('keydown', this.handleEvent); - } + openFiles() { + this.$refs.resourceFiles.open(); + }, + handleDelete(project) { + this.$refs.deleteConfirm.open(project); + }, + _handleDelete(project) { + this.$confirm(this.$t('project.delete_tip'), '', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + type: 'warning' + }).then(() => { + this.$get('/project/delete/' + project.id, () => { + if (project.id === getCurrentProjectID()) { + localStorage.removeItem(PROJECT_ID); + this.$post("/user/update/current", {id: getCurrentUser().id, lastProjectId: ''}); + } + Message.success(this.$t('commons.delete_success')); + this.list(); + }); + }).catch(() => { + this.$message({ + type: 'info', + message: this.$t('commons.delete_cancelled') + }); + }); + }, + handleClose() { + removeGoBackListener(this.handleClose); + this.createVisible = false; + this.tapd = false; + this.jira = false; + this.zentao = false; + }, + search() { + this.list(); + }, + list() { + let url = "/project/list/" + this.currentPage + '/' + this.pageSize; + this.result = this.$post(url, this.condition, (response) => { + let data = response.data; + this.items = data.listObject; + this.total = data.itemCount; + }) + }, + sort(column) { + _sort(column, this.condition); + this.list(); + }, + openEnvironmentConfig(project) { + this.$refs.environmentConfig.open(project.id); + }, + }, + created() { + document.addEventListener('keydown', this.handleEvent) + }, + beforeDestroy() { + document.removeEventListener('keydown', this.handleEvent); } +} diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 663306aef7..cee8d7f0e9 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -338,6 +338,7 @@ export default { delete: 'Delete project', delete_confirm: 'Deleting this project will delete all test resources under this project. Are you sure you want to delete?', delete_tip: 'Deleting this project will delete all test resources under this project. Are you sure you want to delete?', + file_delete_tip: 'Deleting this project file: {0}?', search_by_name: 'Search by name', search_by_name_jar: 'Search by name/jar', input_name: 'Please enter a workspace name', @@ -530,6 +531,7 @@ export default { load_exist_jmx: 'Load Project JMX', threadgroup_at_least_one: 'At least one ThreadGroup is enabled', load_api_automation_jmx: 'Import API automation scenario', + project_file_exist: "The file already exists in the project, please import it directly" }, api_test: { creator: "Creator", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 7786e7e492..cf744e4cf7 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -335,6 +335,7 @@ export default { delete: '删除项目', delete_confirm: '确定要删除这个项目吗?', delete_tip: '删除该项目,会删除该项目下所有测试资源,确定要删除吗?', + file_delete_tip: '删除该项目的文件: {0}?', search_by_name: '根据名称搜索', search_by_name_jar: '根据 名称 / jar包 搜索', input_name: '请输入项目名称', @@ -525,10 +526,11 @@ export default { exist_jmx: '已存在的文件', other_resource: '资源文件', upload_file: '上传新文件', - load_exist_file: '加载已有文件', - load_exist_jmx: '加载已有 JMX 文件', + load_exist_file: '加载文件', + load_exist_jmx: '加载 JMX 文件', threadgroup_at_least_one: '至少启用一个线程组', load_api_automation_jmx: '引用接口自动化场景', + project_file_exist: "项目中已存在该文件,请直接引用" }, api_test: { creator: "创建人", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 0707e7a6fa..0cbee14b76 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -335,6 +335,7 @@ export default { delete: '刪除項目', delete_confirm: '確定要刪除這個項目嗎?', delete_tip: '刪除該項目,會刪除該項目下所有測試資源,確定要刪除嗎?', + file_delete_tip: '刪除該項目的文件: {0}?', search_by_name: '根據名稱搜索', search_by_name_jar: '根據名稱/jar包搜索', input_name: '請輸入項目名稱', @@ -525,10 +526,11 @@ export default { exist_jmx: '已存在的文件', other_resource: '資源文件', upload_file: '上傳新文件', - load_exist_file: '加載已有文件', - load_exist_jmx: '加載已有 JMX 文件', + load_exist_file: '加載文件', + load_exist_jmx: '加載 JMX 文件', threadgroup_at_least_one: '至少啟用一個線程組', load_api_automation_jmx: '引用接口自動化場景', + project_file_exist: "項目中已存在該文件,請直接引用" }, api_test: { creator: "創建人", From 7fe6b3660de7d5a7e0e6f8fce319083e73538444 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 16 Mar 2021 13:47:56 +0800 Subject: [PATCH 2/3] =?UTF-8?q?refactor(=E6=80=A7=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95):=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E5=88=B7=E6=96=B0=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/performance/test/components/ResourceFiles.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/performance/test/components/ResourceFiles.vue b/frontend/src/business/components/performance/test/components/ResourceFiles.vue index a54952cfc5..f2989ce4e0 100644 --- a/frontend/src/business/components/performance/test/components/ResourceFiles.vue +++ b/frontend/src/business/components/performance/test/components/ResourceFiles.vue @@ -139,8 +139,8 @@ export default { }).then(() => { this.$get('/project/delete/file/' + row.id, response => { Message.success(this.$t('commons.delete_success')); + this.getProjectFiles(); }); - this.getProjectFiles(); }).catch(() => { }); From d35d135478b0bf63689946acfa3b37b793f571ad Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 16 Mar 2021 13:53:48 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=BE=91=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=97=B6=E5=88=A0=E9=99=A4=E4=B8=8D=E7=9B=B8=E5=85=B3=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../performance/service/PerformanceTestService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java index 1100f9dba3..6a73af82b5 100644 --- a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java +++ b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java @@ -238,9 +238,11 @@ public class PerformanceTestService { // 相减 List deleteFileIds = ListUtils.subtract(originFileIds, updatedFileIds); // 删除已经不相关的文件 - LoadTestFileExample example3 = new LoadTestFileExample(); - example3.createCriteria().andFileIdIn(deleteFileIds); - loadTestFileMapper.deleteByExample(example3); + if (!CollectionUtils.isEmpty(deleteFileIds)) { + LoadTestFileExample example3 = new LoadTestFileExample(); + example3.createCriteria().andFileIdIn(deleteFileIds); + loadTestFileMapper.deleteByExample(example3); + } // 导入项目里其他的文件 List addFileIds = ListUtils.subtract(updatedFileIds, originFileIds);