Merge branch 'v1.8' of github.com:metersphere/metersphere into v1.8

This commit is contained in:
chenjianxing 2021-03-31 16:50:22 +08:00
commit b1a3dd3473
24 changed files with 257 additions and 29 deletions

View File

@ -139,7 +139,7 @@
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>springdoc-openapi-ui</artifactId>
<version>1.2.32</version> <version>1.5.6</version>
</dependency> </dependency>
<!-- jmeter --> <!-- jmeter -->
@ -280,7 +280,7 @@
<dependency> <dependency>
<groupId>io.swagger.parser.v3</groupId> <groupId>io.swagger.parser.v3</groupId>
<artifactId>swagger-parser</artifactId> <artifactId>swagger-parser</artifactId>
<version>2.0.22</version> <version>2.0.24</version>
</dependency> </dependency>
<!-- ApacheJMeter_core scope 是 runtime这里去掉scope --> <!-- ApacheJMeter_core scope 是 runtime这里去掉scope -->

View File

@ -12,8 +12,7 @@ import io.metersphere.api.dto.datacount.response.TaskInfoResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.service.*; import io.metersphere.api.service.*;
import io.metersphere.base.domain.ApiTest; import io.metersphere.base.domain.*;
import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.CronUtils;
@ -30,13 +29,15 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles;
import org.python.core.AstList;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.*; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import static io.metersphere.commons.utils.JsonPathUtils.getListJson; import static io.metersphere.commons.utils.JsonPathUtils.getListJson;
@ -251,9 +252,7 @@ public class APITestController {
@GetMapping("/testSceneInfoCount/{projectId}") @GetMapping("/testSceneInfoCount/{projectId}")
public ApiDataCountDTO testSceneInfoCount(@PathVariable String projectId) { public ApiDataCountDTO testSceneInfoCount(@PathVariable String projectId) {
ApiDataCountDTO apiCountResult = new ApiDataCountDTO(); ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
long scenarioCountNumber = apiAutomationService.countScenarioByProjectID(projectId); long scenarioCountNumber = apiAutomationService.countScenarioByProjectID(projectId);
apiCountResult.setAllApiDataCountNumber(scenarioCountNumber); apiCountResult.setAllApiDataCountNumber(scenarioCountNumber);
@ -272,17 +271,46 @@ public class APITestController {
//未执行未通过已通过 //未执行未通过已通过
List<ApiDataCountResult> countResultByRunResult = apiAutomationService.countRunResultByProjectID(projectId); List<ApiDataCountResult> countResultByRunResult = apiAutomationService.countRunResultByProjectID(projectId);
apiCountResult.countRunResult(countResultByRunResult); apiCountResult.countRunResult(countResultByRunResult);
long allCount = apiCountResult.getUnexecuteCount() + apiCountResult.getExecutionPassCount() + apiCountResult.getExecutionFailedCount(); long allCount = apiCountResult.getUnexecuteCount() + apiCountResult.getExecutionPassCount() + apiCountResult.getExecutionFailedCount();
if (allCount != 0) {
float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount;
DecimalFormat df = new DecimalFormat("0.0"); DecimalFormat df = new DecimalFormat("0.0");
if (allCount != 0) {
//通过率
float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount;
apiCountResult.setPassRage(df.format(coverageRageNumber) + "%"); apiCountResult.setPassRage(df.format(coverageRageNumber) + "%");
} }
return apiCountResult; return apiCountResult;
}
@GetMapping("/countInterfaceCoverage/{projectId}")
public String countInterfaceCoverage(@PathVariable String projectId) {
String returnStr = "100%";
/**
* 接口覆盖率
* 复制的接口定义/复制或引用的单接口用例/ 添加的自定义请求 url 路径与现有的接口定义一致的请求
*/
long startTime1 = System.currentTimeMillis();
List<ApiScenarioWithBLOBs> allScenarioInfoList = apiAutomationService.selectIdAndScenarioByProjectId(projectId);
long startTime2 = System.currentTimeMillis();
System.out.println("Search data time : " + (startTime2 - startTime1));
startTime1 = System.currentTimeMillis();
List<ApiDefinition> allEffectiveApiIdList = apiDefinitionService.selectEffectiveIdByProjectId(projectId);
startTime2 = System.currentTimeMillis();
System.out.println("Search data time api info : " + (startTime2 - startTime1));
List<ApiTestCase> allEffectiveApiCaseList = apiTestCaseService.selectEffectiveTestCaseByProjectId(projectId);
long startTime3 = System.currentTimeMillis();
System.out.println("Search data time (case info): " + (startTime3 - startTime2));
try {
startTime1 = System.currentTimeMillis();
float intetfaceCoverageRageNumber = apiAutomationService.countInterfaceCoverage(allScenarioInfoList, allEffectiveApiIdList, allEffectiveApiCaseList);
startTime2 = System.currentTimeMillis();
System.out.println("Count data time : " + (startTime2 - startTime1));
DecimalFormat df = new DecimalFormat("0.0");
returnStr = df.format(intetfaceCoverageRageNumber) + "%";
}catch (Exception e){
e.printStackTrace();
}
return returnStr;
} }
@GetMapping("/scheduleTaskInfoCount/{projectId}") @GetMapping("/scheduleTaskInfoCount/{projectId}")
@ -346,11 +374,11 @@ public class APITestController {
@GetMapping("/runningTask/{projectID}/{callFrom}") @GetMapping("/runningTask/{projectID}/{callFrom}")
public List<TaskInfoResult> runningTask(@PathVariable String projectID, @PathVariable String callFrom) { public List<TaskInfoResult> runningTask(@PathVariable String projectID, @PathVariable String callFrom) {
List<String> typeFilter = new ArrayList<>(); List<String> typeFilter = new ArrayList<>();
if(StringUtils.equals(callFrom, "api_test")) { // 接口测试首页显示的运行中定时任务只要这3种不需要 性能测试api_test(旧版) if (StringUtils.equals(callFrom, "api_test")) { // 接口测试首页显示的运行中定时任务只要这3种不需要 性能测试api_test(旧版)
typeFilter.add(ScheduleGroup.API_SCENARIO_TEST.name()); typeFilter.add(ScheduleGroup.API_SCENARIO_TEST.name());
typeFilter.add(ScheduleGroup.SWAGGER_IMPORT.name()); typeFilter.add(ScheduleGroup.SWAGGER_IMPORT.name());
typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name()); typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name());
} else if(StringUtils.equals(callFrom, "track_home")) { // 测试跟踪首页只显示测试计划的定时任务 } else if (StringUtils.equals(callFrom, "track_home")) { // 测试跟踪首页只显示测试计划的定时任务
typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name()); typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name());
} }
List<TaskInfoResult> resultList = scheduleService.findRunningTaskInfoByProjectID(projectID, typeFilter); List<TaskInfoResult> resultList = scheduleService.findRunningTaskInfoByProjectID(projectID, typeFilter);
@ -386,7 +414,7 @@ public class APITestController {
String testName = runRequest.getName(); String testName = runRequest.getName();
//将jmx处理封装为通用方法 //将jmx处理封装为通用方法
JmxInfoDTO dto = apiTestService.updateJmxString(jmxString,testName,false); JmxInfoDTO dto = apiTestService.updateJmxString(jmxString, testName, false);
dto.setName(runRequest.getName() + ".jmx"); dto.setName(runRequest.getName() + ".jmx");
return dto; return dto;
} }

View File

@ -111,6 +111,11 @@ public class ApiDataCountDTO {
*/ */
private String successRage = " 0%"; private String successRage = " 0%";
/**
* 接口覆盖率
*/
private String interfaceCoverage = " 0%";
public ApiDataCountDTO(){} public ApiDataCountDTO(){}
/** /**

View File

@ -1,6 +1,7 @@
package io.metersphere.api.service; package io.metersphere.api.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath; import com.alibaba.fastjson.JSONPath;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
@ -710,6 +711,10 @@ public class ApiAutomationService {
return extApiScenarioMapper.countByProjectID(projectId); return extApiScenarioMapper.countByProjectID(projectId);
} }
public List<ApiScenarioWithBLOBs> selectIdAndScenarioByProjectId(String projectId) {
return extApiScenarioMapper.selectIdAndScenarioByProjectId(projectId);
}
public long countScenarioByProjectIDAndCreatInThisWeek(String projectId) { public long countScenarioByProjectIDAndCreatInThisWeek(String projectId) {
Map<String, Date> startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date()); Map<String, Date> startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date());
Date firstTime = startAndEndDateInWeek.get("firstTime"); Date firstTime = startAndEndDateInWeek.get("firstTime");
@ -1031,4 +1036,131 @@ public class ApiAutomationService {
this.deleteBatch(request.getIds()); this.deleteBatch(request.getIds());
} }
/**
* 统计接口覆盖率
* 1.场景中复制的接口
* 2.场景中引用/复制的案例
* 3.场景中的自定义路径与接口定义中的匹配
*
* @param allScenarioInfoList 场景集合id / scenario大字段 必须有数据
* @param allEffectiveApiList 接口集合id / path 必须有数据
* @param allEffectiveApiCaseList 案例集合(id /api_definition_id 必须有数据)
* @return
*/
public float countInterfaceCoverage(List<ApiScenarioWithBLOBs> allScenarioInfoList, List<ApiDefinition> allEffectiveApiList, List<ApiTestCase> allEffectiveApiCaseList) {
// float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount;
float intetfaceCoverage = 0;
if (allEffectiveApiList == null || allEffectiveApiList.isEmpty()) {
return 100;
}
/**
* 前置工作
* 1将接口集合转化数据结构: map<url,List<id>> urlMap 用来做3的筛选
* 2将案例集合转化数据结构map<testCase.id,List<testCase.apiId>> caseIdMap 用来做2的筛选
* 3将接口集合转化数据结构: List<id> allApiIdList 用来做1的筛选
* 4自定义List<api.id> coveragedIdList 已覆盖的id集合 最终计算公式是 coveragedIdList/allApiIdList
*
* 解析allScenarioList的scenarioDefinition字段
* 1提取每个步骤的url urlMap筛选
* 2提取每个步骤的id. 在caseIdMap allApiIdList
*/
Map<String, List<String>> urlMap = new HashMap<>();
List<String> allApiIdList = new ArrayList<>();
Map<String,List<String>> caseIdMap = new HashMap<>();
for (ApiDefinition model : allEffectiveApiList) {
String url = model.getPath();
String id = model.getId();
allApiIdList.add(id);
if (urlMap.containsKey(url)) {
urlMap.get(url).add(id);
} else {
List<String> list = new ArrayList<>();
list.add(id);
urlMap.put(url, list);
}
}
for (ApiTestCase model : allEffectiveApiCaseList){
String caseId = model.getId();
String apiId = model.getApiDefinitionId();
if (urlMap.containsKey(caseId)) {
urlMap.get(caseId).add(apiId);
} else {
List<String> list = new ArrayList<>();
list.add(apiId);
urlMap.put(caseId, list);
}
}
if (allApiIdList.isEmpty()) {
return 100;
}
List<String> urlList = new ArrayList<>();
List<String> idList= new ArrayList<>();
for (ApiScenarioWithBLOBs model : allScenarioInfoList) {
String scenarioDefiniton = model.getScenarioDefinition();
this.addUrlAndIdToList(scenarioDefiniton,urlList,idList);
}
List<String> containsApiIdList = new ArrayList<>();
for (String url : urlList) {
List<String> apiIdList = urlMap.get(url);
if(apiIdList!=null ){
for (String api : apiIdList) {
if(!containsApiIdList.contains(api)){
containsApiIdList.add(api);
}
}
}
}
for (String id : idList) {
List<String> apiIdList = caseIdMap.get(id);
if(apiIdList!=null ){
for (String api : apiIdList) {
if(!containsApiIdList.contains(api)){
containsApiIdList.add(api);
}
}
}
if(allApiIdList.contains(id)){
if(!containsApiIdList.contains(id)){
containsApiIdList.add(id);
}
}
}
float coverageRageNumber = (float) containsApiIdList.size() * 100 / allApiIdList.size();
return coverageRageNumber;
}
private void addUrlAndIdToList(String scenarioDefiniton, List<String> urlList, List<String> idList) {
try {
JSONObject scenarioObj = JSONObject.parseObject(scenarioDefiniton);
if(scenarioObj.containsKey("hashTree")){
JSONArray hashArr = scenarioObj.getJSONArray("hashTree");
for (int i = 0; i < hashArr.size(); i++) {
JSONObject elementObj = hashArr.getJSONObject(i);
if(elementObj.containsKey("id")){
String id = elementObj.getString("id");
idList.add(id);
}
if(elementObj.containsKey("url")){
String url = elementObj.getString("url");
urlList.add(url);
}
if(elementObj.containsKey("path")){
String path = elementObj.getString("path");
urlList.add(path);
}
}
}
}catch (Exception e){
}
}
} }

View File

@ -912,4 +912,8 @@ public class ApiDefinitionService {
} }
return apiExportResult; return apiExportResult;
} }
public List<ApiDefinition> selectEffectiveIdByProjectId(String projectId) {
return extApiDefinitionMapper.selectEffectiveIdByProjectId(projectId);
}
} }

View File

@ -648,4 +648,8 @@ public class ApiTestCaseService {
public ApiDefinitionExecResult getInfo(String id){ public ApiDefinitionExecResult getInfo(String id){
return apiDefinitionExecResultMapper.selectByPrimaryKey(id); return apiDefinitionExecResultMapper.selectByPrimaryKey(id);
} }
public List<ApiTestCase> selectEffectiveTestCaseByProjectId(String projectId) {
return extApiTestCaseMapper.selectEffectiveTestCaseByProjectId(projectId);
}
} }

View File

@ -38,4 +38,6 @@ public interface ExtApiDefinitionMapper {
List<ApiDefinitionResult> listRelevance(@Param("request")ApiDefinitionRequest request); List<ApiDefinitionResult> listRelevance(@Param("request")ApiDefinitionRequest request);
List<ApiDefinitionResult> listRelevanceReview(@Param("request")ApiDefinitionRequest request); List<ApiDefinitionResult> listRelevanceReview(@Param("request")ApiDefinitionRequest request);
List<String> selectIds(@Param("request") BaseQueryRequest query); List<String> selectIds(@Param("request") BaseQueryRequest query);
List<ApiDefinition> selectEffectiveIdByProjectId(String projectId);
} }

View File

@ -465,6 +465,11 @@
<include refid="queryWhereCondition"/> <include refid="queryWhereCondition"/>
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/> <include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
</select> </select>
<select id="selectEffectiveIdByProjectId" resultType="io.metersphere.base.domain.ApiDefinition">
select id,path
from api_definition
WHERE project_id = #{0} AND status != 'Trash'
</select>
<sql id="queryWhereCondition"> <sql id="queryWhereCondition">
<where> <where>

View File

@ -6,7 +6,6 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioExample; import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.controller.request.BaseQueryRequest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -28,6 +27,8 @@ public interface ExtApiScenarioMapper {
long countByProjectID(String projectId); long countByProjectID(String projectId);
List<ApiScenarioWithBLOBs> selectIdAndScenarioByProjectId(String projectId);
long countByProjectIDAndCreatInThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp); long countByProjectIDAndCreatInThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
List<ApiDataCountResult> countRunResultByProjectID(String projectId); List<ApiDataCountResult> countRunResultByProjectID(String projectId);

View File

@ -304,6 +304,9 @@
<select id="countByProjectID" resultType="java.lang.Long"> <select id="countByProjectID" resultType="java.lang.Long">
SELECT COUNT(id) AS countNumber FROM api_scenario WHERE project_id = #{0} AND status != 'Trash' SELECT COUNT(id) AS countNumber FROM api_scenario WHERE project_id = #{0} AND status != 'Trash'
</select> </select>
<select id="selectIdAndScenarioByProjectId" resultType="io.metersphere.base.domain.ApiScenarioWithBLOBs">
SELECT id,scenario_definition FROM api_scenario WHERE project_id = #{0} AND status != 'Trash'
</select>
<select id="countByProjectIDAndCreatInThisWeek" resultType="java.lang.Long"> <select id="countByProjectIDAndCreatInThisWeek" resultType="java.lang.Long">
SELECT count(id) AS countNumber FROM api_scenario SELECT count(id) AS countNumber FROM api_scenario
WHERE project_id = #{projectId} AND status != 'Trash' WHERE project_id = #{projectId} AND status != 'Trash'

View File

@ -31,4 +31,6 @@ public interface ExtApiTestCaseMapper {
ApiTestCase getNextNum(@Param("definitionId") String definitionId); ApiTestCase getNextNum(@Param("definitionId") String definitionId);
ApiTestCaseInfo selectApiCaseInfoByPrimaryKey(String id); ApiTestCaseInfo selectApiCaseInfoByPrimaryKey(String id);
List<ApiTestCase> selectEffectiveTestCaseByProjectId(String projectId);
} }

View File

@ -394,5 +394,8 @@
<select id="listPorjectAllCaseName" resultType="java.lang.String"> <select id="listPorjectAllCaseName" resultType="java.lang.String">
select name from api_test_case where project_id = #{projectId} select name from api_test_case where project_id = #{projectId}
</select> </select>
<select id="selectEffectiveTestCaseByProjectId" resultType="io.metersphere.base.domain.ApiTestCase">
select id,api_definition_id from api_test_case where project_id = #{projectId}
</select>
</mapper> </mapper>

View File

@ -91,8 +91,8 @@ public class TestPlanController {
@PostMapping("/edit") @PostMapping("/edit")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void editTestPlan(@RequestBody TestPlanDTO testPlanDTO) { public String editTestPlan(@RequestBody TestPlanDTO testPlanDTO) {
testPlanService.editTestPlan(testPlanDTO, true); return testPlanService.editTestPlan(testPlanDTO, true);
} }
@PostMapping("/edit/status/{planId}") @PostMapping("/edit/status/{planId}")

View File

@ -176,7 +176,7 @@ public class TestPlanService {
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlan()); return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlan());
} }
public int editTestPlan(TestPlanDTO testPlan, Boolean isSendMessage) { public String editTestPlan(TestPlanDTO testPlan, Boolean isSendMessage) {
checkTestPlanExist(testPlan); checkTestPlanExist(testPlan);
TestPlan res = testPlanMapper.selectByPrimaryKey(testPlan.getId()); // 先查一次库 TestPlan res = testPlanMapper.selectByPrimaryKey(testPlan.getId()); // 先查一次库
testPlan.setUpdateTime(System.currentTimeMillis()); testPlan.setUpdateTime(System.currentTimeMillis());
@ -230,7 +230,7 @@ public class TestPlanService {
.build(); .build();
noticeSendService.send(NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel); noticeSendService.send(NoticeConstants.TaskType.TEST_PLAN_TASK, noticeModel);
} }
return i; return testPlan.getId();
} }
//计划内容 //计划内容

View File

@ -152,6 +152,7 @@
saveApiAndCase(api) { saveApiAndCase(api) {
this.visible = true; this.visible = true;
this.api = api; this.api = api;
this.currentApi = api;
this.addCase(); this.addCase();
}, },
setEnvironment(environment) { setEnvironment(environment) {

View File

@ -34,7 +34,7 @@
<ms-test-case-info-card @redirectPage="redirectPage" :test-case-count-data="testCaseCountData"/> <ms-test-case-info-card @redirectPage="redirectPage" :test-case-count-data="testCaseCountData"/>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<ms-scene-info-card @redirectPage="redirectPage" :scene-count-data="sceneCountData"/> <ms-scene-info-card @redirectPage="redirectPage" :scene-count-data="sceneCountData" :interface-coverage="interfaceCoverage"/>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<ms-schedule-task-info-card :schedule-task-count-data="scheduleTaskCountData"/> <ms-schedule-task-info-card :schedule-task-count-data="scheduleTaskCountData"/>
@ -82,6 +82,7 @@ export default {
sceneCountData: {}, sceneCountData: {},
testCaseCountData: {}, testCaseCountData: {},
scheduleTaskCountData: {}, scheduleTaskCountData: {},
interfaceCoverage: "waitting...",
tipsType: "1", tipsType: "1",
result: {}, result: {},
} }
@ -109,6 +110,10 @@ export default {
this.sceneCountData = response.data; this.sceneCountData = response.data;
}); });
this.$get("/api/countInterfaceCoverage/" + selectProjectId, response => {
this.interfaceCoverage = response.data;
});
this.$get("/api/testCaseInfoCount/" + selectProjectId, response => { this.$get("/api/testCaseInfoCount/" + selectProjectId, response => {
this.testCaseCountData = response.data; this.testCaseCountData = response.data;
}); });

View File

@ -52,16 +52,29 @@
<el-main style="padding: 5px;margin-top: 10px"> <el-main style="padding: 5px;margin-top: 10px">
<el-container> <el-container>
<el-aside width="60%" class="count-number-show" style="margin-bottom: 0px;margin-top: 0px"> <el-aside width="60%" class="count-number-show" style="margin-bottom: 0px;margin-top: 0px">
<el-container> <el-container style="height: 50px;margin-top: 10px">
<el-aside width="30%"> <el-aside width="50%" style="line-height: 40px;">
{{$t('api_test.home_page.detail_card.rate.pass')+":"}} {{$t('api_test.home_page.detail_card.rate.pass')+":"}}
</el-aside> </el-aside>
<el-main style="padding: 0px 0px 0px 0px; line-height: 100px; text-align: center;"> <el-main style="padding: 0px 0px 0px 0px; line-height: 40px; text-align: center;">
<span class="count-number"> <span class="rows-count-number">
{{sceneCountData.passRage}} {{sceneCountData.passRage}}
</span> </span>
</el-main> </el-main>
</el-container> </el-container>
<el-container style="height: 50px;margin-top: 1px">
<el-aside width="50%" style="line-height: 40px;">
<span>{{$t('api_test.home_page.detail_card.rate.interface_coverage')+":"}}</span>
</el-aside>
<el-main style="padding: 0px 0px 0px 0px; line-height: 40px; text-align: center;">
<span v-if="interfaceCoverage === 'waitting...'">
{{interfaceCoverage}}
</span>
<span v-else class="rows-count-number">
{{interfaceCoverage}}
</span>
</el-main>
</el-container>
</el-aside> </el-aside>
<el-main style="padding: 5px"> <el-main style="padding: 5px">
<el-card class="no-shadow-card" body-style="padding-left:5px;padding-right:5px"> <el-card class="no-shadow-card" body-style="padding-left:5px;padding-right:5px">
@ -120,6 +133,7 @@ export default {
props:{ props:{
sceneCountData:{}, sceneCountData:{},
interfaceCoverage:String,
}, },
methods: { methods: {
@ -141,6 +155,13 @@ export default {
margin:20px auto; margin:20px auto;
} }
.rows-count-number{
font-family:'ArialMT', 'Arial', sans-serif;
font-size:30px;
color: var(--count_number);
margin:20px auto;
}
.main-number-show { .main-number-show {
width: 100px; width: 100px;
height: 100px; height: 100px;

View File

@ -11,7 +11,6 @@
<ms-node-tree <ms-node-tree
v-loading="result.loading" v-loading="result.loading"
:tree-nodes="data" :tree-nodes="data"
:allLabel="$t('commons.module.default_module')"
@add="add" @add="add"
:type="'edit'" :type="'edit'"
@edit="edit" @edit="edit"

View File

@ -379,14 +379,17 @@
.common-tree { .common-tree {
overflow: auto; overflow: auto;
height: 200px; min-height: 200px;
max-height: 400px;
} }
.ms-tree-select { .ms-tree-select {
width: 100%; width: 100%;
z-index: 111; z-index: 111;
} }
/deep/.el-tree-node__children{
overflow: inherit;
}
.ok { .ok {
float: right; float: right;
} }

View File

@ -711,7 +711,7 @@ export default {
.border-hidden >>> .el-textarea__inner { .border-hidden >>> .el-textarea__inner {
border-style: hidden; border-style: hidden;
background-color: white; background-color: white;
color: #606266; color: #060505;
} }
.cast_label { .cast_label {
@ -785,4 +785,5 @@ p {
height: 550px; height: 550px;
overflow: auto; overflow: auto;
} }
</style> </style>

View File

@ -549,4 +549,10 @@ export default {
.comment-card >>> .el-card__body { .comment-card >>> .el-card__body {
height: calc(100vh - 120px); height: calc(100vh - 120px);
} }
.tb-edit >>> .el-textarea__inner {
border-style: hidden;
background-color: white;
color: #060505;
}
</style> </style>

View File

@ -1001,6 +1001,7 @@ export default {
coverage: "Coverage rate", coverage: "Coverage rate",
pass: "Pass rate", pass: "Pass rate",
success: "Success rate", success: "Success rate",
interface_coverage: "Interface coverage",
}, },
}, },
api_details_card: { api_details_card: {

View File

@ -1005,6 +1005,7 @@ export default {
coverage: "覆盖率", coverage: "覆盖率",
pass: "通过率", pass: "通过率",
success: "成功率", success: "成功率",
interface_coverage: "接口覆盖率",
}, },
}, },
api_details_card: { api_details_card: {

View File

@ -1003,6 +1003,7 @@ export default {
coverage: "覆蓋率", coverage: "覆蓋率",
pass: "通過率", pass: "通過率",
success: "成功率", success: "成功率",
interface_coverage: "接口覆蓋率",
}, },
}, },
api_details_card: { api_details_card: {