refactor(mock测试,报表管理,接口报表): #1006965 #1006966 接口报表的json格式改为json-shcema展示、开源版本看不到报表菜单、导出接口时没有mock设置信息的问题及mock测试json参数匹配度有误的问题
【【github#6183】mock接口填不同参数,没有按设置的期望返回结果,返回】https://www.tapd.cn/55049933/bugtrace/bugs/view?bug_id=1155049933001006966;【【接口测试】导出接口定义没有导出mock设置】https://www.tapd.cn/55049933/bugtrace/bugs/view?bug_id=1155049933001006965
This commit is contained in:
parent
0a47d283a2
commit
ff1407d24f
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.api.dto.definition;
|
package io.metersphere.api.dto.definition;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.mockconfig.MockConfigImportDTO;
|
||||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||||
|
|
||||||
|
@ -17,4 +18,5 @@ public class MsApiExportResult extends ApiExportResult {
|
||||||
private String version;
|
private String version;
|
||||||
private List<ApiDefinitionWithBLOBs> data;
|
private List<ApiDefinitionWithBLOBs> data;
|
||||||
private List<ApiTestCaseWithBLOBs> cases;
|
private List<ApiTestCaseWithBLOBs> cases;
|
||||||
|
private List<MockConfigImportDTO> mocks;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.api.dto.definition.parse;
|
package io.metersphere.api.dto.definition.parse;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.parse.ms.NodeTree;
|
import io.metersphere.api.dto.definition.parse.ms.NodeTree;
|
||||||
|
import io.metersphere.api.dto.mockconfig.MockConfigImportDTO;
|
||||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||||
import io.metersphere.base.domain.EsbApiParamsWithBLOBs;
|
import io.metersphere.base.domain.EsbApiParamsWithBLOBs;
|
||||||
|
@ -21,5 +22,8 @@ public class ApiDefinitionImport {
|
||||||
//ESB文件导入的附属数据类
|
//ESB文件导入的附属数据类
|
||||||
private Map<String,EsbApiParamsWithBLOBs> esbApiParamsMap;
|
private Map<String,EsbApiParamsWithBLOBs> esbApiParamsMap;
|
||||||
|
|
||||||
|
//Mock数据相关
|
||||||
|
private List<MockConfigImportDTO> mocks;
|
||||||
|
|
||||||
private List<NodeTree> nodeTree;
|
private List<NodeTree> nodeTree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package io.metersphere.api.dto.mockconfig;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author song.tianyang
|
||||||
|
* @Date 2021/9/27 5:54 下午
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MockConfigImportDTO extends MockExpectConfigWithBLOBs {
|
||||||
|
public String apiId;
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import io.metersphere.api.dto.definition.parse.Swagger3Parser;
|
||||||
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
import io.metersphere.api.dto.definition.request.ParameterConfig;
|
||||||
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
|
||||||
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
|
||||||
|
import io.metersphere.api.dto.mockconfig.MockConfigImportDTO;
|
||||||
import io.metersphere.api.dto.scenario.Body;
|
import io.metersphere.api.dto.scenario.Body;
|
||||||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||||
import io.metersphere.api.dto.scenario.request.RequestType;
|
import io.metersphere.api.dto.scenario.request.RequestType;
|
||||||
|
@ -210,6 +211,8 @@ public class ApiDefinitionService {
|
||||||
extApiDefinitionExecResultMapper.deleteByResourceId(apiId);
|
extApiDefinitionExecResultMapper.deleteByResourceId(apiId);
|
||||||
apiDefinitionMapper.deleteByPrimaryKey(apiId);
|
apiDefinitionMapper.deleteByPrimaryKey(apiId);
|
||||||
esbApiParamService.deleteByResourceId(apiId);
|
esbApiParamService.deleteByResourceId(apiId);
|
||||||
|
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
|
||||||
|
mockConfigService.deleteMockConfigByApiId(apiId);
|
||||||
FileUtils.deleteBodyFiles(apiId);
|
FileUtils.deleteBodyFiles(apiId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +222,10 @@ public class ApiDefinitionService {
|
||||||
esbApiParamService.deleteByResourceIdIn(apiIds);
|
esbApiParamService.deleteByResourceIdIn(apiIds);
|
||||||
apiDefinitionMapper.deleteByExample(example);
|
apiDefinitionMapper.deleteByExample(example);
|
||||||
apiTestCaseService.deleteBatchByDefinitionId(apiIds);
|
apiTestCaseService.deleteBatchByDefinitionId(apiIds);
|
||||||
|
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
|
||||||
|
for (String apiId : apiIds) {
|
||||||
|
mockConfigService.deleteMockConfigByApiId(apiId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeToGc(List<String> apiIds) {
|
public void removeToGc(List<String> apiIds) {
|
||||||
|
@ -466,7 +473,7 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiDefinition importCreate(ApiDefinitionWithBLOBs apiDefinition, ApiDefinitionMapper batchMapper,
|
private ApiDefinition importCreate(ApiDefinitionWithBLOBs apiDefinition, ApiDefinitionMapper batchMapper,
|
||||||
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases,
|
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases, List<MockConfigImportDTO> mocks,
|
||||||
Boolean repeatable) {
|
Boolean repeatable) {
|
||||||
SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest();
|
SaveApiDefinitionRequest saveReq = new SaveApiDefinitionRequest();
|
||||||
BeanUtils.copyBean(saveReq, apiDefinition);
|
BeanUtils.copyBean(saveReq, apiDefinition);
|
||||||
|
@ -493,7 +500,7 @@ public class ApiDefinitionService {
|
||||||
sameRequest = getSameRequestById(apiDefinition.getId(), apiTestImportRequest.getProjectId());
|
sameRequest = getSameRequestById(apiDefinition.getId(), apiTestImportRequest.getProjectId());
|
||||||
}
|
}
|
||||||
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
|
if (StringUtils.equals("fullCoverage", apiTestImportRequest.getModeId())) {
|
||||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases);
|
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases, mocks);
|
||||||
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
} else if (StringUtils.equals("incrementalMerge", apiTestImportRequest.getModeId())) {
|
||||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||||
//postman 可能含有前置脚本,接口定义去掉脚本
|
//postman 可能含有前置脚本,接口定义去掉脚本
|
||||||
|
@ -507,7 +514,7 @@ public class ApiDefinitionService {
|
||||||
importApiCase(apiDefinition, apiTestImportRequest);
|
importApiCase(apiDefinition, apiTestImportRequest);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases);
|
_importCreate(sameRequest, batchMapper, apiDefinition, apiTestCaseMapper, apiTestImportRequest, cases, mocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiDefinition;
|
return apiDefinition;
|
||||||
|
@ -534,12 +541,13 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _importCreate(List<ApiDefinition> sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition,
|
private void _importCreate(List<ApiDefinition> sameRequest, ApiDefinitionMapper batchMapper, ApiDefinitionWithBLOBs apiDefinition,
|
||||||
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases) {
|
ApiTestCaseMapper apiTestCaseMapper, ApiTestImportRequest apiTestImportRequest, List<ApiTestCaseWithBLOBs> cases ,List<MockConfigImportDTO> mocks) {
|
||||||
String originId = apiDefinition.getId();
|
String originId = apiDefinition.getId();
|
||||||
if (CollectionUtils.isEmpty(sameRequest)) {
|
if (CollectionUtils.isEmpty(sameRequest)) {
|
||||||
apiDefinition.setId(UUID.randomUUID().toString());
|
apiDefinition.setId(UUID.randomUUID().toString());
|
||||||
apiDefinition.setOrder(getImportNextOrder(apiTestImportRequest.getProjectId()));
|
apiDefinition.setOrder(getImportNextOrder(apiTestImportRequest.getProjectId()));
|
||||||
reSetImportCasesApiId(cases, originId, apiDefinition.getId());
|
reSetImportCasesApiId(cases, originId, apiDefinition.getId());
|
||||||
|
reSetImportMocksApiId(mocks, originId, apiDefinition.getId());
|
||||||
if (StringUtils.equalsIgnoreCase(apiDefinition.getProtocol(), RequestType.HTTP)) {
|
if (StringUtils.equalsIgnoreCase(apiDefinition.getProtocol(), RequestType.HTTP)) {
|
||||||
batchMapper.insert(apiDefinition);
|
batchMapper.insert(apiDefinition);
|
||||||
String request = setImportHashTree(apiDefinition);
|
String request = setImportHashTree(apiDefinition);
|
||||||
|
@ -595,6 +603,16 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reSetImportMocksApiId(List<MockConfigImportDTO> mocks, String originId, String newId) {
|
||||||
|
if (CollectionUtils.isNotEmpty(mocks)) {
|
||||||
|
mocks.forEach(item -> {
|
||||||
|
if (StringUtils.equals(item.getApiId(), originId)) {
|
||||||
|
item.setApiId(newId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String setImportHashTree(ApiDefinitionWithBLOBs apiDefinition) {
|
private String setImportHashTree(ApiDefinitionWithBLOBs apiDefinition) {
|
||||||
String request = apiDefinition.getRequest();
|
String request = apiDefinition.getRequest();
|
||||||
MsHTTPSamplerProxy msHTTPSamplerProxy = JSONObject.parseObject(request, MsHTTPSamplerProxy.class);
|
MsHTTPSamplerProxy msHTTPSamplerProxy = JSONObject.parseObject(request, MsHTTPSamplerProxy.class);
|
||||||
|
@ -936,14 +954,14 @@ public class ApiDefinitionService {
|
||||||
if (apiImport.getEsbApiParamsMap() != null) {
|
if (apiImport.getEsbApiParamsMap() != null) {
|
||||||
String apiId = item.getId();
|
String apiId = item.getId();
|
||||||
EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId);
|
EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId);
|
||||||
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), project.getRepeatable());
|
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), apiImport.getMocks(), project.getRepeatable());
|
||||||
if (model != null) {
|
if (model != null) {
|
||||||
apiImport.getEsbApiParamsMap().remove(apiId);
|
apiImport.getEsbApiParamsMap().remove(apiId);
|
||||||
model.setResourceId(item.getId());
|
model.setResourceId(item.getId());
|
||||||
apiImport.getEsbApiParamsMap().put(item.getId(), model);
|
apiImport.getEsbApiParamsMap().put(item.getId(), model);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), project.getRepeatable());
|
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), apiImport.getMocks(), project.getRepeatable());
|
||||||
}
|
}
|
||||||
if (i % 300 == 0) {
|
if (i % 300 == 0) {
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
|
@ -967,6 +985,11 @@ public class ApiDefinitionService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(apiImport.getMocks())) {
|
||||||
|
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
|
||||||
|
mockConfigService.importMock(apiImport, sqlSession, request);
|
||||||
|
}
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(apiImport.getCases())) {
|
if (!CollectionUtils.isEmpty(apiImport.getCases())) {
|
||||||
importMsCase(apiImport, sqlSession, request);
|
importMsCase(apiImport, sqlSession, request);
|
||||||
}
|
}
|
||||||
|
@ -1253,9 +1276,11 @@ public class ApiDefinitionService {
|
||||||
example.createCriteria().andIdIn(request.getIds());
|
example.createCriteria().andIdIn(request.getIds());
|
||||||
|
|
||||||
if (StringUtils.equals(type, "MS")) { // 导出为 Metersphere 格式
|
if (StringUtils.equals(type, "MS")) { // 导出为 Metersphere 格式
|
||||||
|
MockConfigService mockConfigService = CommonBeanFactory.getBean(MockConfigService.class);
|
||||||
apiExportResult = new MsApiExportResult();
|
apiExportResult = new MsApiExportResult();
|
||||||
((MsApiExportResult) apiExportResult).setData(apiDefinitionMapper.selectByExampleWithBLOBs(example));
|
((MsApiExportResult) apiExportResult).setData(apiDefinitionMapper.selectByExampleWithBLOBs(example));
|
||||||
((MsApiExportResult) apiExportResult).setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds()));
|
((MsApiExportResult) apiExportResult).setCases(apiTestCaseService.selectCasesBydApiIds(request.getIds()));
|
||||||
|
((MsApiExportResult) apiExportResult).setMocks(mockConfigService.selectMockExpectConfigByApiIdIn(request.getIds()));
|
||||||
((MsApiExportResult) apiExportResult).setProjectName(request.getProjectId());
|
((MsApiExportResult) apiExportResult).setProjectName(request.getProjectId());
|
||||||
((MsApiExportResult) apiExportResult).setProtocol(request.getProtocol());
|
((MsApiExportResult) apiExportResult).setProtocol(request.getProtocol());
|
||||||
((MsApiExportResult) apiExportResult).setProjectId(request.getProjectId());
|
((MsApiExportResult) apiExportResult).setProjectId(request.getProjectId());
|
||||||
|
|
|
@ -4,9 +4,12 @@ import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.fastjson.JSONValidator;
|
import com.alibaba.fastjson.JSONValidator;
|
||||||
|
import io.metersphere.api.dto.ApiTestImportRequest;
|
||||||
import io.metersphere.api.dto.automation.EsbDataStruct;
|
import io.metersphere.api.dto.automation.EsbDataStruct;
|
||||||
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
|
||||||
import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser;
|
import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser;
|
||||||
|
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
|
||||||
|
import io.metersphere.api.dto.mockconfig.MockConfigImportDTO;
|
||||||
import io.metersphere.api.dto.mockconfig.MockConfigRequest;
|
import io.metersphere.api.dto.mockconfig.MockConfigRequest;
|
||||||
import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest;
|
import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest;
|
||||||
import io.metersphere.api.dto.mockconfig.response.JsonSchemaReturnObj;
|
import io.metersphere.api.dto.mockconfig.response.JsonSchemaReturnObj;
|
||||||
|
@ -23,6 +26,7 @@ import io.metersphere.jmeter.utils.ScriptEngineUtils;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.ibatis.session.SqlSession;
|
||||||
import org.json.XML;
|
import org.json.XML;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -65,6 +69,28 @@ public class MockConfigService {
|
||||||
return this.assemblyMockConfingResponse(configList);
|
return this.assemblyMockConfingResponse(configList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<MockExpectConfigWithBLOBs> selectMockExpectConfigByApiId(String apiId){
|
||||||
|
return extMockExpectConfigMapper.selectByApiId(apiId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MockConfigImportDTO> selectMockExpectConfigByApiIdIn(List<String> apiIds){
|
||||||
|
if(CollectionUtils.isNotEmpty(apiIds)){
|
||||||
|
List<MockConfigImportDTO> returnDTO = new ArrayList<>();
|
||||||
|
for (String apiId : apiIds) {
|
||||||
|
List<MockExpectConfigWithBLOBs> mockExpectConfigWithBLOBsList = extMockExpectConfigMapper.selectByApiId(apiId);
|
||||||
|
for (MockExpectConfigWithBLOBs model : mockExpectConfigWithBLOBsList) {
|
||||||
|
MockConfigImportDTO dto = new MockConfigImportDTO();
|
||||||
|
BeanUtils.copyBean(dto, model);
|
||||||
|
dto.setApiId(apiId);
|
||||||
|
returnDTO.add(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnDTO;
|
||||||
|
}else {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MockConfigResponse assemblyMockConfingResponse(List<MockConfig> configList) {
|
private MockConfigResponse assemblyMockConfingResponse(List<MockConfig> configList) {
|
||||||
if (!configList.isEmpty()) {
|
if (!configList.isEmpty()) {
|
||||||
MockConfig config = configList.get(0);
|
MockConfig config = configList.get(0);
|
||||||
|
@ -610,6 +636,19 @@ public class MockConfigService {
|
||||||
mockExpectConfigMapper.deleteByPrimaryKey(id);
|
mockExpectConfigMapper.deleteByPrimaryKey(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteMockConfigByApiId(String apiId){
|
||||||
|
MockConfigExample configExample = new MockConfigExample();
|
||||||
|
configExample.createCriteria().andApiIdEqualTo(apiId);
|
||||||
|
List<MockConfig> mockConfigList = mockConfigMapper.selectByExample(configExample);
|
||||||
|
MockExpectConfigExample example = new MockExpectConfigExample();
|
||||||
|
for (MockConfig mockConfig : mockConfigList) {
|
||||||
|
example.clear();
|
||||||
|
example.createCriteria().andMockConfigIdEqualTo(mockConfig.getId());
|
||||||
|
mockExpectConfigMapper.deleteByExample(example);
|
||||||
|
}
|
||||||
|
mockConfigMapper.deleteByExample(configExample);
|
||||||
|
}
|
||||||
|
|
||||||
public JSONObject getGetParamMap(String urlParams, ApiDefinitionWithBLOBs api, HttpServletRequest request) {
|
public JSONObject getGetParamMap(String urlParams, ApiDefinitionWithBLOBs api, HttpServletRequest request) {
|
||||||
JSONObject paramMap = this.getSendRestParamMapByIdAndUrl(api, urlParams);
|
JSONObject paramMap = this.getSendRestParamMapByIdAndUrl(api, urlParams);
|
||||||
Enumeration<String> paramNameItor = request.getParameterNames();
|
Enumeration<String> paramNameItor = request.getParameterNames();
|
||||||
|
@ -1187,4 +1226,51 @@ public class MockConfigService {
|
||||||
}
|
}
|
||||||
return isJson;
|
return isJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void importMock(ApiDefinitionImport apiImport, SqlSession sqlSession, ApiTestImportRequest request) {
|
||||||
|
if(CollectionUtils.isNotEmpty(apiImport.getMocks())){
|
||||||
|
Map<String,List<MockExpectConfigWithBLOBs>> saveMap = new HashMap<>();
|
||||||
|
for (MockConfigImportDTO dto : apiImport.getMocks()) {
|
||||||
|
String apiId = dto.getApiId();//de33108c-26e2-4d4f-826a-a5f8e017d2f4
|
||||||
|
if(saveMap.containsKey(apiId)){
|
||||||
|
saveMap.get(apiId).add(dto);
|
||||||
|
}else {
|
||||||
|
List<MockExpectConfigWithBLOBs> list = new ArrayList<>();
|
||||||
|
list.add(dto);
|
||||||
|
saveMap.put(apiId,list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String,List<MockExpectConfigWithBLOBs>> entry : saveMap.entrySet()) {
|
||||||
|
String apiId = entry.getKey();
|
||||||
|
this.deleteMockConfigByApiId(apiId);
|
||||||
|
|
||||||
|
List<MockExpectConfigWithBLOBs> list = entry.getValue();
|
||||||
|
|
||||||
|
String mockId = UUID.randomUUID().toString();
|
||||||
|
MockConfig config = new MockConfig();
|
||||||
|
config.setProjectId(request.getProjectId());
|
||||||
|
config.setId(mockId);
|
||||||
|
config.setCreateUserId(SessionUtils.getUserId());
|
||||||
|
config.setCreateTime(System.currentTimeMillis());
|
||||||
|
config.setUpdateTime(System.currentTimeMillis());
|
||||||
|
config.setApiId(apiId);
|
||||||
|
mockConfigMapper.insert(config);
|
||||||
|
|
||||||
|
int batchCount = 0;
|
||||||
|
for (MockExpectConfigWithBLOBs mockExpect : list) {
|
||||||
|
mockExpect.setId(UUID.randomUUID().toString());
|
||||||
|
mockExpect.setMockConfigId(mockId);
|
||||||
|
mockExpect.setCreateTime(System.currentTimeMillis());
|
||||||
|
mockExpect.setUpdateTime(System.currentTimeMillis());
|
||||||
|
mockExpect.setCreateUserId(SessionUtils.getUserId());
|
||||||
|
mockExpectConfigMapper.insert(mockExpect);
|
||||||
|
}
|
||||||
|
if (batchCount % 300 == 0) {
|
||||||
|
sqlSession.flushStatements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
package io.metersphere.base.mapper.ext;
|
package io.metersphere.base.mapper.ext;
|
||||||
|
|
||||||
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
|
import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ExtMockExpectConfigMapper {
|
public interface ExtMockExpectConfigMapper {
|
||||||
|
|
||||||
List<MockExpectConfigWithBLOBs> selectByProjectIdAndStatusIsOpen(String projectId);
|
List<MockExpectConfigWithBLOBs> selectByProjectIdAndStatusIsOpen(String projectId);
|
||||||
|
|
||||||
|
List<MockExpectConfigWithBLOBs> selectByApiId(String apiId);
|
||||||
|
|
||||||
|
List<MockExpectConfigWithBLOBs> selectByApiIdIn(@Param("values") List<String> apiIds);
|
||||||
}
|
}
|
|
@ -6,5 +6,19 @@
|
||||||
SELECT * FROM mock_expect_config WHERE status = 'true' AND mock_config_id IN
|
SELECT * FROM mock_expect_config WHERE status = 'true' AND mock_config_id IN
|
||||||
(SELECT id FROM mock_config WHERE api_path IS NULL AND project_id = #{0} )
|
(SELECT id FROM mock_config WHERE api_path IS NULL AND project_id = #{0} )
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectByApiId" resultType="io.metersphere.base.domain.MockExpectConfigWithBLOBs">
|
||||||
|
SELECT * FROM mock_expect_config WHERE mock_config_id IN
|
||||||
|
(
|
||||||
|
SELECT id FROM mock_config WHERE api_id = #{0}
|
||||||
|
)
|
||||||
|
</select>
|
||||||
|
<select id="selectByApiIdIn" resultType="io.metersphere.base.domain.MockExpectConfigWithBLOBs">
|
||||||
|
SELECT * FROM mock_expect_config WHERE mock_config_id IN
|
||||||
|
(
|
||||||
|
SELECT id FROM mock_config WHERE api_id IN
|
||||||
|
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||||
|
#{value}
|
||||||
|
</foreach>
|
||||||
|
)
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -10,6 +10,7 @@ import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON数据结构相关的工具类
|
* JSON数据结构相关的工具类
|
||||||
|
*
|
||||||
* @author song.tianyang
|
* @author song.tianyang
|
||||||
* @Date 2021/8/16 3:50 下午
|
* @Date 2021/8/16 3:50 下午
|
||||||
*/
|
*/
|
||||||
|
@ -26,14 +27,18 @@ public class JsonStructUtils {
|
||||||
if (sourceObj == null && matchObj == null) {
|
if (sourceObj == null && matchObj == null) {
|
||||||
return true;
|
return true;
|
||||||
} else if (sourceObj != null && matchObj != null) {
|
} else if (sourceObj != null && matchObj != null) {
|
||||||
boolean isMatch = false;
|
boolean lastMatchResultIsTrue = false;
|
||||||
|
boolean hasNotMatchResult = false;
|
||||||
try {
|
try {
|
||||||
Set<String> matchKeys = matchObj.keySet();
|
Set<String> matchKeys = matchObj.keySet();
|
||||||
for (String key : matchKeys) {
|
for (String key : matchKeys) {
|
||||||
if (sourceObj.containsKey(key)) {
|
if (sourceObj.containsKey(key)) {
|
||||||
Object sourceObjItem = sourceObj.get(key);
|
Object sourceObjItem = sourceObj.get(key);
|
||||||
Object matchObjItem = matchObj.get(key);
|
Object matchObjItem = matchObj.get(key);
|
||||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
lastMatchResultIsTrue = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||||
|
if (!lastMatchResultIsTrue) {
|
||||||
|
hasNotMatchResult = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +46,7 @@ public class JsonStructUtils {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return isMatch;
|
return lastMatchResultIsTrue && !hasNotMatchResult;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -52,9 +57,9 @@ public class JsonStructUtils {
|
||||||
return true;
|
return true;
|
||||||
} else if (sourceArray != null && matchArray != null && sourceArray.size() > matchArray.size()) {
|
} else if (sourceArray != null && matchArray != null && sourceArray.size() > matchArray.size()) {
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < matchArray.size(); i ++) {
|
for (int i = 0; i < matchArray.size(); i++) {
|
||||||
Object obj = matchArray.get(i);
|
Object obj = matchArray.get(i);
|
||||||
if(!sourceArray.contains(obj)){
|
if (!sourceArray.contains(obj)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,13 +75,13 @@ public class JsonStructUtils {
|
||||||
public static boolean checkJsonArrayContainsObj(JSONArray sourceArray, JSONObject matchObj) {
|
public static boolean checkJsonArrayContainsObj(JSONArray sourceArray, JSONObject matchObj) {
|
||||||
if (sourceArray == null && matchObj == null) {
|
if (sourceArray == null && matchObj == null) {
|
||||||
return true;
|
return true;
|
||||||
} else if (sourceArray != null && matchObj != null ) {
|
} else if (sourceArray != null && matchObj != null) {
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < sourceArray.size(); i ++) {
|
for (int i = 0; i < sourceArray.size(); i++) {
|
||||||
Object obj = sourceArray.get(i);
|
Object obj = sourceArray.get(i);
|
||||||
if(obj instanceof JSONObject){
|
if (obj instanceof JSONObject) {
|
||||||
boolean isMatch = checkJsonObjCompliance((JSONObject) obj,matchObj);
|
boolean isMatch = checkJsonObjCompliance((JSONObject) obj, matchObj);
|
||||||
if(isMatch){
|
if (isMatch) {
|
||||||
return isMatch;
|
return isMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +97,7 @@ public class JsonStructUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
|
* 检查一个JSON对象的数据集合是否包含另一个对象(包含)
|
||||||
|
*
|
||||||
* @param sourceArray
|
* @param sourceArray
|
||||||
* @param matchObj
|
* @param matchObj
|
||||||
* @return
|
* @return
|
||||||
|
@ -103,14 +109,14 @@ public class JsonStructUtils {
|
||||||
boolean isMatch = false;
|
boolean isMatch = false;
|
||||||
try {
|
try {
|
||||||
Set<String> matchKeys = matchObj.keySet();
|
Set<String> matchKeys = matchObj.keySet();
|
||||||
for(int sourceIndex = 0;sourceIndex < sourceArray.size();sourceIndex ++){
|
for (int sourceIndex = 0; sourceIndex < sourceArray.size(); sourceIndex++) {
|
||||||
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
|
JSONObject sourceObj = sourceArray.getJSONObject(sourceIndex);
|
||||||
for (String key : matchKeys) {
|
for (String key : matchKeys) {
|
||||||
if (sourceObj.containsKey(key)) {
|
if (sourceObj.containsKey(key)) {
|
||||||
Object sourceObjItem = sourceObj.get(key);
|
Object sourceObjItem = sourceObj.get(key);
|
||||||
Object matchObjItem = matchObj.get(key);
|
Object matchObjItem = matchObj.get(key);
|
||||||
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
isMatch = checkObjCompliance(sourceObjItem, matchObjItem);
|
||||||
if(!isMatch){
|
if (!isMatch) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -119,7 +125,7 @@ public class JsonStructUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isMatch){
|
if (isMatch) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,12 +179,12 @@ public class JsonStructUtils {
|
||||||
public static void deepParseKeyByJsonObject(JSONObject jsonObject, List<String> keyList) {
|
public static void deepParseKeyByJsonObject(JSONObject jsonObject, List<String> keyList) {
|
||||||
for (String key : jsonObject.keySet()) {
|
for (String key : jsonObject.keySet()) {
|
||||||
Object obj = jsonObject.get(key);
|
Object obj = jsonObject.get(key);
|
||||||
if(obj instanceof JSONArray) {
|
if (obj instanceof JSONArray) {
|
||||||
deepParseKeyByJsonArray((JSONArray) obj, keyList);
|
deepParseKeyByJsonArray((JSONArray) obj, keyList);
|
||||||
}else if(obj instanceof JSONObject){
|
} else if (obj instanceof JSONObject) {
|
||||||
deepParseKeyByJsonObject((JSONObject) obj,keyList);
|
deepParseKeyByJsonObject((JSONObject) obj, keyList);
|
||||||
}else {
|
} else {
|
||||||
if(!keyList.contains(key)){
|
if (!keyList.contains(key)) {
|
||||||
keyList.add(key);
|
keyList.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,10 +192,10 @@ public class JsonStructUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deepParseKeyByJsonArray(JSONArray jsonArray, List<String> keyList) {
|
public static void deepParseKeyByJsonArray(JSONArray jsonArray, List<String> keyList) {
|
||||||
for (int i = 0; i < jsonArray.size(); i ++) {
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
Object itemObj = jsonArray.get(i);
|
Object itemObj = jsonArray.get(i);
|
||||||
if(itemObj instanceof JSONObject){
|
if (itemObj instanceof JSONObject) {
|
||||||
deepParseKeyByJsonObject((JSONObject)itemObj,keyList);
|
deepParseKeyByJsonObject((JSONObject) itemObj, keyList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,31 +210,31 @@ public class JsonStructUtils {
|
||||||
JSONValidator matchValidator = JSONValidator.from(matchJson);
|
JSONValidator matchValidator = JSONValidator.from(matchJson);
|
||||||
String sourceType = sourceValidator.getType().name();
|
String sourceType = sourceValidator.getType().name();
|
||||||
String matchType = matchValidator.getType().name();
|
String matchType = matchValidator.getType().name();
|
||||||
if(StringUtils.equalsIgnoreCase(sourceType,"array")&&StringUtils.equalsIgnoreCase(matchType,"array")){
|
if (StringUtils.equalsIgnoreCase(sourceType, "array") && StringUtils.equalsIgnoreCase(matchType, "array")) {
|
||||||
isSourceJsonIsArray = true;
|
isSourceJsonIsArray = true;
|
||||||
isMatchJsonIsArray = true;
|
isMatchJsonIsArray = true;
|
||||||
}else if(StringUtils.equalsIgnoreCase(sourceType,"array")){
|
} else if (StringUtils.equalsIgnoreCase(sourceType, "array")) {
|
||||||
isSourceJsonIsArray = true;
|
isSourceJsonIsArray = true;
|
||||||
}else if(StringUtils.equalsIgnoreCase(matchType,"array")){
|
} else if (StringUtils.equalsIgnoreCase(matchType, "array")) {
|
||||||
isMatchJsonIsArray = true;
|
isMatchJsonIsArray = true;
|
||||||
}
|
}
|
||||||
if(isSourceJsonIsArray && isMatchJsonIsArray){
|
if (isSourceJsonIsArray && isMatchJsonIsArray) {
|
||||||
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
||||||
JSONArray compArr = JSONArray.parseArray(matchJson);
|
JSONArray compArr = JSONArray.parseArray(matchJson);
|
||||||
isMatch = checkJsonArrayCompliance(sourceArr,compArr);
|
isMatch = checkJsonArrayCompliance(sourceArr, compArr);
|
||||||
}else if(isSourceJsonIsArray && !isMatchJsonIsArray){
|
} else if (isSourceJsonIsArray && !isMatchJsonIsArray) {
|
||||||
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
JSONArray sourceArr = JSONArray.parseArray(sourceJson);
|
||||||
JSONObject compObj = JSONObject.parseObject(matchJson);
|
JSONObject compObj = JSONObject.parseObject(matchJson);
|
||||||
isMatch = checkJsonArrayContainsObj(sourceArr,compObj);
|
isMatch = checkJsonArrayContainsObj(sourceArr, compObj);
|
||||||
}else if(!isSourceJsonIsArray && !isMatchJsonIsArray){
|
} else if (!isSourceJsonIsArray && !isMatchJsonIsArray) {
|
||||||
JSONObject sourceObj = JSONObject.parseObject(sourceJson);
|
JSONObject sourceObj = JSONObject.parseObject(sourceJson);
|
||||||
JSONObject compObj = JSONObject.parseObject(matchJson);
|
JSONObject compObj = JSONObject.parseObject(matchJson);
|
||||||
isMatch = checkJsonObjCompliance(sourceObj,compObj);
|
isMatch = checkJsonObjCompliance(sourceObj, compObj);
|
||||||
}else {
|
} else {
|
||||||
isMatch = false;
|
isMatch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (Exception e){
|
} catch (Exception e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
return isMatch;
|
return isMatch;
|
||||||
|
|
|
@ -3,28 +3,40 @@
|
||||||
<el-container v-loading="isLoading">
|
<el-container v-loading="isLoading">
|
||||||
<el-main style="padding-top: 0px;padding-bottom: 0px">
|
<el-main style="padding-top: 0px;padding-bottom: 0px">
|
||||||
<el-row v-if="sharePage" style="margin-top: 10px">
|
<el-row v-if="sharePage" 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"
|
<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>
|
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="createTimeDesc" :label="$t('api_test.definition.document.create_time_sort')"
|
||||||
<el-option key="editTimeAsc" :label="$t('api_test.definition.document.edit_time_positive_sequence')" value="editTimeAsc"/>
|
value="createTimeDesc"/>
|
||||||
<el-option key="editTimeDesc" :label="$t('api_test.definition.document.edit_time_Reverse_order')" value="editTimeDesc"/>
|
<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>
|
||||||
|
|
||||||
<el-select size="small" :placeholder="$t('api_test.definition.document.request_method')" v-model="apiSearch.type" style="float: right;width: 180px;margin-right: 5px"
|
<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>
|
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="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="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="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="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="DELETE" :label="'DELETE '+$t('api_test.definition.document.request_interface')"
|
||||||
<el-option key="PATCH" :label="'PATCH '+$t('api_test.definition.document.request_interface')" value="PATCH"/>
|
value="DELETE"/>
|
||||||
<el-option key="OPTIONS" :label="'OPTIONS '+$t('api_test.definition.document.request_interface')" value="OPTIONS"/>
|
<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="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-option key="CONNECT" :label="'CONNECT '+$t('api_test.definition.document.request_interface')"
|
||||||
|
value="CONNECT"/>
|
||||||
</el-select>
|
</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"
|
<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"/>
|
@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" @shareApiDocument="shareApiDocument"
|
||||||
|
:project-id="projectId" :share-url="batchShareUrl"
|
||||||
|
style="float: right;margin: 6px;font-size: 17px"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row v-else
|
<el-row v-else
|
||||||
style="margin-top: 0px;position: fixed;float: right;margin-right: 0px;margin-left: 400px;top: 135px; right: 90px;">
|
style="margin-top: 0px;position: fixed;float: right;margin-right: 0px;margin-left: 400px;top: 135px; right: 90px;">
|
||||||
|
@ -46,19 +58,26 @@
|
||||||
<el-option key="GET" :label="'GET '+$t('api_test.definition.document.request_interface')" value="GET"/>
|
<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="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="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="DELETE" :label="'DELETE '+$t('api_test.definition.document.request_interface')"
|
||||||
<el-option key="PATCH" :label="'PATCH '+$t('api_test.definition.document.request_interface')" value="PATCH"/>
|
value="DELETE"/>
|
||||||
<el-option key="OPTIONS" :label="'OPTIONS '+$t('api_test.definition.document.request_interface')" value="OPTIONS"/>
|
<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="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-option key="CONNECT" :label="'CONNECT '+$t('api_test.definition.document.request_interface')"
|
||||||
|
value="CONNECT"/>
|
||||||
</el-select>
|
</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"
|
<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"/>
|
@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" @shareApiDocument="shareApiDocument"
|
||||||
|
:project-id="projectId" :share-url="batchShareUrl"
|
||||||
|
style="float: right;margin: 6px;font-size: 17px"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-divider></el-divider>
|
<el-divider></el-divider>
|
||||||
<div ref="apiDocInfoDiv" @scroll="handleScroll" >
|
<div ref="apiDocInfoDiv" @scroll="handleScroll">
|
||||||
<div v-for="(apiInfo) in apiShowArray" :key="apiInfo.id" ref="apiDocInfoDivItem">
|
<div v-for="(apiInfo) in apiShowArray" :key="apiInfo.id" ref="apiDocInfoDivItem">
|
||||||
<div style="font-size: 17px">
|
<div style="font-size: 17px">
|
||||||
<el-popover
|
<el-popover
|
||||||
|
@ -66,10 +85,11 @@
|
||||||
placement="right"
|
placement="right"
|
||||||
width="260"
|
width="260"
|
||||||
@show="shareApiDocument('false')">
|
@show="shareApiDocument('false')">
|
||||||
<p>{{shareUrl}}</p>
|
<p>{{ shareUrl }}</p>
|
||||||
<div style="text-align: right; margin: 0">
|
<div style="text-align: right; margin: 0">
|
||||||
<el-button type="primary" size="mini"
|
<el-button type="primary" size="mini"
|
||||||
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }}</el-button>
|
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<i class="el-icon-share" slot="reference" style="margin-right: 10px;cursor: pointer"></i>
|
<i class="el-icon-share" slot="reference" style="margin-right: 10px;cursor: pointer"></i>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
@ -131,10 +151,6 @@
|
||||||
:label="$t('api_test.definition.document.table_coloum.name')"
|
:label="$t('api_test.definition.document.table_coloum.name')"
|
||||||
min-width="120px"
|
min-width="120px"
|
||||||
show-overflow-tooltip/>
|
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="required"
|
<el-table-column prop="required"
|
||||||
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
:label="$t('api_test.definition.document.table_coloum.is_required')"
|
||||||
:formatter="formatBoolean"
|
:formatter="formatBoolean"
|
||||||
|
@ -187,12 +203,11 @@
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div v-else-if="apiInfo.requestBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
<div v-else-if="apiInfo.requestBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
||||||
<ms-json-code-edit :body="apiInfo.jsonSchemaBody" ref="jsonCodeEdit"/>
|
<ms-json-code-edit :show-preview="false" :body="apiInfo.jsonSchemaBody" ref="jsonCodeEdit"/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="formatRowDataToJsonSchema(apiInfo,'request') " style="margin-left: 10px">
|
||||||
|
<ms-json-code-edit :show-preview="false" :body="apiInfo.requestJsonSchema" ref="jsonCodeEdit"/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-else-if="apiInfo.requestBodyParamType == 'XML'" style="margin-left: 10px">-->
|
|
||||||
<!-- <ms-json-code-edit :body="apiInfo.jsonSchemaBody" ref="jsonCodeEdit"/>-->
|
|
||||||
<!-- <editor v-model="formatData" :lang="mode" @init="editorInit" :theme="theme" :height="height"/>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<div v-else class="showDataDiv">
|
<div v-else class="showDataDiv">
|
||||||
<br/>
|
<br/>
|
||||||
<p style="margin: 0px 20px;"
|
<p style="margin: 0px 20px;"
|
||||||
|
@ -274,7 +289,10 @@
|
||||||
show-overflow-tooltip/>
|
show-overflow-tooltip/>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div v-else-if="apiInfo.responseBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
<div v-else-if="apiInfo.responseBodyParamType == 'JSON-SCHEMA'" style="margin-left: 10px">
|
||||||
<ms-json-code-edit :body="apiInfo.jsonSchemaResponseBody" ref="jsonCodeEdit"/>
|
<ms-json-code-edit :show-preview="false" :body="apiInfo.jsonSchemaResponseBody" ref="jsonCodeEdit"/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="formatRowDataToJsonSchema(apiInfo,'response') " style="margin-left: 10px">
|
||||||
|
<ms-json-code-edit :show-preview="false" :body="apiInfo.responseJsonSchema" ref="jsonCodeEdit"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="showDataDiv">
|
<div v-else class="showDataDiv">
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -305,7 +323,7 @@
|
||||||
</el-main>
|
</el-main>
|
||||||
<!-- 右侧列表 -->
|
<!-- 右侧列表 -->
|
||||||
<el-aside width="200px" style="margin-top: 30px;">
|
<el-aside width="200px" style="margin-top: 30px;">
|
||||||
<div ref="apiDocList" >
|
<div ref="apiDocList">
|
||||||
<el-steps style="height: 40%" direction="vertical" :active="apiStepIndex">
|
<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-step v-for="(apiInfo) in apiInfoArray" :key="apiInfo.id" @click.native="clickStep(apiInfo.id)">
|
||||||
<el-link slot="title">{{ apiInfo.name }}</el-link>
|
<el-link slot="title">{{ apiInfo.name }}</el-link>
|
||||||
|
@ -326,9 +344,10 @@ import {calculate} from "@/business/components/api/definition/model/ApiTestModel
|
||||||
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
|
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
|
||||||
import Api from "@/business/components/api/router";
|
import Api from "@/business/components/api/router";
|
||||||
import {generateApiDocumentShareInfo} from "@/network/share";
|
import {generateApiDocumentShareInfo} from "@/network/share";
|
||||||
|
import Convert from "@/business/components/common/json-schema/convert/convert";
|
||||||
|
|
||||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
const apiDocumentBatchShare = (requireComponent!=null&&requireComponent.keys().length) > 0 ? requireComponent("./share/ApiDocumentBatchShare.vue") : {};
|
const apiDocumentBatchShare = (requireComponent != null && requireComponent.keys().length) > 0 ? requireComponent("./share/ApiDocumentBatchShare.vue") : {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ApiDocumentAnchor",
|
name: "ApiDocumentAnchor",
|
||||||
|
@ -341,21 +360,21 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
shareUrl:"",
|
shareUrl: "",
|
||||||
batchShareUrl:"",
|
batchShareUrl: "",
|
||||||
apiStepIndex: 0,
|
apiStepIndex: 0,
|
||||||
showXpackCompnent:false,
|
showXpackCompnent: false,
|
||||||
apiInfoArray: [],
|
apiInfoArray: [],
|
||||||
modes: ['text', 'json', 'xml', 'html'],
|
modes: ['text', 'json', 'xml', 'html'],
|
||||||
formParamTypes: ['form-data', 'x-www-from-urlencoded', 'BINARY'],
|
formParamTypes: ['form-data', 'x-www-from-urlencoded', 'BINARY'],
|
||||||
mockVariableFuncs: [],
|
mockVariableFuncs: [],
|
||||||
apiSearch:{
|
apiSearch: {
|
||||||
name:"",
|
name: "",
|
||||||
type:"ALL",
|
type: "ALL",
|
||||||
orderCondition:"createTimeDesc",
|
orderCondition: "createTimeDesc",
|
||||||
},
|
},
|
||||||
apiInfoBaseObj: {
|
apiInfoBaseObj: {
|
||||||
selectedFlag:false,
|
selectedFlag: false,
|
||||||
method: "无",
|
method: "无",
|
||||||
uri: "无",
|
uri: "无",
|
||||||
name: "无",
|
name: "无",
|
||||||
|
@ -365,9 +384,9 @@ export default {
|
||||||
requestBodyParamType: "无",
|
requestBodyParamType: "无",
|
||||||
requestBodyFormData: '[]',
|
requestBodyFormData: '[]',
|
||||||
requestBodyStrutureData: "",
|
requestBodyStrutureData: "",
|
||||||
sharePopoverVisible:false,
|
sharePopoverVisible: false,
|
||||||
jsonSchemaBody: {},
|
jsonSchemaBody: {},
|
||||||
JsonSchemaResponseBody:{},
|
JsonSchemaResponseBody: {},
|
||||||
responseHead: "无",
|
responseHead: "无",
|
||||||
responseBody: "",
|
responseBody: "",
|
||||||
responseBodyParamType: "无",
|
responseBodyParamType: "无",
|
||||||
|
@ -377,19 +396,19 @@ export default {
|
||||||
},
|
},
|
||||||
methodColorMap: new Map(API_METHOD_COLOUR),
|
methodColorMap: new Map(API_METHOD_COLOUR),
|
||||||
clientHeight: '',//浏览器高度,
|
clientHeight: '',//浏览器高度,
|
||||||
maxCompnentSize : 5, //浏览器最多渲染的api信息体数量
|
maxCompnentSize: 5, //浏览器最多渲染的api信息体数量
|
||||||
apiShowArray:[],//浏览器要渲染的api信息集合
|
apiShowArray: [],//浏览器要渲染的api信息集合
|
||||||
needAsyncSelect: false, //是否需要异步查询api详细数据做展现。只有本次要展示的数据总量大于maxCompnentSize时为true
|
needAsyncSelect: false, //是否需要异步查询api详细数据做展现。只有本次要展示的数据总量大于maxCompnentSize时为true
|
||||||
currentApiIndexInApiShowArray: 0,//当前主要展示的api信息在apiShowArray的索引
|
currentApiIndexInApiShowArray: 0,//当前主要展示的api信息在apiShowArray的索引
|
||||||
clickStepFlag:false,
|
clickStepFlag: false,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
projectId: String,
|
projectId: String,
|
||||||
documentId: String,
|
documentId: String,
|
||||||
moduleIds: Array,
|
moduleIds: Array,
|
||||||
sharePage:Boolean,
|
sharePage: Boolean,
|
||||||
pageHeaderHeight:Number,
|
pageHeaderHeight: Number,
|
||||||
trashEnable: {
|
trashEnable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -402,10 +421,10 @@ export default {
|
||||||
window.onresize = function () {
|
window.onresize = function () {
|
||||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||||
this.changeFixed(this.clientHeight);
|
this.changeFixed(this.clientHeight);
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
if(requireComponent!=null && JSON.stringify(apiDocumentBatchShare) != '{}'){
|
if (requireComponent != null && JSON.stringify(apiDocumentBatchShare) != '{}') {
|
||||||
this.showXpackCompnent = true;
|
this.showXpackCompnent = true;
|
||||||
}
|
}
|
||||||
this.initApiDocSimpleList();
|
this.initApiDocSimpleList();
|
||||||
|
@ -415,7 +434,7 @@ export default {
|
||||||
this.clientHeight = `${document.documentElement.clientHeight}`;
|
this.clientHeight = `${document.documentElement.clientHeight}`;
|
||||||
this.changeFixed(this.clientHeight);
|
this.changeFixed(this.clientHeight);
|
||||||
};
|
};
|
||||||
window.addEventListener('scroll',that.handleScroll);
|
window.addEventListener('scroll', that.handleScroll);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let that = this;
|
let that = this;
|
||||||
|
@ -424,10 +443,9 @@ export default {
|
||||||
that.changeFixed(that.clientHeight);
|
that.changeFixed(that.clientHeight);
|
||||||
};
|
};
|
||||||
// 监听滚动事件,然后用handleScroll这个方法进行相应的处理
|
// 监听滚动事件,然后用handleScroll这个方法进行相应的处理
|
||||||
window.addEventListener('scroll',this.handleScroll);
|
window.addEventListener('scroll', this.handleScroll);
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
},
|
},
|
||||||
|
computed: {},
|
||||||
watch: {
|
watch: {
|
||||||
moduleIds() {
|
moduleIds() {
|
||||||
this.initApiDocSimpleList();
|
this.initApiDocSimpleList();
|
||||||
|
@ -440,18 +458,39 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatRowDataToJsonSchema(api, jsonType) {
|
||||||
|
if (jsonType === 'request' && api.requestBodyStrutureData) {
|
||||||
|
try {
|
||||||
|
JSON.parse(api.requestBodyStrutureData);
|
||||||
|
api.requestJsonSchema = {'raw': api.requestBodyStrutureData};
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (jsonType === 'response' && api.responseBodyStrutureData) {
|
||||||
|
try {
|
||||||
|
JSON.parse(api.responseBodyStrutureData);
|
||||||
|
api.responseJsonSchema = {'raw': api.responseBodyStrutureData};
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
formatRowData(dataType, data) {
|
formatRowData(dataType, data) {
|
||||||
var returnData = data;
|
var returnData = data;
|
||||||
if (data) {
|
if (data) {
|
||||||
returnData = "<xmp>"+returnData+"</xmp>";
|
returnData = "<xmp>" + returnData + "</xmp>";
|
||||||
}
|
}
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
changeFixed(clientHeight) {
|
changeFixed(clientHeight) {
|
||||||
if (this.$refs.apiDocInfoDiv) {
|
if (this.$refs.apiDocInfoDiv) {
|
||||||
let countPageHeight = 210;
|
let countPageHeight = 210;
|
||||||
if(this.pageHeaderHeight!=0 && this.pageHeaderHeight != null){
|
if (this.pageHeaderHeight != 0 && this.pageHeaderHeight != null) {
|
||||||
countPageHeight = this.pageHeaderHeight
|
countPageHeight = this.pageHeaderHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$refs.apiDocInfoDiv.style.height = clientHeight - countPageHeight + 'px';
|
this.$refs.apiDocInfoDiv.style.height = clientHeight - countPageHeight + 'px';
|
||||||
|
@ -461,7 +500,7 @@ export default {
|
||||||
},
|
},
|
||||||
initApiDocSimpleList() {
|
initApiDocSimpleList() {
|
||||||
//首先跳转到第一个节点(为了让滚动条变为0,防止重新加载后滚动条位置出现动乱导致页面混乱)
|
//首先跳转到第一个节点(为了让滚动条变为0,防止重新加载后滚动条位置出现动乱导致页面混乱)
|
||||||
if(this.apiInfoArray.length > 0){
|
if (this.apiInfoArray.length > 0) {
|
||||||
this.clickStep(this.apiInfoArray[0].id);
|
this.clickStep(this.apiInfoArray[0].id);
|
||||||
}
|
}
|
||||||
this.apiInfoArray = [];
|
this.apiInfoArray = [];
|
||||||
|
@ -487,21 +526,21 @@ export default {
|
||||||
this.apiInfoArray = response.data;
|
this.apiInfoArray = response.data;
|
||||||
this.apiStepIndex = 0;
|
this.apiStepIndex = 0;
|
||||||
if (this.apiInfoArray.length > 0) {
|
if (this.apiInfoArray.length > 0) {
|
||||||
this.checkApiInfoNode(this.apiStepIndex,true);
|
this.checkApiInfoNode(this.apiStepIndex, true);
|
||||||
}
|
}
|
||||||
if(response.data.length > this.maxCompnentSize){
|
if (response.data.length > this.maxCompnentSize) {
|
||||||
this.needAsyncSelect = true;
|
this.needAsyncSelect = true;
|
||||||
}else{
|
} else {
|
||||||
this.needAsyncSelect = false;
|
this.needAsyncSelect = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
shareApiDocument(isBatchShare){
|
shareApiDocument(isBatchShare) {
|
||||||
this.shareUrl = "";
|
this.shareUrl = "";
|
||||||
this.batchShareUrl = "";
|
this.batchShareUrl = "";
|
||||||
let shareIdArr = [];
|
let shareIdArr = [];
|
||||||
let shareType = "Single";
|
let shareType = "Single";
|
||||||
if(isBatchShare == 'true'){
|
if (isBatchShare == 'true') {
|
||||||
this.apiInfoArray.forEach(f => {
|
this.apiInfoArray.forEach(f => {
|
||||||
if (!f.id) {
|
if (!f.id) {
|
||||||
return;
|
return;
|
||||||
|
@ -509,7 +548,7 @@ export default {
|
||||||
shareIdArr.push(f.id);
|
shareIdArr.push(f.id);
|
||||||
});
|
});
|
||||||
shareType = "Batch";
|
shareType = "Batch";
|
||||||
}else{
|
} else {
|
||||||
shareIdArr.push(this.apiInfoArray[this.apiStepIndex].id);
|
shareIdArr.push(this.apiInfoArray[this.apiStepIndex].id);
|
||||||
}
|
}
|
||||||
let genShareInfoParam = {};
|
let genShareInfoParam = {};
|
||||||
|
@ -518,49 +557,49 @@ export default {
|
||||||
|
|
||||||
generateApiDocumentShareInfo(genShareInfoParam, (data) => {
|
generateApiDocumentShareInfo(genShareInfoParam, (data) => {
|
||||||
let thisHost = window.location.host;
|
let thisHost = window.location.host;
|
||||||
if(shareType == "Batch"){
|
if (shareType == "Batch") {
|
||||||
this.batchShareUrl = thisHost + "/document" + data.shareUrl;
|
this.batchShareUrl = thisHost + "/document" + data.shareUrl;
|
||||||
}else{
|
} else {
|
||||||
this.shareUrl = thisHost + "/document" + data.shareUrl;
|
this.shareUrl = thisHost + "/document" + data.shareUrl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
selectApiInfo(index,apiId,needUpdateShowArray) {
|
selectApiInfo(index, apiId, needUpdateShowArray) {
|
||||||
let simpleInfoUrl = "/share/info/selectApiInfoById/" + apiId;
|
let simpleInfoUrl = "/share/info/selectApiInfoById/" + apiId;
|
||||||
this.$get(simpleInfoUrl, response => {
|
this.$get(simpleInfoUrl, response => {
|
||||||
let returnData = response.data;
|
let returnData = response.data;
|
||||||
this.$set(this.apiInfoArray,index,returnData);
|
this.$set(this.apiInfoArray, index, returnData);
|
||||||
if(needUpdateShowArray){
|
if (needUpdateShowArray) {
|
||||||
let showApiIndex = -1;
|
let showApiIndex = -1;
|
||||||
for(let i = 0;i< this.apiShowArray.length;i++){
|
for (let i = 0; i < this.apiShowArray.length; i++) {
|
||||||
if(this.apiShowArray[i].id === apiId){
|
if (this.apiShowArray[i].id === apiId) {
|
||||||
showApiIndex = i;
|
showApiIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(showApiIndex > -1){
|
if (showApiIndex > -1) {
|
||||||
this.$set(this.apiShowArray,showApiIndex,returnData);
|
this.$set(this.apiShowArray, showApiIndex, returnData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//itemIndex,afterNodeIndex,beforeNodeIndex 三个是回调参数,用于重新构建showArray的数据 isRedirectScroll:是否调用跳转函数
|
//itemIndex,afterNodeIndex,beforeNodeIndex 三个是回调参数,用于重新构建showArray的数据 isRedirectScroll:是否调用跳转函数
|
||||||
selectApiInfoBatch(indexArr,apiIdArr,itemIndex,afterNodeIndex,beforeNodeIndex,isRedirectScroll) {
|
selectApiInfoBatch(indexArr, apiIdArr, itemIndex, afterNodeIndex, beforeNodeIndex, isRedirectScroll) {
|
||||||
if(indexArr.length != apiIdArr.length){
|
if (indexArr.length != apiIdArr.length) {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.clickStepFlag = false;
|
this.clickStepFlag = false;
|
||||||
return;
|
return;
|
||||||
}else {
|
} else {
|
||||||
let params = {};
|
let params = {};
|
||||||
params.apiIdList = apiIdArr;
|
params.apiIdList = apiIdArr;
|
||||||
this.$post("/share/info/selectApiInfoByParam", params, response => {
|
this.$post("/share/info/selectApiInfoByParam", params, response => {
|
||||||
let returnDatas = response.data;
|
let returnDatas = response.data;
|
||||||
for(let dataIndex = 0; dataIndex < returnDatas.length;dataIndex ++){
|
for (let dataIndex = 0; dataIndex < returnDatas.length; dataIndex++) {
|
||||||
let index = indexArr[dataIndex];
|
let index = indexArr[dataIndex];
|
||||||
let data = returnDatas[dataIndex];
|
let data = returnDatas[dataIndex];
|
||||||
this.$set(this.apiInfoArray,index,data);
|
this.$set(this.apiInfoArray, index, data);
|
||||||
}
|
}
|
||||||
this.updateShowArray(itemIndex,afterNodeIndex,beforeNodeIndex);
|
this.updateShowArray(itemIndex, afterNodeIndex, beforeNodeIndex);
|
||||||
if(isRedirectScroll){
|
if (isRedirectScroll) {
|
||||||
this.redirectScroll();
|
this.redirectScroll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -577,17 +616,17 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//检查数据
|
//检查数据
|
||||||
this.checkApiInfoNode(this.apiStepIndex,true);
|
this.checkApiInfoNode(this.apiStepIndex, true);
|
||||||
},
|
},
|
||||||
getColor(enable, method) {
|
getColor(enable, method) {
|
||||||
return this.methodColorMap.get(method);
|
return this.methodColorMap.get(method);
|
||||||
},
|
},
|
||||||
formatBoolean(row, column, cellValue) {
|
formatBoolean(row, column, cellValue) {
|
||||||
var ret = '' //你想在页面展示的值
|
var ret = ''; //你想在页面展示的值
|
||||||
if (cellValue) {
|
if (cellValue) {
|
||||||
ret = "是" //根据自己的需求设定
|
ret = "是"; //根据自己的需求设定
|
||||||
} else {
|
} else {
|
||||||
ret = "否"
|
ret = "否";
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
@ -614,7 +653,7 @@ export default {
|
||||||
for (var key in previewData) {
|
for (var key in previewData) {
|
||||||
// showDataObj.set(key,previewData[key]);
|
// showDataObj.set(key,previewData[key]);
|
||||||
let value = previewData[key];
|
let value = previewData[key];
|
||||||
if(typeof(value)=='string'){
|
if (typeof (value) == 'string') {
|
||||||
if (value.indexOf("@") >= 0) {
|
if (value.indexOf("@") >= 0) {
|
||||||
value = this.showPreview(value);
|
value = this.showPreview(value);
|
||||||
}
|
}
|
||||||
|
@ -650,7 +689,7 @@ export default {
|
||||||
return itemValue;
|
return itemValue;
|
||||||
},
|
},
|
||||||
onCopySuccess: function (e) {
|
onCopySuccess: function (e) {
|
||||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
if (this.apiStepIndex < this.apiInfoArray.length) {
|
||||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||||
}
|
}
|
||||||
this.$message({
|
this.$message({
|
||||||
|
@ -659,146 +698,146 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onCopyError: function (e) {
|
onCopyError: function (e) {
|
||||||
if(this.apiStepIndex < this.apiInfoArray.length){
|
if (this.apiStepIndex < this.apiInfoArray.length) {
|
||||||
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
this.apiInfoArray[this.apiStepIndex].sharePopoverVisible = false;
|
||||||
}
|
}
|
||||||
this.$message.error(this.$t('api_report.error'));
|
this.$message.error(this.$t('api_report.error'));
|
||||||
},
|
},
|
||||||
handleScroll(){
|
handleScroll() {
|
||||||
if(!this.clickStepFlag && this.$refs.apiDocInfoDiv){
|
if (!this.clickStepFlag && this.$refs.apiDocInfoDiv) {
|
||||||
//apiDocInfoDiv的总高度,是(每个item的高度+20)数量
|
//apiDocInfoDiv的总高度,是(每个item的高度+20)数量
|
||||||
let apiDocDivScrollTop = 0;
|
let apiDocDivScrollTop = 0;
|
||||||
if(this.$refs.apiDocInfoDiv&&this.$refs.apiDocInfoDiv.scrollTop){
|
if (this.$refs.apiDocInfoDiv && this.$refs.apiDocInfoDiv.scrollTop) {
|
||||||
apiDocDivScrollTop = this.$refs.apiDocInfoDiv.scrollTop;
|
apiDocDivScrollTop = this.$refs.apiDocInfoDiv.scrollTop;
|
||||||
}
|
}
|
||||||
let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
let apiDocDivClientTop = this.$refs.apiDocInfoDiv.clientHeight;
|
||||||
let scrolledHeigh = apiDocDivScrollTop+apiDocDivClientTop;
|
let scrolledHeigh = apiDocDivScrollTop + apiDocDivClientTop;
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
for (let index = 0; index < this.apiShowArray.length; index++) {
|
for (let index = 0; index < this.apiShowArray.length; index++) {
|
||||||
//判断移动到了第几个元素. 公式: 移动过的高度+页面显示高度-第index子元素的高度(含20px)>0 的 index最大值
|
//判断移动到了第几个元素. 公式: 移动过的高度+页面显示高度-第index子元素的高度(含20px)>0 的 index最大值
|
||||||
if(scrolledHeigh>0){
|
if (scrolledHeigh > 0) {
|
||||||
lastIndex = index;
|
lastIndex = index;
|
||||||
let itemHeight = this.$refs.apiDocInfoDivItem[index].offsetHeight+10;
|
let itemHeight = this.$refs.apiDocInfoDivItem[index].offsetHeight + 10;
|
||||||
scrolledHeigh = scrolledHeigh - itemHeight;
|
scrolledHeigh = scrolledHeigh - itemHeight;
|
||||||
}else{
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lastIndex < this.currentApiIndexInApiShowArray){
|
if (lastIndex < this.currentApiIndexInApiShowArray) {
|
||||||
//上移
|
//上移
|
||||||
// if(this.needAsyncSelect){
|
// if(this.needAsyncSelect){
|
||||||
//进行判断:是否还需要为apiShowArray 增加数据。 由于在当前数据前后最多展现2条数据,
|
//进行判断:是否还需要为apiShowArray 增加数据。 由于在当前数据前后最多展现2条数据,
|
||||||
//可得: apiStepIndex-1- 2 < apiInfoArray,需要添加数据
|
//可得: apiStepIndex-1- 2 < apiInfoArray,需要添加数据
|
||||||
let dataIndex = this.apiStepIndex -3;
|
let dataIndex = this.apiStepIndex - 3;
|
||||||
if(dataIndex >= 0){
|
if (dataIndex >= 0) {
|
||||||
let apiInfo = this.apiInfoArray[dataIndex];
|
let apiInfo = this.apiInfoArray[dataIndex];
|
||||||
let haveData = false;
|
let haveData = false;
|
||||||
//检查showArray是否存在这条数据。不存在才加入
|
//检查showArray是否存在这条数据。不存在才加入
|
||||||
this.apiShowArray.forEach(api => {
|
this.apiShowArray.forEach(api => {
|
||||||
if(api.id === apiInfo.id){
|
if (api.id === apiInfo.id) {
|
||||||
haveData = true;
|
haveData = true;
|
||||||
}
|
|
||||||
});
|
|
||||||
if(!haveData){
|
|
||||||
this.apiShowArray.unshift(apiInfo);
|
|
||||||
if(!apiInfo.selectedFlag){
|
|
||||||
this.selectApiInfo(dataIndex,this.apiInfoArray[dataIndex].id,true);
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.currentApiIndexInApiShowArray--;
|
|
||||||
}
|
}
|
||||||
}else{
|
});
|
||||||
|
if (!haveData) {
|
||||||
|
this.apiShowArray.unshift(apiInfo);
|
||||||
|
if (!apiInfo.selectedFlag) {
|
||||||
|
this.selectApiInfo(dataIndex, this.apiInfoArray[dataIndex].id, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.currentApiIndexInApiShowArray--;
|
this.currentApiIndexInApiShowArray--;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.currentApiIndexInApiShowArray--;
|
||||||
|
}
|
||||||
|
|
||||||
if(this.apiShowArray.length > (this.currentApiIndexInApiShowArray+3)){
|
if (this.apiShowArray.length > (this.currentApiIndexInApiShowArray + 3)) {
|
||||||
this.apiShowArray.pop();
|
this.apiShowArray.pop();
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
this.apiStepIndex --;
|
this.apiStepIndex--;
|
||||||
}else if(lastIndex > this.currentApiIndexInApiShowArray){
|
} else if (lastIndex > this.currentApiIndexInApiShowArray) {
|
||||||
//下滚
|
//下滚
|
||||||
//进行判断:是否还需要为apiShowArray 增加数据。 由于在当前数据前后最多展现2条数据,
|
//进行判断:是否还需要为apiShowArray 增加数据。 由于在当前数据前后最多展现2条数据,
|
||||||
//可得: apiStepIndex+1+ 2 < apiInfoArray,需要添加数据
|
//可得: apiStepIndex+1+ 2 < apiInfoArray,需要添加数据
|
||||||
let dataIndex = this.apiStepIndex +3;
|
let dataIndex = this.apiStepIndex + 3;
|
||||||
if(dataIndex < this.apiInfoArray.length){
|
if (dataIndex < this.apiInfoArray.length) {
|
||||||
let apiInfo = this.apiInfoArray[dataIndex];
|
let apiInfo = this.apiInfoArray[dataIndex];
|
||||||
|
|
||||||
let haveData = false;
|
let haveData = false;
|
||||||
//检查showArray是否存在这条数据。不存在才加入
|
//检查showArray是否存在这条数据。不存在才加入
|
||||||
this.apiShowArray.forEach(api => {
|
this.apiShowArray.forEach(api => {
|
||||||
if(api.id === apiInfo.id){
|
if (api.id === apiInfo.id) {
|
||||||
haveData = true;
|
haveData = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(!haveData){
|
if (!haveData) {
|
||||||
this.apiShowArray.push(apiInfo);
|
this.apiShowArray.push(apiInfo);
|
||||||
if(!apiInfo.selectedFlag){
|
if (!apiInfo.selectedFlag) {
|
||||||
this.selectApiInfo(dataIndex,this.apiInfoArray[dataIndex].id,true);
|
this.selectApiInfo(dataIndex, this.apiInfoArray[dataIndex].id, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.apiShowArray.length <= this.maxCompnentSize){
|
if (this.apiShowArray.length <= this.maxCompnentSize) {
|
||||||
//判断currentApiIndexInApiShowArray 是否需要添加,以及是否需要删除第一个元素
|
//判断currentApiIndexInApiShowArray 是否需要添加,以及是否需要删除第一个元素
|
||||||
this.currentApiIndexInApiShowArray++;
|
this.currentApiIndexInApiShowArray++;
|
||||||
}else{
|
} else {
|
||||||
this.apiShowArray.shift();
|
this.apiShowArray.shift();
|
||||||
let itemHeight = this.$refs.apiDocInfoDivItem[0].offsetHeight+10;
|
let itemHeight = this.$refs.apiDocInfoDivItem[0].offsetHeight + 10;
|
||||||
if(this.$refs.apiDocInfoDiv&&this.$refs.apiDocInfoDiv.scrollTop){
|
if (this.$refs.apiDocInfoDiv && this.$refs.apiDocInfoDiv.scrollTop) {
|
||||||
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivScrollTop-itemHeight);
|
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivScrollTop - itemHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.apiStepIndex ++;
|
this.apiStepIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clickStepFlag = false;
|
this.clickStepFlag = false;
|
||||||
},
|
},
|
||||||
redirectScroll(){
|
redirectScroll() {
|
||||||
if(!this.$refs.apiDocInfoDiv){
|
if (!this.$refs.apiDocInfoDiv) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//滚动条跳转:将滚动条下拉到显示对应对api接口的位置
|
//滚动条跳转:将滚动条下拉到显示对应对api接口的位置
|
||||||
let apiDocDivClientTop = 0;
|
let apiDocDivClientTop = 0;
|
||||||
let itemHeightCount = 0;
|
let itemHeightCount = 0;
|
||||||
if(this.currentApiIndexInApiShowArray > 0){
|
if (this.currentApiIndexInApiShowArray > 0) {
|
||||||
for (let i = 0; i <= this.currentApiIndexInApiShowArray-1; i++) {
|
for (let i = 0; i <= this.currentApiIndexInApiShowArray - 1; i++) {
|
||||||
let itemHeight = this.$refs.apiDocInfoDivItem[i].offsetHeight+10;
|
let itemHeight = this.$refs.apiDocInfoDivItem[i].offsetHeight + 10;
|
||||||
itemHeightCount+=itemHeight;
|
itemHeightCount += itemHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.clickStepFlag = true;
|
this.clickStepFlag = true;
|
||||||
let scrollTopIndex = this.$refs.apiDocInfoDiv.scrollTop;
|
let scrollTopIndex = this.$refs.apiDocInfoDiv.scrollTop;
|
||||||
if(this.$refs.apiDocInfoDiv&&this.$refs.apiDocInfoDiv.scrollTop){
|
if (this.$refs.apiDocInfoDiv && this.$refs.apiDocInfoDiv.scrollTop) {
|
||||||
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop+itemHeightCount);
|
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop + itemHeightCount);
|
||||||
}else if(scrollTopIndex === 0){
|
} else if (scrollTopIndex === 0) {
|
||||||
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop+itemHeightCount);
|
this.$refs.apiDocInfoDiv.scrollTop = (apiDocDivClientTop + itemHeightCount);
|
||||||
}
|
}
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
//检查要展示的api信息节点,和上下个2个及以内的范围内数据有没有查询过。并赋值为showArray
|
//检查要展示的api信息节点,和上下个2个及以内的范围内数据有没有查询过。并赋值为showArray
|
||||||
//isRedirectScroll 最后是否调用跳转函数
|
//isRedirectScroll 最后是否调用跳转函数
|
||||||
checkApiInfoNode(itemIndex,isRedirectScroll){
|
checkApiInfoNode(itemIndex, isRedirectScroll) {
|
||||||
let beforeNodeIndex = itemIndex<2?0:(itemIndex-2);
|
let beforeNodeIndex = itemIndex < 2 ? 0 : (itemIndex - 2);
|
||||||
let afterNodeIndex = (itemIndex+2)<this.apiInfoArray.length?(itemIndex+2):this.apiInfoArray.length;
|
let afterNodeIndex = (itemIndex + 2) < this.apiInfoArray.length ? (itemIndex + 2) : this.apiInfoArray.length;
|
||||||
this.apiShowArray = [];
|
this.apiShowArray = [];
|
||||||
|
|
||||||
let selectIndexArr = [];
|
let selectIndexArr = [];
|
||||||
let selectApiId = [];
|
let selectApiId = [];
|
||||||
|
|
||||||
//查当前节点前两个
|
//查当前节点前两个
|
||||||
for(let afterIndex = beforeNodeIndex;afterIndex <itemIndex;afterIndex++){
|
for (let afterIndex = beforeNodeIndex; afterIndex < itemIndex; afterIndex++) {
|
||||||
let apiInfo = this.apiInfoArray[afterIndex];
|
let apiInfo = this.apiInfoArray[afterIndex];
|
||||||
if(apiInfo==null){
|
if (apiInfo == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
if (apiInfo == null || !apiInfo.selectedFlag) {
|
||||||
let apiId = apiInfo.id;
|
let apiId = apiInfo.id;
|
||||||
if(!apiInfo.isSearching) {
|
if (!apiInfo.isSearching) {
|
||||||
apiInfo.isSearching = true;
|
apiInfo.isSearching = true;
|
||||||
selectIndexArr.push(afterIndex);
|
selectIndexArr.push(afterIndex);
|
||||||
selectApiId.push(apiId);
|
selectApiId.push(apiId);
|
||||||
|
@ -808,14 +847,14 @@ export default {
|
||||||
}
|
}
|
||||||
this.currentApiIndexInApiShowArray = this.apiShowArray.length;
|
this.currentApiIndexInApiShowArray = this.apiShowArray.length;
|
||||||
//查当前节点以及后三个
|
//查当前节点以及后三个
|
||||||
for(let beforeIndex = itemIndex;beforeIndex <= afterNodeIndex;beforeIndex++){
|
for (let beforeIndex = itemIndex; beforeIndex <= afterNodeIndex; beforeIndex++) {
|
||||||
let apiInfo = this.apiInfoArray[beforeIndex];
|
let apiInfo = this.apiInfoArray[beforeIndex];
|
||||||
if(apiInfo==null){
|
if (apiInfo == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(apiInfo == null || !apiInfo.selectedFlag){
|
if (apiInfo == null || !apiInfo.selectedFlag) {
|
||||||
let apiId = apiInfo.id;
|
let apiId = apiInfo.id;
|
||||||
if(!apiInfo.isSearching){
|
if (!apiInfo.isSearching) {
|
||||||
apiInfo.isSearching = true;
|
apiInfo.isSearching = true;
|
||||||
selectIndexArr.push(beforeIndex);
|
selectIndexArr.push(beforeIndex);
|
||||||
selectApiId.push(apiId);
|
selectApiId.push(apiId);
|
||||||
|
@ -823,10 +862,10 @@ export default {
|
||||||
}
|
}
|
||||||
this.apiShowArray.push(apiInfo);
|
this.apiShowArray.push(apiInfo);
|
||||||
}
|
}
|
||||||
if(selectIndexArr.length>0){
|
if (selectIndexArr.length > 0) {
|
||||||
this.selectApiInfoBatch(selectIndexArr,selectApiId,itemIndex,afterNodeIndex,beforeNodeIndex,isRedirectScroll);
|
this.selectApiInfoBatch(selectIndexArr, selectApiId, itemIndex, afterNodeIndex, beforeNodeIndex, isRedirectScroll);
|
||||||
}else{
|
} else {
|
||||||
if(isRedirectScroll){
|
if (isRedirectScroll) {
|
||||||
//进行跳转
|
//进行跳转
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.redirectScroll();
|
this.redirectScroll();
|
||||||
|
@ -835,28 +874,28 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//该方法只用于批量查询后的函数处理。 因为查询完成,数据更新,重新为apiShowArray赋值
|
//该方法只用于批量查询后的函数处理。 因为查询完成,数据更新,重新为apiShowArray赋值
|
||||||
updateShowArray(itemIndex,afterNodeIndex,beforeNodeIndex){
|
updateShowArray(itemIndex, afterNodeIndex, beforeNodeIndex) {
|
||||||
this.apiShowArray = [];
|
this.apiShowArray = [];
|
||||||
//查当前节点前两个
|
//查当前节点前两个
|
||||||
for(let afterIndex = beforeNodeIndex;afterIndex <itemIndex;afterIndex++){
|
for (let afterIndex = beforeNodeIndex; afterIndex < itemIndex; afterIndex++) {
|
||||||
let apiInfo = this.apiInfoArray[afterIndex];
|
let apiInfo = this.apiInfoArray[afterIndex];
|
||||||
if(apiInfo==null){
|
if (apiInfo == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.apiShowArray.push(apiInfo);
|
this.apiShowArray.push(apiInfo);
|
||||||
}
|
}
|
||||||
this.currentApiIndexInApiShowArray = this.apiShowArray.length;
|
this.currentApiIndexInApiShowArray = this.apiShowArray.length;
|
||||||
//查当前节点以及后三个
|
//查当前节点以及后三个
|
||||||
for(let beforeIndex = itemIndex;beforeIndex <= afterNodeIndex;beforeIndex++){
|
for (let beforeIndex = itemIndex; beforeIndex <= afterNodeIndex; beforeIndex++) {
|
||||||
let apiInfo = this.apiInfoArray[beforeIndex];
|
let apiInfo = this.apiInfoArray[beforeIndex];
|
||||||
if(apiInfo==null){
|
if (apiInfo == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.apiShowArray.push(apiInfo);
|
this.apiShowArray.push(apiInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -898,6 +937,11 @@ export default {
|
||||||
/*
|
/*
|
||||||
步骤条中,已经完成后的节点样式和里面a标签的样式
|
步骤条中,已经完成后的节点样式和里面a标签的样式
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/deep/ .el-step {
|
||||||
|
flex-basis: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/deep/ .el-step__head.is-finish {
|
/deep/ .el-step__head.is-finish {
|
||||||
color: #C0C4CC;
|
color: #C0C4CC;
|
||||||
border-color: #C0C4CC;
|
border-color: #C0C4CC;
|
||||||
|
@ -910,15 +954,38 @@ export default {
|
||||||
/*
|
/*
|
||||||
步骤条中,当前节点样式和当前a标签的样式
|
步骤条中,当前节点样式和当前a标签的样式
|
||||||
*/
|
*/
|
||||||
|
/deep/ .el-step__head {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
/deep/ .el-step__head.is-process {
|
/deep/ .el-step__head.is-process {
|
||||||
color: #783887;
|
color: #783887;
|
||||||
border-color: #783887;
|
border-color: #783887;
|
||||||
|
width: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-step__title.is-process /deep/ .el-link.el-link--default {
|
/deep/ .el-step__title.is-process .el-link.el-link--default.is-underline {
|
||||||
color: #783887;
|
color: #783887;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/deep/ .el-link--inner {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-step__icon-inner {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-step.is-vertical .el-step__line {
|
||||||
|
left: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/deep/ .el-step__icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.document-table {
|
.document-table {
|
||||||
margin: 10px 10px;
|
margin: 10px 10px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -942,6 +1009,7 @@ export default {
|
||||||
background-color: #FAFAFA;
|
background-color: #FAFAFA;
|
||||||
border-right: 0px solid #EBEEF5
|
border-right: 0px solid #EBEEF5
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-divider--horizontal {
|
.el-divider--horizontal {
|
||||||
margin: 12px 0;
|
margin: 12px 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,717 +0,0 @@
|
||||||
<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 = "/share/info/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("/share/info/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 = "/share/info/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(){
|
|
||||||
if(!this.$refs.apiDocInfoDiv){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
if(this.$refs.apiDocInfoDiv){
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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>
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- <api-document-item :project-id="projectId" :module-ids="moduleIds"/>-->
|
|
||||||
<api-document-anchor :is-share-page="isSharePage" :trash-enable="trashEnable" :project-id="projectId" :module-ids="moduleIds"></api-document-anchor>
|
<api-document-anchor :is-share-page="isSharePage" :trash-enable="trashEnable" :project-id="projectId" :module-ids="moduleIds"></api-document-anchor>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item index="/report" onselectstart="return false"
|
<el-menu-item index="/report" onselectstart="return false"
|
||||||
v-permission="['PROJECT_TRACK_CASE:READ','PROJECT_TRACK_PLAN:READ','PROJECT_TRACK_REVIEW:READ']"
|
v-permission="['PROJECT_TRACK_CASE:READ','PROJECT_TRACK_PLAN:READ','PROJECT_TRACK_REVIEW:READ']"
|
||||||
v-if="isReport && check('reportStat')">
|
>
|
||||||
{{ $t('commons.report_statistics.title') }}
|
{{ $t('commons.report_statistics.title') }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ import {mapGetters} from "vuex";
|
||||||
import {hasLicense} from "@/common/js/utils";
|
import {hasLicense} from "@/common/js/utils";
|
||||||
import {MODULE_CHANGE, ModuleEvent} from "@/business/components/common/head/ListEvent";
|
import {MODULE_CHANGE, ModuleEvent} from "@/business/components/common/head/ListEvent";
|
||||||
|
|
||||||
const requireContext = require.context('@/business/components/xpack/', true, /router\.js$/);
|
// const requireContext = require.context('@/business/components/xpack/', true, /router\.js$/);
|
||||||
const report = requireContext.keys().map(key => requireContext(key).report);
|
// const report = requireContext.keys().map(key => requireContext(key).report);
|
||||||
const isReport = report && report != null && report.length > 0 && report[0] != undefined ? true : false;
|
// const isReport = report && report != null && report.length > 0 && report[0] != undefined ? true : false;
|
||||||
|
|
||||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
const module = requireComponent.keys().length > 0 ? requireComponent("./module/Module.vue") : {};
|
const module = requireComponent.keys().length > 0 ? requireComponent("./module/Module.vue") : {};
|
||||||
|
@ -52,7 +52,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeIndex: '/',
|
activeIndex: '/',
|
||||||
isReport: isReport,
|
isReport: true,
|
||||||
modules: {},
|
modules: {},
|
||||||
menuKey: 0,
|
menuKey: 0,
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<json-schema-editor class="schema" :value="schema" lang="zh_CN" custom/>
|
<json-schema-editor class="schema" :value="schema" lang="zh_CN" custom/>
|
||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('schema.preview')" name="preview">
|
<el-tab-pane v-if="showPreview" :label="$t('schema.preview')" name="preview">
|
||||||
<div style="min-height: 200px">
|
<div style="min-height: 200px">
|
||||||
<pre>{{this.preview}}</pre>
|
<pre>{{this.preview}}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,6 +29,10 @@
|
||||||
components: {MsImportJson},
|
components: {MsImportJson},
|
||||||
props: {
|
props: {
|
||||||
body: {},
|
body: {},
|
||||||
|
showPreview: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (!this.body.jsonSchema && this.body.raw && this.checkIsJson(this.body.raw)) {
|
if (!this.body.jsonSchema && this.body.raw && this.checkIsJson(this.body.raw)) {
|
||||||
|
@ -46,6 +50,19 @@
|
||||||
this.body.jsonSchema = this.schema.root;
|
this.body.jsonSchema = this.schema.root;
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
handler(newValue, oldValue) {
|
||||||
|
if (!this.body.jsonSchema && this.body.raw && this.checkIsJson(this.body.raw)) {
|
||||||
|
let obj = {"root": MsConvert.format(JSON.parse(this.body.raw))}
|
||||||
|
this.schema = obj;
|
||||||
|
}
|
||||||
|
else if (this.body.jsonSchema) {
|
||||||
|
this.schema = {"root": this.body.jsonSchema};
|
||||||
|
}
|
||||||
|
this.body.jsonSchema = this.schema.root;
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -405,7 +405,9 @@ export default {
|
||||||
handler:function(){
|
handler:function(){
|
||||||
this.init();
|
this.init();
|
||||||
if(this.data && this.data.length > 0){
|
if(this.data && this.data.length > 0){
|
||||||
this.$refs.tree.setCheckedKeys(this.defaultKey);
|
if(this.defaultKey instanceof Array){
|
||||||
|
this.$refs.tree.setCheckedKeys(this.defaultKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep:true
|
deep:true
|
||||||
|
@ -413,7 +415,9 @@ export default {
|
||||||
data:{
|
data:{
|
||||||
handler:function(){
|
handler:function(){
|
||||||
if(this.defaultKey && this.defaultKey.length > 0 && this.defaultKey instanceof Array){
|
if(this.defaultKey && this.defaultKey.length > 0 && this.defaultKey instanceof Array){
|
||||||
this.$refs.tree.setCheckedKeys(this.defaultKey);
|
if(this.defaultKey instanceof Array){
|
||||||
|
this.$refs.tree.setCheckedKeys(this.defaultKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep:true
|
deep:true
|
||||||
|
|
Loading…
Reference in New Issue