From 1c1d419852fcf386ed50ad6bec774bed6b20d534 Mon Sep 17 00:00:00 2001 From: haifeng414 Date: Wed, 12 Feb 2020 16:41:19 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter/TimestampFormatDateFilter.js | 27 ++++++ .../testPlan/components/BasicConfig.vue | 91 +++++++++++++++++-- frontend/src/performance/main.js | 4 + 3 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 frontend/src/performance/components/common/filter/TimestampFormatDateFilter.js diff --git a/frontend/src/performance/components/common/filter/TimestampFormatDateFilter.js b/frontend/src/performance/components/common/filter/TimestampFormatDateFilter.js new file mode 100644 index 0000000000..678f3b9de3 --- /dev/null +++ b/frontend/src/performance/components/common/filter/TimestampFormatDateFilter.js @@ -0,0 +1,27 @@ +let timestampFormatDate = function (timestamp) { + if (!timestamp) { + return timestamp + } + + let date = new Date(timestamp); + + let y = date.getFullYear(); + + let MM = date.getMonth() + 1; + MM = MM < 10 ? ('0' + MM) : MM; + + let d = date.getDate(); + d = d < 10 ? ('0' + d) : d; + + let h = date.getHours(); + h = h < 10 ? ('0' + h) : h; + + let m = date.getMinutes(); + m = m < 10 ? ('0' + m) : m; + + let s = date.getSeconds(); + s = s < 10 ? ('0' + s) : s; + + return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s +}; +export default timestampFormatDate diff --git a/frontend/src/performance/components/testPlan/components/BasicConfig.vue b/frontend/src/performance/components/testPlan/components/BasicConfig.vue index b5176eeacc..873008607f 100644 --- a/frontend/src/performance/components/testPlan/components/BasicConfig.vue +++ b/frontend/src/performance/components/testPlan/components/BasicConfig.vue @@ -1,12 +1,52 @@ diff --git a/frontend/src/performance/main.js b/frontend/src/performance/main.js index db085981a7..60d5aeca91 100644 --- a/frontend/src/performance/main.js +++ b/frontend/src/performance/main.js @@ -7,6 +7,7 @@ import ajax from "../common/ajax"; import App from './App.vue'; import router from "./components/router/router"; import i18n from "../i18n/i18n"; +import timestampFormatDate from "./components/common/filter/TimestampFormatDateFilter"; Vue.config.productionTip = false; Vue.use(icon); @@ -16,6 +17,9 @@ Vue.use(ElementUI, { Vue.use(filters); Vue.use(ajax); +// filter +Vue.filter('timestampFormatDate', timestampFormatDate); + new Vue({ el: '#app', router, From a732a7291b2bd056b59b08bfa299361cfe65ade9 Mon Sep 17 00:00:00 2001 From: haifeng414 Date: Wed, 12 Feb 2020 20:55:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=92=8C=E5=88=A0=E9=99=A4=E7=9A=84=E5=89=8D=E7=AB=AF=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TestPlanController.java | 23 ++++++- .../testplan/FileOperationRequest.java | 13 ++++ .../io/metersphere/service/FileService.java | 23 +++++++ .../testPlan/components/BasicConfig.vue | 63 ++++++++++++++++--- 4 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/requests/testplan/FileOperationRequest.java diff --git a/backend/src/main/java/io/metersphere/controller/TestPlanController.java b/backend/src/main/java/io/metersphere/controller/TestPlanController.java index 48d4f27dca..b8b639f7eb 100644 --- a/backend/src/main/java/io/metersphere/controller/TestPlanController.java +++ b/backend/src/main/java/io/metersphere/controller/TestPlanController.java @@ -1,12 +1,18 @@ package io.metersphere.controller; +import io.metersphere.requests.testplan.FileOperationRequest; import io.metersphere.service.FileService; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RestController @@ -16,7 +22,22 @@ public class TestPlanController { private FileService fileService; @PostMapping("/file/upload") - public void upload(MultipartFile file) throws IOException { + public void uploadJmx(MultipartFile file) throws IOException { fileService.upload(file.getOriginalFilename(), file); } + + @PostMapping("/file/delete") + public void deleteJmx(@RequestBody FileOperationRequest request) { + System.out.println(String.format("delete %s", request.getName())); + } + + @PostMapping("/file/download") + public ResponseEntity downloadJmx(@RequestBody FileOperationRequest fileOperationRequest, HttpServletResponse response) { + org.springframework.core.io.Resource resource = fileService.loadFileAsResource(fileOperationRequest.getName()); + + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType("application/octet-stream")) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileOperationRequest.getName() + "\"") + .body(resource); + } } diff --git a/backend/src/main/java/io/metersphere/requests/testplan/FileOperationRequest.java b/backend/src/main/java/io/metersphere/requests/testplan/FileOperationRequest.java new file mode 100644 index 0000000000..88ff096c6a --- /dev/null +++ b/backend/src/main/java/io/metersphere/requests/testplan/FileOperationRequest.java @@ -0,0 +1,13 @@ +package io.metersphere.requests.testplan; + +public class FileOperationRequest { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/backend/src/main/java/io/metersphere/service/FileService.java b/backend/src/main/java/io/metersphere/service/FileService.java index f6b7090a73..3c0d7d6dfc 100644 --- a/backend/src/main/java/io/metersphere/service/FileService.java +++ b/backend/src/main/java/io/metersphere/service/FileService.java @@ -1,18 +1,41 @@ package io.metersphere.service; +import org.springframework.core.io.InputStreamResource; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service public class FileService { + // 将上传的文件保存在内存,方便测试 + private Map fileMap = new ConcurrentHashMap<>(); + public void upload(String name, MultipartFile file) throws IOException { String result = new BufferedReader(new InputStreamReader(file.getInputStream())) .lines().collect(Collectors.joining("\n")); System.out.println(String.format("upload file: %s, content: \n%s", name, result)); + + fileMap.put(name, file); + } + + public Resource loadFileAsResource(String name) { + final MultipartFile file = fileMap.get(name); + + if (file != null) { + try { + return new InputStreamResource(file.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return null; } } \ No newline at end of file diff --git a/frontend/src/performance/components/testPlan/components/BasicConfig.vue b/frontend/src/performance/components/testPlan/components/BasicConfig.vue index 873008607f..bb47c2d106 100644 --- a/frontend/src/performance/components/testPlan/components/BasicConfig.vue +++ b/frontend/src/performance/components/testPlan/components/BasicConfig.vue @@ -3,6 +3,7 @@ @@ -54,6 +55,8 @@ data() { return { jmxUploadPath: '/testplan/file/upload', + jmxDownloadPath: '/testplan/file/download', + jmxDeletePath: '/testplan/file/delete', fileList: [], tableData: [], }; @@ -77,17 +80,61 @@ return true; }, - handleDownload(row) { - /// todo - window.console.log("download: " + row); + handleDownload(file) { + let data = { + name: file.name + }; + + this.$post(this.jmxDownloadPath, data).then(response => { + if (response) { + const content = response.data; + const blob = new Blob([content]); + if ("download" in document.createElement("a")) { + // 非IE下载 + // chrome/firefox + let aTag = document.createElement('a'); + aTag.download = file.name; + aTag.href = URL.createObjectURL(blob) + aTag.click(); + URL.revokeObjectURL(aTag.href) + } else { + // IE10+下载 + navigator.msSaveBlob(blob, this.filename) + } + } + }).catch((response) => { + this.$message.error(response.message); + }); }, - handleDelete(row) { - /// todo - window.console.log("delete: " + row); + handleDelete(file, index) { + this.$alert('确认删除文件: ' + file.name + "?", '', { + confirmButtonText: '确定', + callback: () => { + this._handleDelete(file, index); + } + }); + }, + _handleDelete(file, index) { + let data = { + name: file.name + }; + + this.$post(this.jmxDeletePath, data).then(response => { + if (response.data.success) { + this.fileList.splice(index, 1); + this.tableData.splice(index, 1); + + this.$message({ + message: '删除成功!', + type: 'success' + }); + } else { + this.$message.error(response.message); + } + }); }, fileValidator(file) { /// todo: 是否需要对文件内容和大小做限制 - return file.size > 0; }, }, From c636d111a70021550a85746595a4db10252368c8 Mon Sep 17 00:00:00 2001 From: haifeng414 Date: Wed, 12 Feb 2020 22:23:15 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8B=A5=E5=B9=B2?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/testPlan/CreateTestPlan.vue | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/frontend/src/performance/components/testPlan/CreateTestPlan.vue b/frontend/src/performance/components/testPlan/CreateTestPlan.vue index 3be9afc501..2a1cd96af5 100644 --- a/frontend/src/performance/components/testPlan/CreateTestPlan.vue +++ b/frontend/src/performance/components/testPlan/CreateTestPlan.vue @@ -1,11 +1,29 @@