fix: 解决冲突

This commit is contained in:
chenjianxing 2021-03-23 20:15:26 +08:00
commit 9c4b6614bf
39 changed files with 1522 additions and 278 deletions

View File

@ -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<ApiDefinitionResult>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) {
@ -254,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);
}
}

View File

@ -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<EsbDataStruct> 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;

View File

@ -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<ApiTestCaseWithBLOBs> cases;
//ESB文件导入的附属数据类
private Map<String,EsbApiParamsWithBLOBs> esbApiParamsMap;
}

View File

@ -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;
}

View File

@ -0,0 +1,769 @@
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<String, Model> 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<String, XSSFCellStyle> cellStyleMap = createCellStle(workbook);
XSSFSheet headSheet = workbook.createSheet("公共报文头");
generateSheet(headSheet,true, font,cellStyleMap);
XSSFSheet bodySheet = workbook.createSheet("接口报文信息");
generateSheet(bodySheet, false,font,cellStyleMap);
return workbook;
}
private static Map<String, XSSFCellStyle> createCellStle(XSSFWorkbook workbook) {
Map<String, XSSFCellStyle> 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,boolean isHead, XSSFFont font,Map<String, XSSFCellStyle> cellStyleMap) {
if (sheet == null) {
return;
}
sheet.setColumnWidth(0, 4000);
sheet.setColumnWidth(1, 4000);
sheet.setColumnWidth(2, 4000);
sheet.setColumnWidth(3, 4000);
if(isHead){
sheet.setColumnWidth(4, 880);
sheet.setColumnWidth(5, 4000);
sheet.setColumnWidth(6, 4000);
sheet.setColumnWidth(7, 4000);
sheet.setColumnWidth(8, 4000);
sheet.setColumnWidth(9, 4000);
}else {
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交易名称 head的话是56(紫色[pop]背景空白单元格,下同) 7服务名称 8服务场景
* row2: 1.请输入交易码(必填) 2请输入交易名称(必填) 7请输入服务名称(如果不填则以交易名称为主) 8请输入服务场景(选填)
* row3: 合并7-10单元格输入请输入系统名称 背景色:黄色[yellow]
* row4: 1.英文名称2.中文名称3.数据类型/长度4.是否必输5.备注 7.英文名称8.数据类型/长度9.中文名称 10备注 背景色:黄色
* row5: 整行都是青色green1:输入
* 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"));
if(isHead){
setCellValue("", row1.createCell(4), font,cellStyleMap.get("default"));
setCellValue("服务名称", row1.createCell(5), font,cellStyleMap.get("default"));
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"));
}else{
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"));
if(isHead){
setCellValue("", row2.createCell(4), font,cellStyleMap.get("pop"));
setCellValue("请输入服务名称(如果不填,则以交易名称为主)", row2.createCell(5), font,null);
setCellValue("请输入服务场景(选填)", row2.createCell(6), font,cellStyleMap.get("default"));
setCellValue("", row2.createCell(7), font,cellStyleMap.get("default"));
setCellValue("", row2.createCell(8), font,cellStyleMap.get("default"));
setCellValue("", row2.createCell(9), font,cellStyleMap.get("default"));
}else{
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"));
if(isHead){
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"));
CellRangeAddress region1 = new CellRangeAddress(2, 2, 0, 3);
sheet.addMergedRegion(region1);
CellRangeAddress region2 = new CellRangeAddress(2, 2, 5, 9);
sheet.addMergedRegion(region2);
}else{
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"));
if(isHead){
setCellValue("备注", row4.createCell(3), font,cellStyleMap.get("yellow"));
setCellValue("", row4.createCell(4), font,cellStyleMap.get("pop"));
setCellValue("英文名称", row4.createCell(5), font,cellStyleMap.get("yellow"));
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"));
}else {
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"));
if(!isHead){
setCellValue("", row5.createCell(10), font,cellStyleMap.get("green"));
}
XSSFRow row6 = sheet.createRow(5);
setCellValue("", row6.createCell(0), font,cellStyleMap.get("default"));
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"));
if(isHead){
setCellValue("", row6.createCell(4), font,cellStyleMap.get("pop"));
setCellValue("", row6.createCell(5), font,cellStyleMap.get("default"));
setCellValue("请输入STRING(具体长度) 或 ARRAY", 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"));
}else {
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("", row7.createCell(1), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(2), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(3), font,cellStyleMap.get("default"));
if(isHead){
setCellValue("", row7.createCell(4), font,cellStyleMap.get("pop"));
setCellValue("", row7.createCell(5), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(6), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(7), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(8), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(9), font,cellStyleMap.get("default"));
}else {
setCellValue("", row7.createCell(4), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(5), font,cellStyleMap.get("pop"));
setCellValue("", row7.createCell(6), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(7), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(8), font,cellStyleMap.get("default"));
setCellValue("", row7.createCell(9), font,cellStyleMap.get("default"));
setCellValue("", row7.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"));
if(!isHead){
setCellValue("", row8.createCell(10), font,cellStyleMap.get("green"));
}
XSSFRow row9 = sheet.createRow(8);
setCellValue("", row9.createCell(0), font,cellStyleMap.get("default"));
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"));
if(isHead){
setCellValue("", row9.createCell(4), font,cellStyleMap.get("pop"));
setCellValue("", row9.createCell(5), font,cellStyleMap.get("default"));
setCellValue("请输入STRING(具体长度) 或 ARRAY", row9.createCell(6), 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"));
}else {
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<EsbSheetDataStruct> 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 simpleCodeIndex = 0;
int simpleNameIndex = 1;
int apiNameIndex = 6;
int apiDescIndex = 7;
int chineNameIndex = 8;
int descIndex = 9;
int apiPositionIndex = 10;
int cellCount = 11;
if(isHeadSheet){
apiNameIndex = 5;
apiDescIndex = 6;
chineNameIndex = 7;
descIndex = 8;
apiPositionIndex = 9;
cellCount = 10;
}
int rowCount = headSheet.getLastRowNum();
//根据模版样式如果不是报文头则要取接口信息
if (!isHeadSheet) {
Row interfaceInfoRow = headSheet.getRow(1);
if (interfaceInfoRow != null) {
List<String> rowDataArr = this.getRowDataByStartIndexAndEndIndex(interfaceInfoRow, 0, cellCount-1);
if (rowDataArr.size() >= cellCount) {
String interfaceCode = rowDataArr.get(simpleCodeIndex);
String interfaceName = rowDataArr.get(apiNameIndex);
String interfaceDesc = rowDataArr.get(apiDescIndex);
if (StringUtils.isEmpty(interfaceName)) {
interfaceName = rowDataArr.get(simpleNameIndex);
}
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<String> rowDataArr = this.getRowDataByStartIndexAndEndIndex(row, 0, cellCount-1);
boolean isBlankRow = this.checkBlankRow(rowDataArr, cellCount);
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(apiNameIndex), rowDataArr.get(apiDescIndex), rowDataArr.get(chineNameIndex), rowDataArr.get(descIndex));
if (!initDataSuccess) {
continue;
}
boolean isHead = isHeadSheet;
if (rowDataArr.size() > cellCount) {
if (StringUtils.equals(rowDataArr.get(apiPositionIndex), "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<String> 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<String> getRowDataByStartIndexAndEndIndex(Row row, int startCell, int endCell) {
List<String> 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));
}else {
returnArray.add("");
}
}
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<ApiDefinitionWithBLOBs> apiDataList = new ArrayList<>();
ApiModule parentNode = ApiDefinitionImportUtil.getSelectModule(importRequest.getModuleId());
EsbSheetDataStruct headSheetData = esbExcelDataStruct.getHeadData();
List<EsbSheetDataStruct> interfaceDataList = esbExcelDataStruct.getInterfaceList();
List<String> savedNames = new ArrayList<>();
Map<String, EsbApiParamsWithBLOBs> 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<EsbDataStruct> headList = new ArrayList<>();
List<EsbDataStruct> 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<String, EsbDataStruct> 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<String, EsbDataStruct> 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<EsbDataStruct> list = new ArrayList<>();
list.add(dataStruct);
return JSONArray.toJSONString(list);
}
// private void parseParameters(HarRequest harRequest, MsHTTPSamplerProxy request) {
// List<HarQueryParm> queryStringList = harRequest.queryString;
// queryStringList.forEach(harQueryParm -> {
// parseQueryParameters(harQueryParm, request.getArguments());
// });
// List<HarHeader> harHeaderList = harRequest.headers;
// harHeaderList.forEach(harHeader -> {
// parseHeaderParameters(harHeader, request.getHeaders());
// });
// List<HarCookie> harCookieList = harRequest.cookies;
// harCookieList.forEach(harCookie -> {
// parseCookieParameters(harCookie, request.getHeaders());
// });
// }
private String getDefaultStringValue(String val) {
return StringUtils.isBlank(val) ? "" : val;
}
}

View File

@ -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<ApiDefinitionImport> {
protected void buildModule(ApiModule parentModule, ApiDefinitionWithBLOBs apiDefinition, List<String> tags) {
if (tags != null) {
tags.forEach(tag -> {
ApiModule module = ApiDefinitionImportUtil.buildModule(parentModule, tag, this.projectId);
apiDefinition.setModuleId(module.getId());
});
}else {
apiDefinition.setModuleId(parentModule.getId());
}
}
}

View File

@ -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<EsbSheetDataStruct> interfaceList = new ArrayList<>();
}

View File

@ -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<EsbDataStruct> requestList = new ArrayList<>();
private List<EsbDataStruct> responseList = new ArrayList<>();
//单个接口内也可能有报文头中要增加的数据
private List<EsbDataStruct> reqHeadList = new ArrayList<>();
private List<EsbDataStruct> 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;
}
}

View File

@ -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() {

View File

@ -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> {
T parse(InputStream source, ApiTestImportRequest request);
T parse(InputStream source, ApiTestImportRequest request) throws IOException, InvalidFormatException, Exception;
}

View File

@ -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;
@ -343,26 +344,43 @@ public class ApiDefinitionService {
private void _importCreate(List<ApiDefinition> sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition,
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> 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);
}
}
}
@ -374,6 +392,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<ApiTestCaseWithBLOBs> cases = apiImport.getCases();
@ -567,11 +593,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<EsbApiParamsWithBLOBs> 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);

View File

@ -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<KeyValue> childValueList = this.genKeyValueByEsbDataStruct(request.getChildren(), itemName);
@ -351,4 +351,5 @@ public class EsbApiParamService {
example.createCriteria().andResourceIdIn(apiIds);
esbApiParamsMapper.deleteByExample(example);
}
}

View File

@ -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<UserExcelData> generateExportTemplate() {
List<UserExcelData> list = new ArrayList<>();
List<String> types = TestCaseConstants.Type.getValues();
List<String> 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);
}
}
}

View File

@ -36,9 +36,12 @@
SELECT * FROM (
SELECT testCase.testCaseID,testCase.testCaseName AS caseName,testCase.testPlanName AS testPlan ,caseErrorCountData.dataCountNumber AS failureTimes,'apiCase' AS caseType
FROM (
SELECT apiCase.id AS testCaseID,apiCase.`name` AS testCaseName,group_concat(testPlan.`name`) AS testPlanName FROM api_test_case apiCase
SELECT apiCase.id AS testCaseID,apiCase.`name` AS testCaseName,group_concat(testPlan.`name`) AS testPlanName, testPlanCase.update_time as updateTime
FROM api_test_case apiCase
inner join api_definition on api_definition.id = apiCase.api_definition_id
INNER JOIN test_plan_api_case testPlanCase ON testPlanCase.api_case_id = apiCase.id
INNER JOIN test_plan testPlan ON testPlan.id = testPlanCase.test_plan_id
and api_definition.status != 'Trash'
GROUP BY apiCase.id
ORDER BY apiCase.create_time DESC
)testCase
@ -48,7 +51,7 @@
SELECT id FROM api_test_case WHERE project_id = #{projectId}
) and `status` = 'error' GROUP BY resource_id
) caseErrorCountData ON caseErrorCountData.testCaseID =testCase.testCaseID
WHERE caseErrorCountData.executeTime >= #{startTimestamp}
WHERE testCase.updateTime >= #{startTimestamp}
UNION
SELECT scene.id AS testCaseID,scene.`name` AS caseName,apiScene.testPlanName AS testPlan,count(report.id) AS failureTimes,'scenario' AS caseType
FROM api_scenario_report report

View File

@ -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

View File

@ -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
}

View File

@ -0,0 +1,9 @@
package io.metersphere.excel.domain;
/**
* @author song.tianyang
* @Date 2021/3/22 7:04 下午
* @Description
*/
public class EsbExcelData {
}

View File

@ -23,7 +23,6 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
@ -87,18 +86,10 @@ public class TrackService {
public List<ChartsData> getCaseMaintenanceBar(String projectId) {
List<TrackCountResult> funcMaintainer = extTestCaseMapper.countFuncMaintainer(projectId);
List<TrackCountResult> relevanceMaintainer = extTestCaseMapper.countRelevanceMaintainer(projectId);
List<String> list = relevanceMaintainer.stream().map(TrackCountResult::getGroupField).collect(Collectors.toList());
List<ChartsData> charts = new ArrayList<>();
for (TrackCountResult result : funcMaintainer) {
String groupField = result.getGroupField();
if (!list.contains(groupField)) {
// 创建了功能用例但是未关联测试
TrackCountResult trackCount = new TrackCountResult();
trackCount.setCountNumber(0);
trackCount.setGroupField(groupField);
relevanceMaintainer.add(trackCount);
}
ChartsData chartsData = new ChartsData();
chartsData.setxAxis(groupField);
chartsData.setyAxis(BigDecimal.valueOf(result.getCountNumber()));

View File

@ -133,6 +133,9 @@
});
}
}
},
selectNodeIds() {
this.activeName = "default";
}
},
methods: {

View File

@ -164,7 +164,7 @@
</div>
<!--接口列表-->
<scenario-api-relevance @save="pushApiOrCase" ref="scenarioApiRelevance" v-if="type!=='detail'"/>
<scenario-api-relevance @save="pushApiOrCase" @close="setHideBtn" ref="scenarioApiRelevance" v-if="type!=='detail'"/>
<!--自定义接口-->
<el-drawer v-if="type!=='detail'" :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr"
@ -173,7 +173,7 @@
<ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
</el-drawer>
<!--场景导入 -->
<scenario-relevance v-if="type!=='detail'" @save="addScenario" ref="scenarioRelevance"/>
<scenario-relevance v-if="type!=='detail'" @save="addScenario" @close="setHideBtn" ref="scenarioRelevance"/>
<!-- 环境 -->
<api-environment-config v-if="type!=='detail'" ref="environmentConfig" @close="environmentConfigClose"/>
@ -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: [],
@ -442,6 +442,9 @@
},
},
methods: {
setHideBtn() {
this.isBtnHide = false;
},
//
openScenario(data) {
this.$emit('openScenario', data);
@ -533,6 +536,7 @@
this.scenarioDefinition.push(new LoopController());
break;
case ELEMENT_TYPE.scenario:
this.isBtnHide = true;
this.$refs.scenarioRelevance.open();
break;
default:
@ -560,12 +564,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) {
@ -632,13 +638,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 = {};
@ -677,6 +687,7 @@
data.forEach(item => {
this.setApiParameter(item, refType, referenced);
});
this.isBtnHide = false;
this.sort();
this.reload();
this.initProjectIds();

View File

@ -244,6 +244,9 @@
});
},
list(data) {
if (data.protocol === "dubbo://") {
data.protocol = "DUBBO";
}
let url = "/api/module/list/" + getCurrentProjectID() + "/" + data.protocol;
this.result = this.$get(url, response => {
if (response.data != undefined && response.data != null) {

View File

@ -128,6 +128,7 @@ export default {
}
},
close() {
this.$emit('close');
this.refresh();
this.$refs.relevanceDialog.close();
},

View File

@ -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();
},

View File

@ -6,7 +6,7 @@
<div class="el-step__icon-inner">{{data.index}}</div>
</div>
<el-tag class="ms-left-btn" size="small" :style="{'color': color, 'background-color': backgroundColor}">{{title}}</el-tag>
<el-tag size="mini" v-if="data.method">{{data.method}}</el-tag>
<el-tag size="mini" v-if="data.method">{{getMethod()}}</el-tag>
</slot>
<span>
@ -125,6 +125,17 @@
//this.$set(this.data, 'active', !this.data.active);
this.$emit('active');
},
getMethod() {
if (this.data.protocol === "HTTP") {
return this.data.method;
}
else if (this.data.protocol === "dubbo://") {
return "DUBBO";
}
else {
return this.data.protocol;
}
},
copyRow() {
this.$emit('copy');
},

View File

@ -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("当前循环下没有请求,不能执行")

View File

@ -13,7 +13,7 @@
</el-dropdown-menu>
</el-dropdown>
<ms-variable-list ref="scenarioParameters"/>
<ms-add-basis-api ref="api"/>
<ms-add-basis-api :currentProtocol="currentProtocol" ref="api"/>
</div>
</template>
@ -32,6 +32,7 @@
data() {
return {
allSamplers: ELEMENTS.get('AllSamplerProxy'),
currentProtocol: "HTTP",
}
},
methods: {
@ -63,7 +64,8 @@
}
});
},
saveAsApi(){
saveAsApi() {
this.currentProtocol = this.data.protocol;
this.$refs.api.open(this.data);
}
}

View File

@ -1,152 +1,152 @@
<template>
<div>
<ms-container v-if="renderComponent">
<ms-aside-container>
<ms-api-module
@nodeSelectEvent="nodeChange"
@protocolChange="handleProtocolChange"
@refreshTable="refresh"
@exportAPI="exportAPI"
@debug="debug"
@saveAsEdit="editApi"
@setModuleOptions="setModuleOptions"
@setNodeTree="setNodeTree"
@enableTrash="enableTrash"
:type="'edit'"
ref="nodeTree"/>
</ms-aside-container>
<ms-container v-if="renderComponent">
<ms-aside-container>
<ms-api-module
@nodeSelectEvent="nodeChange"
@protocolChange="handleProtocolChange"
@refreshTable="refresh"
@exportAPI="exportAPI"
@debug="debug"
@saveAsEdit="editApi"
@setModuleOptions="setModuleOptions"
@setNodeTree="setNodeTree"
@enableTrash="enableTrash"
:type="'edit'"
ref="nodeTree"/>
</ms-aside-container>
<ms-main-container>
<!-- 主框架列表 -->
<el-tabs v-model="apiDefaultTab" @edit="handleTabRemove" @tab-click="addTab">
<el-tab-pane v-for="(item) in apiTabs"
:key="item.name"
:label="item.title"
:closable="item.closable"
:name="item.name">
<ms-tab-button
v-if="item.type === 'list'"
:active-dom.sync="activeDom"
:left-tip="$t('api_test.definition.api_title')"
:right-tip="$t('api_test.definition.doc_title')"
:middle-tip="$t('api_test.definition.case_title')"
left-content="API"
middle-content="CASE"
:right-content="$t('api_test.definition.doc_title')">
<!-- 列表集合 -->
<ms-api-list
v-if="activeDom==='left'"
@runTest="runTest"
:module-tree="nodeTree"
:module-options="moduleOptions"
:current-protocol="currentProtocol"
:visible="visible"
:currentRow="currentRow"
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:queryDataType="queryDataType"
:selectDataRange="selectDataRange"
:is-read-only="isReadOnly"
@changeSelectDataRangeAll="changeSelectDataRangeAll"
@editApi="editApi"
@handleCase="handleCase"
@showExecResult="showExecResult"
ref="apiList"/>
<!--测试用例列表-->
<api-case-simple-list
v-if="activeDom==='middle'"
:current-protocol="currentProtocol"
:visible="visible"
:currentRow="currentRow"
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:queryDataType="queryDataType"
:is-read-only="isReadOnly"
@changeSelectDataRangeAll="changeSelectDataRangeAll"
@handleCase="handleCase"
@showExecResult="showExecResult"
ref="apiList"/>
<api-documents-page class="api-doc-page"
v-if="activeDom==='right'"
:project-id="projectId"
:module-ids="selectNodeIds"/>
</ms-tab-button>
<!-- 添加/编辑测试窗口-->
<div v-if="item.type=== 'ADD'" class="ms-api-div">
<ms-api-config :syncTabs="syncTabs" @runTest="runTest" @saveApi="saveApi" @createRootModel="createRootModel" ref="apiConfig"
:current-api="item.api"
:project-id="projectId"
:currentProtocol="currentProtocol"
:moduleOptions="moduleOptions"/>
</div>
<!-- 快捷调试 -->
<div v-else-if="item.type=== 'debug'" class="ms-api-div">
<ms-debug-http-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='HTTP'"/>
<ms-debug-jdbc-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='SQL'"/>
<ms-debug-tcp-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='TCP'"/>
<ms-debug-dubbo-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='DUBBO'"/>
</div>
<ms-main-container>
<!-- 主框架列表 -->
<el-tabs v-model="apiDefaultTab" @edit="handleTabRemove" @tab-click="addTab">
<el-tab-pane v-for="(item) in apiTabs"
:key="item.name"
:label="item.title"
:closable="item.closable"
:name="item.name">
<ms-tab-button
v-if="item.type === 'list'"
:active-dom.sync="activeDom"
:left-tip="$t('api_test.definition.api_title')"
:right-tip="$t('api_test.definition.doc_title')"
:middle-tip="$t('api_test.definition.case_title')"
left-content="API"
middle-content="CASE"
:right-content="$t('api_test.definition.doc_title')">
<!-- 列表集合 -->
<ms-api-list
v-if="activeDom==='left'"
@runTest="runTest"
:module-tree="nodeTree"
:module-options="moduleOptions"
:current-protocol="currentProtocol"
:visible="visible"
:currentRow="currentRow"
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:queryDataType="queryDataType"
:selectDataRange="selectDataRange"
:is-read-only="isReadOnly"
@changeSelectDataRangeAll="changeSelectDataRangeAll"
@editApi="editApi"
@handleCase="handleCase"
@showExecResult="showExecResult"
ref="apiList"/>
<!--测试用例列表-->
<api-case-simple-list
v-if="activeDom==='middle'"
:current-protocol="currentProtocol"
:visible="visible"
:currentRow="currentRow"
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
:queryDataType="queryDataType"
:is-read-only="isReadOnly"
@changeSelectDataRangeAll="changeSelectDataRangeAll"
@handleCase="handleCase"
@showExecResult="showExecResult"
ref="apiList"/>
<api-documents-page class="api-doc-page"
v-if="activeDom==='right'"
:project-id="projectId"
:module-ids="selectNodeIds"/>
</ms-tab-button>
<!-- 添加/编辑测试窗口-->
<div v-if="item.type=== 'ADD'" class="ms-api-div">
<ms-api-config :syncTabs="syncTabs" @runTest="runTest" @saveApi="saveApi" @createRootModel="createRootModel" ref="apiConfig"
:current-api="item.api"
:project-id="projectId"
:currentProtocol="currentProtocol"
:moduleOptions="moduleOptions"/>
</div>
<!-- 快捷调试 -->
<div v-else-if="item.type=== 'debug'" class="ms-api-div">
<ms-debug-http-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='HTTP'"/>
<ms-debug-jdbc-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='SQL'"/>
<ms-debug-tcp-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='TCP'"/>
<ms-debug-dubbo-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi"
v-if="currentProtocol==='DUBBO'"/>
</div>
<!-- 测试-->
<div v-else-if="item.type=== 'TEST'" class="ms-api-div">
<ms-run-test-http-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='HTTP'"/>
<ms-run-test-tcp-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='TCP'"/>
<ms-run-test-sql-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='SQL'"/>
<ms-run-test-dubbo-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='DUBBO'"/>
</div>
</el-tab-pane>
<!-- 测试-->
<div v-else-if="item.type=== 'TEST'" class="ms-api-div">
<ms-run-test-http-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='HTTP'"/>
<ms-run-test-tcp-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='TCP'"/>
<ms-run-test-sql-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='SQL'"/>
<ms-run-test-dubbo-page :syncTabs="syncTabs" :currentProtocol="currentProtocol" :api-data="item.api" :project-id="projectId"
@saveAsApi="editApi" @refresh="refresh" v-if="currentProtocol==='DUBBO'"/>
</div>
</el-tab-pane>
<el-tab-pane name="add">
<template v-slot:label>
<el-dropdown @command="handleCommand" v-tester>
<el-button type="primary" plain icon="el-icon-plus" size="mini" v-tester/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="debug">{{ $t('api_test.definition.request.fast_debug') }}</el-dropdown-item>
<el-dropdown-item command="ADD">{{ $t('api_test.definition.request.title') }}</el-dropdown-item>
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-tab-pane>
</el-tabs>
<el-tab-pane name="add">
<template v-slot:label>
<el-dropdown @command="handleCommand" v-tester>
<el-button type="primary" plain icon="el-icon-plus" size="mini" v-tester/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="debug">{{ $t('api_test.definition.request.fast_debug') }}</el-dropdown-item>
<el-dropdown-item command="ADD">{{ $t('api_test.definition.request.title') }}</el-dropdown-item>
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-tab-pane>
</el-tabs>
</ms-main-container>
</ms-container>
</ms-main-container>
</ms-container>
</div>
</template>
<script>
import MsApiList from './components/list/ApiList';
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsAsideContainer from "../../common/components/MsAsideContainer";
import MsApiConfig from "./components/ApiConfig";
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
import MsApiList from './components/list/ApiList';
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsAsideContainer from "../../common/components/MsAsideContainer";
import MsApiConfig from "./components/ApiConfig";
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
import {checkoutTestManagerOrTestUser, getCurrentUser, getUUID} from "@/common/js/utils";
import MsApiModule from "./components/module/ApiModule";
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
import {checkoutTestManagerOrTestUser, getCurrentUser, getUUID} from "@/common/js/utils";
import MsApiModule from "./components/module/ApiModule";
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
import ApiDocumentsPage from "@/business/components/api/definition/components/list/ApiDocumentsPage";
import MsTableButton from "@/business/components/common/components/MsTableButton";
import MsTabButton from "@/business/components/common/components/MsTabButton";
import MsTableButton from "@/business/components/common/components/MsTableButton";
import MsTabButton from "@/business/components/common/components/MsTabButton";
export default {
name: "ApiDefinition",
@ -157,7 +157,7 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
this.changeRedirectParam(redirectIDParam);
return routeParam;
},
isReadOnly(){
isReadOnly() {
return !checkoutTestManagerOrTestUser();
},
projectId() {
@ -221,6 +221,9 @@ import MsTabButton from "@/business/components/common/components/MsTabButton";
currentProtocol() {
this.handleCommand("CLOSE_ALL");
},
selectNodeIds() {
this.apiDefaultTab = "default";
},
redirectID() {
this.renderComponent = false;
this.$nextTick(() => {

View File

@ -18,6 +18,7 @@
{{ assertion.desc }}
</div>
<div class="assertion-item btn circle">
<i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle @click="showPage"/>
<el-button :disabled="isReadOnly" type="success" size="mini" icon="el-icon-edit" circle @click="detail"/>
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove"/>
</div>
@ -27,23 +28,23 @@
<el-row type="flex" justify="space-between" align="middle" class="quick-script-block">
<div class="assertion-item input">
<el-input size="small" v-model="assertion.variable"
:placeholder="$t('api_test.request.assertions.variable_name')" @change="quickScript"/>
:placeholder="$t('api_test.request.assertions.variable_name')" @change="quickScript" :disabled="disabled"/>
</div>
<div class="assertion-item select">
<el-select v-model="assertion.operator" :placeholder="$t('commons.please_select')" size="small"
@change="changeOperator">
@change="changeOperator" :disabled="disabled">
<el-option v-for="o in operators" :key="o.value" :label="$t(o.label)" :value="o.value"/>
</el-select>
</div>
<div class="assertion-item input">
<el-input size="small" v-model="assertion.value" :placeholder="$t('api_test.value')"
@change="quickScript" v-if="!hasEmptyOperator"/>
@change="quickScript" v-if="!hasEmptyOperator" :disabled="disabled"/>
</div>
</el-row>
<el-input size="small" v-model="assertion.desc" :placeholder="$t('api_test.request.assertions.script_name')"
class="quick-script-block"/>
<ms-jsr233-processor ref="jsr233" :is-read-only="isReadOnly" :jsr223-processor="assertion" :templates="templates"
class="quick-script-block" :disabled="disabled"/>
<ms-jsr233-processor ref="jsr233" :is-read-only="disabled" :jsr223-processor="assertion" :templates="templates"
:height="300" @languageChange="quickScript"/>
<template v-slot:footer v-if="!edit">
<ms-dialog-footer
@ -84,6 +85,7 @@
data() {
return {
visible: false,
disabled: false,
operators: {
EQ: {
label: "commons.adv_search.operators.equals",
@ -260,6 +262,11 @@
}
},
detail() {
this.disabled = false;
this.visible = true;
},
showPage() {
this.disabled = true;
this.visible = true;
},
close() {

View File

@ -42,7 +42,7 @@
</div>
<div class="ms-body" v-if="body.type == 'XML'">
<ms-code-edit :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" :mode="'xml'" ref="codeEdit"/>
<ms-code-edit :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" :mode="'text'" ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'Raw'">

View File

@ -29,11 +29,17 @@
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
</el-select>
</el-form-item>
<el-form-item v-if="!isScenarioModel&&!isHar" :label="$t('commons.import_mode')" prop="modeId">
<el-form-item v-if="!isScenarioModel&&showImportModel" :label="$t('commons.import_mode')" prop="modeId">
<el-select size="small" v-model="formData.modeId" class="project-select" clearable>
<el-option v-for="item in modeOptions" :key="item.id" :label="item.name" :value="item.id"/>
</el-select>
</el-form-item>
<el-form-item v-if="showTemplate">
<el-link type="primary" class="download-template"
@click="downloadTemplate"
>{{$t('test_track.case.import.download_template')}}
</el-link>
</el-form-item>
<el-form-item v-if="isSwagger2">
<el-switch
v-model="swaggerUrlEnable"
@ -105,6 +111,7 @@ export default {
default: true,
},
moduleOptions: {},
propotal:String,
model: {
type: String,
default: 'definition'
@ -133,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: {},
@ -182,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) {
@ -191,13 +210,43 @@ 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'){
this.platforms.push(this.esbPlanform);
return true;
}else if(this.propotal === 'HTTP'){
this.platforms.push(this.postmanPlanform);
this.platforms.push(this.swaggerPlanform);
this.platforms.push(this.harPlanform);
return false;
}
}
},
computed: {
isSwagger2() {
return this.selectedPlatformValue === 'Swagger2';
},
isHar() {
return this.selectedPlatformValue === 'Har';
showImportModel() {
return this.selectedPlatformValue != 'Har' && this.selectedPlatformValue != 'ESB';
},
showTemplate() {
return this.selectedPlatformValue === 'ESB';
},
isScenarioModel() {
return this.model === 'scenario';
@ -235,6 +284,11 @@ export default {
handleRemove(file, fileList) {
this.formData.file = undefined;
},
downloadTemplate(){
if(this.selectedPlatformValue == "ESB"){
this.$fileDownload('/api/definition/export/esbExcelTemplate');
}
},
uploadValidate(file, fileList) {
let suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
if (this.selectedPlatform.suffixes && !this.selectedPlatform.suffixes.has(suffix)) {
@ -307,7 +361,7 @@ export default {
<style scoped>
.api-import >>> .el-dialog {
min-width: 700px;
min-width: 750px;
}
.format-tip {

View File

@ -49,7 +49,7 @@
@saveAsEdit="saveAsEdit"
@refresh="refresh"
ref="basisApi"/>
<api-import ref="apiImport" :moduleOptions="moduleOptions" @refresh="$emit('refresh')"/>
<api-import :propotal="condition.protocol" ref="apiImport" :moduleOptions="moduleOptions" @refresh="$emit('refresh')"/>
</div>
</template>
@ -113,7 +113,7 @@ export default {
return;
}
this.protocol = "HTTP";
this.result = this.$get("/api/module/list/" + this.projectId + "/" + this.protocol, response => {
this.result = this.$get("/api/module/list/" + this.projectId + "/" + this.condition.protocol, response => {
if (response.data != undefined && response.data != null) {
this.data = response.data;
let moduleOptions = [];
@ -122,8 +122,8 @@ export default {
});
this.moduleOptions = moduleOptions
}
this.$refs.apiImport.open(this.moduleOptions);
});
this.$refs.apiImport.open(this.currentModule);
break;
}
},

View File

@ -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;

View File

@ -1,16 +1,25 @@
<template>
<div v-loading="result.loading" class="pressure-config-container">
<el-row>
<el-col>
<ms-chart class="chart-container" ref="chart1" :options="options" :autoresize="true"></ms-chart>
</el-col>
</el-row>
<el-row>
<el-collapse v-model="activeNames">
<el-collapse-item :title="threadGroup.attributes.testname" :name="index"
v-for="(threadGroup, index) in threadGroups.filter(th=>th.enabled === 'true' && th.deleted=='false')"
:key="index">
<el-col :span="10">
<el-col :span="10">
<el-collapse v-model="activeNames" accordion>
<el-collapse-item :name="index"
v-for="(threadGroup, index) in threadGroups.filter(th=>th.enabled === 'true' && th.deleted=='false')"
:key="index">
<template slot="title">
<div style="padding-right: 10px">
{{ threadGroup.attributes.testname }}
</div>
<el-tag type="primary" size="mini" v-if="threadGroup.threadType === 'DURATION'">
{{ $t('load_test.thread_num') }}{{ threadGroup.threadNumber }},
{{ $t('load_test.duration') }}: {{ threadGroup.duration }} {{ getUnitLabel(threadGroup) }}
</el-tag>
<el-tag type="primary" size="mini" v-if="threadGroup.threadType === 'ITERATION'">
{{ $t('load_test.thread_num') }} {{ threadGroup.threadNumber }},
{{ $t('load_test.iterate_num') }} {{ threadGroup.iterateNum }}
</el-tag>
</template>
<el-form :inline="true">
<el-form-item :label="$t('load_test.thread_num')">
<el-input-number
@ -34,7 +43,7 @@
:disabled="true"
v-model="threadGroup.duration"
:min="1"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item>
@ -51,7 +60,7 @@
<el-input-number
:disabled="true"
v-model="threadGroup.rpsLimit"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
:min="1"
size="mini"/>
</el-form-item>
@ -63,7 +72,7 @@
:min="1"
:max="threadGroup.duration"
v-model="threadGroup.rampUpTime"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_minutes', [getUnitLabel(threadGroup)])">
@ -72,7 +81,7 @@
:min="1"
:max="Math.min(threadGroup.threadNumber, threadGroup.rampUpTime)"
v-model="threadGroup.step"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_times')"/>
@ -96,7 +105,7 @@
:disabled="true"
v-model="threadGroup.iterateNum"
:min="1"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<br>
@ -106,7 +115,7 @@
<el-input-number
:disabled="true || !threadGroup.rpsLimitEnable"
v-model="threadGroup.rpsLimit"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
:min="1"
size="mini"/>
</el-form-item>
@ -116,19 +125,18 @@
:disabled="true"
:min="1"
v-model="threadGroup.iterateRampUp"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
</div>
</el-form>
</el-col>
<el-col :span="14">
<div class="title">{{ $t('load_test.pressure_prediction_chart') }}</div>
<ms-chart class="chart-container" :options="threadGroup.options" :autoresize="true"></ms-chart>
</el-col>
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</el-col>
<el-col :span="14">
<ms-chart class="chart-container" ref="chart1" :options="options" :autoresize="true"></ms-chart>
</el-col>
</el-row>
</div>
</template>
@ -240,8 +248,7 @@ export default {
break;
}
});
this.calculateChart(this.threadGroups[i]);
this.calculateTotalChart(this.threadGroups[i]);
}
},
getLoadConfig() {

View File

@ -14,21 +14,33 @@
</el-select>
</el-form-item>
</el-form>
<ms-chart class="chart-container" ref="chart1" :options="options" :autoresize="true"></ms-chart>
</el-col>
</el-row>
<el-row>
<el-collapse v-model="activeNames">
<el-collapse-item :title="threadGroup.attributes.testname" :name="index"
v-for="(threadGroup, index) in threadGroups.filter(th=>th.enabled === 'true' && th.deleted=='false')"
:key="index">
<el-col :span="10">
<el-col :span="12">
<el-collapse v-model="activeNames" accordion>
<el-collapse-item :name="index"
v-for="(threadGroup, index) in threadGroups.filter(th=>th.enabled === 'true' && th.deleted=='false')"
:key="index">
<template slot="title">
<div style="padding-right: 20px; font-size: 16px;">
{{ threadGroup.attributes.testname }}
</div>
<el-tag type="primary" size="mini" v-if="threadGroup.threadType === 'DURATION'">
{{ $t('load_test.thread_num') }}{{ threadGroup.threadNumber }},
{{ $t('load_test.duration') }}: {{ threadGroup.duration }} {{ getUnitLabel(threadGroup) }}
</el-tag>
<el-tag type="primary" size="mini" v-if="threadGroup.threadType === 'ITERATION'">
{{ $t('load_test.thread_num') }} {{ threadGroup.threadNumber }},
{{$t('load_test.iterate_num')}} {{threadGroup.iterateNum}}
</el-tag>
</template>
<el-form :inline="true">
<el-form-item :label="$t('load_test.thread_num')">
<el-input-number
:disabled="isReadOnly"
v-model="threadGroup.threadNumber"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
:min="resourcePoolResourceLength"
size="mini"/>
</el-form-item>
@ -47,7 +59,7 @@
v-model="threadGroup.duration"
:min="1"
:max="9999"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item>
@ -64,7 +76,7 @@
<el-input-number
:disabled="isReadOnly || !threadGroup.rpsLimitEnable"
v-model="threadGroup.rpsLimit"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
:min="1"
:max="99999"
size="mini"/>
@ -77,7 +89,7 @@
:min="1"
:max="threadGroup.duration"
v-model="threadGroup.rampUpTime"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_minutes', [getUnitLabel(threadGroup)])">
@ -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"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_times')"/>
@ -98,7 +110,7 @@
:disabled="isReadOnly"
:min="1"
v-model="threadGroup.rampUpTime"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
@ -112,7 +124,7 @@
v-model="threadGroup.iterateNum"
:min="1"
:max="9999999"
@change="calculateChart(threadGroup)"
@change="calculateTotalChart(threadGroup)"
size="mini"/>
</el-form-item>
<br>
@ -137,13 +149,13 @@
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
</div>
</el-form>
</el-col>
<el-col :span="14">
<div class="title">{{ $t('load_test.pressure_prediction_chart') }}</div>
<ms-chart class="chart-container" :options="threadGroup.options" :autoresize="true"></ms-chart>
</el-col>
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</el-col>
<el-col :span="12">
<div class="title">{{ $t('load_test.pressure_prediction_chart') }}</div>
<ms-chart class="chart-container" ref="chart1" :options="options" :autoresize="true"></ms-chart>
</el-col>
</el-row>
</div>
</template>
@ -303,8 +315,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();
}
@ -639,18 +649,33 @@ export default {
border-bottom: 1px solid #DCDFE6;
}
/deep/ .el-collapse-item__content{
padding-left: 10px;
padding-bottom: 5px;
border-left-width: 8px;
border-left-style: solid;
border-left-color: #F5F7FA;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.chart-container {
width: 100%;
height: 300px;
}
.el-form-item {
margin-top: 5px;
margin-bottom: 5px;
}
.el-col .el-form {
margin-top: 15px;
margin-top: 5px;
text-align: left;
}
.el-col {
margin-top: 15px;
margin-top: 5px;
text-align: left;
}

View File

@ -110,7 +110,7 @@ export default {
this.testCaseForm.projectId = this.projectId;
this.testCaseForm.type = "";
this.testCaseForm.priority = "P0";
if (this.currentModule && this.currentModule !== 0) {
if (this.currentModule && this.currentModule !== 0 && this.currentModule.path && this.currentModule.path !== 0) {
this.testCaseForm.nodePath = this.currentModule.path;
this.testCaseForm.nodeId = this.currentModule.id;
} else {
@ -118,7 +118,7 @@ export default {
this.testCaseForm.nodeId = "root"
}
this.result = this.$post(path, this.testCaseForm, response => {
this.testCaseForm.id=response.data.id
this.testCaseForm.id = response.data.id
this.$success(this.$t('commons.save_success'));
this.visible = false;
if (saveAs) {

View File

@ -34,7 +34,8 @@
</el-col>
<el-col :span="6">
<div class="square">
<relevance-case-card :relevance-count-data="relevanceCountData" class="track-card" @redirectPage="redirectPage"/>
<relevance-case-card :relevance-count-data="relevanceCountData" class="track-card"
@redirectPage="redirectPage"/>
</div>
</el-col>
<el-col :span="12">
@ -140,8 +141,8 @@ export default {
xAxis.push(d.xAxis);
}
});
let yAxis1 = data.filter(d => d.groupName === 'FUNCTIONCASE').map(d => d.yAxis);
let yAxis2 = data.filter(d => d.groupName === 'RELEVANCECASE').map(d => d.yAxis);
let yAxis1 = data.filter(d => d.groupName === 'FUNCTIONCASE').map(d => [d.xAxis, d.yAxis]);
let yAxis2 = data.filter(d => d.groupName === 'RELEVANCECASE').map(d => [d.xAxis, d.yAxis]);
let option = {
tooltip: {
trigger: 'axis',
@ -190,10 +191,10 @@ export default {
};
this.caseOption = option;
},
redirectPage(page,dataType,selectType){
redirectPage(page, dataType, selectType) {
//test_plan
// this.$router.push('/track/plan/view/'+selectType);
switch (page){
switch (page) {
case "case":
this.$router.push({
name:'testCase',

View File

@ -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",

View File

@ -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文件",

View File

@ -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文件",