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:
song-tianyang 2021-09-28 10:52:04 +08:00 committed by song-tianyang
parent 0a47d283a2
commit ff1407d24f
14 changed files with 457 additions and 929 deletions

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ import io.metersphere.api.dto.definition.parse.Swagger3Parser;
import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.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());

View File

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

View File

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

View File

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

View File

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

View File

@ -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, //apimaxCompnentSizetrue needAsyncSelect: false, //apimaxCompnentSizetrue
currentApiIndexInApiShowArray: 0,//apiapiShowArray currentApiIndexInApiShowArray: 0,//apiapiShowArray
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){ if (!haveData) {
this.apiShowArray.unshift(apiInfo); this.apiShowArray.unshift(apiInfo);
if(!apiInfo.selectedFlag){ if (!apiInfo.selectedFlag) {
this.selectApiInfo(dataIndex,this.apiInfoArray[dataIndex].id,true); this.selectApiInfo(dataIndex, this.apiInfoArray[dataIndex].id, true);
} }
}else { } else {
this.currentApiIndexInApiShowArray--; this.currentApiIndexInApiShowArray--;
} }
}else{ } else {
this.currentApiIndexInApiShowArray--; 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;
}, },
//api2showArray //api2showArray
//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;
} }

View File

@ -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){
//api3
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>

View File

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

View File

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

View File

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

View File

@ -405,16 +405,20 @@ export default {
handler:function(){ handler:function(){
this.init(); this.init();
if(this.data && this.data.length > 0){ if(this.data && this.data.length > 0){
if(this.defaultKey instanceof Array){
this.$refs.tree.setCheckedKeys(this.defaultKey); this.$refs.tree.setCheckedKeys(this.defaultKey);
} }
}
}, },
deep:true deep:true
}, },
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){
if(this.defaultKey instanceof Array){
this.$refs.tree.setCheckedKeys(this.defaultKey); this.$refs.tree.setCheckedKeys(this.defaultKey);
} }
}
}, },
deep:true deep:true
}, },