From 08c9cc09dff7a3cfbab1be7163b221d195430c3f Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 23 Mar 2021 16:12:43 +0800 Subject: [PATCH 01/17] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89)?= =?UTF-8?q?:=20=E6=B5=8B=E8=AF=95=E6=89=A7=E8=A1=8C-=E5=8F=A6=E5=AD=98?= =?UTF-8?q?=E6=96=B0=E6=8E=A5=E5=8F=A3=20=E5=A2=9E=E5=8A=A0=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E5=8F=8D=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/definition/components/runtest/RunTestHTTPPage.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue b/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue index 58e2d947bd..957e8be89b 100644 --- a/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue +++ b/frontend/src/business/components/api/definition/components/runtest/RunTestHTTPPage.vue @@ -191,6 +191,7 @@ export default { req.id = getUUID(); data.request = JSON.stringify(req); data.method = this.api.method; + data.path = this.api.path; data.url = this.api.url; data.status = this.api.status; data.userId = this.api.userId; From 3dba18779ff5191f58f167348e0719a65bd7aaca Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 23 Mar 2021 16:35:47 +0800 Subject: [PATCH 02/17] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=AC=A1=E6=95=B0=E5=BE=AA=E7=8E=AF=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E5=90=8E=E7=BB=A7=E7=BB=AD=E5=BE=AA=E7=8E=AF=20?= =?UTF-8?q?=E5=BC=80=E5=85=B3=E6=A0=A1=E9=AA=8C=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scenario/component/LoopController.vue | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/frontend/src/business/components/api/automation/scenario/component/LoopController.vue b/frontend/src/business/components/api/automation/scenario/component/LoopController.vue index f279355cf1..a61d1f1e68 100644 --- a/frontend/src/business/components/api/automation/scenario/component/LoopController.vue +++ b/frontend/src/business/components/api/automation/scenario/component/LoopController.vue @@ -90,6 +90,7 @@ import ApiResponseComponent from "./ApiResponseComponent"; import MsRun from "../DebugRun"; import {getUUID} from "@/common/js/utils"; + import {ELEMENT_TYPE, ELEMENTS} from "../Setting"; export default { name: "MsLoopController", @@ -186,7 +187,37 @@ this.controller.countController.proceed = true; return; } + // 递归遍历所有请求数量 + if (this.controller.hashTree && this.controller.hashTree.length === 1 + && this.controller.hashTree[0].hashTree && this.controller.hashTree[0].hashTree.length > 0) { + let count = 0; + this.controller.hashTree[0].hashTree.forEach(item => { + if (ELEMENTS.get("AllSamplerProxy").indexOf(item.type) != -1) { + count++; + } + if (item.hashTree && item.hashTree.length > 0) { + this.recursive(item.hashTree, count); + } + }) + + if (count > 1) { + this.$warning("当前循环下超过一个请求,不能关闭状态") + this.controller.countController.proceed = true; + return; + } + } }, + recursive(arr, count) { + for (let i in arr) { + if (ELEMENTS.get("AllSamplerProxy").indexOf(arr[i].type) != -1) { + count++; + } + if (arr[i].hashTree && arr[i].hashTree.length > 0) { + this.recursive(arr[i].hashTree, count); + } + } + }, + runDebug() { if (!this.controller.hashTree || this.controller.hashTree.length < 1) { this.$warning("当前循环下没有请求,不能执行") From c4ae15256b3d1810ffe1f318b6c2e37edfcc93b2 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 23 Mar 2021 17:00:39 +0800 Subject: [PATCH 03/17] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=9D=A1=E4=BB=B6=E6=8E=A7=E5=88=B6=E5=99=A8=20?= =?UTF-8?q?=E6=8A=A5=E5=91=8A=E4=B8=AD=E5=90=8D=E5=AD=97=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../definition/request/controller/MsIfController.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java index 5b7df4a228..61867a6079 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java @@ -43,10 +43,13 @@ public class MsIfController extends MsTestElement { private IfController ifController() { IfController ifController = new IfController(); ifController.setEnabled(this.isEnable()); - ifController.setName(StringUtils.isEmpty(this.getName()) ? "IfController" : this.getName()); + if (StringUtils.isEmpty(this.getName())) { + this.setName(getLabelName()); + } + ifController.setName(this.getName()); ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName()); ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel")); - ifController.setCondition(this.getCondition()); + ifController.setCondition("true"); ifController.setEvaluateAll(false); ifController.setUseExpression(true); return ifController; @@ -61,13 +64,13 @@ public class MsIfController extends MsTestElement { public String getLabelName() { if (isValid()) { - String label = variable + " " + operator; + String label = "条件控制器:" + variable + " " + operator; if (StringUtils.isNotBlank(value)) { label += " " + this.value; } return label; } - return ""; + return "IfController"; } public String getCondition() { From d83df6e1cca638b092151b8b23834a1004f4f55a Mon Sep 17 00:00:00 2001 From: "song.tianyang" Date: Tue, 23 Mar 2021 17:25:20 +0800 Subject: [PATCH 04/17] =?UTF-8?q?feat:=20ESB=E6=8E=A5=E5=8F=A3=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=92=8C=E6=A8=A1=E6=9D=BF=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ESB接口导入和模板下载 --- .../controller/ApiDefinitionController.java | 30 +- .../api/dto/automation/EsbDataStruct.java | 57 +- .../definition/parse/ApiDefinitionImport.java | 7 +- .../ApiDefinitionImportParserFactory.java | 2 + .../api/dto/definition/parse/ESBParser.java | 663 ++++++++++++++++++ .../definition/parse/EsbAbstractParser.java | 28 + .../parse/esb/EsbExcelDataStruct.java | 19 + .../parse/esb/EsbSheetDataStruct.java | 44 ++ .../api/parse/ApiImportParser.java | 4 +- .../api/service/ApiDefinitionService.java | 91 ++- .../api/service/EsbApiParamService.java | 3 +- .../api/service/EsbImportService.java | 80 +++ .../commons/constants/ApiImportPlatform.java | 2 +- .../excel/domain/EsbExcelData.java | 9 + .../components/import/ApiImport.vue | 43 +- .../components/module/ApiModuleHeader.vue | 8 +- frontend/src/i18n/en-US.js | 2 + frontend/src/i18n/zh-CN.js | 2 + frontend/src/i18n/zh-TW.js | 2 + 19 files changed, 1058 insertions(+), 38 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/ESBParser.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/EsbAbstractParser.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbExcelDataStruct.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbSheetDataStruct.java create mode 100644 backend/src/main/java/io/metersphere/api/service/EsbImportService.java create mode 100644 backend/src/main/java/io/metersphere/excel/domain/EsbExcelData.java diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index 6fca4e8cb6..4dba923d8b 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -13,6 +13,7 @@ import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult; import io.metersphere.api.dto.swaggerurl.SwaggerUrlRequest; import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.api.service.EsbApiParamService; +import io.metersphere.api.service.EsbImportService; import io.metersphere.base.domain.ApiDefinition; import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; @@ -32,6 +33,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import java.net.MalformedURLException; import java.util.Date; import java.util.List; @@ -49,6 +51,8 @@ public class ApiDefinitionController { private CheckPermissionService checkPermissionService; @Resource private EsbApiParamService esbApiParamService; + @Resource + private EsbImportService esbImportService; @PostMapping("/list/{goPage}/{pageSize}") public Pager> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) { @@ -63,6 +67,7 @@ public class ApiDefinitionController { request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId()); return PageUtils.setPageInfo(page, apiDefinitionService.listRelevance(request)); } + @PostMapping("/list/relevance/review/{goPage}/{pageSize}") public Pager> listRelevanceReview(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); @@ -103,7 +108,7 @@ public class ApiDefinitionController { @PostMapping(value = "/updateEsbRequest") public SaveApiDefinitionRequest updateEsbRequest(@RequestBody SaveApiDefinitionRequest request) { - if(StringUtils.equals(request.getMethod(),"ESB")){ + if (StringUtils.equals(request.getMethod(), "ESB")) { //ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据 request = esbApiParamService.updateEsbRequest(request); } @@ -180,15 +185,18 @@ public class ApiDefinitionController { public void createSchedule(@RequestBody ScheduleRequest request) throws MalformedURLException { apiDefinitionService.createSchedule(request); } + @PostMapping(value = "/schedule/update") - public void updateSchedule(@RequestBody Schedule request){ + public void updateSchedule(@RequestBody Schedule request) { apiDefinitionService.updateSchedule(request); } + //查找定时任务资源Id @PostMapping(value = "/getResourceId") - public String getResourceId(@RequestBody SwaggerUrlRequest swaggerUrlRequest){ + public String getResourceId(@RequestBody SwaggerUrlRequest swaggerUrlRequest) { return apiDefinitionService.getResourceId(swaggerUrlRequest); } + //查找定时任务列表 @GetMapping("/scheduleTask/{projectId}") public List getSwaggerScheduleList(@PathVariable String projectId) { @@ -198,12 +206,13 @@ public class ApiDefinitionController { resultList) { swaggerTaskResult.setIndex(dataIndex++); Date nextExecutionTime = CronUtils.getNextTriggerTime(swaggerTaskResult.getRule()); - if(nextExecutionTime!=null){ + if (nextExecutionTime != null) { swaggerTaskResult.setNextExecutionTime(nextExecutionTime.getTime()); } } - return resultList; + return resultList; } + //更新定时任务 @PostMapping(value = "/schedule/updateByPrimyKey") public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoSwaggerUrlRequest request) { @@ -211,11 +220,13 @@ public class ApiDefinitionController { schedule.setEnable(request.getTaskStatus()); apiDefinitionService.updateSchedule(schedule); } + //删除定时任务和swaggereUrl @PostMapping("/schedule/deleteByPrimyKey") public void deleteSchedule(@RequestBody ScheduleInfoSwaggerUrlRequest request) { apiDefinitionService.deleteSchedule(request); } + @PostMapping("/getReference") public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) { return apiDefinitionService.getReference(request); @@ -237,8 +248,9 @@ public class ApiDefinitionController { public void testPlanRelevance(@RequestBody ApiCaseRelevanceRequest request) { apiDefinitionService.testPlanRelevance(request); } + @PostMapping("/relevance/review") - public void testCaseReviewRelevance(@RequestBody ApiCaseRelevanceRequest request){ + public void testCaseReviewRelevance(@RequestBody ApiCaseRelevanceRequest request) { apiDefinitionService.testCaseReviewRelevance(request); } @@ -246,4 +258,10 @@ public class ApiDefinitionController { public String preview(@RequestBody String jsonSchema) { return JSONSchemaGenerator.getJson(jsonSchema); } + + @GetMapping("/export/esbExcelTemplate") + @RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.ORG_ADMIN, RoleConstants.TEST_MANAGER}, logical = Logical.OR) + public void testCaseTemplateExport(HttpServletResponse response) { + esbImportService.templateExport(response); + } } diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java b/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java index 0fa226b32f..49f30fdfcd 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/EsbDataStruct.java @@ -8,6 +8,7 @@ import org.dom4j.Element; import java.util.ArrayList; import java.util.List; +import java.util.UUID; /** * //ESB数据格式 @@ -19,15 +20,69 @@ import java.util.List; @Getter @Setter public class EsbDataStruct { + private String uuid; private String name; private String value; private String type; private String systemName; private String contentType; - private String required; + private boolean required; private String description; private List children; + public void init(){ + this.uuid = UUID.randomUUID().toString(); + this.systemName = ""; + this.description = ""; + this.value=""; + this.required = true; + this.contentType = ""; + this.type = ""; + this.children = new ArrayList<>(); + } + + public boolean initDefaultData(String name, String typeLength,String chineseName,String desc){ + this.init(); + if(StringUtils.isEmpty(name)){return false; } + if(typeLength == null){ + typeLength = ""; + }else{ + typeLength = typeLength.trim(); + typeLength = typeLength.toLowerCase(); + } + + this.name = name; + + if(typeLength.startsWith("string")){ + this.type = "string"; + String lengthStr = typeLength.substring(6); + if(lengthStr.startsWith("(") && lengthStr.endsWith(")")){ + try { + int length = Integer.parseInt(lengthStr.substring(1,lengthStr.length()-1)); + this.contentType = String.valueOf(length); + }catch (Exception e){ } + + } + }else if(typeLength.startsWith("array")){ + this.type = "array"; + }else{ + this.type = "object"; + } + + if(StringUtils.isEmpty(desc)){desc = "";} + if(StringUtils.isNotEmpty(chineseName)){ + this.description = chineseName+":"+desc; + }else{ + this.description =desc; + } + + if(this.description.endsWith(":")){ + this.description = this.description.substring(0,this.description.length()-1); + } + + return true; + } + public EsbDataStruct copy(boolean copyChildren) { EsbDataStruct returnObj = new EsbDataStruct(); returnObj.name = this.name; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java index c58d775624..cc1c6626d7 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImport.java @@ -1,12 +1,12 @@ package io.metersphere.api.dto.definition.parse; -import io.metersphere.api.dto.definition.request.MsScenario; import io.metersphere.base.domain.ApiDefinitionWithBLOBs; -import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiTestCaseWithBLOBs; +import io.metersphere.base.domain.EsbApiParamsWithBLOBs; import lombok.Data; import java.util.List; +import java.util.Map; @Data public class ApiDefinitionImport { @@ -16,4 +16,7 @@ public class ApiDefinitionImport { // 新版本带用例导出 private List cases; + + //ESB文件导入的附属数据类 + private Map esbApiParamsMap; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportParserFactory.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportParserFactory.java index f7db9334b0..3fb2000af7 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportParserFactory.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ApiDefinitionImportParserFactory.java @@ -14,6 +14,8 @@ public class ApiDefinitionImportParserFactory { return new Swagger2Parser(); }else if (StringUtils.equals(ApiImportPlatform.Har.name(), platform)) { return new HarParser(); + }else if (StringUtils.equals(ApiImportPlatform.ESB.name(), platform)) { + return new ESBParser(); } return null; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/ESBParser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ESBParser.java new file mode 100644 index 0000000000..e596542492 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/ESBParser.java @@ -0,0 +1,663 @@ +package io.metersphere.api.dto.definition.parse; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import io.metersphere.api.dto.ApiTestImportRequest; +import io.metersphere.api.dto.automation.EsbDataStruct; +import io.metersphere.api.dto.definition.parse.esb.EsbExcelDataStruct; +import io.metersphere.api.dto.definition.parse.esb.EsbSheetDataStruct; +import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; +import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; +import io.metersphere.api.dto.scenario.request.RequestType; +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiModule; +import io.metersphere.base.domain.EsbApiParamsWithBLOBs; +import io.metersphere.commons.utils.SessionUtils; +import io.swagger.models.Model; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.*; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.text.DateFormat; +import java.util.*; +import java.util.regex.Pattern; + +/** + * @author song.tianyang + * @Date 2021/3/10 11:14 上午 + * @Description + */ +public class ESBParser extends EsbAbstractParser { + + private final int REQUEST_MESSAGE_ROW = 5; + + private Map definitions = null; + + public static void export(HttpServletResponse response, String fileName) { + + XSSFWorkbook wb = null; + ServletOutputStream out = null; + try { + wb = getTemplate(); + out = response.getOutputStream(); + response.reset(); + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx"); + wb.write(out); + wb.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + out.close(); + } catch (Exception e) { + + } + } + if (wb != null) { + try { + wb.close(); + } catch (Exception e) { + + } + } + } + } + + private static XSSFWorkbook getTemplate() { + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFFont font = workbook.createFont(); + font.setFontHeightInPoints((short) 9); + Map cellStyleMap = createCellStle(workbook); + XSSFSheet headSheet = workbook.createSheet("公共报文头"); + generateSheet(headSheet, font,cellStyleMap); + XSSFSheet bodySheet = workbook.createSheet("接口报文信息"); + generateSheet(bodySheet, font,cellStyleMap); + return workbook; + } + + private static Map createCellStle(XSSFWorkbook workbook) { + Map cellStype = new HashMap<>(); + short[] colorIndexArr = {IndexedColors.LIGHT_GREEN.getIndex(), IndexedColors.ORCHID.getIndex(), IndexedColors.YELLOW.getIndex()}; + for (short colorIndex : colorIndexArr) { + XSSFCellStyle style = workbook.createCellStyle(); +// style.setFillForegroundColor(IndexedColors.VIOLET.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + style.setBorderTop(BorderStyle.THIN); + + String name = ""; + if(colorIndex == IndexedColors.LIGHT_GREEN.getIndex()){ + style.setFillForegroundColor(new XSSFColor(new java.awt.Color(204, 255, 204))); + name = "green"; + }else if(colorIndex == IndexedColors.ORCHID.getIndex()){ + style.setFillForegroundColor(new XSSFColor(new java.awt.Color(151, 50, 101))); + name = "pop"; + }else if(colorIndex == IndexedColors.YELLOW.getIndex()){ + style.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 255, 153))); + name = "yellow"; + }else{ + name = "default"; + } + cellStype.put(name,style); + } + return cellStype; + } + + private static void generateSheet(XSSFSheet sheet, XSSFFont font,Map cellStyleMap) { + if (sheet == null) { + return; + } + + sheet.setColumnWidth(0, 4000); + sheet.setColumnWidth(1, 4000); + sheet.setColumnWidth(2, 4000); + sheet.setColumnWidth(3, 4000); + sheet.setColumnWidth(4, 4000); + sheet.setColumnWidth(5, 880); + sheet.setColumnWidth(6, 4000); + sheet.setColumnWidth(7, 4000); + sheet.setColumnWidth(8, 4000); + sheet.setColumnWidth(9, 4000); + sheet.setColumnWidth(10, 4000); + + /** + * 模版生成: + * 字体大小:9 + * row1: 1交易码 2交易名称 6(紫色[pop]背景空白单元格,下同) 7服务名称 8服务场景 + * row2: 1.请输入交易码(必填) 2请输入交易名称(必填) 7请输入服务名称(如果不填,则以交易名称为主) 8请输入服务场景(选填) + * row3: 合并7-10单元格,输入:请输入系统名称 背景色:黄色[yellow] + * row4: 1.英文名称2.中文名称3.数据类型/长度4.是否必输5.备注 7.英文名称8.数据类型/长度9.中文名称 10备注 背景色:黄色 + * row5: 整行都是青色【green】,1:输入 + * row6: 3:请输入STRING(具体长度) 或 ARRAY; 8:同3 + * row7:无 + * row8: 整行都是青色,1:输出 + * row9: 3:请输入STRING(具体长度) 或 ARRAY; 8:同3 + */ + XSSFRow row1 = sheet.createRow(0); + setCellValue("交易码", row1.createCell(0), font,cellStyleMap.get("default")); + setCellValue("交易名称", row1.createCell(1), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(2), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(3), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(4), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("服务名称", row1.createCell(6), font,cellStyleMap.get("default")); + setCellValue("服务场景", row1.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(8), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(9), font,cellStyleMap.get("default")); + setCellValue("", row1.createCell(10), font,cellStyleMap.get("default")); + + XSSFRow row2 = sheet.createRow(1); + setCellValue("请输入交易码(必填)", row2.createCell(0), font,cellStyleMap.get("default")); + setCellValue("请输入交易名称(必填)", row2.createCell(1), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(2), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(3), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(4), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("请输入服务名称(如果不填,则以交易名称为主)", row2.createCell(6), font,null); + setCellValue("请输入服务场景(选填)", row2.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(8), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(9), font,cellStyleMap.get("default")); + setCellValue("", row2.createCell(10), font,cellStyleMap.get("default")); + + XSSFRow row3 = sheet.createRow(2); + setCellValue("", row3.createCell(0), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(1), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(2), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(3), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(4), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(5), font,cellStyleMap.get("yellow")); + setCellValue("请输入系统名称", row3.createCell(6), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(7), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(8), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(9), font,cellStyleMap.get("yellow")); + setCellValue("", row3.createCell(10), font,cellStyleMap.get("yellow")); + + CellRangeAddress region1 = new CellRangeAddress(2, 2, 0, 4); + sheet.addMergedRegion(region1); + CellRangeAddress region2 = new CellRangeAddress(2, 2, 6, 10); + sheet.addMergedRegion(region2); + + XSSFRow row4 = sheet.createRow(3); + setCellValue("英文名称", row4.createCell(0), font,cellStyleMap.get("yellow")); + setCellValue("中文名称", row4.createCell(1), font,cellStyleMap.get("yellow")); + setCellValue("数据类型/长度", row4.createCell(2), font,cellStyleMap.get("yellow")); + setCellValue("是否必输", row4.createCell(3), font,cellStyleMap.get("yellow")); + setCellValue("备注", row4.createCell(4), font,cellStyleMap.get("yellow")); + setCellValue("", row4.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("英文名称", row4.createCell(6), font,cellStyleMap.get("yellow")); + setCellValue("数据类型/长度", row4.createCell(7), font,cellStyleMap.get("yellow")); + setCellValue("中文名称", row4.createCell(8), font,cellStyleMap.get("yellow")); + setCellValue("备注", row4.createCell(9), font,cellStyleMap.get("yellow")); + setCellValue("所在报文位置", row4.createCell(10), font,cellStyleMap.get("yellow")); + + XSSFRow row5 = sheet.createRow(4); + setCellValue("输入", row5.createCell(0), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(1), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(2), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(3), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(4), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(5), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(6), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(7), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(8), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(9), font,cellStyleMap.get("green")); + setCellValue("", row5.createCell(10), font,cellStyleMap.get("green")); + + XSSFRow row6 = sheet.createRow(5); + setCellValue("", row6.createCell(1), font,cellStyleMap.get("default")); + setCellValue("请输入STRING(具体长度) 或 ARRAY", row6.createCell(2), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(3), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(4), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("", row6.createCell(6), font,cellStyleMap.get("default")); + setCellValue("请输入STRING(具体长度) 或 ARRAY", row6.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(8), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(9), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(10), font,cellStyleMap.get("default")); + + XSSFRow row7 = sheet.createRow(6); + setCellValue("", row6.createCell(1), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(2), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(3), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(4), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("", row6.createCell(6), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(8), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(9), font,cellStyleMap.get("default")); + setCellValue("", row6.createCell(10), font,cellStyleMap.get("default")); + + XSSFRow row8 = sheet.createRow(7); + setCellValue("输出", row8.createCell(0), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(1), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(2), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(3), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(4), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(5), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(6), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(7), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(8), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(9), font,cellStyleMap.get("green")); + setCellValue("", row8.createCell(10), font,cellStyleMap.get("green")); + + XSSFRow row9 = sheet.createRow(8); + setCellValue("", row9.createCell(1), font,cellStyleMap.get("default")); + setCellValue("请输入STRING(具体长度) 或 ARRAY", row9.createCell(2), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(3), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(4), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(5), font,cellStyleMap.get("pop")); + setCellValue("", row9.createCell(6), font,cellStyleMap.get("default")); + setCellValue("请输入STRING(具体长度) 或 ARRAY", row9.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(7), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(8), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(9), font,cellStyleMap.get("default")); + setCellValue("", row9.createCell(10), font,cellStyleMap.get("default")); + + } + + private static void setCellValue(String textValue, Cell cell, XSSFFont font,XSSFCellStyle cellStyle) { +// HSSFRichTextString richString = new HSSFRichTextString(textValue); + XSSFRichTextString richString = new XSSFRichTextString(textValue); + richString.applyFont(font); + if(cellStyle!=null){ + cell.setCellStyle(cellStyle); + } + cell.setCellValue(richString); + } + + + @Override + public ApiDefinitionImport parse(InputStream source, ApiTestImportRequest request) throws Exception { + EsbSheetDataStruct esbImportDataStruct = new EsbSheetDataStruct(); + EsbExcelDataStruct excelDataStruct = this.esbImport(source); + + this.projectId = request.getProjectId(); + ApiDefinitionImport definitionImport = this.parseApiDefinitionImport(excelDataStruct, request); + + return definitionImport; + } + + public EsbExcelDataStruct esbImport(InputStream source) throws IOException, InvalidFormatException { + Workbook workbook = WorkbookFactory.create(source); + int sheetCount = workbook.getNumberOfSheets(); + EsbSheetDataStruct headStruct = null; + List interfaceStruct = new ArrayList<>(); + if (sheetCount > 0) { + Sheet headSheet = workbook.getSheetAt(0); + headStruct = this.parseExcelSheet(headSheet, true); + for (int index = 1; index < sheetCount; index++) { + Sheet dataSheet = workbook.getSheetAt(index); + EsbSheetDataStruct bodyStruct = this.parseExcelSheet(dataSheet, false); + interfaceStruct.add(bodyStruct); + } + } + + EsbExcelDataStruct excelData = new EsbExcelDataStruct(); + excelData.setHeadData(headStruct); + excelData.setInterfaceList(interfaceStruct); + return excelData; + } + + private EsbSheetDataStruct parseExcelSheet(Sheet headSheet, boolean isHeadSheet) { + EsbSheetDataStruct importDataStruct = new EsbSheetDataStruct(); + if (headSheet == null) { + return importDataStruct; + } + int rowCount = headSheet.getLastRowNum(); + //根据模版样式,如果不是报文头,则要取接口信息 + if (!isHeadSheet) { + Row interfaceInfoRow = headSheet.getRow(1); + if (interfaceInfoRow != null) { + List rowDataArr = this.getRowDataByStartIndexAndEndIndex(interfaceInfoRow, 0, 9); + if (rowDataArr.size() > 8) { + String interfaceCode = rowDataArr.get(0); + String interfaceName = rowDataArr.get(6); + String interfaceDesc = rowDataArr.get(7); + if (StringUtils.isEmpty(interfaceName)) { + interfaceName = rowDataArr.get(1); + } + importDataStruct.setInterfaceInfo(interfaceCode, interfaceName, interfaceDesc); + } + } + } + //超过5行为空白,直接退出。 + //部分office/wpf生成的文件会出现几万多空行,容易造成内存溢出。这里进行判断,连续五行为空白时认为读取结束。 + int blankRowCount = 0; + boolean isRequest = true; + for (int startRow = REQUEST_MESSAGE_ROW; startRow < rowCount; startRow++) { + Row row = headSheet.getRow(startRow); + List rowDataArr = this.getRowDataByStartIndexAndEndIndex(row, 0, 9); + boolean isBlankRow = this.checkBlankRow(rowDataArr, 10); + if (!isBlankRow) { + String cellFlag = rowDataArr.get(0); + if (StringUtils.equals(cellFlag, "输出")) { + isRequest = false; + } + } + if (isBlankRow) { + if (isRequest) { + isRequest = false; + } + blankRowCount++; + if (blankRowCount > 5) { + break; + } + } else { + blankRowCount = 0; + EsbDataStruct dataStruct = new EsbDataStruct(); + boolean initDataSuccess = dataStruct.initDefaultData(rowDataArr.get(6), rowDataArr.get(7), rowDataArr.get(8), rowDataArr.get(9)); + if (!initDataSuccess) { + continue; + } + boolean isHead = isHeadSheet; + if (rowDataArr.size() > 10) { + if (StringUtils.equals(rowDataArr.get(10), "SYS_HEAD")) { + isHead = true; + } + + } + if (isRequest) { + if (isHead) { + importDataStruct.getReqHeadList().add(dataStruct); + } else { + importDataStruct.getRequestList().add(dataStruct); + } + } else { + if (isHead) { + importDataStruct.getRspHeadList().add(dataStruct); + } else { + importDataStruct.getResponseList().add(dataStruct); + } + } + } + } + return importDataStruct; + } + + private boolean checkBlankRow(List rowDataArr, int rowCheckLength) { + if (rowDataArr == null || rowDataArr.size() < rowCheckLength) { + return true; + } + for (String str : rowDataArr) { + if (StringUtils.isNotEmpty(str)) { + return false; + } + } + return true; + } + + private List getRowDataByStartIndexAndEndIndex(Row row, int startCell, int endCell) { + List returnArray = new ArrayList<>(); + if (row == null) { + return returnArray; + } + for (int i = startCell; i <= endCell; i++) { + Cell cell = row.getCell(i); + if (cell != null) { + returnArray.add(getCellValue(cell)); + } + } + return returnArray; + } + + private String getCellValue(Cell cell) { + String returnCellValue = ""; + int cellType = cell.getCellType(); + switch (cellType) { + case Cell.CELL_TYPE_BLANK: + returnCellValue = ""; + break; + case Cell.CELL_TYPE_BOOLEAN: + returnCellValue = String.valueOf(cell.getBooleanCellValue()); + break; + case Cell.CELL_TYPE_ERROR: + returnCellValue = ""; + break; + case Cell.CELL_TYPE_NUMERIC: + returnCellValue = getValueOfNumericCell(cell); + break; + case Cell.CELL_TYPE_FORMULA: + try { + returnCellValue = getValueOfNumericCell(cell); + } catch (IllegalStateException e) { + try { + returnCellValue = cell.getRichStringCellValue().toString(); + } catch (IllegalStateException e2) { + } + } catch (Exception e) { + e.printStackTrace(); + } + break; + default: + returnCellValue = cell.getRichStringCellValue().getString(); + } + if (returnCellValue == null) { + returnCellValue = ""; + } + return returnCellValue; + } + + private String getValueOfNumericCell(Cell cell) { + Boolean isDate = DateUtil.isCellDateFormatted(cell); + Double d = cell.getNumericCellValue(); + String o = null; + if (isDate) { + o = DateFormat.getDateTimeInstance() + .format(cell.getDateCellValue()); + } else { + o = getRealStringValueOfDouble(d); + } + return o; + } + + // 处理科学计数法与普通计数法的字符串显示,尽最大努力保持精度 + private static String getRealStringValueOfDouble(Double d) { + String doubleStr = d.toString(); + boolean b = doubleStr.contains("E"); + int indexOfPoint = doubleStr.indexOf('.'); + if (b) { + int indexOfE = doubleStr.indexOf('E'); + // 小数部分 + BigInteger xs = new BigInteger(doubleStr.substring(indexOfPoint + + BigInteger.ONE.intValue(), indexOfE)); + // 指数 + int pow = Integer.valueOf(doubleStr.substring(indexOfE + + BigInteger.ONE.intValue())); + int xsLen = xs.toByteArray().length; + int scale = xsLen - pow > 0 ? xsLen - pow : 0; + doubleStr = String.format("%." + scale + "f", d); + } else { + java.util.regex.Pattern p = Pattern.compile(".0$"); + java.util.regex.Matcher m = p.matcher(doubleStr); + if (m.find()) { + doubleStr = doubleStr.replace(".0", ""); + } + } + return doubleStr; + } + + private ApiDefinitionImport parseApiDefinitionImport(EsbExcelDataStruct esbExcelDataStruct, ApiTestImportRequest importRequest) { + ApiDefinitionImport resultModel = new ApiDefinitionImport(); + List apiDataList = new ArrayList<>(); + + ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId()); + EsbSheetDataStruct headSheetData = esbExcelDataStruct.getHeadData(); + List interfaceDataList = esbExcelDataStruct.getInterfaceList(); + List savedNames = new ArrayList<>(); + Map esbApiParams = new HashMap<>(); + for (EsbSheetDataStruct interfaceData : interfaceDataList) { + String reqName = interfaceData.getServiceName(); + if (savedNames.contains(reqName)) { + continue; + } else { + savedNames.add(reqName); + } + + String apiId = UUID.randomUUID().toString(); + ApiDefinitionWithBLOBs apiDefinition = new ApiDefinitionWithBLOBs(); + apiDefinition.setName(reqName); + apiDefinition.setMethod("ESB"); + apiDefinition.setId(apiId); + apiDefinition.setProjectId(this.projectId); + apiDefinition.setRequest(genTCPSampler()); + if (StringUtils.equalsIgnoreCase("schedule", importRequest.getType())) { + apiDefinition.setUserId(importRequest.getUserId()); + } else { + apiDefinition.setUserId(SessionUtils.getUserId()); + } + apiDefinition.setProtocol(RequestType.TCP); + buildModule(parentNode, apiDefinition, null); + apiDataList.add(apiDefinition); + + EsbApiParamsWithBLOBs apiParams = new EsbApiParamsWithBLOBs(); + apiParams.setId(UUID.randomUUID().toString()); + apiParams.setResourceId(apiId); + String reqDataStructStr = generateDataStrcut(headSheetData, interfaceData, true); + String respDataStrutStr = generateDataStrcut(headSheetData, interfaceData, false); + + apiParams.setDataStruct(reqDataStructStr); + apiParams.setResponseDataStruct(respDataStrutStr); + esbApiParams.put(apiId, apiParams); + } + + resultModel.setData(apiDataList); + resultModel.setEsbApiParamsMap(esbApiParams); + + return resultModel; + } + + private String genTCPSampler() { + MsTCPSampler tcpSampler = new MsTCPSampler(); + MsJSR223PreProcessor preProcessor = new MsJSR223PreProcessor(); + tcpSampler.setTcpPreProcessor(preProcessor); + tcpSampler.setProtocol("ESB"); + tcpSampler.setClassname("TCPSampler"); + + return JSON.toJSONString(tcpSampler); + } + + private String generateDataStrcut(EsbSheetDataStruct head, EsbSheetDataStruct body, boolean isRequest) { + EsbDataStruct dataStruct = new EsbDataStruct(); + dataStruct.initDefaultData("SERVICE", null, null, null); + List headList = new ArrayList<>(); + List bodyList = new ArrayList<>(); + if (head != null) { + if (isRequest) { + headList.addAll(head.getReqHeadList()); + bodyList.addAll(head.getRequestList()); + } else { + headList.addAll(head.getRspHeadList()); + bodyList.addAll(head.getResponseList()); + } + } + if (body != null) { + if (isRequest) { + headList.addAll(body.getReqHeadList()); + bodyList.addAll(body.getRequestList()); + } else { + headList.addAll(body.getRspHeadList()); + bodyList.addAll(body.getResponseList()); + } + } + + if (!headList.isEmpty()) { + EsbDataStruct headStruct = new EsbDataStruct(); + headStruct.initDefaultData("SYS_HEAD", null, null, null); + dataStruct.getChildren().add(headStruct); + Map childrenEsbDataStructMap = new HashMap<>(); + //用来判断节点有没有在array节点内 + String lastArrayDataStrcutName = null; + for (EsbDataStruct headData : headList) { + if (StringUtils.equalsIgnoreCase("array", headData.getType())) { + if (lastArrayDataStrcutName == null) { + lastArrayDataStrcutName = headData.getName(); + EsbDataStruct arrayStrcut = new EsbDataStruct(); + arrayStrcut.initDefaultData(headData.getName(), headData.getType(), headData.getContentType(), headData.getDescription()); + headStruct.getChildren().add(arrayStrcut); + childrenEsbDataStructMap.put(lastArrayDataStrcutName, arrayStrcut); + } else { + lastArrayDataStrcutName = null; + } + } else { + if (lastArrayDataStrcutName == null) { + headStruct.getChildren().add(headData); + } else { + EsbDataStruct arrayStrcut = childrenEsbDataStructMap.get(lastArrayDataStrcutName); + if (arrayStrcut != null) { + arrayStrcut.getChildren().add(headData); + } + } + } + } + } + + if (!bodyList.isEmpty()) { + EsbDataStruct bodyStruct = new EsbDataStruct(); + bodyStruct.initDefaultData("SYS_BODY", null, null, null); + dataStruct.getChildren().add(bodyStruct); + Map childrenEsbDataStructMap = new HashMap<>(); + //用来判断节点有没有在array节点内 + String lastArrayDataStrcutName = null; + for (EsbDataStruct bodyData : bodyList) { + if (StringUtils.equalsIgnoreCase("array", bodyData.getType())) { + if (lastArrayDataStrcutName == null) { + lastArrayDataStrcutName = bodyData.getName(); + EsbDataStruct arrayStrcut = new EsbDataStruct(); + arrayStrcut.initDefaultData(bodyData.getName(), bodyData.getType(), bodyData.getContentType(), bodyData.getDescription()); + bodyStruct.getChildren().add(arrayStrcut); + childrenEsbDataStructMap.put(lastArrayDataStrcutName, arrayStrcut); + } else { + lastArrayDataStrcutName = null; + } + } else { + if (lastArrayDataStrcutName == null) { + bodyStruct.getChildren().add(bodyData); + } else { + EsbDataStruct arrayStrcut = childrenEsbDataStructMap.get(lastArrayDataStrcutName); + if (arrayStrcut != null) { + arrayStrcut.getChildren().add(bodyData); + } + } + } + } + } + List list = new ArrayList<>(); + list.add(dataStruct); + return JSONArray.toJSONString(list); + } + +// private void parseParameters(HarRequest harRequest, MsHTTPSamplerProxy request) { +// List queryStringList = harRequest.queryString; +// queryStringList.forEach(harQueryParm -> { +// parseQueryParameters(harQueryParm, request.getArguments()); +// }); +// List harHeaderList = harRequest.headers; +// harHeaderList.forEach(harHeader -> { +// parseHeaderParameters(harHeader, request.getHeaders()); +// }); +// List harCookieList = harRequest.cookies; +// harCookieList.forEach(harCookie -> { +// parseCookieParameters(harCookie, request.getHeaders()); +// }); +// } + + + private String getDefaultStringValue(String val) { + return StringUtils.isBlank(val) ? "" : val; + } + + +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/EsbAbstractParser.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/EsbAbstractParser.java new file mode 100644 index 0000000000..b049b5bc46 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/EsbAbstractParser.java @@ -0,0 +1,28 @@ +package io.metersphere.api.dto.definition.parse; + + +import io.metersphere.api.parse.ApiImportAbstractParser; +import io.metersphere.base.domain.ApiDefinitionWithBLOBs; +import io.metersphere.base.domain.ApiModule; + +import java.util.List; + +/** + * @author song.tianyang + * @Date 2021/3/10 11:15 上午 + * @Description + */ +public abstract class EsbAbstractParser extends ApiImportAbstractParser { + + protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List tags) { + if (tags != null) { + tags.forEach(tag -> { + ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId); + apiDefinition.setModuleId(module.getId()); + }); + }else { + apiDefinition.setModuleId(parentModule.getId()); + } + } + +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbExcelDataStruct.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbExcelDataStruct.java new file mode 100644 index 0000000000..90e238819b --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbExcelDataStruct.java @@ -0,0 +1,19 @@ +package io.metersphere.api.dto.definition.parse.esb; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author song.tianyang + * @Date 2021/3/23 12:55 下午 + * @Description + */ +@Getter +@Setter +public class EsbExcelDataStruct { + private EsbSheetDataStruct headData; + private List interfaceList = new ArrayList<>(); +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbSheetDataStruct.java b/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbSheetDataStruct.java new file mode 100644 index 0000000000..6f8899b7a4 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/parse/esb/EsbSheetDataStruct.java @@ -0,0 +1,44 @@ +package io.metersphere.api.dto.definition.parse.esb; + +import io.metersphere.api.dto.automation.EsbDataStruct; +import io.metersphere.commons.exception.MSException; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author song.tianyang + * @Date 2021/3/22 9:42 下午 + * @Description + */ +@Getter +@Setter +public class EsbSheetDataStruct { + private String serviceName; + private String serviceDesc; + private List requestList = new ArrayList<>(); + private List responseList = new ArrayList<>(); + + //单个接口内也可能有报文头中要增加的数据 + private List reqHeadList = new ArrayList<>(); + private List rspHeadList = new ArrayList<>(); + + + public void setInterfaceInfo(String interfaceCode, String interfaceName, String interfaceDesc) { + if(StringUtils.isEmpty(interfaceCode) && StringUtils.isEmpty(interfaceName)){ + MSException.throwException("接口的交易码或服务名称不能都为空"); + } + if(StringUtils.isNotEmpty(interfaceCode)){ + this.serviceName = interfaceCode+":"+interfaceName; + }else { + this.serviceName = interfaceName; + } + if (this.serviceName.endsWith(":")){ + this.serviceName = this.serviceName.substring(0,this.serviceName.length()-1); + } + this.serviceDesc = interfaceDesc; + } +} diff --git a/backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java b/backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java index d3017c710a..9619cb4fe9 100644 --- a/backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java @@ -1,9 +1,11 @@ package io.metersphere.api.parse; import io.metersphere.api.dto.ApiTestImportRequest; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import java.io.IOException; import java.io.InputStream; public interface ApiImportParser { - T parse(InputStream source, ApiTestImportRequest request); + T parse(InputStream source, ApiTestImportRequest request) throws IOException, InvalidFormatException, Exception; } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 52bafba745..761f53a2f3 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -14,6 +14,7 @@ import io.metersphere.api.dto.definition.parse.Swagger3Parser; import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.ScheduleInfoSwaggerUrlRequest; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; +import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.swaggerurl.SwaggerTaskResult; @@ -347,26 +348,43 @@ public class ApiDefinitionService { private void _importCreate(List sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition, ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List cases) { if (CollectionUtils.isEmpty(sameRequest)) { - String request = setImportHashTree(apiDefinition); - batchMapper.insert(apiDefinition); - apiDefinition.setRequest(request); - importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true); + if(StringUtils.equalsIgnoreCase(apiDefinition.getProtocol(),RequestType.HTTP)){ + String request = setImportHashTree(apiDefinition); + batchMapper.insert(apiDefinition); + apiDefinition.setRequest(request); + importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, true); + }else{ + if(StringUtils.equalsAnyIgnoreCase(apiDefinition.getProtocol(),RequestType.TCP)){ + String request = setImportTCPHashTree(apiDefinition); + } + batchMapper.insert(apiDefinition); + } + } else { String originId = apiDefinition.getId(); - //如果存在则修改 - apiDefinition.setId(sameRequest.get(0).getId()); - String request = setImportHashTree(apiDefinition); - apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); - apiDefinition.setRequest(request); - importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, false); - // 如果是带用例导出,重新设置接口id - if (CollectionUtils.isNotEmpty(cases)) { - cases.forEach(item -> { - if (StringUtils.equals(item.getApiDefinitionId(), originId)) { - item.setApiDefinitionId(apiDefinition.getId()); - } - }); + if(StringUtils.equalsIgnoreCase(apiDefinition.getProtocol(),RequestType.HTTP)){ + //如果存在则修改 + apiDefinition.setId(sameRequest.get(0).getId()); + String request = setImportHashTree(apiDefinition); + apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); + apiDefinition.setRequest(request); + importApiCase(apiDefinition, apiTestCaseMapper, apiTestImportRequest, false); + // 如果是带用例导出,重新设置接口id + if (CollectionUtils.isNotEmpty(cases)) { + cases.forEach(item -> { + if (StringUtils.equals(item.getApiDefinitionId(), originId)) { + item.setApiDefinitionId(apiDefinition.getId()); + } + }); + } + }else { + apiDefinition.setId(sameRequest.get(0).getId()); + if(StringUtils.equalsAnyIgnoreCase(apiDefinition.getProtocol(),RequestType.TCP)){ + String request = setImportTCPHashTree(apiDefinition); + } + apiDefinitionMapper.updateByPrimaryKeyWithBLOBs(apiDefinition); } + } } @@ -378,6 +396,14 @@ public class ApiDefinitionService { apiDefinition.setRequest(JSONObject.toJSONString(msHTTPSamplerProxy)); return request; } + private String setImportTCPHashTree(ApiDefinitionWithBLOBs apiDefinition) { + String request = apiDefinition.getRequest(); + MsTCPSampler tcpSampler = JSONObject.parseObject(request, MsTCPSampler.class); + tcpSampler.setId(apiDefinition.getId()); + tcpSampler.setHashTree(new LinkedList<>()); + apiDefinition.setRequest(JSONObject.toJSONString(tcpSampler)); + return request; + } private void importMsCase(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestCaseMapper apiTestCaseMapper) { List cases = apiImport.getCases(); @@ -571,11 +597,40 @@ public class ApiDefinitionService { item.setName(item.getName().substring(0, 255)); } item.setNum(num++); - importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases()); + //如果EsbData需要存储,则需要进行接口是否更新的判断 + if(apiImport.getEsbApiParamsMap()!= null){ + String apiId = item.getId(); + EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId); + importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases()); + if(model!=null){ + apiImport.getEsbApiParamsMap().remove(apiId); + model.setResourceId(item.getId()); + apiImport.getEsbApiParamsMap().put(item.getId(),model); + } + }else { + importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases()); + } if (i % 300 == 0) { sqlSession.flushStatements(); } } + //判断EsbData是否需要存储 + if(apiImport.getEsbApiParamsMap()!= null && apiImport.getEsbApiParamsMap().size() > 0){ + EsbApiParamsMapper esbApiParamsMapper = sqlSession.getMapper(EsbApiParamsMapper.class); + for (EsbApiParamsWithBLOBs model : apiImport.getEsbApiParamsMap().values()) { + EsbApiParamsExample example = new EsbApiParamsExample(); + example.createCriteria().andResourceIdEqualTo(model.getResourceId()); + List exiteModelList = esbApiParamsMapper.selectByExampleWithBLOBs(example); + if(exiteModelList.isEmpty()){ + esbApiParamsMapper.insert(model); + }else{ + model.setId(exiteModelList.get(0).getId()); + esbApiParamsMapper.updateByPrimaryKeyWithBLOBs(model); + } + + } + } + if (!CollectionUtils.isEmpty(apiImport.getCases())) { for (int i = 0; i < apiImport.getCases().size(); i++) { importMsCase(apiImport, sqlSession, apiTestCaseMapper); diff --git a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java index a8d38ced9e..09a80dda05 100644 --- a/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java +++ b/backend/src/main/java/io/metersphere/api/service/EsbApiParamService.java @@ -75,7 +75,7 @@ public class EsbApiParamService { kv.setType(request.getType()); kv.setDescription(request.getDescription()); kv.setContentType(request.getContentType()); - kv.setRequired(Boolean.parseBoolean(request.getRequired())); + kv.setRequired(request.isRequired()); returnList.add(kv); if (request.getChildren() != null) { List childValueList = this.genKeyValueByEsbDataStruct(request.getChildren(), itemName); @@ -351,4 +351,5 @@ public class EsbApiParamService { example.createCriteria().andResourceIdIn(apiIds); esbApiParamsMapper.deleteByExample(example); } + } diff --git a/backend/src/main/java/io/metersphere/api/service/EsbImportService.java b/backend/src/main/java/io/metersphere/api/service/EsbImportService.java new file mode 100644 index 0000000000..7c8b0ee971 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/service/EsbImportService.java @@ -0,0 +1,80 @@ +package io.metersphere.api.service; + +import io.metersphere.api.dto.definition.parse.ESBParser; +import io.metersphere.commons.constants.TestCaseConstants; +import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.user.SessionUser; +import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.excel.domain.UserExcelData; +import io.metersphere.excel.domain.UserExcelDataFactory; +import io.metersphere.excel.utils.EasyExcelExporter; +import io.metersphere.i18n.Translator; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * @author song.tianyang + * @Date 2021/3/22 7:02 下午 + * @Description + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class EsbImportService { + + public void esbTemplateExport(HttpServletResponse response) { + try { + EasyExcelExporter easyExcelExporter = new EasyExcelExporter(new UserExcelDataFactory().getExcelDataByLocal()); + easyExcelExporter.export(response, generateExportTemplate(), + Translator.get("user_import_template_name"), Translator.get("user_import_template_sheet")); + } catch (Exception e) { + MSException.throwException(e); + } + } + + private List generateExportTemplate() { + List list = new ArrayList<>(); + List types = TestCaseConstants.Type.getValues(); + List methods = TestCaseConstants.Method.getValues(); + SessionUser user = SessionUtils.getUser(); + for (int i = 1; i <= 2; i++) { + UserExcelData data = new UserExcelData(); + data.setId("user_id_" + i); + data.setName(Translator.get("user") + i); + String workspace = ""; + for (int workspaceIndex = 1; workspaceIndex <= i; workspaceIndex++) { + if (workspaceIndex == 1) { + workspace = "workspace" + workspaceIndex; + } else { + workspace = workspace + "\n" + "workspace" + workspaceIndex; + } + } + data.setUserIsAdmin(Translator.get("options_no")); + data.setUserIsTester(Translator.get("options_no")); + data.setUserIsOrgMember(Translator.get("options_no")); + data.setUserIsViewer(Translator.get("options_no")); + data.setUserIsTestManager(Translator.get("options_no")); + data.setUserIsOrgAdmin(Translator.get("options_yes")); + data.setOrgAdminOrganization(workspace); + list.add(data); + } + + list.add(new UserExcelData()); + UserExcelData explain = new UserExcelData(); + explain.setName(Translator.get("do_not_modify_header_order")); + explain.setOrgAdminOrganization("多个工作空间请换行展示"); + list.add(explain); + return list; + } + + public void templateExport(HttpServletResponse response) { + try { + ESBParser.export(response,"EsbTemplate"); + } catch (Exception e) { + MSException.throwException(e); + } + } +} diff --git a/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java b/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java index 95aed8d749..eb22a9b40b 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java +++ b/backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java @@ -1,5 +1,5 @@ package io.metersphere.commons.constants; public enum ApiImportPlatform { - Metersphere, Postman, Swagger2, Plugin, Jmeter, Har + Metersphere, Postman, Swagger2, Plugin, Jmeter, Har,ESB } diff --git a/backend/src/main/java/io/metersphere/excel/domain/EsbExcelData.java b/backend/src/main/java/io/metersphere/excel/domain/EsbExcelData.java new file mode 100644 index 0000000000..58d670701d --- /dev/null +++ b/backend/src/main/java/io/metersphere/excel/domain/EsbExcelData.java @@ -0,0 +1,9 @@ +package io.metersphere.excel.domain; + +/** + * @author song.tianyang + * @Date 2021/3/22 7:04 下午 + * @Description + */ +public class EsbExcelData { +} diff --git a/frontend/src/business/components/api/definition/components/import/ApiImport.vue b/frontend/src/business/components/api/definition/components/import/ApiImport.vue index e4e77933fc..fc6c468419 100644 --- a/frontend/src/business/components/api/definition/components/import/ApiImport.vue +++ b/frontend/src/business/components/api/definition/components/import/ApiImport.vue @@ -29,11 +29,17 @@ - + + + {{$t('test_track.case.import.download_template')}} + + .api-import >>> .el-dialog { - min-width: 700px; + min-width: 750px; } .format-tip { diff --git a/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue b/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue index 4f5b2b6bb4..c29f31f7b4 100644 --- a/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue +++ b/frontend/src/business/components/api/definition/components/module/ApiModuleHeader.vue @@ -49,7 +49,7 @@ @saveAsEdit="saveAsEdit" @refresh="refresh" ref="basisApi"/> - + @@ -108,8 +108,8 @@ export default { this.$warning(this.$t('commons.check_project_tip')); return; } - this.protocol = "HTTP"; - this.result = this.$get("/api/module/list/" + getCurrentProjectID() + "/" + this.protocol, response => { + // this.protocol = "HTTP"; + this.result = this.$get("/api/module/list/" + getCurrentProjectID() + "/" + this.condition.protocol, response => { if (response.data != undefined && response.data != null) { this.data = response.data; let moduleOptions = []; @@ -118,8 +118,8 @@ export default { }); this.moduleOptions = moduleOptions } + this.$refs.apiImport.open(this.moduleOptions); }); - this.$refs.apiImport.open(this.currentModule); break; } }, diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 502c42e06a..dacdeca97b 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -946,8 +946,10 @@ export default { ms_tip: "Support for MeterSphere JSON format", ms_export_tip: "Export jSON-formatted files via MeterSphere website or browser plug-ins", har_export_tip: "Export Har files by browser dev-tool", + esb_export_tip: "Can not export esb files now", swagger_tip: "Swagger 2.0 and 3.0 json files are supported", har_tip: "Only Har files are supported", + esb_tip: "Only ESB xlsx files are supported", postman_tip: "Only Postman Collection V2.1 json files are supported", postman_export_tip: "Export the test collection by Postman", swagger_export_tip: "Export jSON-formatted files via Swagger website", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 684f4abf22..19c8562cc3 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -949,9 +949,11 @@ export default { ms_tip: "支持 MeterSphere json 格式", ms_export_tip: "通过 MeterSphere 接口测试页面或者浏览器插件导出 json 格式文件", har_export_tip: "通过 浏览器的开发者工具 导出 Har 格式文件", + esb_export_tip: "暂时不支持ESB文件的导出", postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件", swagger_tip: "支持 Swagger 2.0 与 3.0 版本的 json 文件", har_tip: "只支持 Har 文件", + esb_tip: "只支持 ESB 模版的xlsx文件", post_export_tip: "通过 Postman 导出测试集合", swagger_export_tip: "通过 Swagger 页面导出", jmeter_export_tip: "通过 JMeter 生成JMX文件", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 54185a8feb..7a0f458c8d 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -948,9 +948,11 @@ export default { ms_tip: "支持 MeterSphere json 格式", ms_export_tip: "通過 MeterSphere 接口測試頁面或者瀏覽器插件導出 json 格式文件", har_export_tip: "通过 瀏覽器到開發者工具 导出 Har 格式文件", + esb_export_tip: "暫時不支持ESB文件的导出", postman_tip: "只支持 Postman Collection v2.1 格式的 json 文件", swagger_tip: "支持 Swagger 2.0 與 3.0 版本的 json 文件", har_tip: "只支持 Har 文件", + esb_tip: "只支持 ESB 模板的xlsx文件", post_export_tip: "通過 Postman 導出測試集合", swagger_export_tip: "通過 Swagger 頁面導出", jmeter_export_tip: "通過 JMeter 生成JMX文件", From eeedae7a4a42849159539194e754564a99a85f24 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 23 Mar 2021 17:30:23 +0800 Subject: [PATCH 05/17] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=9C=BA=E6=99=AF=E6=AD=A5=E9=AA=A4=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../automation/scenario/EditApiScenario.vue | 23 ++++++++++++++----- .../automation/scenario/api/ApiRelevance.vue | 1 + .../scenario/api/ScenarioRelevance.vue | 7 ++++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index e2075432d1..b96dbcec64 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -164,7 +164,7 @@ - + - + @@ -288,7 +288,7 @@ loading: false, apiListVisible: false, customizeVisible: false, - scenarioVisible: false, + isBtnHide: false, debugVisible: false, customizeRequest: {protocol: "HTTP", type: "API", hashTree: [], referenced: 'Created', active: false}, operatingElements: [], @@ -441,6 +441,9 @@ } }, methods: { + setHideBtn() { + this.isBtnHide = false; + }, // 打开引用的场景 openScenario(data) { this.$emit('openScenario', data); @@ -532,6 +535,7 @@ this.scenarioDefinition.push(new LoopController()); break; case ELEMENT_TYPE.scenario: + this.isBtnHide = true; this.$refs.scenarioRelevance.open(); break; default: @@ -559,12 +563,14 @@ } }, showAll() { - if (!this.customizeVisible) { + // 控制当有弹出页面操作时禁止刷新按钮列表 + if (!this.customizeVisible && !this.isBtnHide) { this.operatingElements = ELEMENTS.get("ALL"); this.selectedTreeNode = undefined; } }, apiListImport() { + this.isBtnHide = true; this.$refs.scenarioApiRelevance.open(); }, recursiveSorting(arr) { @@ -631,13 +637,17 @@ item.hashTree = []; } item.enable === undefined ? item.enable = true : item.enable; - this.scenarioDefinition.push(item); + if (this.selectedTreeNode != undefined) { + this.selectedTreeNode.hashTree.push(item); + } else { + this.scenarioDefinition.push(item); + } }) } + this.isBtnHide = false; this.sort(); this.reload(); this.initProjectIds(); - this.scenarioVisible = false; }, setApiParameter(item, refType, referenced) { let request = {}; @@ -676,6 +686,7 @@ data.forEach(item => { this.setApiParameter(item, refType, referenced); }); + this.isBtnHide = false; this.sort(); this.reload(); this.initProjectIds(); diff --git a/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue b/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue index c27bce8408..1a453d7153 100644 --- a/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue +++ b/frontend/src/business/components/api/automation/scenario/api/ApiRelevance.vue @@ -128,6 +128,7 @@ export default { } }, close() { + this.$emit('close'); this.refresh(); this.$refs.relevanceDialog.close(); }, diff --git a/frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue b/frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue index e73d8b202a..f69e67365f 100644 --- a/frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue +++ b/frontend/src/business/components/api/automation/scenario/api/ScenarioRelevance.vue @@ -90,8 +90,10 @@ response.data.forEach(item => { let scenarioDefinition = JSON.parse(item.scenarioDefinition); if (scenarioDefinition && scenarioDefinition.hashTree) { - let obj = {id: item.id, name: item.name, type: "scenario", headers: scenarioDefinition.headers, variables: scenarioDefinition.variables, environmentMap: scenarioDefinition.environmentMap, - referenced: 'Copy', resourceId: getUUID(), hashTree: scenarioDefinition.hashTree, projectId: item.projectId}; + let obj = { + id: item.id, name: item.name, type: "scenario", headers: scenarioDefinition.headers, variables: scenarioDefinition.variables, environmentMap: scenarioDefinition.environmentMap, + referenced: 'Copy', resourceId: getUUID(), hashTree: scenarioDefinition.hashTree, projectId: item.projectId + }; scenarios.push(obj); } }); @@ -101,6 +103,7 @@ }) }, close() { + this.$emit('close'); this.refresh(); this.$refs.relevanceDialog.close(); }, From e0ffb4ad650e16aed8eba86d773feccfb041f285 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Tue, 23 Mar 2021 17:34:04 +0800 Subject: [PATCH 06/17] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA)?= =?UTF-8?q?:=20=E9=A6=96=E9=A1=B5=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E6=95=B0=E7=BB=9F=E8=AE=A1=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml index 82948829e2..b23321eba5 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml @@ -387,7 +387,8 @@ union all select tpac.id as s from test_plan_api_case tpac join api_test_case on tpac.api_case_id = api_test_case.id - where tpac.test_plan_id = #{planId} + join api_definition on api_test_case.api_definition_id = api_definition.id + where tpac.test_plan_id = #{planId} and api_definition.status != 'Trash' union all select tplc.id as s from test_plan_load_case tplc join load_test on tplc.load_case_id = load_test.id From 40c1ebea2062ef1fb4da1af10f35ad908b4a53fc Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Tue, 23 Mar 2021 17:36:25 +0800 Subject: [PATCH 07/17] =?UTF-8?q?refactor(=E6=80=A7=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95):=20=E4=BF=AE=E6=94=B9=E5=8E=8B=E5=8A=9B=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=9A=84=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/PerformancePressureConfig.vue | 59 +++++++++++-------- .../components/PerformancePressureConfig.vue | 53 ++++++++++------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue b/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue index 6ef4fc1ef0..ee9ebb5d74 100644 --- a/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue +++ b/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue @@ -1,16 +1,25 @@ @@ -240,8 +248,7 @@ export default { break; } }); - this.calculateChart(this.threadGroups[i]); - + this.calculateTotalChart(this.threadGroups[i]); } }, getLoadConfig() { diff --git a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue index ee4f21d433..7b4db96d6f 100644 --- a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue @@ -14,21 +14,33 @@ - - - - + + + + @@ -47,7 +59,7 @@ v-model="threadGroup.duration" :min="1" :max="9999" - @change="calculateChart(threadGroup)" + @change="calculateTotalChart(threadGroup)" size="mini"/> @@ -64,7 +76,7 @@ @@ -77,7 +89,7 @@ :min="1" :max="threadGroup.duration" v-model="threadGroup.rampUpTime" - @change="calculateChart(threadGroup)" + @change="calculateTotalChart(threadGroup)" size="mini"/> @@ -86,7 +98,7 @@ :min="1" :max="Math.min(threadGroup.threadNumber, threadGroup.rampUpTime)" v-model="threadGroup.step" - @change="calculateChart(threadGroup)" + @change="calculateTotalChart(threadGroup)" size="mini"/> @@ -98,7 +110,7 @@ :disabled="isReadOnly" :min="1" v-model="threadGroup.rampUpTime" - @change="calculateChart(threadGroup)" + @change="calculateTotalChart(threadGroup)" size="mini"/> @@ -112,7 +124,7 @@ v-model="threadGroup.iterateNum" :min="1" :max="9999999" - @change="calculateChart(threadGroup)" + @change="calculateTotalChart(threadGroup)" size="mini"/>
@@ -137,13 +149,12 @@ - - -
{{ $t('load_test.pressure_prediction_chart') }}
- -
- - + + + + + + @@ -303,8 +314,6 @@ export default { this.$set(this.threadGroups[i], "enabled", this.threadGroups[i].enabled || 'true'); this.$set(this.threadGroups[i], "deleted", this.threadGroups[i].deleted || 'false'); }) - this.calculateChart(this.threadGroups[i]); - } this.calculateTotalChart(); } From 066ac69c6d08709bafe9f4060798aaa3b1fddd00 Mon Sep 17 00:00:00 2001 From: "song.tianyang" Date: Tue, 23 Mar 2021 17:47:49 +0800 Subject: [PATCH 08/17] =?UTF-8?q?feat:=20=E6=8E=A5=E5=8F=A3=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=AF=BC=E5=85=A5-=E6=A0=B9=E6=8D=AE=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E7=9A=84=E6=8E=A5=E5=8F=A3=E9=80=89=E6=8B=A9=EF=BC=8C?= =?UTF-8?q?=E5=B1=95=E7=8E=B0=E4=B8=8D=E5=90=8C=E7=9A=84=E5=88=B0=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接口定义导入-根据不同的接口选择,展现不同的到导入方式 --- .../components/import/ApiImport.vue | 89 +++++++++++-------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/frontend/src/business/components/api/definition/components/import/ApiImport.vue b/frontend/src/business/components/api/definition/components/import/ApiImport.vue index 9d743d8cad..291f056a97 100644 --- a/frontend/src/business/components/api/definition/components/import/ApiImport.vue +++ b/frontend/src/business/components/api/definition/components/import/ApiImport.vue @@ -140,28 +140,35 @@ export default { exportTip: this.$t('api_test.api_import.ms_export_tip'), suffixes: new Set(['json']) }, - { - name: 'Postman', - value: 'Postman', - tip: this.$t('api_test.api_import.postman_tip'), - exportTip: this.$t('api_test.api_import.post_export_tip'), - suffixes: new Set(['json']) - }, - { - name: 'Swagger', - value: 'Swagger2', - tip: this.$t('api_test.api_import.swagger_tip'), - exportTip: this.$t('api_test.api_import.swagger_export_tip'), - suffixes: new Set(['json']) - }, - { - name: 'HAR', - value: 'Har', - tip: this.$t('api_test.api_import.har_tip'), - exportTip: this.$t('api_test.api_import.har_export_tip'), - suffixes: new Set(['har']) - }, ], + postmanPlanform:{ + name: 'Postman', + value: 'Postman', + tip: this.$t('api_test.api_import.postman_tip'), + exportTip: this.$t('api_test.api_import.post_export_tip'), + suffixes: new Set(['json']) + }, + swaggerPlanform:{ + name: 'Swagger', + value: 'Swagger2', + tip: this.$t('api_test.api_import.swagger_tip'), + exportTip: this.$t('api_test.api_import.swagger_export_tip'), + suffixes: new Set(['json']) + }, + harPlanform:{ + name: 'HAR', + value: 'Har', + tip: this.$t('api_test.api_import.har_tip'), + exportTip: this.$t('api_test.api_import.har_export_tip'), + suffixes: new Set(['har']) + }, + esbPlanform : { + name: 'ESB', + value: 'ESB', + tip: this.$t('api_test.api_import.esb_tip'), + exportTip: this.$t('api_test.api_import.esb_export_tip'), + suffixes: new Set(['xlsx','xls']) + }, selectedPlatform: {}, selectedPlatformValue: 'Metersphere', result: {}, @@ -189,6 +196,11 @@ export default { activated() { this.selectedPlatform = this.platforms[0]; }, + created() { + this.platforms.push(this.postmanPlanform); + this.platforms.push(this.swaggerPlanform); + this.platforms.push(this.harPlanform); + }, watch: { selectedPlatformValue() { for (let i in this.platforms) { @@ -199,22 +211,29 @@ export default { } }, propotal(){ + let postmanIndex = this.platforms.indexOf(this.postmanPlanform); + let swaggerPlanformIndex = this.platforms.indexOf(this.swaggerPlanform); + let harPlanformIndex = this.platforms.indexOf(this.harPlanform); + let esbPlanformIndex = this.platforms.indexOf(this.esbPlanform); + if(postmanIndex>=0){ + this.platforms.splice(this.platforms.indexOf(this.postmanPlanform),1); + } + if(swaggerPlanformIndex>=0){ + this.platforms.splice(this.platforms.indexOf(this.swaggerPlanform),1); + } + if(harPlanformIndex>=0){ + this.platforms.splice(this.platforms.indexOf(this.harPlanform),1); + } + if(esbPlanformIndex>=0){ + this.platforms.splice(this.platforms.indexOf(this.esbPlanform),1); + } if(this.propotal === 'TCP'){ - if(this.platforms.length < 5){ - let esbElement = { - name: 'ESB', - value: 'ESB', - tip: this.$t('api_test.api_import.esb_tip'), - exportTip: this.$t('api_test.api_import.esb_export_tip'), - suffixes: new Set(['xlsx','xls']) - }; - this.platforms.push(esbElement); - } + this.platforms.push(this.esbPlanform); return true; - }else{ - if(this.platforms.length == 5){ - this.platforms.pop(); - } + }else if(this.propotal === 'HTTP'){ + this.platforms.push(this.postmanPlanform); + this.platforms.push(this.swaggerPlanform); + this.platforms.push(this.harPlanform); return false; } } From 478c98ac21f4af39d1b9c42bc6152b7a2a17c6f5 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Tue, 23 Mar 2021 18:05:51 +0800 Subject: [PATCH 09/17] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=9C=BA=E6=99=AF=E6=AD=A5=E9=AA=A4=E6=96=AD?= =?UTF-8?q?=E8=A8=80=E8=A7=84=E5=88=99=E5=A2=9E=E5=8A=A0=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/assertion/ApiAssertionJsr223.vue | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frontend/src/business/components/api/definition/components/assertion/ApiAssertionJsr223.vue b/frontend/src/business/components/api/definition/components/assertion/ApiAssertionJsr223.vue index b1294b679d..c32bfb8ef7 100644 --- a/frontend/src/business/components/api/definition/components/assertion/ApiAssertionJsr223.vue +++ b/frontend/src/business/components/api/definition/components/assertion/ApiAssertionJsr223.vue @@ -18,6 +18,7 @@ {{ assertion.desc }}
+
@@ -27,23 +28,23 @@
+ :placeholder="$t('api_test.request.assertions.variable_name')" @change="quickScript" :disabled="disabled"/>
+ @change="changeOperator" :disabled="disabled">
+ @change="quickScript" v-if="!hasEmptyOperator" :disabled="disabled"/>
- +