feat: 接口定义针对 TCP 请求增加 ESB 子类型(X-Pack)
接口定义针对 TCP 请求增加 ESB 子类型(X-Pack)
This commit is contained in:
parent
a1d4e965d0
commit
72f9e143c5
|
@ -233,6 +233,4 @@ public class ApiDefinitionController {
|
|||
public String preview(@RequestBody String jsonSchema) {
|
||||
return JSONSchemaGenerator.getJson(jsonSchema);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* //ESB数据格式
|
||||
*
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/15 4:37 下午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class EsbDataStruct {
|
||||
private String name;
|
||||
private String value;
|
||||
private String type;
|
||||
private String systemName;
|
||||
private String contentType;
|
||||
private String required;
|
||||
private String description;
|
||||
private List<EsbDataStruct> children;
|
||||
|
||||
public EsbDataStruct copy(boolean copyChildren) {
|
||||
EsbDataStruct returnObj = new EsbDataStruct();
|
||||
returnObj.name = this.name;
|
||||
returnObj.value = this.value;
|
||||
returnObj.type = this.type;
|
||||
returnObj.systemName = this.systemName;
|
||||
returnObj.contentType = this.contentType;
|
||||
returnObj.required = this.required;
|
||||
returnObj.description = this.description;
|
||||
if (copyChildren) {
|
||||
returnObj.children = this.children;
|
||||
} else {
|
||||
returnObj.children = new ArrayList<>();
|
||||
}
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
public Element genXmlElementByChildren(Element document) {
|
||||
this.name = this.name.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
.replace("\"", """).replace("©", "'");
|
||||
if (StringUtils.isEmpty(this.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Element element = null;
|
||||
try {
|
||||
element = document.addElement(this.name);
|
||||
if (StringUtils.equalsAnyIgnoreCase(type, "string", "array")) {
|
||||
long lengthNum = Long.parseLong(this.contentType);
|
||||
String attrString = "";
|
||||
if (StringUtils.equalsIgnoreCase(this.type, "string")) {
|
||||
attrString = "s," + contentType;
|
||||
} else if (StringUtils.equalsIgnoreCase(this.type, "array")) {
|
||||
attrString = "a," + contentType;
|
||||
}
|
||||
element.addAttribute("attr", attrString);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(this.name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
if (this.children == null || this.children.isEmpty()) {
|
||||
element.addText(this.value);
|
||||
} else {
|
||||
for (EsbDataStruct child : children) {
|
||||
child.genXmlElementByChildren(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public Element genXmlElementByDocument(Document document) {
|
||||
this.name = this.name.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
.replace("\"", """).replace("©", "'");
|
||||
if (StringUtils.isEmpty(this.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Element element = null;
|
||||
try {
|
||||
element = document.addElement(this.name);
|
||||
if (StringUtils.equalsAnyIgnoreCase(type, "string", "array")) {
|
||||
long lengthNum = Long.parseLong(this.contentType);
|
||||
String attrString = "";
|
||||
if (StringUtils.equalsIgnoreCase(this.type, "string")) {
|
||||
attrString = "s," + contentType;
|
||||
} else if (StringUtils.equalsIgnoreCase(this.type, "array")) {
|
||||
attrString = "a," + contentType;
|
||||
}
|
||||
element.addAttribute("attr", attrString);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(this.name);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
if (this.children == null || this.children.isEmpty()) {
|
||||
element.addText(this.value);
|
||||
} else {
|
||||
for (EsbDataStruct child : children) {
|
||||
child.genXmlElementByChildren(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/17 11:41 上午
|
||||
* @Description
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class GenEsbSendReportRequest {
|
||||
String frontScript;
|
||||
List<EsbDataStruct> structList;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package io.metersphere.api.dto.automation.parse;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import io.metersphere.api.dto.automation.EsbDataStruct;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/15 5:00 下午
|
||||
* @Description
|
||||
*/
|
||||
public class EsbDataParser {
|
||||
public static String esbData2XmlByParamStruct(List<EsbDataStruct> esbDataList, String[] paramArr) {
|
||||
String xmlString = "";
|
||||
try {
|
||||
if (esbDataList == null || esbDataList.isEmpty()) {
|
||||
return xmlString;
|
||||
}
|
||||
// 创建解析器工厂
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = factory.newDocumentBuilder();
|
||||
Document document = DocumentHelper.createDocument();
|
||||
EsbDataStruct dataStruct = selectEsbDataStructByNameStruct(esbDataList, paramArr, 0);
|
||||
if (dataStruct != null) {
|
||||
dataStruct.genXmlElementByDocument(document);
|
||||
xmlString = document.getRootElement().asXML();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (StringUtils.isEmpty(xmlString)) {
|
||||
xmlString = "";
|
||||
}
|
||||
return xmlString;
|
||||
}
|
||||
|
||||
//根据参数结构,递归查询数据
|
||||
private static EsbDataStruct selectEsbDataStructByNameStruct(List<EsbDataStruct> esbDataList, String[] paramArr, int index) {
|
||||
EsbDataStruct returnData = null;
|
||||
if (paramArr.length > index) {
|
||||
String param = paramArr[index];
|
||||
for (EsbDataStruct dataStuct : esbDataList) {
|
||||
if (StringUtils.equals(dataStuct.getName(), param)) {
|
||||
int newIndex = index + 1;
|
||||
if (paramArr.length > newIndex && dataStuct.getChildren() != null) {
|
||||
EsbDataStruct childElement = selectEsbDataStructByNameStruct(dataStuct.getChildren(), paramArr, newIndex);
|
||||
if (childElement != null) {
|
||||
returnData = dataStuct.copy(false);
|
||||
returnData.getChildren().add(childElement);
|
||||
}
|
||||
} else {
|
||||
returnData = dataStuct.copy(true);
|
||||
}
|
||||
}else if(index == 0){
|
||||
//如果是第一个节点不符合,则遍历子节点是否有符合的。
|
||||
int newIndex = index;
|
||||
EsbDataStruct itemData = selectEsbDataStructByNameStruct(dataStuct.getChildren(), paramArr, newIndex);
|
||||
if(itemData != null ){
|
||||
returnData = itemData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String str = "[{\"systemName\":\"\",\"children\":[{\"systemName\":\"\",\"children\":[{\"systemName\":\"\",\"children\":[],\"name\":\"CardNo\",\"description\":\"\",\"type\":\"string\",\"contentType\":\"30\",\"uuid\":\"295f4\",\"value\":\"627713288321\",\"required\":true,\"status\":\"\"},{\"name\":\"AccoutNo\",\"systemName\":\"\",\"status\":\"\",\"type\":\"string\",\"contentType\":\"6\",\"required\":false,\"description\":\"\",\"uuid\":\"3e8ef\",\"children\":[],\"value\":\"371421321\"}],\"name\":\"HEAD\",\"description\":\"\",\"type\":\"[object]\",\"contentType\":\"\",\"uuid\":\"55483\",\"required\":false,\"status\":\"\"},{\"name\":\"Body\",\"systemName\":\"\",\"status\":\"\",\"type\":\"[object]\",\"contentType\":\"\",\"required\":false,\"description\":\"\",\"uuid\":\"a088b\",\"children\":[{\"name\":\"returnFlag\",\"systemName\":\"\",\"status\":\"\",\"type\":\"string\",\"contentType\":\"2\",\"required\":false,\"description\":\"\",\"uuid\":\"76d75\",\"children\":[],\"value\":\"1\"}]}],\"name\":\"SERVICE\",\"description\":\"\",\"type\":\"[object]\",\"contentType\":\"\",\"uuid\":\"faf95\",\"required\":false,\"status\":\"\"}]";
|
||||
List<EsbDataStruct> list = JSONArray.parseArray(str, EsbDataStruct.class);
|
||||
String[] paramArr = new String[]{"HEAD"};
|
||||
System.out.println(esbData2XmlByParamStruct(list, paramArr));
|
||||
|
||||
paramArr = new String[]{"SERVICE"};
|
||||
System.out.println(esbData2XmlByParamStruct(list, paramArr));
|
||||
|
||||
paramArr = new String[]{"Body"};
|
||||
System.out.println(esbData2XmlByParamStruct(list, paramArr));
|
||||
|
||||
paramArr = new String[]{"SERVICE","Body"};
|
||||
System.out.println(esbData2XmlByParamStruct(list, paramArr));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -49,4 +49,9 @@ public class SaveApiDefinitionRequest {
|
|||
private List<String> bodyUploadIds;
|
||||
|
||||
private String tags;
|
||||
|
||||
//ESB参数。 可为null
|
||||
private String esbDataStruct;
|
||||
private String backEsbDataStruct;
|
||||
private String backScript;
|
||||
}
|
||||
|
|
|
@ -37,4 +37,8 @@ public class SaveApiTestCaseRequest {
|
|||
private List<String> bodyUploadIds;
|
||||
|
||||
private String tags;
|
||||
|
||||
//ESB参数。 可为null
|
||||
private String esbDataStruct;
|
||||
private String backEsbDataStruct;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ public class ApiDefinitionService {
|
|||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
@Resource
|
||||
private ApiTestEnvironmentService environmentService;
|
||||
@Resource
|
||||
private EsbApiParamService esbApiParamService;
|
||||
|
||||
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
|
||||
|
||||
|
@ -162,12 +164,14 @@ public class ApiDefinitionService {
|
|||
deleteFileByTestId(apiId);
|
||||
extApiDefinitionExecResultMapper.deleteByResourceId(apiId);
|
||||
apiDefinitionMapper.deleteByPrimaryKey(apiId);
|
||||
esbApiParamService.deleteByResourceId(apiId);
|
||||
deleteBodyFiles(apiId);
|
||||
}
|
||||
|
||||
public void deleteBatch(List<String> apiIds) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(apiIds);
|
||||
esbApiParamService.deleteByResourceIdIn(apiIds);
|
||||
apiDefinitionMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
|
@ -229,6 +233,10 @@ public class ApiDefinitionService {
|
|||
|
||||
private ApiDefinition updateTest(SaveApiDefinitionRequest request) {
|
||||
checkNameExist(request);
|
||||
if(StringUtils.equals(request.getMethod(),"ESB")){
|
||||
//ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据
|
||||
request = esbApiParamService.handleEsbRequest(request);
|
||||
}
|
||||
final ApiDefinitionWithBLOBs test = new ApiDefinitionWithBLOBs();
|
||||
test.setId(request.getId());
|
||||
test.setName(request.getName());
|
||||
|
@ -254,6 +262,10 @@ public class ApiDefinitionService {
|
|||
|
||||
private ApiDefinition createTest(SaveApiDefinitionRequest request) {
|
||||
checkNameExist(request);
|
||||
if(StringUtils.equals(request.getMethod(),"ESB")){
|
||||
//ESB的接口类型数据,采用TCP方式去发送。并将方法类型改为TCP。 并修改发送数据
|
||||
request = esbApiParamService.handleEsbRequest(request);
|
||||
}
|
||||
final ApiDefinitionWithBLOBs test = new ApiDefinitionWithBLOBs();
|
||||
test.setId(request.getId());
|
||||
test.setName(request.getName());
|
||||
|
@ -710,6 +722,10 @@ public class ApiDefinitionService {
|
|||
res.setCasePassingRate("-");
|
||||
res.setCaseStatus("-");
|
||||
}
|
||||
|
||||
if(StringUtils.equals("ESB",res.getMethod())){
|
||||
esbApiParamService.handleApiEsbParams(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,12 +75,19 @@ public class ApiTestCaseService {
|
|||
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
||||
@Resource
|
||||
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||
@Resource
|
||||
private EsbApiParamService esbApiParamService;
|
||||
|
||||
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
|
||||
|
||||
public List<ApiTestCaseResult> list(ApiTestCaseRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extApiTestCaseMapper.list(request);
|
||||
List<ApiTestCaseResult> returnList = extApiTestCaseMapper.list(request);
|
||||
|
||||
for (ApiTestCaseResult res : returnList) {
|
||||
esbApiParamService.handleApiEsbParams(res);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public List<ApiTestCaseDTO> listSimple(ApiTestCaseRequest request) {
|
||||
|
@ -169,6 +176,7 @@ public class ApiTestCaseService {
|
|||
deleteFileByTestId(testId);
|
||||
extApiDefinitionExecResultMapper.deleteByResourceId(testId);
|
||||
apiTestCaseMapper.deleteByPrimaryKey(testId);
|
||||
esbApiParamService.deleteByResourceId(testId);
|
||||
deleteBodyFiles(testId);
|
||||
}
|
||||
|
||||
|
@ -219,6 +227,11 @@ public class ApiTestCaseService {
|
|||
|
||||
private ApiTestCase updateTest(SaveApiTestCaseRequest request) {
|
||||
checkNameExist(request);
|
||||
|
||||
if(StringUtils.isNotEmpty(request.getEsbDataStruct())){
|
||||
request = esbApiParamService.handleEsbRequest(request);
|
||||
}
|
||||
|
||||
final ApiTestCaseWithBLOBs test = new ApiTestCaseWithBLOBs();
|
||||
test.setId(request.getId());
|
||||
test.setName(request.getName());
|
||||
|
@ -237,6 +250,11 @@ public class ApiTestCaseService {
|
|||
private ApiTestCase createTest(SaveApiTestCaseRequest request) {
|
||||
request.setId(UUID.randomUUID().toString());
|
||||
checkNameExist(request);
|
||||
|
||||
if(StringUtils.isNotEmpty(request.getEsbDataStruct())||StringUtils.isNotEmpty(request.getBackEsbDataStruct())){
|
||||
request = esbApiParamService.handleEsbRequest(request);
|
||||
}
|
||||
|
||||
final ApiTestCaseWithBLOBs test = new ApiTestCaseWithBLOBs();
|
||||
test.setId(request.getId());
|
||||
test.setName(request.getName());
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.automation.EsbDataStruct;
|
||||
import io.metersphere.api.dto.automation.parse.EsbDataParser;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseResult;
|
||||
import io.metersphere.api.dto.definition.SaveApiDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.SaveApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.base.domain.EsbApiParamsExample;
|
||||
import io.metersphere.base.domain.EsbApiParamsWithBLOBs;
|
||||
import io.metersphere.base.mapper.EsbApiParamsMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author song.tianyang
|
||||
* @Date 2021/3/16 4:57 下午
|
||||
* @Description
|
||||
*/
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class EsbApiParamService {
|
||||
@Resource
|
||||
private EsbApiParamsMapper esbApiParamsMapper;
|
||||
|
||||
public EsbApiParamsWithBLOBs createEsbApiParam(String resourceId, String esbDataStruct, String backedEsbDataStrcut, String backedScript) {
|
||||
EsbApiParamsWithBLOBs model = null;
|
||||
|
||||
EsbApiParamsExample example = new EsbApiParamsExample();
|
||||
example.createCriteria().andResourceIdEqualTo(resourceId);
|
||||
List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example);
|
||||
|
||||
if (list.isEmpty()) {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
model = new EsbApiParamsWithBLOBs();
|
||||
model.setId(uuid);
|
||||
model.setResourceId(resourceId);
|
||||
model.setDataStruct(esbDataStruct);
|
||||
model.setResponseDataStruct(backedEsbDataStrcut);
|
||||
model.setBackedScript(backedScript);
|
||||
esbApiParamsMapper.insert(model);
|
||||
} else {
|
||||
model = list.get(0);
|
||||
model.setDataStruct(esbDataStruct);
|
||||
model.setResponseDataStruct(backedEsbDataStrcut);
|
||||
model.setBackedScript(backedScript);
|
||||
esbApiParamsMapper.updateByPrimaryKeyWithBLOBs(model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
public List<KeyValue> genKeyValueByEsbDataStruct(List<EsbDataStruct> dataStructRequestList, String prefix) {
|
||||
List<KeyValue> returnList = new ArrayList<>();
|
||||
for (EsbDataStruct request : dataStructRequestList) {
|
||||
String itemName = request.getName();
|
||||
if (StringUtils.isNotEmpty(prefix)) {
|
||||
itemName = prefix + "." + itemName;
|
||||
}
|
||||
KeyValue kv = new KeyValue();
|
||||
kv.setName(itemName);
|
||||
kv.setValue(request.getValue());
|
||||
kv.setType(request.getType());
|
||||
kv.setDescription(request.getDescription());
|
||||
kv.setContentType(request.getContentType());
|
||||
kv.setRequired(Boolean.parseBoolean(request.getRequired()));
|
||||
returnList.add(kv);
|
||||
if (request.getChildren() != null) {
|
||||
List<KeyValue> childValueList = this.genKeyValueByEsbDataStruct(request.getChildren(), itemName);
|
||||
if (!childValueList.isEmpty()) {
|
||||
returnList.addAll(childValueList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public EsbApiParamsWithBLOBs getEsbParamBLOBsByResourceID(String resourceId) {
|
||||
EsbApiParamsExample example = new EsbApiParamsExample();
|
||||
example.createCriteria().andResourceIdEqualTo(resourceId);
|
||||
|
||||
String returnStr = null;
|
||||
List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example);
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return list.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteByResourceId(String resourceId) {
|
||||
EsbApiParamsExample example = new EsbApiParamsExample();
|
||||
example.createCriteria().andResourceIdEqualTo(resourceId);
|
||||
esbApiParamsMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
public void handleApiEsbParams(ApiDefinitionResult res) {
|
||||
EsbApiParamsWithBLOBs esbParamBlobs = this.getEsbParamBLOBsByResourceID(res.getId());
|
||||
if (esbParamBlobs == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(res.getRequest())) {
|
||||
JSONObject jsonObj = JSONObject.parseObject(res.getRequest());
|
||||
|
||||
JSONArray esbDataArray = JSONArray.parseArray(esbParamBlobs.getDataStruct());
|
||||
jsonObj.put("esbDataStruct", esbDataArray);
|
||||
|
||||
JSONArray responseDataArray = JSONArray.parseArray(esbParamBlobs.getResponseDataStruct());
|
||||
jsonObj.put("backEsbDataStruct", responseDataArray);
|
||||
|
||||
JSONObject backedScriptObj = JSONObject.parseObject(esbParamBlobs.getBackedScript());
|
||||
jsonObj.put("backScript", backedScriptObj);
|
||||
|
||||
jsonObj.put("esbFrontedScript", esbParamBlobs.getFrontedScript());
|
||||
|
||||
res.setRequest(jsonObj.toJSONString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleApiEsbParams(ApiTestCaseResult res) {
|
||||
EsbApiParamsWithBLOBs esbParamBlobs = this.getEsbParamBLOBsByResourceID(res.getId());
|
||||
if (esbParamBlobs == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(res.getRequest())) {
|
||||
JSONObject jsonObj = JSONObject.parseObject(res.getRequest());
|
||||
JSONArray esbDataArray = JSONArray.parseArray(esbParamBlobs.getDataStruct());
|
||||
jsonObj.put("esbDataStruct", esbDataArray);
|
||||
jsonObj.put("esbFrontedScript", esbParamBlobs.getFrontedScript());
|
||||
|
||||
JSONArray responseDataArray = JSONArray.parseArray(esbParamBlobs.getResponseDataStruct());
|
||||
jsonObj.put("backEsbDataStruct", responseDataArray);
|
||||
|
||||
res.setRequest(jsonObj.toJSONString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public SaveApiDefinitionRequest handleEsbRequest(SaveApiDefinitionRequest request) {
|
||||
try {
|
||||
//修改reqeust.parameters
|
||||
//用户交互感受:ESB的发送数据以报文模板为主框架,同时前端不再有key-value的表格数据填充。
|
||||
//业务逻辑: 发送ESB接口数据时,使用报文模板中的数据,同时报文模板中的${取值}目的是为了拼接数据结构(比如xml的子节点)
|
||||
//代码实现: 此处打算解析前端传来的EsbDataStruct数据结构,将数据结构按照报文模板中的${取值}为最高优先级组装keyValue对象。这样Jmeter会自动拼装为合适的xml
|
||||
if (StringUtils.isNotEmpty(request.getEsbDataStruct())) {
|
||||
MsTCPSampler tcpSampler = (MsTCPSampler) request.getRequest();
|
||||
List<KeyValue> keyValueList = this.genKeyValueListByDataStruct(tcpSampler, request.getEsbDataStruct());
|
||||
tcpSampler.setParameters(keyValueList);
|
||||
}
|
||||
|
||||
//更新EsbApiParams类
|
||||
EsbApiParamsWithBLOBs esbApiParams = this.createEsbApiParam(request.getId(), request.getEsbDataStruct(), request.getBackEsbDataStruct(), request.getBackScript());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
//通过esb数据结构生成keyValue集合,以及发送参数
|
||||
private List<KeyValue> genKeyValueListByDataStruct(MsTCPSampler tcpSampler, String esbDataStruct) {
|
||||
List<KeyValue> keyValueList = new ArrayList<>();
|
||||
String sendRequest = tcpSampler.getRequest();
|
||||
String paramRegexStr = "\\$\\{([^}]*)\\}";
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(sendRequest)) {
|
||||
List<String> paramList = new ArrayList<>();
|
||||
List<EsbDataStruct> dataStructRequestList = JSONArray.parseArray(esbDataStruct, EsbDataStruct.class);
|
||||
Pattern regex = Pattern.compile(paramRegexStr);
|
||||
Matcher matcher = regex.matcher(sendRequest);
|
||||
while (matcher.find()) {
|
||||
paramList.add(matcher.group(1));
|
||||
}
|
||||
for (String param : paramList) {
|
||||
String value = this.genValueFromEsbDataStructByParam(dataStructRequestList, param);
|
||||
if (StringUtils.isNotEmpty(value)) {
|
||||
KeyValue kv = new KeyValue();
|
||||
kv.setName(param);
|
||||
kv.setValue(value);
|
||||
kv.setRequired(true);
|
||||
keyValueList.add(kv);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return keyValueList;
|
||||
}
|
||||
|
||||
//通过报文模版中的变量参数,解析报文数据结构,生成对应的xml数据
|
||||
private String genValueFromEsbDataStructByParam(List<EsbDataStruct> dataStructRequestList, String param) {
|
||||
String returnValue = "";
|
||||
if (StringUtils.isNotEmpty(param)) {
|
||||
//多层结构使用"."来表示。aaa.bb.cc 代表的是dataStructRequestList中,aaa节点下,bb节点下的cc节点数据
|
||||
String[] paramArr = param.split("\\.");
|
||||
returnValue = EsbDataParser.esbData2XmlByParamStruct(dataStructRequestList, paramArr);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public SaveApiTestCaseRequest handleEsbRequest(SaveApiTestCaseRequest request) {
|
||||
try {
|
||||
//修改reqeust.parameters, 将树结构类型数据转化为表格类型数据,供执行时参数的提取
|
||||
if (StringUtils.isNotEmpty(request.getEsbDataStruct())) {
|
||||
MsTCPSampler tcpSampler = (MsTCPSampler) request.getRequest();
|
||||
List<KeyValue> keyValueList = this.genKeyValueListByDataStruct(tcpSampler, request.getEsbDataStruct());
|
||||
tcpSampler.setParameters(keyValueList);
|
||||
}
|
||||
//更新EsbApiParams类
|
||||
EsbApiParamsWithBLOBs esbApiParams = this.createEsbApiParam(request.getId(), request.getEsbDataStruct(), request.getBackEsbDataStruct(), request.getBackEsbDataStruct());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public void deleteByResourceIdIn(List<String> apiIds) {
|
||||
EsbApiParamsExample example = new EsbApiParamsExample();
|
||||
example.createCriteria().andResourceIdIn(apiIds);
|
||||
esbApiParamsMapper.deleteByExample(example);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EsbApiParams implements Serializable {
|
||||
private String id;
|
||||
|
||||
private String resourceId;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EsbApiParamsExample {
|
||||
protected String orderByClause;
|
||||
|
||||
protected boolean distinct;
|
||||
|
||||
protected List<Criteria> oredCriteria;
|
||||
|
||||
public EsbApiParamsExample() {
|
||||
oredCriteria = new ArrayList<Criteria>();
|
||||
}
|
||||
|
||||
public void setOrderByClause(String orderByClause) {
|
||||
this.orderByClause = orderByClause;
|
||||
}
|
||||
|
||||
public String getOrderByClause() {
|
||||
return orderByClause;
|
||||
}
|
||||
|
||||
public void setDistinct(boolean distinct) {
|
||||
this.distinct = distinct;
|
||||
}
|
||||
|
||||
public boolean isDistinct() {
|
||||
return distinct;
|
||||
}
|
||||
|
||||
public List<Criteria> getOredCriteria() {
|
||||
return oredCriteria;
|
||||
}
|
||||
|
||||
public void or(Criteria criteria) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
|
||||
public Criteria or() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
oredCriteria.add(criteria);
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public Criteria createCriteria() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
if (oredCriteria.size() == 0) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected Criteria createCriteriaInternal() {
|
||||
Criteria criteria = new Criteria();
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
oredCriteria.clear();
|
||||
orderByClause = null;
|
||||
distinct = false;
|
||||
}
|
||||
|
||||
protected abstract static class GeneratedCriteria {
|
||||
protected List<Criterion> criteria;
|
||||
|
||||
protected GeneratedCriteria() {
|
||||
super();
|
||||
criteria = new ArrayList<Criterion>();
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return criteria.size() > 0;
|
||||
}
|
||||
|
||||
public List<Criterion> getAllCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public List<Criterion> getCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition) {
|
||||
if (condition == null) {
|
||||
throw new RuntimeException("Value for condition cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value, String property) {
|
||||
if (value == null) {
|
||||
throw new RuntimeException("Value for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value1, Object value2, String property) {
|
||||
if (value1 == null || value2 == null) {
|
||||
throw new RuntimeException("Between values for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value1, value2));
|
||||
}
|
||||
|
||||
public Criteria andIdIsNull() {
|
||||
addCriterion("id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdIsNotNull() {
|
||||
addCriterion("id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdEqualTo(String value) {
|
||||
addCriterion("id =", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotEqualTo(String value) {
|
||||
addCriterion("id <>", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdGreaterThan(String value) {
|
||||
addCriterion("id >", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("id >=", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLessThan(String value) {
|
||||
addCriterion("id <", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("id <=", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdLike(String value) {
|
||||
addCriterion("id like", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotLike(String value) {
|
||||
addCriterion("id not like", value, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdIn(List<String> values) {
|
||||
addCriterion("id in", values, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotIn(List<String> values) {
|
||||
addCriterion("id not in", values, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdBetween(String value1, String value2) {
|
||||
addCriterion("id between", value1, value2, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIdNotBetween(String value1, String value2) {
|
||||
addCriterion("id not between", value1, value2, "id");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdIsNull() {
|
||||
addCriterion("resource_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdIsNotNull() {
|
||||
addCriterion("resource_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdEqualTo(String value) {
|
||||
addCriterion("resource_id =", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdNotEqualTo(String value) {
|
||||
addCriterion("resource_id <>", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdGreaterThan(String value) {
|
||||
addCriterion("resource_id >", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("resource_id >=", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdLessThan(String value) {
|
||||
addCriterion("resource_id <", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("resource_id <=", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdLike(String value) {
|
||||
addCriterion("resource_id like", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdNotLike(String value) {
|
||||
addCriterion("resource_id not like", value, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdIn(List<String> values) {
|
||||
addCriterion("resource_id in", values, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdNotIn(List<String> values) {
|
||||
addCriterion("resource_id not in", values, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdBetween(String value1, String value2) {
|
||||
addCriterion("resource_id between", value1, value2, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceIdNotBetween(String value1, String value2) {
|
||||
addCriterion("resource_id not between", value1, value2, "resourceId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
||||
protected Criteria() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criterion {
|
||||
private String condition;
|
||||
|
||||
private Object value;
|
||||
|
||||
private Object secondValue;
|
||||
|
||||
private boolean noValue;
|
||||
|
||||
private boolean singleValue;
|
||||
|
||||
private boolean betweenValue;
|
||||
|
||||
private boolean listValue;
|
||||
|
||||
private String typeHandler;
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getSecondValue() {
|
||||
return secondValue;
|
||||
}
|
||||
|
||||
public boolean isNoValue() {
|
||||
return noValue;
|
||||
}
|
||||
|
||||
public boolean isSingleValue() {
|
||||
return singleValue;
|
||||
}
|
||||
|
||||
public boolean isBetweenValue() {
|
||||
return betweenValue;
|
||||
}
|
||||
|
||||
public boolean isListValue() {
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public String getTypeHandler() {
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
protected Criterion(String condition) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.typeHandler = null;
|
||||
this.noValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.typeHandler = typeHandler;
|
||||
if (value instanceof List<?>) {
|
||||
this.listValue = true;
|
||||
} else {
|
||||
this.singleValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value) {
|
||||
this(condition, value, null);
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.secondValue = secondValue;
|
||||
this.typeHandler = typeHandler;
|
||||
this.betweenValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue) {
|
||||
this(condition, value, secondValue, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class EsbApiParamsWithBLOBs extends EsbApiParams implements Serializable {
|
||||
private String dataStruct;
|
||||
|
||||
private String frontedScript;
|
||||
|
||||
private String responseDataStruct;
|
||||
|
||||
private String backedScript;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package io.metersphere.base.mapper;
|
||||
|
||||
import io.metersphere.base.domain.EsbApiParams;
|
||||
import io.metersphere.base.domain.EsbApiParamsExample;
|
||||
import io.metersphere.base.domain.EsbApiParamsWithBLOBs;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface EsbApiParamsMapper {
|
||||
long countByExample(EsbApiParamsExample example);
|
||||
|
||||
int deleteByExample(EsbApiParamsExample example);
|
||||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(EsbApiParamsWithBLOBs record);
|
||||
|
||||
int insertSelective(EsbApiParamsWithBLOBs record);
|
||||
|
||||
List<EsbApiParamsWithBLOBs> selectByExampleWithBLOBs(EsbApiParamsExample example);
|
||||
|
||||
List<EsbApiParams> selectByExample(EsbApiParamsExample example);
|
||||
|
||||
EsbApiParamsWithBLOBs selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") EsbApiParamsWithBLOBs record, @Param("example") EsbApiParamsExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") EsbApiParamsWithBLOBs record, @Param("example") EsbApiParamsExample example);
|
||||
|
||||
int updateByExample(@Param("record") EsbApiParams record, @Param("example") EsbApiParamsExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(EsbApiParamsWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(EsbApiParamsWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKey(EsbApiParams record);
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.base.mapper.EsbApiParamsMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.EsbApiParams">
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.EsbApiParamsWithBLOBs">
|
||||
<result column="data_struct" jdbcType="LONGVARCHAR" property="dataStruct" />
|
||||
<result column="fronted_script" jdbcType="LONGVARCHAR" property="frontedScript" />
|
||||
<result column="response_data_struct" jdbcType="LONGVARCHAR" property="responseDataStruct" />
|
||||
<result column="backed_script" jdbcType="LONGVARCHAR" property="backedScript" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="example.oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, resource_id
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
data_struct, fronted_script, response_data_struct, backed_script
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.EsbApiParamsExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from esb_api_params
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.EsbApiParamsExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from esb_api_params
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from esb_api_params
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
|
||||
delete from esb_api_params
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.EsbApiParamsExample">
|
||||
delete from esb_api_params
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.EsbApiParamsWithBLOBs">
|
||||
insert into esb_api_params (id, resource_id, data_struct,
|
||||
fronted_script, response_data_struct,
|
||||
backed_script)
|
||||
values (#{id,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, #{dataStruct,jdbcType=LONGVARCHAR},
|
||||
#{frontedScript,jdbcType=LONGVARCHAR}, #{responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
#{backedScript,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.EsbApiParamsWithBLOBs">
|
||||
insert into esb_api_params
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
id,
|
||||
</if>
|
||||
<if test="resourceId != null">
|
||||
resource_id,
|
||||
</if>
|
||||
<if test="dataStruct != null">
|
||||
data_struct,
|
||||
</if>
|
||||
<if test="frontedScript != null">
|
||||
fronted_script,
|
||||
</if>
|
||||
<if test="responseDataStruct != null">
|
||||
response_data_struct,
|
||||
</if>
|
||||
<if test="backedScript != null">
|
||||
backed_script,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
#{id,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="resourceId != null">
|
||||
#{resourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="dataStruct != null">
|
||||
#{dataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="frontedScript != null">
|
||||
#{frontedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="responseDataStruct != null">
|
||||
#{responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="backedScript != null">
|
||||
#{backedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.EsbApiParamsExample" resultType="java.lang.Long">
|
||||
select count(*) from esb_api_params
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
update esb_api_params
|
||||
<set>
|
||||
<if test="record.id != null">
|
||||
id = #{record.id,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.resourceId != null">
|
||||
resource_id = #{record.resourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.dataStruct != null">
|
||||
data_struct = #{record.dataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.frontedScript != null">
|
||||
fronted_script = #{record.frontedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.responseDataStruct != null">
|
||||
response_data_struct = #{record.responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.backedScript != null">
|
||||
backed_script = #{record.backedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||
update esb_api_params
|
||||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
resource_id = #{record.resourceId,jdbcType=VARCHAR},
|
||||
data_struct = #{record.dataStruct,jdbcType=LONGVARCHAR},
|
||||
fronted_script = #{record.frontedScript,jdbcType=LONGVARCHAR},
|
||||
response_data_struct = #{record.responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
backed_script = #{record.backedScript,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update esb_api_params
|
||||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
resource_id = #{record.resourceId,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.EsbApiParamsWithBLOBs">
|
||||
update esb_api_params
|
||||
<set>
|
||||
<if test="resourceId != null">
|
||||
resource_id = #{resourceId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="dataStruct != null">
|
||||
data_struct = #{dataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="frontedScript != null">
|
||||
fronted_script = #{frontedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="responseDataStruct != null">
|
||||
response_data_struct = #{responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="backedScript != null">
|
||||
backed_script = #{backedScript,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.EsbApiParamsWithBLOBs">
|
||||
update esb_api_params
|
||||
set resource_id = #{resourceId,jdbcType=VARCHAR},
|
||||
data_struct = #{dataStruct,jdbcType=LONGVARCHAR},
|
||||
fronted_script = #{frontedScript,jdbcType=LONGVARCHAR},
|
||||
response_data_struct = #{responseDataStruct,jdbcType=LONGVARCHAR},
|
||||
backed_script = #{backedScript,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.EsbApiParams">
|
||||
update esb_api_params
|
||||
set resource_id = #{resourceId,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -42,7 +42,7 @@ public class ShiroUtils {
|
|||
|
||||
//api-对外文档页面提供的查询接口
|
||||
filterChainDefinitionMap.put("/api/document/**", "anon");
|
||||
// filterChainDefinitionMap.put("/document/**", "anon");
|
||||
filterChainDefinitionMap.put("/document/**", "anon");
|
||||
filterChainDefinitionMap.put("/system/theme", "anon");
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import org.apache.shiro.web.util.WebUtils;
|
|||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ApiKeyFilter extends AnonymousFilter {
|
||||
|
@ -16,15 +15,6 @@ public class ApiKeyFilter extends AnonymousFilter {
|
|||
@Override
|
||||
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||
try {
|
||||
// try{
|
||||
// //这部分代码是为了测试打包完成之后能否访问文档相关路径,封版之前要删除
|
||||
// HttpServletRequest httpServlet = WebUtils.toHttp(request);
|
||||
// String url = httpServlet.getRequestURL().toString();
|
||||
// LogUtil.info("Url message : "+url);
|
||||
// }catch (Exception e){
|
||||
//
|
||||
// }
|
||||
|
||||
if (!SecurityUtils.getSubject().isAuthenticated()) {
|
||||
String userId = ApiKeyHandler.getUser(WebUtils.toHttp(request));
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
|
|
|
@ -159,6 +159,19 @@ UPDATE file_metadata JOIN (SELECT file_id, project_id
|
|||
FROM api_test_file
|
||||
JOIN api_test ON test_id = api_test.id) temp ON file_id = file_metadata.id
|
||||
SET file_metadata.project_id = temp.project_id;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `esb_api_params`
|
||||
(
|
||||
id varchar(50) not null,
|
||||
resource_id varchar(50),
|
||||
data_struct LONGTEXT null,
|
||||
fronted_script LONGTEXT null,
|
||||
response_data_struct LONGTEXT null,
|
||||
backed_script LONGTEXT null,
|
||||
primary key (id),
|
||||
UNIQUE KEY `resource_id` ( `resource_id` )
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4;
|
||||
-- add execution_times testPlan
|
||||
alter table test_plan
|
||||
add execution_times int null;
|
|
@ -125,7 +125,7 @@
|
|||
'$route'(to, from) { // 路由改变时,把接口定义界面中的 ctrl s 保存快捷键监听移除
|
||||
if (to.path.indexOf('/api/automation') == -1) {
|
||||
if (this.$refs && this.$refs.autoScenarioConfig) {
|
||||
console.log(this.$refs.autoScenarioConfig);
|
||||
// console.log(this.$refs.autoScenarioConfig);
|
||||
this.$refs.autoScenarioConfig.forEach(item => {
|
||||
item.removeListener();
|
||||
});
|
||||
|
|
|
@ -50,6 +50,16 @@
|
|||
title: this.$t('api_test.request.processor.code_template_get_global_variable'),
|
||||
value: 'props.get("variable_name")',
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_add_report_length'),
|
||||
value: 'String report = ctx.getCurrentSampler().getRequestData();\n' +
|
||||
'if(report!=null){\n' +
|
||||
' //补足8位长度,前置补0\n' +
|
||||
' String reportlengthStr = String.format("%08d",report.length());\n' +
|
||||
' report = reportlengthStr+report;\n' +
|
||||
' ctx.getCurrentSampler().setRequestData(report);\n' +
|
||||
'}',
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_template_set_global_variable'),
|
||||
value: 'props.put("variable_name", "variable_value")',
|
||||
|
@ -68,6 +78,20 @@
|
|||
title: this.$t('api_test.request.processor.code_template_get_response_result'),
|
||||
value: 'prev.getResponseDataAsString()',
|
||||
disabled: this.isPreProcessor
|
||||
},
|
||||
{
|
||||
title: this.$t('api_test.request.processor.code_hide_report_length'),
|
||||
value: '//Get response data\n' +
|
||||
'String returnData = prev.getResponseDataAsString();\n' +
|
||||
'if(returnData!=null&&returnData.length()>8){\n' +
|
||||
'//remove 8 report length \n' +
|
||||
' String subStringData = returnData.substring(8,returnData.length());\n' +
|
||||
' if(subStringData.startsWith("<")){\n' +
|
||||
' returnData = subStringData;\n' +
|
||||
' prev.setResponseData(returnData);\n' +
|
||||
' }\n' +
|
||||
'}',
|
||||
disabled: this.isPreProcessor
|
||||
}
|
||||
],
|
||||
isCodeEditAlive: true,
|
||||
|
|
|
@ -87,13 +87,19 @@
|
|||
<div v-if="apiCase.active||type==='detail'">
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
<ms-api-request-form :isShowEnable="true" :showScript="true" :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
|
||||
<ms-tcp-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='TCP'"/>
|
||||
<ms-tcp-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.method==='TCP' && apiCase.request.esbDataStruct == null"/>
|
||||
<esb-definition v-xpack :request="apiCase.request" :showScript="true" v-if="showXpackCompnent&&api.method==='ESB'" ref="esbDefinition"/>
|
||||
<ms-sql-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='SQL'"/>
|
||||
<ms-dubbo-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
|
||||
|
||||
<!-- HTTP 请求返回数据 -->
|
||||
<p class="tip">{{$t('api_test.definition.request.res_param')}}</p>
|
||||
<div v-if="showXpackCompnent&&api.method==='ESB'">
|
||||
<esb-definition-response :currentProtocol="apiCase.request.protocol" :request="apiCase.request" :is-api-component="false" :show-options-button="false" :show-header="true" :api-item="apiCase"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<api-response-component :currentProtocol="apiCase.request.protocol" :api-item="apiCase"/>
|
||||
</div>
|
||||
|
||||
<ms-jmx-step :request="apiCase.request" :response="apiCase.responseData"/>
|
||||
<!-- 保存操作 -->
|
||||
|
@ -123,6 +129,9 @@
|
|||
import MsJmxStep from "../step/JmxStep";
|
||||
import ApiResponseComponent from "../../../automation/scenario/component/ApiResponseComponent";
|
||||
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apiDefinition/EsbDefinition.vue") : {};
|
||||
const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apiDefinition/EsbDefinitionResponse.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "ApiCaseItem",
|
||||
|
@ -140,12 +149,15 @@
|
|||
MsApiExtendBtns,
|
||||
MsRequestResultTail,
|
||||
MsJmxStep,
|
||||
ShowMoreBtn
|
||||
ShowMoreBtn,
|
||||
"esbDefinition": esbDefinition.default,
|
||||
"esbDefinitionResponse": esbDefinitionResponse.default
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
grades: [],
|
||||
showXpackCompnent:false,
|
||||
isReadOnly: false,
|
||||
selectedEvent: Object,
|
||||
priorities: PRIORITY,
|
||||
|
@ -185,6 +197,11 @@
|
|||
type: String,
|
||||
isCaseEdit: Boolean,
|
||||
},
|
||||
created() {
|
||||
if (requireComponent != null && JSON.stringify(esbDefinition) != '{}'&& JSON.stringify(esbDefinitionResponse) != '{}') {
|
||||
this.showXpackCompnent = true;
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
handleRunBatch() {
|
||||
|
@ -297,6 +314,14 @@
|
|||
tmp.request.method = this.api.method;
|
||||
}
|
||||
}
|
||||
|
||||
if(tmp.request.esbDataStruct != null){
|
||||
tmp.esbDataStruct = JSON.stringify(tmp.request.esbDataStruct);
|
||||
}
|
||||
if(tmp.request.backEsbDataStruct != null){
|
||||
tmp.backEsbDataStruct = JSON.stringify(tmp.request.backEsbDataStruct);
|
||||
}
|
||||
|
||||
if (tmp.tags instanceof Array) {
|
||||
tmp.tags = JSON.stringify(tmp.tags);
|
||||
}
|
||||
|
|
|
@ -260,6 +260,9 @@
|
|||
if (!request.hashTree) {
|
||||
request.hashTree = [];
|
||||
}
|
||||
if(request.backScript != null){
|
||||
request.hashTree.push(request.backScript);
|
||||
}
|
||||
let uuid = getUUID();
|
||||
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: [], uuid: uuid};
|
||||
obj.request = request;
|
||||
|
|
|
@ -15,26 +15,39 @@
|
|||
<br/>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<ms-basis-api @createRootModelInTree="createRootModelInTree" :moduleOptions="moduleOptions" :basisData="basisData" ref="basicForm"
|
||||
@callback="callback"/>
|
||||
<ms-tcp-basic-api :method-types="methodTypes" @createRootModelInTree="createRootModelInTree" :moduleOptions="moduleOptions" :basisData="basisData" ref="basicForm"
|
||||
@changeApiProtocol="changeApiProtocol" @callback="callback"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 请求参数 -->
|
||||
<div v-if="apiProtocol=='TCP'">
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
<ms-basis-parameters :show-script="false" :request="request"/>
|
||||
</div>
|
||||
<div v-else-if="apiProtocol=='ESB'">
|
||||
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
|
||||
<esb-definition v-xpack v-if="showXpackCompnent" :show-script="false" :request="request" ref="esbDefinition"/>
|
||||
<p class="tip">{{$t('api_test.definition.request.res_param')}}</p>
|
||||
<esb-definition-response :is-api-component="true" :show-options-button="true" :request="request" />
|
||||
<!-- <api-response-component :currentProtocol="apiCase.request.protocol" :api-item="apiCase"/>-->
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsBasisApi from "./BasisApi";
|
||||
import MsTcpBasicApi from "./TCPBasicApi";
|
||||
import MsBasisParameters from "../request/tcp/TcpBasisParameters";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const esbDefinition = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apiDefinition/EsbDefinition.vue") : {};
|
||||
const esbDefinitionResponse = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./apiDefinition/EsbDefinitionResponse.vue") : {};
|
||||
export default {
|
||||
name: "MsAddCompleteTcpApi",
|
||||
components: {MsBasisApi, MsBasisParameters},
|
||||
components: {MsTcpBasicApi, MsBasisParameters,
|
||||
"esbDefinition": esbDefinition.default,
|
||||
"esbDefinitionResponse": esbDefinitionResponse.default},
|
||||
props: {
|
||||
request: {},
|
||||
basisData: {},
|
||||
|
@ -48,6 +61,24 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
validated: false,
|
||||
apiProtocol: "TCP",
|
||||
methodTypes:["TCP"],
|
||||
showXpackCompnent:false,
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if(this.basisData.method != 'TCP'&& this.basisData.method != 'ESB'){
|
||||
this.basisData.method = this.basisData.protocol;
|
||||
}
|
||||
this.apiProtocol = this.basisData.method;
|
||||
if(this.apiProtocol == null || this.apiProtocol == "" ){
|
||||
this.apiProtocol = "TCP";
|
||||
}
|
||||
if (requireComponent != null && JSON.stringify(esbDefinition) != '{}'&& JSON.stringify(esbDefinitionResponse) != '{}') {
|
||||
this.showXpackCompnent = true;
|
||||
if(this.methodTypes.length == 1){
|
||||
this.methodTypes.push("ESB");
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -68,7 +99,7 @@ export default {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
callback() {
|
||||
|
@ -76,7 +107,7 @@ export default {
|
|||
},
|
||||
validateApi() {
|
||||
this.validated = false;
|
||||
this.basisData.method = "TCP";
|
||||
this.basisData.method = this.apiProtocol;
|
||||
this.$refs['basicForm'].validate();
|
||||
},
|
||||
saveApi() {
|
||||
|
@ -84,6 +115,24 @@ export default {
|
|||
if (this.validated) {
|
||||
if (this.basisData.tags instanceof Array) {
|
||||
this.basisData.tags = JSON.stringify(this.basisData.tags);
|
||||
}
|
||||
if(this.basisData.method == 'ESB'){
|
||||
let validataResult = this.$refs.esbDefinition.validateEsbDataStruct(this.request.esbDataStruct);
|
||||
if(!validataResult){
|
||||
return;
|
||||
}
|
||||
if(this.request.esbDataStruct != null){
|
||||
this.esbDataStruct = JSON.stringify(this.request.esbDataStruct);
|
||||
this.basisData.esbDataStruct = this.esbDataStruct;
|
||||
}
|
||||
if(this.request.backEsbDataStruct != null){
|
||||
this.basisData.backEsbDataStruct = JSON.stringify(this.request.backEsbDataStruct);
|
||||
}
|
||||
if(this.request.backScript != null){
|
||||
this.basisData.backScript = JSON.stringify(this.request.backScript);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
this.$emit('saveApi', this.basisData);
|
||||
}
|
||||
|
@ -101,6 +150,9 @@ export default {
|
|||
createRootModelInTree() {
|
||||
this.$emit("createRootModelInTree");
|
||||
},
|
||||
changeApiProtocol(protocol){
|
||||
this.apiProtocol = protocol;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-form :model="basicForm" label-position="right" label-width="80px" size="small" :rules="rule" ref="basicForm" style="margin-right: 20px">
|
||||
<!-- 基础信息 -->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.name')" prop="name">
|
||||
<!-- <el-input class="ms-http-input" size="small" v-model="basicForm.name"/>-->
|
||||
<el-input v-model="basicForm.name" class="ms-http-input" size="small">
|
||||
<el-select v-model="basicForm.method" slot="prepend" style="width: 100px" size="small" @change="methodChange">
|
||||
<el-option v-for="item in methodTypes" :key="item" :label="item" :value="item"/>
|
||||
</el-select>
|
||||
</el-input>
|
||||
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('test_track.module.module')" prop="moduleId">
|
||||
<el-select class="ms-http-input" size="small" v-model="basicForm.moduleId" style="width: 100%" @change="reload">
|
||||
<div v-if="moduleOptions.length>0">
|
||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-option :key="0" :value="''">
|
||||
<div style="margin-left: 40px">
|
||||
<span style="font-size: 14px;color: #606266;font-weight: 48.93">{{ $t('api_test.definition.select_comp.no_data') }},
|
||||
</span>
|
||||
<el-link type="primary" @click="createModules">{{ $t('api_test.definition.select_comp.add_data') }}</el-link>
|
||||
</div>
|
||||
</el-option>
|
||||
</div>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.status')" prop="status">
|
||||
<el-select class="ms-http-input" size="small" v-model="basicForm.status" style="width: 100%">
|
||||
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.definition.request.responsible')" prop="userId">
|
||||
<el-select v-model="basicForm.userId"
|
||||
:placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
|
||||
class="ms-http-input" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in maintainerOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.tag')" prop="tag">
|
||||
<ms-input-tag :currentScenario="basicForm" ref="tag"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.description')" prop="description">
|
||||
<el-input class="ms-http-textarea"
|
||||
v-model="basicForm.description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 10}"
|
||||
:rows="2" size="small"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {API_STATUS} from "../../model/JsonData";
|
||||
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
|
||||
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
|
||||
|
||||
export default {
|
||||
name: "MsTcpBasicApi",
|
||||
components: {MsInputTag},
|
||||
props: {
|
||||
currentProtocol: {
|
||||
type: String,
|
||||
default: "HTTP"
|
||||
},
|
||||
moduleOptions: Array,
|
||||
methodTypes: Array,
|
||||
basisData: {},
|
||||
},
|
||||
created() {
|
||||
this.getMaintainerOptions();
|
||||
this.basicForm = this.basisData;
|
||||
if(this.basicForm.protocol == null){
|
||||
this.basicForm.protocol = "TCP";
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
basicForm: {},
|
||||
httpVisible: false,
|
||||
currentModule: {},
|
||||
maintainerOptions: [],
|
||||
loading: false,
|
||||
rule: {
|
||||
name: [
|
||||
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
|
||||
{max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
|
||||
],
|
||||
userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
|
||||
moduleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
|
||||
status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
|
||||
},
|
||||
value: API_STATUS[0].id,
|
||||
options: API_STATUS,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||
this.maintainerOptions = response.data;
|
||||
});
|
||||
},
|
||||
reload() {
|
||||
this.loading = true
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
validate() {
|
||||
this.$refs['basicForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit('callback');
|
||||
}
|
||||
})
|
||||
},
|
||||
createModules() {
|
||||
this.$emit("createRootModelInTree");
|
||||
},
|
||||
methodChange() {
|
||||
this.$emit("changeApiProtocol",this.basicForm.method);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -1,119 +0,0 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="wrapper">
|
||||
<div class="section" style="width:80%;margin-left: 8px" v-for="(item, index) in list" :key="index">
|
||||
<div class="border" style="width:100%;height:200px;font-size:30px;text-align:center;color:black;">
|
||||
<el-divider><i class="el-icon-mobile-phone">111</i></el-divider>
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nac" style="height:500px;"></div>
|
||||
<nav style="position:fixed;right:30px;top:100px;">
|
||||
<span class="nav1 hand" v-for="(item, index) in navList" :key="index" @click="jump(index)"
|
||||
:class="index==0?'current':''">{{item}}</span>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
name:"MsAnchor",
|
||||
data() {
|
||||
return {
|
||||
scroll: '',
|
||||
list: [{
|
||||
name: "第一条wwwwwwww",
|
||||
backgroundcolor: "#90B2A3"
|
||||
}, {
|
||||
name: "第二条eeeeeeee",
|
||||
backgroundcolor: "#A593B2"
|
||||
}, {
|
||||
name: "第三条",
|
||||
backgroundcolor: "#A7B293"
|
||||
}, {
|
||||
name: "第四条",
|
||||
backgroundcolor: "#0F2798"
|
||||
}, {
|
||||
name: "第五条",
|
||||
backgroundcolor: "#0A464D"
|
||||
}],
|
||||
navList: [11111111, 2111111111111, 31111, 4111111, 5111111111]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dataScroll: function () {
|
||||
this.scroll = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
},
|
||||
jump(index) {
|
||||
let jump = document.getElementsByClassName('section');
|
||||
// 获取需要滚动的距离
|
||||
let total = jump[index].offsetTop;
|
||||
// Chrome
|
||||
document.body.scrollTop = total;
|
||||
// Firefox
|
||||
document.documentElement.scrollTop = total;
|
||||
// Safari
|
||||
window.pageYOffset = total;
|
||||
// $('html, body').animate({
|
||||
// 'scrollTop': total
|
||||
// }, 400);
|
||||
},
|
||||
loadSroll: function () {
|
||||
// var self = this;
|
||||
// var $navs = $(".nav1");
|
||||
// var sections = document.getElementsByClassName('section');
|
||||
// for (var i = sections.length - 1; i >= 0; i--) {
|
||||
// if (self.scroll >= sections[i].offsetTop - 100) {
|
||||
// $navs.eq(i).addClass("current").siblings().removeClass("current")
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scroll: function () {
|
||||
this.loadSroll()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('scroll', this.dataScroll);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav1 {
|
||||
display: block;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.navs1 .active {
|
||||
color: #847ec3;
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.hand {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.current {
|
||||
color: #fff;
|
||||
background: #847ec3;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1px solid #eee;
|
||||
border-top: 0
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,734 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-container>
|
||||
<el-main style="padding-top: 0px;padding-bottom: 0px">
|
||||
<el-row style="margin-top: 10px">
|
||||
<el-select size="small" :placeholder="$t('api_test.definition.document.order')" v-model="apiSearch.orderCondition" style="float: right;width: 180px;margin-right: 5px"
|
||||
class="ms-api-header-select" @change="initApiDocSimpleList" clearable>
|
||||
<el-option key="createTimeDesc" :label="$t('api_test.definition.document.create_time_sort')" value="createTimeDesc" />
|
||||
<el-option key="editTimeAsc" :label="$t('api_test.definition.document.edit_time_positive_sequence')" value="editTimeAsc"/>
|
||||
<el-option key="editTimeDesc" :label="$t('api_test.definition.document.edit_time_Reverse_order')" value="editTimeDesc"/>
|
||||
</el-select>
|
||||
|
||||
<el-select size="small" :placeholder="$t('api_test.definition.document.request_method')" v-model="apiSearch.type" style="float: right;width: 180px;margin-right: 5px"
|
||||
class="ms-api-header-select" @change="initApiDocSimpleList" clearable>
|
||||
<el-option key="ALL" :label="$t('api_test.definition.document.data_set.all')" value="ALL"/>
|
||||
<el-option key="GET" :label="'GET '+$t('api_test.definition.document.request_interface')" value="GET"/>
|
||||
<el-option key="POST" :label="'POST '+$t('api_test.definition.document.request_interface')" value="POST"/>
|
||||
<el-option key="PUT" :label="'PUT '+$t('api_test.definition.document.request_interface')" value="PUT"/>
|
||||
<el-option key="DELETE" :label="'DELETE '+$t('api_test.definition.document.request_interface')" value="DELETE"/>
|
||||
<el-option key="PATCH" :label="'PATCH '+$t('api_test.definition.document.request_interface')" value="PATCH"/>
|
||||
<el-option key="OPTIONS" :label="'OPTIONS '+$t('api_test.definition.document.request_interface')" value="OPTIONS"/>
|
||||
<el-option key="HEAD" :label="'HEAD '+$t('api_test.definition.document.request_interface')" value="HEAD"/>
|
||||
<el-option key="CONNECT" :label="'CONNECT '+$t('api_test.definition.document.request_interface')" value="CONNECT"/>
|
||||
</el-select>
|
||||
<el-input :placeholder="$t('api_test.definition.document.search_by_api_name')" @blur="initApiDocSimpleList()" style="float: right;width: 180px;margin-right: 5px" size="small"
|
||||
@keyup.enter.native="initApiDocSimpleList()" v-model="apiSearch.name"/>
|
||||
<api-document-batch-share v-xpack v-if="showXpackCompnent" @shareApiDocument="shareApiDocument" :project-id="projectId" :share-url="batchShareUrl" style="float: right;margin: 6px;font-size: 17px"/>
|
||||
<!-- <api-document-batch-share v-xpack v-if="showXpackCompnent"/>-->
|
||||
</el-row>
|
||||
<el-divider></el-divider>
|
||||
<div ref="apiDocInfoDiv" @scroll="handleScroll" >
|
||||
<div v-for="(apiInfo) in apiInfoArray" :key="apiInfo.id" ref="apiDocInfoDivItem">
|
||||
<div style="font-size: 17px">
|
||||
<el-popover
|
||||
v-if="projectId"
|
||||
placement="right"
|
||||
width="260"
|
||||
@show="shareApiDocument('false')">
|
||||
<p>{{shareUrl}}</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button type="primary" size="mini"
|
||||
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }}</el-button>
|
||||
</div>
|
||||
<i class="el-icon-share" slot="reference" style="margin-right: 10px;cursor: pointer"></i>
|
||||
</el-popover>
|
||||
{{ apiInfo.name }}
|
||||
<span class="apiStatusTag">
|
||||
<api-status :value="apiInfo.status"/>
|
||||
</span>
|
||||
</div>
|
||||
<!--api请求信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">
|
||||
{{ $t('api_test.definition.document.request_info') }}
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="simpleFontClass">
|
||||
<el-tag size="medium"
|
||||
:style="{'background-color': getColor(true,apiInfo.method), border: getColor(true,apiInfo.method),borderRadius:'0px', marginRight:'20px',color:'white'}">
|
||||
{{ apiInfo.method }}
|
||||
</el-tag>
|
||||
{{ apiInfo.uri }}
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.request_head') }}:
|
||||
<div v-if="getJsonArr(apiInfo.requestHead).length==0">
|
||||
<div class="simpleFontClass" style="margin-top: 10px">
|
||||
{{ $t('api_test.definition.document.data_set.none') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.requestHead)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--URL参数-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
URL{{ $t('api_test.definition.document.request_param') }}:
|
||||
<div v-if="getJsonArr(apiInfo.urlParams).length==0">
|
||||
<div class="simpleFontClass" style="margin-top: 10px">
|
||||
{{ $t('api_test.definition.document.data_set.none') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border
|
||||
:data="getJsonArr(apiInfo.urlParams)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="isEnable"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求体 以及表格-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.request_body') }}
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
{{ $t('api_test.definition.document.table_coloum.type') }}:{{ apiInfo.requestBodyParamType }}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="formParamTypes.includes(apiInfo.requestBodyParamType)"
|
||||
:data="getJsonArr(apiInfo.requestBodyFormData)" row-key="name"
|
||||
class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
:label="$t('api_test.definition.document.table_coloum.type')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="required"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
:formatter="formatBoolean"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.default_value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
<div v-else-if="apiInfo.requestBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
||||
<ms-json-code-edit :body="apiInfo.jsonSchemaBody" ref="jsonCodeEdit"/>
|
||||
</div>
|
||||
<div v-else class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="formatRowData(apiInfo.requestBodyParamType,apiInfo.requestBodyStrutureData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--范例展示-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.example_presentation') }}
|
||||
</div>
|
||||
<div class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="genPreviewData(apiInfo.requestPreviewData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">
|
||||
{{ $t('api_test.definition.document.response_info') }}
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
|
||||
</el-row>
|
||||
<!--响应头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_head') }}:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseHead)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应体-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_body') }}
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
{{ $t('api_test.definition.document.table_coloum.type') }}:{{ apiInfo.responseBodyParamType }}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="formParamTypes.includes(apiInfo.responseBodyParamType)"
|
||||
:data="getJsonArr(apiInfo.responseBodyFormData)" row-key="id"
|
||||
class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
:label="$t('api_test.definition.document.table_coloum.type')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="required"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
:formatter="formatBoolean"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.default_value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
<div v-else class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="formatRowData(apiInfo.responseBodyParamType,apiInfo.responseBodyStrutureData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应状态码-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_code') }}:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseCode)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
<!-- 右侧列表 -->
|
||||
<el-aside width="200px" style="margin-top: 70px;">
|
||||
<div ref="apiDocList" >
|
||||
<el-steps style="height: 40%" direction="vertical" :active="apiStepIndex">
|
||||
<el-step v-for="(apiInfo) in apiInfoArray" :key="apiInfo.id" @click.native="clickStep(apiInfo.id)">
|
||||
<el-link slot="title">{{ apiInfo.name }}</el-link>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {API_METHOD_COLOUR} from "@/business/components/api/definition/model/JsonData";
|
||||
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
|
||||
import {formatJson,} from "@/common/js/format-utils";
|
||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
import {calculate} from "@/business/components/api/definition/model/ApiTestModel";
|
||||
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
|
||||
import Api from "@/business/components/api/router";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const apiDocumentBatchShare = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./share/ApiDocumentBatchShare.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "ApiDocumentItem",
|
||||
components: {
|
||||
Api,
|
||||
MsJsonCodeEdit,
|
||||
ApiStatus, MsCodeEdit,
|
||||
"ApiDocumentBatchShare": apiDocumentBatchShare.default
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shareUrl:"",
|
||||
batchShareUrl:"",
|
||||
apiStepIndex: 0,
|
||||
showXpackCompnent:false,
|
||||
apiShowArray: [],
|
||||
apiInfoArray: [],
|
||||
modes: ['text', 'json', 'xml', 'html'],
|
||||
formParamTypes: ['form-data', 'x-www-from-urlencoded', 'BINARY'],
|
||||
mockVariableFuncs: [],
|
||||
apiSearch:{
|
||||
name:"",
|
||||
type:"ALL",
|
||||
orderCondition:"createTimeDesc",
|
||||
},
|
||||
apiInfoBaseObj: {
|
||||
selectedFlag:false,
|
||||
method: "无",
|
||||
uri: "无",
|
||||
name: "无",
|
||||
id: "",
|
||||
requestHead: "无",
|
||||
urlParams: "无",
|
||||
requestBodyParamType: "无",
|
||||
requestBodyFormData: '[]',
|
||||
requestBodyStrutureData: "",
|
||||
sharePopoverVisible:false,
|
||||
jsonSchemaBody: {},
|
||||
responseHead: "无",
|
||||
responseBody: "",
|
||||
responseBodyParamType: "无",
|
||||
responseBodyFormData: "无",
|
||||
responseBodyStrutureData: "无",
|
||||
responseCode: "无",
|
||||
},
|
||||
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||
clientHeight: '',//坚挺浏览器高度
|
||||
}
|
||||
},
|
||||
props: {
|
||||
projectId: String,
|
||||
documentId: String,
|
||||
moduleIds: Array,
|
||||
pageHeaderHeight:Number,
|
||||
},
|
||||
activated() {
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if(requireComponent!=null && JSON.stringify(apiDocumentBatchShare) != '{}'){
|
||||
this.showXpackCompnent = true;
|
||||
}
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
};
|
||||
window.addEventListener('scroll',that.handleScroll);
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
that.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
that.changeFixed(that.clientHeight);
|
||||
};
|
||||
// 监听滚动事件,然后用handleScroll这个方法进行相应的处理
|
||||
window.addEventListener('scroll',this.handleScroll);
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
moduleIds() {
|
||||
this.initApiDocSimpleList();
|
||||
},
|
||||
clientHeight() { //如果clientHeight 发生改变,这个函数就会运行
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatRowData(dataType, data) {
|
||||
var returnData = data;
|
||||
if (data) {
|
||||
returnData = data.replace(/\n/g, '<br>');
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
changeFixed(clientHeight) {
|
||||
if (this.$refs.apiDocInfoDiv) {
|
||||
let countPageHeight = 350;
|
||||
if(this.pageHeaderHeight!=0 && this.pageHeaderHeight != null){
|
||||
countPageHeight = this.pageHeaderHeight
|
||||
}
|
||||
|
||||
this.$refs.apiDocInfoDiv.style.height = clientHeight - countPageHeight + 'px';
|
||||
this.$refs.apiDocInfoDiv.style.overflow = 'auto';
|
||||
this.$refs.apiDocList.style.height = clientHeight - countPageHeight + 'px';
|
||||
}
|
||||
},
|
||||
initApiDocSimpleList() {
|
||||
let simpleRequest = this.apiSearch;
|
||||
if (this.projectId != null && this.projectId != "") {
|
||||
simpleRequest.projectId = this.projectId;
|
||||
}
|
||||
if (this.documentId != null && this.documentId != "") {
|
||||
simpleRequest.shareId = this.documentId;
|
||||
}
|
||||
if (this.moduleIds.length > 0) {
|
||||
simpleRequest.moduleIds = this.moduleIds;
|
||||
}
|
||||
|
||||
let simpleInfoUrl = "/document/selectApiSimpleInfo";
|
||||
this.apiInfoArray = [];
|
||||
this.$post(simpleInfoUrl, simpleRequest, response => {
|
||||
this.apiInfoArray = response.data;
|
||||
this.apiStepIndex = 0;
|
||||
if(response.data.length > 7){
|
||||
this.apiShowArray = [
|
||||
response.data[0],
|
||||
response.data[1],
|
||||
response.data[2],
|
||||
response.data[3],
|
||||
response.data[4],
|
||||
response.data[5],
|
||||
response.data[6],
|
||||
];
|
||||
}else{
|
||||
this.apiShowArray = response.data;
|
||||
}
|
||||
if (this.apiInfoArray.length > 0) {
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
}
|
||||
});
|
||||
},
|
||||
shareApiDocument(isBatchShare){
|
||||
let thisHost = window.location.host;
|
||||
this.shareUrl = "";
|
||||
this.batchShareUrl = "";
|
||||
let shareIdArr = [];
|
||||
let shareType = "Single";
|
||||
if(isBatchShare == 'true'){
|
||||
this.apiInfoArray.forEach(f => {
|
||||
if (!f.id) {
|
||||
return;
|
||||
}
|
||||
shareIdArr.push(f.id);
|
||||
});
|
||||
shareType = "Batch";
|
||||
}else{
|
||||
shareIdArr.push(this.apiInfoArray[this.apiStepIndex].id);
|
||||
}
|
||||
let genShareInfoParam = {};
|
||||
genShareInfoParam.shareApiIdList = shareIdArr;
|
||||
genShareInfoParam.shareType = shareType;
|
||||
|
||||
this.$post("/document/generateApiDocumentShareInfo", genShareInfoParam, res => {
|
||||
if(shareType == "Batch"){
|
||||
this.batchShareUrl = thisHost+"/document"+res.data.shareUrl;
|
||||
}else{
|
||||
this.shareUrl = thisHost+"/document"+res.data.shareUrl;
|
||||
}
|
||||
}, (error) => {
|
||||
});
|
||||
},
|
||||
selectApiInfo(index,apiId) {
|
||||
let simpleInfoUrl = "/document/selectApiInfoById/" + apiId;
|
||||
this.$get(simpleInfoUrl, response => {
|
||||
let returnData = response.data;
|
||||
this.$set(this.apiInfoArray,index,returnData);
|
||||
});
|
||||
},
|
||||
clickStep(apiId) {
|
||||
for (let index = 0; index < this.apiInfoArray.length; index++) {
|
||||
if (apiId == this.apiInfoArray[index].id) {
|
||||
this.apiStepIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//检查数据
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
//进行跳转
|
||||
this.redirectScroll(this.apiStepIndex);
|
||||
},
|
||||
stepClick(stepIndex) {
|
||||
this.apiStepIndex = stepIndex;
|
||||
},
|
||||
getColor(enable, method) {
|
||||
return this.methodColorMap.get(method);
|
||||
},
|
||||
formatBoolean(row, column, cellValue) {
|
||||
var ret = '' //你想在页面展示的值
|
||||
if (cellValue) {
|
||||
ret = "是" //根据自己的需求设定
|
||||
} else {
|
||||
ret = "否"
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getJsonArr(jsonString) {
|
||||
let returnJsonArr = [];
|
||||
if (jsonString == '无' || jsonString == null) {
|
||||
return returnJsonArr;
|
||||
}
|
||||
|
||||
let jsonArr = JSON.parse(jsonString);
|
||||
//遍历,把必填项空的数据去掉
|
||||
for (var index = 0; index < jsonArr.length; index++) {
|
||||
var item = jsonArr[index];
|
||||
if (item.name != "" && item.name != null) {
|
||||
returnJsonArr.push(item);
|
||||
}
|
||||
}
|
||||
return returnJsonArr;
|
||||
},
|
||||
//构建预览数据
|
||||
genPreviewData(previewData) {
|
||||
if (previewData != null && previewData != '') {
|
||||
let showDataObj = {};
|
||||
for (var key in previewData) {
|
||||
// showDataObj.set(key,previewData[key]);
|
||||
let value = previewData[key];
|
||||
if(typeof(value)=='string'){
|
||||
if (value.indexOf("@") >= 0) {
|
||||
value = this.showPreview(value);
|
||||
}
|
||||
}
|
||||
showDataObj[key] = value;
|
||||
}
|
||||
showDataObj = JSON.stringify(showDataObj);
|
||||
previewData = formatJson(showDataObj);
|
||||
}
|
||||
return previewData;
|
||||
},
|
||||
showPreview(itemValue) {
|
||||
// 找到变量本身
|
||||
if (!itemValue) {
|
||||
return;
|
||||
}
|
||||
let index = itemValue.indexOf("|");
|
||||
if (index > -1) {
|
||||
itemValue = itemValue.substring(0, index).trim();
|
||||
}
|
||||
|
||||
this.mockVariableFuncs.forEach(f => {
|
||||
if (!f.name) {
|
||||
return;
|
||||
}
|
||||
itemValue += "|" + f.name;
|
||||
if (f.params) {
|
||||
itemValue += ":" + f.params.map(p => p.value).join(",");
|
||||
}
|
||||
});
|
||||
|
||||
itemValue = calculate(itemValue);
|
||||
return itemValue;
|
||||
},
|
||||
onCopySuccess: function (e) {
|
||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('commons.copy_success'),
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
onCopyError: function (e) {
|
||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||
}
|
||||
this.$message.error(this.$t('api_report.error'));
|
||||
},
|
||||
handleScroll(){
|
||||
|
||||
//apiDocInfoDiv的总高度,是(每个item的高度+20)数量
|
||||
let apiDocDivScrollTop = this.$refs.apiDocInfoDiv.scrollTop;
|
||||
let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
||||
|
||||
let scrolledHeigh = apiDocDivScrollTop+apiDocDivClientTop;
|
||||
let lastIndex = 0;
|
||||
for (let index = 0; index < this.apiInfoArray.length; index++) {
|
||||
//判断移动到了第几个元素. 公式: 移动过的高度+页面显示高度-第index子元素的高度(含20px)>0 的 index最大值
|
||||
if(scrolledHeigh>0){
|
||||
lastIndex = index;
|
||||
let itemHeight = this.$refs.apiDocInfoDivItem[index].offsetHeight+20;
|
||||
scrolledHeigh = scrolledHeigh - itemHeight;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.apiStepIndex = lastIndex;
|
||||
//检查上下文 3个以内的节点有没有查询出来
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
},
|
||||
redirectScroll(itemIndex){
|
||||
//滚动条跳转:将滚动条下拉到显示对应对api接口的位置
|
||||
// let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
||||
let apiDocDivClientTop = 0;
|
||||
let itemHeightCount = 0;
|
||||
for (let i = 0; i <= itemIndex-1; i++) {
|
||||
let itemHeight = this.$refs.apiDocInfoDivItem[i].offsetHeight+20;
|
||||
itemHeightCount+=itemHeight;
|
||||
}
|
||||
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop+itemHeightCount);
|
||||
},
|
||||
checkApiInfoNode(itemIndex){
|
||||
//检查要展示的api信息节点,和上下个3个及以内的范围内数据有没有查询过
|
||||
let beforeNodeIndex = itemIndex<3?0:(itemIndex-3);
|
||||
let afterNodeIndex = (itemIndex+3)<this.apiInfoArray.length?(itemIndex+3):this.apiInfoArray.length;
|
||||
|
||||
for(let beforeIndex = itemIndex;beforeIndex < afterNodeIndex;beforeIndex++){
|
||||
let apiInfo = this.apiInfoArray[beforeIndex];
|
||||
if(apiInfo==null){
|
||||
continue;
|
||||
}
|
||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
||||
let apiId = apiInfo.id;
|
||||
if(!apiInfo.isSearching){
|
||||
apiInfo.isSearching = true;
|
||||
this.selectApiInfo(beforeIndex,apiId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let afterIndex = beforeNodeIndex;afterIndex <itemIndex;afterIndex++){
|
||||
let apiInfo = this.apiInfoArray[afterIndex];
|
||||
if(apiInfo==null){
|
||||
continue;
|
||||
}
|
||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
||||
let apiId = apiInfo.id;
|
||||
if(!apiInfo.isSearching) {
|
||||
apiInfo.isSearching = true;
|
||||
this.selectApiInfo(afterIndex,apiId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.simpleFontClass {
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.blackFontClass {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.smallFontClass {
|
||||
font-size: 13px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
}
|
||||
|
||||
.apiInfoRow {
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.apiStatusTag {
|
||||
margin: 20px 5px;
|
||||
}
|
||||
|
||||
.showDataDiv {
|
||||
background-color: #F5F7F9;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
/*
|
||||
步骤条中,已经完成后的节点样式和里面a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-finish {
|
||||
color: #C0C4CC;
|
||||
border-color: #C0C4CC;
|
||||
}
|
||||
|
||||
/deep/ .el-step__title.is-finish /deep/ .el-link.el-link--default {
|
||||
color: #C0C4CC;
|
||||
}
|
||||
|
||||
/*
|
||||
步骤条中,当前节点样式和当前a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-process {
|
||||
color: #783887;
|
||||
border-color: #783887;
|
||||
}
|
||||
|
||||
/deep/ .el-step__title.is-process /deep/ .el-link.el-link--default {
|
||||
color: #783887;
|
||||
}
|
||||
|
||||
.document-table {
|
||||
margin: 20px 10px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.document-table /deep/ .el-table__row {
|
||||
font-size: 12px;
|
||||
font-weight: initial;
|
||||
}
|
||||
|
||||
.document-table /deep/ .has-gutter {
|
||||
font-size: 12px;
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
.document-table /deep/ td {
|
||||
border-right: 0px solid #EBEEF5
|
||||
}
|
||||
|
||||
.document-table /deep/ th {
|
||||
background-color: #FAFAFA;
|
||||
border-right: 0px solid #EBEEF5
|
||||
}
|
||||
.el-divider--horizontal {
|
||||
margin: 12px 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,720 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-container>
|
||||
<el-main style="padding-top: 0px;padding-bottom: 0px">
|
||||
<el-row style="margin-top: 10px">
|
||||
<el-select size="small" :placeholder="$t('api_test.definition.document.order')" v-model="apiSearch.orderCondition" style="float: right;width: 180px;margin-right: 5px"
|
||||
class="ms-api-header-select" @change="initApiDocSimpleList" clearable>
|
||||
<el-option key="createTimeDesc" :label="$t('api_test.definition.document.create_time_sort')" value="createTimeDesc" />
|
||||
<el-option key="editTimeAsc" :label="$t('api_test.definition.document.edit_time_positive_sequence')" value="editTimeAsc"/>
|
||||
<el-option key="editTimeDesc" :label="$t('api_test.definition.document.edit_time_Reverse_order')" value="editTimeDesc"/>
|
||||
</el-select>
|
||||
|
||||
<el-select size="small" :placeholder="$t('api_test.definition.document.request_method')" v-model="apiSearch.type" style="float: right;width: 180px;margin-right: 5px"
|
||||
class="ms-api-header-select" @change="initApiDocSimpleList" clearable>
|
||||
<el-option key="ALL" :label="$t('api_test.definition.document.data_set.all')" value="ALL"/>
|
||||
<el-option key="GET" :label="'GET '+$t('api_test.definition.document.request_interface')" value="GET"/>
|
||||
<el-option key="POST" :label="'POST '+$t('api_test.definition.document.request_interface')" value="POST"/>
|
||||
<el-option key="PUT" :label="'PUT '+$t('api_test.definition.document.request_interface')" value="PUT"/>
|
||||
<el-option key="DELETE" :label="'DELETE '+$t('api_test.definition.document.request_interface')" value="DELETE"/>
|
||||
<el-option key="PATCH" :label="'PATCH '+$t('api_test.definition.document.request_interface')" value="PATCH"/>
|
||||
<el-option key="OPTIONS" :label="'OPTIONS '+$t('api_test.definition.document.request_interface')" value="OPTIONS"/>
|
||||
<el-option key="HEAD" :label="'HEAD '+$t('api_test.definition.document.request_interface')" value="HEAD"/>
|
||||
<el-option key="CONNECT" :label="'CONNECT '+$t('api_test.definition.document.request_interface')" value="CONNECT"/>
|
||||
</el-select>
|
||||
<el-input :placeholder="$t('api_test.definition.document.search_by_api_name')" @blur="initApiDocSimpleList()" style="float: right;width: 180px;margin-right: 5px" size="small"
|
||||
@keyup.enter.native="initApiDocSimpleList()" v-model="apiSearch.name"/>
|
||||
<api-document-batch-share v-xpack v-if="showXpackCompnent" @shareApiDocument="shareApiDocument" :project-id="projectId" :share-url="batchShareUrl" style="float: right;margin: 6px;font-size: 17px"/>
|
||||
<!-- <api-document-batch-share v-xpack v-if="showXpackCompnent"/>-->
|
||||
</el-row>
|
||||
<el-divider></el-divider>
|
||||
<div ref="apiDocInfoDiv" @scroll="handleScroll" >
|
||||
<div v-for="(apiInfo) in apiInfoArray" :key="apiInfo.id" ref="apiDocInfoDivItem">
|
||||
<div style="font-size: 17px">
|
||||
<el-popover
|
||||
v-if="projectId"
|
||||
placement="right"
|
||||
width="260"
|
||||
@show="shareApiDocument('false')">
|
||||
<p>{{shareUrl}}</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button type="primary" size="mini"
|
||||
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }}</el-button>
|
||||
</div>
|
||||
<i class="el-icon-share" slot="reference" style="margin-right: 10px;cursor: pointer"></i>
|
||||
</el-popover>
|
||||
{{ apiInfo.name }}
|
||||
<span class="apiStatusTag">
|
||||
<api-status :value="apiInfo.status"/>
|
||||
</span>
|
||||
</div>
|
||||
<!--api请求信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">
|
||||
{{ $t('api_test.definition.document.request_info') }}
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="simpleFontClass">
|
||||
<el-tag size="medium"
|
||||
:style="{'background-color': getColor(true,apiInfo.method), border: getColor(true,apiInfo.method),borderRadius:'0px', marginRight:'20px',color:'white'}">
|
||||
{{ apiInfo.method }}
|
||||
</el-tag>
|
||||
{{ apiInfo.uri }}
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.request_head') }}:
|
||||
<div v-if="getJsonArr(apiInfo.requestHead).length==0">
|
||||
<div class="simpleFontClass" style="margin-top: 10px">
|
||||
{{ $t('api_test.definition.document.data_set.none') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.requestHead)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--URL参数-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
URL{{ $t('api_test.definition.document.request_param') }}:
|
||||
<div v-if="getJsonArr(apiInfo.urlParams).length==0">
|
||||
<div class="simpleFontClass" style="margin-top: 10px">
|
||||
{{ $t('api_test.definition.document.data_set.none') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table border
|
||||
:data="getJsonArr(apiInfo.urlParams)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="isEnable"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--api请求体 以及表格-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.request_body') }}
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
{{ $t('api_test.definition.document.table_coloum.type') }}:{{ apiInfo.requestBodyParamType }}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="formParamTypes.includes(apiInfo.requestBodyParamType)"
|
||||
:data="getJsonArr(apiInfo.requestBodyFormData)" row-key="name"
|
||||
class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
:label="$t('api_test.definition.document.table_coloum.type')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="required"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
:formatter="formatBoolean"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.default_value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
<div v-else-if="apiInfo.requestBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
||||
<ms-json-code-edit :body="apiInfo.jsonSchemaBody" ref="jsonCodeEdit"/>
|
||||
</div>
|
||||
<div v-else class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="formatRowData(apiInfo.requestBodyParamType,apiInfo.requestBodyStrutureData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--范例展示-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.example_presentation') }}
|
||||
</div>
|
||||
<div class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="genPreviewData(apiInfo.requestPreviewData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应信息-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="tip">
|
||||
{{ $t('api_test.definition.document.response_info') }}
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row class="apiInfoRow">
|
||||
|
||||
</el-row>
|
||||
<!--响应头-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_head') }}:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseHead)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应体-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_body') }}
|
||||
</div>
|
||||
<div class="smallFontClass">
|
||||
{{ $t('api_test.definition.document.table_coloum.type') }}:{{ apiInfo.responseBodyParamType }}
|
||||
</div>
|
||||
<div>
|
||||
<el-table border v-if="formParamTypes.includes(apiInfo.responseBodyParamType)"
|
||||
:data="getJsonArr(apiInfo.responseBodyFormData)" row-key="id"
|
||||
class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="contentType"
|
||||
:label="$t('api_test.definition.document.table_coloum.type')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="description"
|
||||
:label="$t('api_test.definition.document.table_coloum.desc')"
|
||||
min-width="280px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="required"
|
||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||
:formatter="formatBoolean"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.default_value')"
|
||||
min-width="120px"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
<div v-else class="showDataDiv">
|
||||
<br/>
|
||||
<p style="margin: 0px 20px;"
|
||||
v-html="formatRowData(apiInfo.responseBodyParamType,apiInfo.responseBodyStrutureData)">
|
||||
</p>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
<!--响应状态码-->
|
||||
<el-row class="apiInfoRow">
|
||||
<div class="blackFontClass">
|
||||
{{ $t('api_test.definition.document.response_code') }}:
|
||||
<el-table border :show-header="false"
|
||||
:data="getJsonArr(apiInfo.responseCode)" row-key="name" class="test-content document-table">
|
||||
<el-table-column prop="name"
|
||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="value"
|
||||
:label="$t('api_test.definition.document.table_coloum.value')"
|
||||
show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
<!-- 右侧列表 -->
|
||||
<el-aside width="200px" style="margin-top: 70px;">
|
||||
<div ref="apiDocList" >
|
||||
<el-steps style="height: 40%" direction="vertical" :active="apiStepIndex">
|
||||
<el-step v-for="(apiInfo) in apiInfoArray" :key="apiInfo.id" @click.native="clickStep(apiInfo.id)">
|
||||
<el-link slot="title">{{ apiInfo.name }}</el-link>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {API_METHOD_COLOUR} from "@/business/components/api/definition/model/JsonData";
|
||||
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
|
||||
import {formatJson,} from "@/common/js/format-utils";
|
||||
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
|
||||
import {calculate} from "@/business/components/api/definition/model/ApiTestModel";
|
||||
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
|
||||
import Api from "@/business/components/api/router";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const apiDocumentBatchShare = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./share/ApiDocumentBatchShare.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "ApiDocumentItem",
|
||||
components: {
|
||||
Api,
|
||||
MsJsonCodeEdit,
|
||||
ApiStatus, MsCodeEdit,
|
||||
"ApiDocumentBatchShare": apiDocumentBatchShare.default
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shareUrl:"",
|
||||
batchShareUrl:"",
|
||||
apiStepIndex: 0,
|
||||
showXpackCompnent:false,
|
||||
apiInfoArray: [],
|
||||
modes: ['text', 'json', 'xml', 'html'],
|
||||
formParamTypes: ['form-data', 'x-www-from-urlencoded', 'BINARY'],
|
||||
mockVariableFuncs: [],
|
||||
apiSearch:{
|
||||
name:"",
|
||||
type:"ALL",
|
||||
orderCondition:"createTimeDesc",
|
||||
},
|
||||
apiInfoBaseObj: {
|
||||
selectedFlag:false,
|
||||
method: "无",
|
||||
uri: "无",
|
||||
name: "无",
|
||||
id: "",
|
||||
requestHead: "无",
|
||||
urlParams: "无",
|
||||
requestBodyParamType: "无",
|
||||
requestBodyFormData: '[]',
|
||||
requestBodyStrutureData: "",
|
||||
sharePopoverVisible:false,
|
||||
jsonSchemaBody: {},
|
||||
responseHead: "无",
|
||||
responseBody: "",
|
||||
responseBodyParamType: "无",
|
||||
responseBodyFormData: "无",
|
||||
responseBodyStrutureData: "无",
|
||||
responseCode: "无",
|
||||
},
|
||||
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||
clientHeight: '',//坚挺浏览器高度
|
||||
}
|
||||
},
|
||||
props: {
|
||||
projectId: String,
|
||||
documentId: String,
|
||||
moduleIds: Array,
|
||||
pageHeaderHeight:Number,
|
||||
},
|
||||
activated() {
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if(requireComponent!=null && JSON.stringify(apiDocumentBatchShare) != '{}'){
|
||||
this.showXpackCompnent = true;
|
||||
}
|
||||
this.initApiDocSimpleList();
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;//获取浏览器可视区域高度
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
this.changeFixed(this.clientHeight);
|
||||
};
|
||||
window.addEventListener('scroll',that.handleScroll);
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
window.onresize = function () {
|
||||
that.clientHeight = `${document.documentElement.clientHeight}`;
|
||||
that.changeFixed(that.clientHeight);
|
||||
};
|
||||
// 监听滚动事件,然后用handleScroll这个方法进行相应的处理
|
||||
window.addEventListener('scroll',this.handleScroll);
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
moduleIds() {
|
||||
this.initApiDocSimpleList();
|
||||
},
|
||||
clientHeight() { //如果clientHeight 发生改变,这个函数就会运行
|
||||
this.changeFixed(this.clientHeight);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatRowData(dataType, data) {
|
||||
var returnData = data;
|
||||
if (data) {
|
||||
returnData = data.replace(/\n/g, '<br>');
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
changeFixed(clientHeight) {
|
||||
if (this.$refs.apiDocInfoDiv) {
|
||||
let countPageHeight = 350;
|
||||
if(this.pageHeaderHeight!=0 && this.pageHeaderHeight != null){
|
||||
countPageHeight = this.pageHeaderHeight
|
||||
}
|
||||
|
||||
this.$refs.apiDocInfoDiv.style.height = clientHeight - countPageHeight + 'px';
|
||||
this.$refs.apiDocInfoDiv.style.overflow = 'auto';
|
||||
this.$refs.apiDocList.style.height = clientHeight - countPageHeight + 'px';
|
||||
}
|
||||
},
|
||||
initApiDocSimpleList() {
|
||||
let simpleRequest = this.apiSearch;
|
||||
if (this.projectId != null && this.projectId != "") {
|
||||
simpleRequest.projectId = this.projectId;
|
||||
}
|
||||
if (this.documentId != null && this.documentId != "") {
|
||||
simpleRequest.shareId = this.documentId;
|
||||
}
|
||||
if (this.moduleIds.length > 0) {
|
||||
simpleRequest.moduleIds = this.moduleIds;
|
||||
}
|
||||
|
||||
let simpleInfoUrl = "/document/selectApiSimpleInfo";
|
||||
this.apiInfoArray = [];
|
||||
this.$post(simpleInfoUrl, simpleRequest, response => {
|
||||
this.apiInfoArray = response.data;
|
||||
this.apiStepIndex = 0;
|
||||
if (this.apiInfoArray.length > 0) {
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
}
|
||||
});
|
||||
},
|
||||
shareApiDocument(isBatchShare){
|
||||
let thisHost = window.location.host;
|
||||
this.shareUrl = "";
|
||||
this.batchShareUrl = "";
|
||||
let shareIdArr = [];
|
||||
let shareType = "Single";
|
||||
if(isBatchShare == 'true'){
|
||||
this.apiInfoArray.forEach(f => {
|
||||
if (!f.id) {
|
||||
return;
|
||||
}
|
||||
shareIdArr.push(f.id);
|
||||
});
|
||||
shareType = "Batch";
|
||||
}else{
|
||||
shareIdArr.push(this.apiInfoArray[this.apiStepIndex].id);
|
||||
}
|
||||
let genShareInfoParam = {};
|
||||
genShareInfoParam.shareApiIdList = shareIdArr;
|
||||
genShareInfoParam.shareType = shareType;
|
||||
|
||||
this.$post("/document/generateApiDocumentShareInfo", genShareInfoParam, res => {
|
||||
if(shareType == "Batch"){
|
||||
this.batchShareUrl = thisHost+"/document"+res.data.shareUrl;
|
||||
}else{
|
||||
this.shareUrl = thisHost+"/document"+res.data.shareUrl;
|
||||
}
|
||||
}, (error) => {
|
||||
});
|
||||
},
|
||||
selectApiInfo(index,apiId) {
|
||||
let simpleInfoUrl = "/document/selectApiInfoById/" + apiId;
|
||||
this.$get(simpleInfoUrl, response => {
|
||||
let returnData = response.data;
|
||||
this.$set(this.apiInfoArray,index,returnData);
|
||||
});
|
||||
},
|
||||
clickStep(apiId) {
|
||||
for (let index = 0; index < this.apiInfoArray.length; index++) {
|
||||
if (apiId == this.apiInfoArray[index].id) {
|
||||
this.apiStepIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//检查数据
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
//进行跳转
|
||||
this.redirectScroll(this.apiStepIndex);
|
||||
},
|
||||
stepClick(stepIndex) {
|
||||
this.apiStepIndex = stepIndex;
|
||||
},
|
||||
getColor(enable, method) {
|
||||
return this.methodColorMap.get(method);
|
||||
},
|
||||
formatBoolean(row, column, cellValue) {
|
||||
var ret = '' //你想在页面展示的值
|
||||
if (cellValue) {
|
||||
ret = "是" //根据自己的需求设定
|
||||
} else {
|
||||
ret = "否"
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getJsonArr(jsonString) {
|
||||
let returnJsonArr = [];
|
||||
if (jsonString == '无' || jsonString == null) {
|
||||
return returnJsonArr;
|
||||
}
|
||||
|
||||
let jsonArr = JSON.parse(jsonString);
|
||||
//遍历,把必填项空的数据去掉
|
||||
for (var index = 0; index < jsonArr.length; index++) {
|
||||
var item = jsonArr[index];
|
||||
if (item.name != "" && item.name != null) {
|
||||
returnJsonArr.push(item);
|
||||
}
|
||||
}
|
||||
return returnJsonArr;
|
||||
},
|
||||
//构建预览数据
|
||||
genPreviewData(previewData) {
|
||||
if (previewData != null && previewData != '') {
|
||||
let showDataObj = {};
|
||||
for (var key in previewData) {
|
||||
// showDataObj.set(key,previewData[key]);
|
||||
let value = previewData[key];
|
||||
if(typeof(value)=='string'){
|
||||
if (value.indexOf("@") >= 0) {
|
||||
value = this.showPreview(value);
|
||||
}
|
||||
}
|
||||
showDataObj[key] = value;
|
||||
}
|
||||
showDataObj = JSON.stringify(showDataObj);
|
||||
previewData = formatJson(showDataObj);
|
||||
}
|
||||
return previewData;
|
||||
},
|
||||
showPreview(itemValue) {
|
||||
// 找到变量本身
|
||||
if (!itemValue) {
|
||||
return;
|
||||
}
|
||||
let index = itemValue.indexOf("|");
|
||||
if (index > -1) {
|
||||
itemValue = itemValue.substring(0, index).trim();
|
||||
}
|
||||
|
||||
this.mockVariableFuncs.forEach(f => {
|
||||
if (!f.name) {
|
||||
return;
|
||||
}
|
||||
itemValue += "|" + f.name;
|
||||
if (f.params) {
|
||||
itemValue += ":" + f.params.map(p => p.value).join(",");
|
||||
}
|
||||
});
|
||||
|
||||
itemValue = calculate(itemValue);
|
||||
return itemValue;
|
||||
},
|
||||
onCopySuccess: function (e) {
|
||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('commons.copy_success'),
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
onCopyError: function (e) {
|
||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||
}
|
||||
this.$message.error(this.$t('api_report.error'));
|
||||
},
|
||||
handleScroll(){
|
||||
|
||||
//apiDocInfoDiv的总高度,是(每个item的高度+20)数量
|
||||
let apiDocDivScrollTop = this.$refs.apiDocInfoDiv.scrollTop;
|
||||
let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
||||
|
||||
let scrolledHeigh = apiDocDivScrollTop+apiDocDivClientTop;
|
||||
let lastIndex = 0;
|
||||
for (let index = 0; index < this.apiInfoArray.length; index++) {
|
||||
//判断移动到了第几个元素. 公式: 移动过的高度+页面显示高度-第index子元素的高度(含20px)>0 的 index最大值
|
||||
if(scrolledHeigh>0){
|
||||
lastIndex = index;
|
||||
let itemHeight = this.$refs.apiDocInfoDivItem[index].offsetHeight+20;
|
||||
scrolledHeigh = scrolledHeigh - itemHeight;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.apiStepIndex = lastIndex;
|
||||
//检查上下文 3个以内的节点有没有查询出来
|
||||
this.checkApiInfoNode(this.apiStepIndex);
|
||||
},
|
||||
redirectScroll(itemIndex){
|
||||
//滚动条跳转:将滚动条下拉到显示对应对api接口的位置
|
||||
// let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
||||
let apiDocDivClientTop = 0;
|
||||
let itemHeightCount = 0;
|
||||
for (let i = 0; i <= itemIndex-1; i++) {
|
||||
let itemHeight = this.$refs.apiDocInfoDivItem[i].offsetHeight+20;
|
||||
itemHeightCount+=itemHeight;
|
||||
}
|
||||
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop+itemHeightCount);
|
||||
},
|
||||
checkApiInfoNode(itemIndex){
|
||||
//检查要展示的api信息节点,和上下个3个及以内的范围内数据有没有查询过
|
||||
let beforeNodeIndex = itemIndex<3?0:(itemIndex-3);
|
||||
let afterNodeIndex = (itemIndex+3)<this.apiInfoArray.length?(itemIndex+3):this.apiInfoArray.length;
|
||||
|
||||
for(let beforeIndex = itemIndex;beforeIndex < afterNodeIndex;beforeIndex++){
|
||||
let apiInfo = this.apiInfoArray[beforeIndex];
|
||||
if(apiInfo==null){
|
||||
continue;
|
||||
}
|
||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
||||
let apiId = apiInfo.id;
|
||||
if(!apiInfo.isSearching){
|
||||
apiInfo.isSearching = true;
|
||||
this.selectApiInfo(beforeIndex,apiId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(let afterIndex = beforeNodeIndex;afterIndex <itemIndex;afterIndex++){
|
||||
let apiInfo = this.apiInfoArray[afterIndex];
|
||||
if(apiInfo==null){
|
||||
continue;
|
||||
}
|
||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
||||
let apiId = apiInfo.id;
|
||||
if(!apiInfo.isSearching) {
|
||||
apiInfo.isSearching = true;
|
||||
this.selectApiInfo(afterIndex,apiId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.simpleFontClass {
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.blackFontClass {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.smallFontClass {
|
||||
font-size: 13px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
}
|
||||
|
||||
.apiInfoRow {
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.apiStatusTag {
|
||||
margin: 20px 5px;
|
||||
}
|
||||
|
||||
.showDataDiv {
|
||||
background-color: #F5F7F9;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
/*
|
||||
步骤条中,已经完成后的节点样式和里面a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-finish {
|
||||
color: #C0C4CC;
|
||||
border-color: #C0C4CC;
|
||||
}
|
||||
|
||||
/deep/ .el-step__title.is-finish /deep/ .el-link.el-link--default {
|
||||
color: #C0C4CC;
|
||||
}
|
||||
|
||||
/*
|
||||
步骤条中,当前节点样式和当前a标签的样式
|
||||
*/
|
||||
/deep/ .el-step__head.is-process {
|
||||
color: #783887;
|
||||
border-color: #783887;
|
||||
}
|
||||
|
||||
/deep/ .el-step__title.is-process /deep/ .el-link.el-link--default {
|
||||
color: #783887;
|
||||
}
|
||||
|
||||
.document-table {
|
||||
margin: 20px 10px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.document-table /deep/ .el-table__row {
|
||||
font-size: 12px;
|
||||
font-weight: initial;
|
||||
}
|
||||
|
||||
.document-table /deep/ .has-gutter {
|
||||
font-size: 12px;
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
.document-table /deep/ td {
|
||||
border-right: 0px solid #EBEEF5
|
||||
}
|
||||
|
||||
.document-table /deep/ th {
|
||||
background-color: #FAFAFA;
|
||||
border-right: 0px solid #EBEEF5
|
||||
}
|
||||
.el-divider--horizontal {
|
||||
margin: 12px 0;
|
||||
}
|
||||
</style>
|
|
@ -276,7 +276,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsAnchor from "./Anchor";
|
||||
import {API_METHOD_COLOUR} from "@/business/components/api/definition/model/JsonData";
|
||||
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
|
||||
import {formatJson,} from "@/common/js/format-utils";
|
||||
|
@ -293,7 +292,7 @@ export default {
|
|||
components: {
|
||||
Api,
|
||||
MsJsonCodeEdit,
|
||||
MsAnchor, ApiStatus, MsCodeEdit,
|
||||
ApiStatus, MsCodeEdit,
|
||||
"ApiDocumentBatchShare": apiDocumentBatchShare.default
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="questionList-content-list">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
export default {
|
||||
name: "TestScroll",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
seeThis:0,
|
||||
tabs:['tab0','tab1','tab2'],
|
||||
}
|
||||
},
|
||||
props: {
|
||||
projectId: String,
|
||||
documentId: String,
|
||||
moduleIds: Array,
|
||||
pageHeaderHeight:Number,
|
||||
},
|
||||
activated() {
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('scroll',this.handleScroll)
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
goAnchor(index) { // 也可以用scrollIntoView方法, 但由于这里头部设置了固定定位,所以用了这种方法
|
||||
// document.querySelector('#anchor'+index).scrollIntoView()
|
||||
this.seeThis = index; var anchor = this.$el.querySelector('#anchor'+index)
|
||||
document.body.scrollTop = anchor.offsetTop-100
|
||||
document.documentElement.scrollTop = anchor.offsetTop-100
|
||||
},
|
||||
handleScroll(){
|
||||
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop // 滚动条偏移量
|
||||
let offsetTop = document.querySelector('#boxFixed').offsetTop; // 要滚动到顶部吸附的元素的偏移量
|
||||
var anchorOffset0 = this.$el.querySelector('#anchor0').offsetTop-100
|
||||
var anchorOffset1 = this.$el.querySelector('#anchor1').offsetTop-100
|
||||
var anchorOffset2 = this.$el.querySelector('#anchor2').offsetTop-100
|
||||
if(scrollTop>anchorOffset0&&scrollTop<anchorOffset1){
|
||||
this.seeThis = 0
|
||||
}
|
||||
if(scrollTop>anchorOffset1&&scrollTop<anchorOffset2){
|
||||
this.seeThis = 1
|
||||
}
|
||||
if(scrollTop>anchorOffset2){
|
||||
this.seeThis = 2
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -4,9 +4,7 @@
|
|||
<el-col :span="21" style="padding-bottom: 20px">
|
||||
<div style="border:1px #DCDFE6 solid; height: 100%;border-radius: 4px ;width: 100% ;margin: 10px">
|
||||
<el-form class="tcp" :model="request" :rules="rules" ref="request" :disabled="isReadOnly" style="margin: 20px">
|
||||
|
||||
<el-tabs v-model="activeName" class="request-tabs">
|
||||
|
||||
<!--query 参数-->
|
||||
<el-tab-pane name="parameters">
|
||||
<template v-slot:label>
|
||||
|
@ -18,8 +16,7 @@
|
|||
|
||||
<el-tab-pane :label="$t('api_test.definition.request.message_template')" name="request">
|
||||
<div class="send-request">
|
||||
<ms-code-edit mode="text" :read-only="isReadOnly" :data.sync="request.request"
|
||||
:modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||
<ms-code-edit mode="text" :read-only="isReadOnly" :data.sync="request.request" :modes="['text', 'json', 'xml', 'html']" theme="eclipse"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
|
@ -75,8 +72,6 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<el-row :gutter="10" style="margin-left: 30px">
|
||||
<el-col :span="9">
|
||||
<el-form-item :label="$t('api_test.request.tcp.re_use_connection')">
|
||||
|
@ -95,10 +90,7 @@
|
|||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -328,7 +328,13 @@ export default {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
beforeUploadJmx(file){
|
||||
this.$refs.existFiles.beforeUploadFile(file);
|
||||
},
|
||||
handleUpload(file){
|
||||
this.$refs.existFiles.handleUpload(file);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -9,12 +9,10 @@
|
|||
<script>
|
||||
|
||||
import ApiDocumentItem from "@/business/components/api/definition/components/document/ApiDocumentItem";
|
||||
import TestScroll from "@/business/components/api/definition/components/document/TestScroll";
|
||||
|
||||
export default {
|
||||
name: "ApiDocumentsPage",
|
||||
components: {
|
||||
TestScroll,
|
||||
ApiDocumentItem,
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -50,6 +50,7 @@ export default {
|
|||
create_time: 'Created Time',
|
||||
update_time: 'Updated Time',
|
||||
add: 'Add',
|
||||
preview: 'Preview',
|
||||
member: 'Member',
|
||||
email: 'Email',
|
||||
phone: 'Phone',
|
||||
|
@ -117,6 +118,7 @@ export default {
|
|||
weeks_6: 'Sat',
|
||||
test_unit: 'tests',
|
||||
remove: 'Remove',
|
||||
next_level: "Next level",
|
||||
remove_cancel: 'Remove Cancel',
|
||||
remove_success: 'Remove Success',
|
||||
tips: 'The authentication information has expired, please login again',
|
||||
|
@ -629,6 +631,7 @@ export default {
|
|||
assertions_rule: "Assertion rule",
|
||||
response_header: "Response header",
|
||||
response_body: "Response body",
|
||||
response_template: "Response template",
|
||||
console: "Console",
|
||||
status_code: "Status code",
|
||||
query_info: "Follow the address bar? The following parameters, such as updateapi?id=112",
|
||||
|
@ -648,6 +651,15 @@ export default {
|
|||
other_config: "Other Config",
|
||||
message_template: "Message Template",
|
||||
tcp_parameter_tip: "The request parameters can be referenced in the request template ${XXX}",
|
||||
esb_table: {
|
||||
name: "name",
|
||||
type: "type",
|
||||
length: "length",
|
||||
required: "Required",
|
||||
desc: "Description",
|
||||
value: "Data",
|
||||
not_required: "Not required",
|
||||
}
|
||||
},
|
||||
document: {
|
||||
order: "Order",
|
||||
|
@ -874,7 +886,9 @@ export default {
|
|||
code_template_set_global_variable: "Set Global variable",
|
||||
code_template_get_response_header: "Get Response Header",
|
||||
code_template_get_response_code: "Get Response Code",
|
||||
code_template_get_response_result: "Get Response Result"
|
||||
code_template_get_response_result: "Get Response Result",
|
||||
code_add_report_length : "Add report length to head",
|
||||
code_hide_report_length : "Hide report length"
|
||||
},
|
||||
dubbo: {
|
||||
protocol: "protocol",
|
||||
|
|
|
@ -51,6 +51,7 @@ export default {
|
|||
create_time: '创建时间',
|
||||
update_time: '更新时间',
|
||||
add: '添加',
|
||||
preview: '预览',
|
||||
member: '成员',
|
||||
email: '邮箱',
|
||||
phone: '电话',
|
||||
|
@ -118,6 +119,7 @@ export default {
|
|||
port_cannot_be_empty: '端口号不能为空',
|
||||
account_cannot_be_empty: '帐户不能为空',
|
||||
remove: '移除',
|
||||
next_level: "下一级",
|
||||
remove_cancel: '移除取消',
|
||||
remove_success: '移除成功',
|
||||
tips: '认证信息已过期,请重新登录',
|
||||
|
@ -630,6 +632,7 @@ export default {
|
|||
assertions_rule: "断言规则",
|
||||
response_header: "响应头",
|
||||
response_body: "响应体",
|
||||
response_template: "响应报文模版",
|
||||
console: "控制台",
|
||||
status_code: "状态码",
|
||||
query_info: "地址栏中跟在?后面的参数,如updateapi?id=112",
|
||||
|
@ -649,6 +652,15 @@ export default {
|
|||
other_config: "其他设置",
|
||||
message_template: "报文模版",
|
||||
tcp_parameter_tip: "请求参数可以在请求模版通过${xxx}引用",
|
||||
esb_table: {
|
||||
name: "参数名",
|
||||
type: "类型",
|
||||
length: "长度",
|
||||
required: "必填",
|
||||
desc: "描述",
|
||||
value: "数据",
|
||||
not_required: "非必填",
|
||||
}
|
||||
},
|
||||
document: {
|
||||
order: "排序方式",
|
||||
|
@ -876,7 +888,9 @@ export default {
|
|||
code_template_set_global_variable: "设置全局变量",
|
||||
code_template_get_response_header: "获取响应头",
|
||||
code_template_get_response_code: "获取响应码",
|
||||
code_template_get_response_result: "获取响应结果"
|
||||
code_template_get_response_result: "获取响应结果",
|
||||
code_add_report_length : "报文头添加长度",
|
||||
code_hide_report_length : "隐藏报文长度"
|
||||
},
|
||||
dubbo: {
|
||||
protocol: "协议",
|
||||
|
|
|
@ -51,6 +51,7 @@ export default {
|
|||
create_time: '創建時間',
|
||||
update_time: '更新時間',
|
||||
add: '添加',
|
||||
preview: '預覽',
|
||||
member: '成員',
|
||||
email: '郵箱',
|
||||
phone: '電話',
|
||||
|
@ -118,6 +119,7 @@ export default {
|
|||
port_cannot_be_empty: '端口號不能為空',
|
||||
account_cannot_be_empty: '帳戶不能為空',
|
||||
remove: '移除',
|
||||
next_level: "下一級",
|
||||
remove_cancel: '移除取消',
|
||||
remove_success: '移除成功',
|
||||
tips: '認證信息已過期,請重新登錄',
|
||||
|
@ -629,6 +631,7 @@ export default {
|
|||
assertions_rule: "斷言規則",
|
||||
response_header: "響應頭",
|
||||
response_body: "響應體",
|
||||
response_template: "響應報文模板",
|
||||
console: "控制臺",
|
||||
status_code: "狀態碼",
|
||||
query_info: "地址欄中跟在?後面的參數,如updateapi?id=112",
|
||||
|
@ -648,6 +651,15 @@ export default {
|
|||
other_config: "其他設置",
|
||||
message_template: "報文模版",
|
||||
tcp_parameter_tip: "請求參數可以在請求模版通過${xxx}引用",
|
||||
esb_table: {
|
||||
name: "參數名",
|
||||
type: "類型",
|
||||
length: "長度",
|
||||
required: "必填",
|
||||
desc: "描述",
|
||||
value: "數據",
|
||||
not_required: "非必填",
|
||||
}
|
||||
},
|
||||
document: {
|
||||
order: "排序方式",
|
||||
|
@ -875,7 +887,9 @@ export default {
|
|||
code_template_set_global_variable: "設置全局變量",
|
||||
code_template_get_response_header: "獲取響應頭",
|
||||
code_template_get_response_code: "獲取響應碼",
|
||||
code_template_get_response_result: "獲取響應結果"
|
||||
code_template_get_response_result: "獲取響應結果",
|
||||
code_add_report_length : "報文头添加長度",
|
||||
code_hide_report_length : "隱藏報文長度"
|
||||
},
|
||||
dubbo: {
|
||||
protocol: "協議",
|
||||
|
|
Loading…
Reference in New Issue