Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
90adde0933
|
@ -541,6 +541,11 @@
|
||||||
<include name="*.html"/>
|
<include name="*.html"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</move>
|
</move>
|
||||||
|
<copy todir="src/main/resources/static/css">
|
||||||
|
<fileset dir="../frontend/src/assets/theme">
|
||||||
|
<include name="index.css"/>
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
</target>
|
</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
<goals>
|
<goals>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.controller.request.BaseQueryRequest;
|
||||||
import io.metersphere.track.dto.TestCaseDTO;
|
import io.metersphere.track.dto.TestCaseDTO;
|
||||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||||
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
import io.metersphere.track.request.testcase.TestCaseBatchRequest;
|
||||||
|
import io.metersphere.track.response.TrackCountResult;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -48,4 +49,32 @@ public interface ExtTestCaseMapper {
|
||||||
int checkIsHave(@Param("caseId") String caseId, @Param("workspaceIds") Set<String> workspaceIds);
|
int checkIsHave(@Param("caseId") String caseId, @Param("workspaceIds") Set<String> workspaceIds);
|
||||||
|
|
||||||
List<String> selectIds(@Param("request") BaseQueryRequest condition);
|
List<String> selectIds(@Param("request") BaseQueryRequest condition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照用例等级统计
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @return 统计结果
|
||||||
|
*/
|
||||||
|
List<TrackCountResult> countPriority(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
long countCreatedThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
|
||||||
|
|
||||||
|
List<TrackCountResult> countStatus(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
List<TrackCountResult> countRelevance(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
long countRelevanceCreatedThisWeek(@Param("projectId") String projectId,@Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp);
|
||||||
|
|
||||||
|
List<TrackCountResult> countCoverage(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
List<TrackCountResult> countFuncMaintainer(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
List<TrackCountResult> countRelevanceMaintainer(@Param("projectId") String projectId);
|
||||||
|
|
||||||
|
int getTestPlanBug(@Param("planId") String planId);
|
||||||
|
int getTestPlanCase(@Param("planId") String planId);
|
||||||
|
int getTestPlanPassCase(@Param("planId") String planId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,4 +319,87 @@
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
<select id="countPriority" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
SELECT test_case.priority as groupField,count(id) AS countNumber FROM test_case WHERE project_id = #{projectId} GROUP BY test_case.priority
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- todo 排除删除的用例统计-->
|
||||||
|
<select id="countCreatedThisWeek" resultType="java.lang.Long">
|
||||||
|
SELECT count(id) AS countNumber FROM test_case WHERE test_case.project_id = #{projectId}
|
||||||
|
AND create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
||||||
|
</select>
|
||||||
|
<!-- todo 排除删除的用例统计-->
|
||||||
|
<select id="countStatus" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
SELECT review_status AS groupField,count(id) AS countNumber FROM test_case WHERE project_id = #{projectId} GROUP BY test_case.review_status
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countRelevance" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
SELECT type AS groupField, count(id) AS countNumber FROM test_case WHERE test_case.project_id = #{projectId} GROUP BY test_case.type
|
||||||
|
</select>
|
||||||
|
<select id="countRelevanceCreatedThisWeek" resultType="java.lang.Long">
|
||||||
|
SELECT count(id) AS countNumber FROM test_case WHERE test_case.project_id = #{projectId}
|
||||||
|
AND create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countCoverage" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
SELECT count(test_case.id) AS countNumber,
|
||||||
|
if(test_case.test_id is null,"uncoverage","coverage") AS groupField
|
||||||
|
FROM test_case WHERE test_case.project_id=#{projectId} and test_case.type != 'functional' GROUP BY groupField
|
||||||
|
</select>
|
||||||
|
<select id="countFuncMaintainer" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id
|
||||||
|
where tc.project_id = #{projectId}
|
||||||
|
group by tc.maintainer
|
||||||
|
</select>
|
||||||
|
<select id="countRelevanceMaintainer" resultType="io.metersphere.track.response.TrackCountResult">
|
||||||
|
select count(tc.id) as countNumber, user.name as groupField from test_case tc right join user on tc.maintainer = user.id
|
||||||
|
where tc.project_id = #{projectId} and tc.test_id is not null
|
||||||
|
group by tc.maintainer
|
||||||
|
</select>
|
||||||
|
<select id="getTestPlanBug" resultType="int">
|
||||||
|
select count(tci.issues_id) from test_plan_test_case tptc join test_case_issues tci on tptc.case_id = tci.test_case_id
|
||||||
|
where tptc.plan_id = #{planId};
|
||||||
|
</select>
|
||||||
|
<select id="getTestPlanCase" resultType="int">
|
||||||
|
select count(s)
|
||||||
|
from (
|
||||||
|
select id as s
|
||||||
|
from test_plan_test_case tptc
|
||||||
|
where tptc.plan_id = #{planId}
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_api_scenario tpas
|
||||||
|
where tpas.test_plan_id = #{planId}
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_api_case tpac
|
||||||
|
where tpac.test_plan_id = #{planId}
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_load_case tplc
|
||||||
|
where tplc.test_plan_id = #{planId}
|
||||||
|
) as temp
|
||||||
|
</select>
|
||||||
|
<select id="getTestPlanPassCase" resultType="int">
|
||||||
|
select count(s)
|
||||||
|
from (
|
||||||
|
select id as s
|
||||||
|
from test_plan_test_case tptc
|
||||||
|
where tptc.plan_id = #{planId} and tptc.status = 'Pass'
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_api_scenario tpas
|
||||||
|
where tpas.test_plan_id = #{planId} and tpas.last_result = 'Success'
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_api_case tpac
|
||||||
|
where tpac.test_plan_id = #{planId} and tpac.status = 'success'
|
||||||
|
union all
|
||||||
|
select id as s
|
||||||
|
from test_plan_load_case tplc
|
||||||
|
where tplc.test_plan_id = #{planId} and tplc.status = 'success'
|
||||||
|
) as temp
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -42,10 +42,13 @@ public class ShiroUtils {
|
||||||
//api-对外文档页面提供的查询接口
|
//api-对外文档页面提供的查询接口
|
||||||
filterChainDefinitionMap.put("/api/document/**", "anon");
|
filterChainDefinitionMap.put("/api/document/**", "anon");
|
||||||
// filterChainDefinitionMap.put("/document/**", "anon");
|
// filterChainDefinitionMap.put("/document/**", "anon");
|
||||||
|
filterChainDefinitionMap.put("/system/theme", "anon");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ignoreCsrfFilter(Map<String, String> filterChainDefinitionMap) {
|
public static void ignoreCsrfFilter(Map<String, String> filterChainDefinitionMap) {
|
||||||
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
|
filterChainDefinitionMap.put("/", "apikey, authc"); // 跳转到 / 不用校验 csrf
|
||||||
|
filterChainDefinitionMap.put("/language", "apikey, authc");// 跳转到 /language 不用校验 csrf
|
||||||
filterChainDefinitionMap.put("/document", "apikey, authc"); // 跳转到 /document 不用校验 csrf
|
filterChainDefinitionMap.put("/document", "apikey, authc"); // 跳转到 /document 不用校验 csrf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -676,6 +676,13 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
((List<?>) durations).remove(0);
|
((List<?>) durations).remove(0);
|
||||||
duration = o.toString();
|
duration = o.toString();
|
||||||
}
|
}
|
||||||
|
Object units = context.getProperty("unit");
|
||||||
|
String unit = "S";
|
||||||
|
if (units instanceof List) {
|
||||||
|
Object o = ((List<?>) units).get(0);
|
||||||
|
((List<?>) units).remove(0);
|
||||||
|
unit = o.toString();
|
||||||
|
}
|
||||||
Object deleteds = context.getProperty("deleted");
|
Object deleteds = context.getProperty("deleted");
|
||||||
String deleted = "false";
|
String deleted = "false";
|
||||||
if (deleteds instanceof List) {
|
if (deleteds instanceof List) {
|
||||||
|
@ -691,6 +698,17 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
enabled = o.toString();
|
enabled = o.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (unit) {
|
||||||
|
case "M":
|
||||||
|
duration = String.valueOf(Long.parseLong(duration) * 60);
|
||||||
|
break;
|
||||||
|
case "H":
|
||||||
|
duration = String.valueOf(Long.parseLong(duration) * 60 * 60);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
threadGroup.setAttribute("enabled", enabled);
|
threadGroup.setAttribute("enabled", enabled);
|
||||||
if (BooleanUtils.toBoolean(deleted)) {
|
if (BooleanUtils.toBoolean(deleted)) {
|
||||||
threadGroup.setAttribute("enabled", "false");
|
threadGroup.setAttribute("enabled", "false");
|
||||||
|
@ -761,6 +779,13 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
((List<?>) holds).remove(0);
|
((List<?>) holds).remove(0);
|
||||||
hold = o.toString();
|
hold = o.toString();
|
||||||
}
|
}
|
||||||
|
Object units = context.getProperty("unit");
|
||||||
|
String unit = "S";
|
||||||
|
if (units instanceof List) {
|
||||||
|
Object o = ((List<?>) units).get(0);
|
||||||
|
((List<?>) units).remove(0);
|
||||||
|
unit = o.toString();
|
||||||
|
}
|
||||||
Object deleteds = context.getProperty("deleted");
|
Object deleteds = context.getProperty("deleted");
|
||||||
String deleted = "false";
|
String deleted = "false";
|
||||||
if (deleteds instanceof List) {
|
if (deleteds instanceof List) {
|
||||||
|
@ -776,6 +801,17 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
enabled = o.toString();
|
enabled = o.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (unit) {
|
||||||
|
case "M":
|
||||||
|
hold = String.valueOf(Long.parseLong(hold) * 60);
|
||||||
|
break;
|
||||||
|
case "H":
|
||||||
|
hold = String.valueOf(Long.parseLong(hold) * 60 * 60);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
threadGroup.setAttribute("enabled", enabled);
|
threadGroup.setAttribute("enabled", enabled);
|
||||||
if (BooleanUtils.toBoolean(deleted)) {
|
if (BooleanUtils.toBoolean(deleted)) {
|
||||||
threadGroup.setAttribute("enabled", "false");
|
threadGroup.setAttribute("enabled", "false");
|
||||||
|
@ -928,10 +964,10 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element createStringProp(Document document, String name, String value) {
|
private Element createStringProp(Document document, String name, String value) {
|
||||||
Element unit = document.createElement(STRING_PROP);
|
Element element = document.createElement(STRING_PROP);
|
||||||
unit.setAttribute("name", name);
|
element.setAttribute("name", name);
|
||||||
unit.appendChild(document.createTextNode(value));
|
element.appendChild(document.createTextNode(value));
|
||||||
return unit;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processThreadGroupName(Element threadGroup) {
|
private void processThreadGroupName(Element threadGroup) {
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
package io.metersphere.track.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.performance.base.ChartsData;
|
||||||
|
import io.metersphere.track.response.BugStatustics;
|
||||||
|
import io.metersphere.track.response.TrackCountResult;
|
||||||
|
import io.metersphere.track.response.TrackStatisticsDTO;
|
||||||
|
import io.metersphere.track.service.TrackService;
|
||||||
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/track")
|
||||||
|
@RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER, RoleConstants.ORG_ADMIN}, logical = Logical.OR)
|
||||||
|
public class TrackController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TrackService trackService;
|
||||||
|
|
||||||
|
@GetMapping("/count/{projectId}")
|
||||||
|
public TrackStatisticsDTO getTrackCount(@PathVariable String projectId) {
|
||||||
|
TrackStatisticsDTO statistics = new TrackStatisticsDTO();
|
||||||
|
|
||||||
|
List<TrackCountResult> priorityResults = trackService.countPriority(projectId);
|
||||||
|
statistics.countPriority(priorityResults);
|
||||||
|
|
||||||
|
long size = trackService.countCreatedThisWeek(projectId);
|
||||||
|
statistics.setThisWeekAddedCount(size);
|
||||||
|
|
||||||
|
List<TrackCountResult> statusResults = trackService.countStatus(projectId);
|
||||||
|
statistics.countStatus(statusResults);
|
||||||
|
|
||||||
|
long total = statistics.getPrepareCount() + statistics.getPassCount() + statistics.getUnPassCount();
|
||||||
|
if (total != 0) {
|
||||||
|
float reviewed = (float) (statistics.getPassCount() + statistics.getUnPassCount()) * 100 / total;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
statistics.setReviewRage(df.format(reviewed) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
statistics.setP0CountStr("P0 <br/><br/>" + statistics.getP0CaseCountNumber());
|
||||||
|
statistics.setP1CountStr("P1 <br/><br/>" + statistics.getP1CaseCountNumber());
|
||||||
|
statistics.setP2CountStr("P2 <br/><br/>" + statistics.getP2CaseCountNumber());
|
||||||
|
statistics.setP3CountStr("P3 <br/><br/>" + statistics.getP3CaseCountNumber());
|
||||||
|
return statistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/relevance/count/{projectId}")
|
||||||
|
public TrackStatisticsDTO getRelevanceCount(@PathVariable String projectId) {
|
||||||
|
TrackStatisticsDTO statistics = new TrackStatisticsDTO();
|
||||||
|
|
||||||
|
List<TrackCountResult> relevanceResults = trackService.countRelevance(projectId);
|
||||||
|
statistics.countRelevance(relevanceResults);
|
||||||
|
|
||||||
|
long size = trackService.countRelevanceCreatedThisWeek(projectId);
|
||||||
|
statistics.setThisWeekAddedCount(size);
|
||||||
|
|
||||||
|
List<TrackCountResult> coverageResults = trackService.countCoverage(projectId);
|
||||||
|
statistics.countCoverage(coverageResults);
|
||||||
|
|
||||||
|
long total = statistics.getUncoverageCount() + statistics.getCoverageCount();
|
||||||
|
|
||||||
|
if (total != 0) {
|
||||||
|
float coverageRageNumber = (float) statistics.getCoverageCount() * 100 / total;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
statistics.setCoverageRage(df.format(coverageRageNumber) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
statistics.setApiCaseCountStr("接口用例 <br/><br/>" + statistics.getApiCaseCount());
|
||||||
|
statistics.setPerformanceCaseCountStr("性能用例 <br/><br/>" + statistics.getPerformanceCaseCount());
|
||||||
|
statistics.setScenarioCaseStr("场景用例 <br/><br/>" + statistics.getScenarioCaseCount());
|
||||||
|
|
||||||
|
return statistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/case/bar/{projectId}")
|
||||||
|
public List<ChartsData> getCaseMaintenanceBar(@PathVariable String projectId) {
|
||||||
|
return trackService.getCaseMaintenanceBar(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/bug/count/{projectId}")
|
||||||
|
public BugStatustics getBugStatistics(@PathVariable String projectId) {
|
||||||
|
return trackService.getBugStatistics(projectId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.track.request.testcase;
|
||||||
|
|
||||||
|
public class TrackCount {
|
||||||
|
public static final String P0 = "P0";
|
||||||
|
public static final String P1 = "P1";
|
||||||
|
public static final String P2 = "P2";
|
||||||
|
public static final String P3 = "P3";
|
||||||
|
|
||||||
|
public static final String API = "api";
|
||||||
|
public static final String PERFORMANCE = "performance";
|
||||||
|
public static final String AUTOMATION = "automation";
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.track.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class BugStatustics {
|
||||||
|
|
||||||
|
private long bugTotalSize;
|
||||||
|
private String rage;
|
||||||
|
private List<TestPlanBugCount> list = new ArrayList<>();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.track.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TestPlanBugCount {
|
||||||
|
private int index;
|
||||||
|
private String planName;
|
||||||
|
private long createTime;
|
||||||
|
private String status;
|
||||||
|
private int caseSize;
|
||||||
|
private int bugSize;
|
||||||
|
private String passRage;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package io.metersphere.track.response;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TrackCountResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分组统计字段
|
||||||
|
*/
|
||||||
|
private String groupField;
|
||||||
|
/**
|
||||||
|
* 数据统计
|
||||||
|
*/
|
||||||
|
private long countNumber;
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
package io.metersphere.track.response;
|
||||||
|
|
||||||
|
import io.metersphere.api.dto.datacount.ApiDataCountResult;
|
||||||
|
import io.metersphere.commons.constants.TestReviewCaseStatus;
|
||||||
|
import io.metersphere.track.request.testcase.TrackCount;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用例数量统计数据
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TrackStatisticsDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用例总计
|
||||||
|
*/
|
||||||
|
private long allCaseCountNumber = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P0登记用例总计
|
||||||
|
*/
|
||||||
|
private long p0CaseCountNumber = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P1登记用例总计
|
||||||
|
*/
|
||||||
|
private long p1CaseCountNumber = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P2登记用例总计
|
||||||
|
*/
|
||||||
|
private long p2CaseCountNumber = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P3登记用例总计
|
||||||
|
*/
|
||||||
|
private long p3CaseCountNumber = 0;
|
||||||
|
|
||||||
|
private String p0CountStr = "";
|
||||||
|
private String p1CountStr = "";
|
||||||
|
private String p2CountStr = "";
|
||||||
|
private String p3CountStr = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联用例数量统计
|
||||||
|
*/
|
||||||
|
private long allRelevanceCaseCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口用例数量统计
|
||||||
|
*/
|
||||||
|
private long apiCaseCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 场景用例数量统计
|
||||||
|
*/
|
||||||
|
private long scenarioCaseCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 性能用例数量统计
|
||||||
|
*/
|
||||||
|
private long performanceCaseCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private String apiCaseCountStr = "";
|
||||||
|
private String scenarioCaseStr = "";
|
||||||
|
private String performanceCaseCountStr = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本周新增数量
|
||||||
|
*/
|
||||||
|
private long thisWeekAddedCount = 0;
|
||||||
|
/**
|
||||||
|
* 未覆盖
|
||||||
|
*/
|
||||||
|
private long uncoverageCount = 0;
|
||||||
|
/**
|
||||||
|
* 已覆盖
|
||||||
|
*/
|
||||||
|
private long coverageCount = 0;
|
||||||
|
/**
|
||||||
|
* 覆盖率
|
||||||
|
*/
|
||||||
|
private String coverageRage = " 0%";
|
||||||
|
/**
|
||||||
|
* 评审率
|
||||||
|
*/
|
||||||
|
private String reviewRage = " 0%";
|
||||||
|
/**
|
||||||
|
* 未评审
|
||||||
|
*/
|
||||||
|
private long prepareCount = 0;
|
||||||
|
/**
|
||||||
|
* 已通过
|
||||||
|
*/
|
||||||
|
private long passCount = 0;
|
||||||
|
/**
|
||||||
|
* 未通过
|
||||||
|
*/
|
||||||
|
private long unPassCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照 Priority 统计
|
||||||
|
* @param trackCountResults 统计结果
|
||||||
|
*/
|
||||||
|
public void countPriority(List<TrackCountResult> trackCountResults) {
|
||||||
|
for (TrackCountResult countResult : trackCountResults) {
|
||||||
|
switch (countResult.getGroupField().toUpperCase()){
|
||||||
|
case TrackCount.P0:
|
||||||
|
this.p0CaseCountNumber += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
case TrackCount.P1:
|
||||||
|
this.p1CaseCountNumber += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
case TrackCount.P2:
|
||||||
|
this.p2CaseCountNumber += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
case TrackCount.P3:
|
||||||
|
this.p3CaseCountNumber += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.allCaseCountNumber += countResult.getCountNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countStatus(List<TrackCountResult> statusResults) {
|
||||||
|
for (TrackCountResult countResult : statusResults) {
|
||||||
|
if(TestReviewCaseStatus.Prepare.name().equals(countResult.getGroupField())){
|
||||||
|
this.prepareCount += countResult.getCountNumber();
|
||||||
|
}else if(TestReviewCaseStatus.Pass.name().equals(countResult.getGroupField())){
|
||||||
|
this.passCount += countResult.getCountNumber();
|
||||||
|
}else if(TestReviewCaseStatus.UnPass.name().equals(countResult.getGroupField())){
|
||||||
|
this.unPassCount += countResult.getCountNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countRelevance(List<TrackCountResult> relevanceResults) {
|
||||||
|
for (TrackCountResult countResult : relevanceResults) {
|
||||||
|
switch (countResult.getGroupField()){
|
||||||
|
case TrackCount.API:
|
||||||
|
this.apiCaseCount += countResult.getCountNumber();
|
||||||
|
this.allRelevanceCaseCount += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
case TrackCount.PERFORMANCE:
|
||||||
|
this.performanceCaseCount += countResult.getCountNumber();
|
||||||
|
this.allRelevanceCaseCount += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
case TrackCount.AUTOMATION:
|
||||||
|
this.scenarioCaseCount += countResult.getCountNumber();
|
||||||
|
this.allRelevanceCaseCount += countResult.getCountNumber();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void countCoverage(List<TrackCountResult> coverageResults) {
|
||||||
|
for (TrackCountResult countResult : coverageResults) {
|
||||||
|
if("coverage".equals(countResult.getGroupField())){
|
||||||
|
this.coverageCount+= countResult.getCountNumber();
|
||||||
|
}else if("uncoverage".equals(countResult.getGroupField())){
|
||||||
|
this.uncoverageCount+= countResult.getCountNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
package io.metersphere.track.service;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.*;
|
||||||
|
import io.metersphere.base.mapper.*;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||||
|
import io.metersphere.commons.utils.DateUtils;
|
||||||
|
import io.metersphere.performance.base.ChartsData;
|
||||||
|
import io.metersphere.track.response.BugStatustics;
|
||||||
|
import io.metersphere.track.response.TestPlanBugCount;
|
||||||
|
import io.metersphere.track.response.TrackCountResult;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class TrackService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExtTestCaseMapper extTestCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private TestPlanMapper testPlanMapper;
|
||||||
|
@Resource
|
||||||
|
private TestPlanTestCaseMapper testPlanTestCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private TestPlanLoadCaseMapper testPlanLoadCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
|
||||||
|
|
||||||
|
public List<TrackCountResult> countPriority(String projectId) {
|
||||||
|
return extTestCaseMapper.countPriority(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long countCreatedThisWeek(String projectId) {
|
||||||
|
Map<String, Date> startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date());
|
||||||
|
|
||||||
|
Date firstTime = startAndEndDateInWeek.get("firstTime");
|
||||||
|
Date lastTime = startAndEndDateInWeek.get("lastTime");
|
||||||
|
|
||||||
|
if (firstTime == null || lastTime == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return extTestCaseMapper.countCreatedThisWeek(projectId, firstTime.getTime(), lastTime.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TrackCountResult> countStatus(String projectId) {
|
||||||
|
return extTestCaseMapper.countStatus(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TrackCountResult> countRelevance(String projectId) {
|
||||||
|
return extTestCaseMapper.countRelevance(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long countRelevanceCreatedThisWeek(String projectId) {
|
||||||
|
Map<String, Date> startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date());
|
||||||
|
|
||||||
|
Date firstTime = startAndEndDateInWeek.get("firstTime");
|
||||||
|
Date lastTime = startAndEndDateInWeek.get("lastTime");
|
||||||
|
|
||||||
|
if (firstTime == null || lastTime == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return extTestCaseMapper.countRelevanceCreatedThisWeek(projectId, firstTime.getTime(), lastTime.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TrackCountResult> countCoverage(String projectId) {
|
||||||
|
return extTestCaseMapper.countCoverage(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ChartsData> getCaseMaintenanceBar(String projectId) {
|
||||||
|
List<TrackCountResult> funcMaintainer = extTestCaseMapper.countFuncMaintainer(projectId);
|
||||||
|
List<TrackCountResult> relevanceMaintainer = extTestCaseMapper.countRelevanceMaintainer(projectId);
|
||||||
|
List<String> list = relevanceMaintainer.stream().map(TrackCountResult::getGroupField).collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<ChartsData> charts = new ArrayList<>();
|
||||||
|
for (TrackCountResult result : funcMaintainer) {
|
||||||
|
String groupField = result.getGroupField();
|
||||||
|
if (!list.contains(groupField)) {
|
||||||
|
// 创建了功能用例,但是未关联测试
|
||||||
|
TrackCountResult trackCount = new TrackCountResult();
|
||||||
|
trackCount.setCountNumber(0);
|
||||||
|
trackCount.setGroupField(groupField);
|
||||||
|
relevanceMaintainer.add(trackCount);
|
||||||
|
}
|
||||||
|
ChartsData chartsData = new ChartsData();
|
||||||
|
chartsData.setxAxis(groupField);
|
||||||
|
chartsData.setyAxis(BigDecimal.valueOf(result.getCountNumber()));
|
||||||
|
chartsData.setGroupName("FUNCTIONCASE");
|
||||||
|
charts.add(chartsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TrackCountResult result : relevanceMaintainer) {
|
||||||
|
ChartsData chartsData = new ChartsData();
|
||||||
|
chartsData.setxAxis(result.getGroupField());
|
||||||
|
chartsData.setyAxis(BigDecimal.valueOf(result.getCountNumber()));
|
||||||
|
chartsData.setGroupName("RELEVANCECASE");
|
||||||
|
charts.add(chartsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return charts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BugStatustics getBugStatistics(String projectId) {
|
||||||
|
TestPlanExample example = new TestPlanExample();
|
||||||
|
example.createCriteria().andProjectIdEqualTo(projectId);
|
||||||
|
List<TestPlan> plans = testPlanMapper.selectByExample(example);
|
||||||
|
List<TestPlanBugCount> list = new ArrayList<>();
|
||||||
|
BugStatustics bugStatustics = new BugStatustics();
|
||||||
|
int index = 1;
|
||||||
|
int totalBugSize = 0;
|
||||||
|
int totalCaseSize = 0;
|
||||||
|
for (TestPlan plan : plans) {
|
||||||
|
TestPlanBugCount testPlanBug = new TestPlanBugCount();
|
||||||
|
testPlanBug.setIndex(index++);
|
||||||
|
testPlanBug.setPlanName(plan.getName());
|
||||||
|
testPlanBug.setCreateTime(plan.getCreateTime());
|
||||||
|
testPlanBug.setStatus(plan.getStatus());
|
||||||
|
|
||||||
|
int planCaseSize = getPlanCaseSize(plan.getId());
|
||||||
|
testPlanBug.setCaseSize(planCaseSize);
|
||||||
|
|
||||||
|
int planBugSize = getPlanBugSize(plan.getId());
|
||||||
|
testPlanBug.setBugSize(planBugSize);
|
||||||
|
testPlanBug.setPassRage(getPlanPassRage(plan.getId(), planCaseSize));
|
||||||
|
list.add(testPlanBug);
|
||||||
|
|
||||||
|
totalBugSize += planBugSize;
|
||||||
|
totalCaseSize += planCaseSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bugStatustics.setList(list);
|
||||||
|
float rage =totalCaseSize == 0 ? 0 : (float) totalBugSize * 100 / totalCaseSize;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
bugStatustics.setRage(df.format(rage) + "%");
|
||||||
|
bugStatustics.setBugTotalSize(totalBugSize);
|
||||||
|
return bugStatustics;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPlanCaseSize(String planId) {
|
||||||
|
return extTestCaseMapper.getTestPlanCase(planId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPlanBugSize(String planId) {
|
||||||
|
return extTestCaseMapper.getTestPlanBug(planId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPlanPassRage(String planId, int totalSize) {
|
||||||
|
if (totalSize == 0) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
int passSize = extTestCaseMapper.getTestPlanPassCase(planId);
|
||||||
|
float rage = (float) passSize * 100 / totalSize;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
return df.format(rage) + "%";
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ import MsView from "./components/common/router/View";
|
||||||
import MsUser from "./components/common/head/HeaderUser";
|
import MsUser from "./components/common/head/HeaderUser";
|
||||||
import MsHeaderOrgWs from "./components/common/head/HeaderOrgWs";
|
import MsHeaderOrgWs from "./components/common/head/HeaderOrgWs";
|
||||||
import MsLanguageSwitch from "./components/common/head/LanguageSwitch";
|
import MsLanguageSwitch from "./components/common/head/LanguageSwitch";
|
||||||
import {hasLicense, saveLocalStorage, setColor, setOriginColor} from "@/common/js/utils";
|
import {hasLicense, saveLocalStorage, setColor, setDefaultTheme} from "@/common/js/utils";
|
||||||
import {registerRequestHeaders} from "@/common/js/ajax";
|
import {registerRequestHeaders} from "@/common/js/ajax";
|
||||||
import {ORIGIN_COLOR} from "@/common/js/constants";
|
import {ORIGIN_COLOR} from "@/common/js/constants";
|
||||||
|
|
||||||
|
@ -55,13 +55,14 @@ export default {
|
||||||
created() {
|
created() {
|
||||||
registerRequestHeaders();
|
registerRequestHeaders();
|
||||||
if (!hasLicense()) {
|
if (!hasLicense()) {
|
||||||
setOriginColor()
|
setDefaultTheme();
|
||||||
this.color = ORIGIN_COLOR;
|
this.color = ORIGIN_COLOR;
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
this.$get('/system/theme', res => {
|
this.$get('/system/theme', res => {
|
||||||
this.color = res.data ? res.data : ORIGIN_COLOR;
|
this.color = res.data ? res.data : ORIGIN_COLOR;
|
||||||
setColor(this.color, this.color, this.color, this.color);
|
setColor(this.color, this.color, this.color, this.color, this.color);
|
||||||
|
this.$store.commit('setTheme', res.data);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("store")) {
|
if (localStorage.getItem("store")) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<template>
|
<template>
|
||||||
<span>{{ $t('commons.operating') }}
|
<span>{{ $t('commons.operating') }}
|
||||||
<i class='el-icon-setting' style="color:#7834c1; margin-left:10px" @click="customHeader"> </i>
|
<i class='el-icon-setting operator-color' @click="customHeader"> </i>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,5 +21,8 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.operator-color {
|
||||||
|
color: var(--count_number);
|
||||||
|
margin-left:10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -37,6 +37,13 @@
|
||||||
@change="calculateChart(threadGroup)"
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio-group v-model="threadGroup.unit" :disabled="true">
|
||||||
|
<el-radio label="S">{{ $t('schedule.cron.seconds') }}</el-radio>
|
||||||
|
<el-radio label="M">{{ $t('schedule.cron.minutes') }}</el-radio>
|
||||||
|
<el-radio label="H">{{ $t('schedule.cron.hours') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<br>
|
<br>
|
||||||
<el-form-item :label="$t('load_test.rps_limit')">
|
<el-form-item :label="$t('load_test.rps_limit')">
|
||||||
<el-switch v-model="threadGroup.rpsLimitEnable" @change="calculateTotalChart()"/>
|
<el-switch v-model="threadGroup.rpsLimitEnable" @change="calculateTotalChart()"/>
|
||||||
|
@ -59,7 +66,7 @@
|
||||||
@change="calculateChart(threadGroup)"
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_minutes')">
|
<el-form-item :label="$t('load_test.ramp_up_time_minutes', [getUnitLabel(threadGroup)])">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
:disabled="true"
|
:disabled="true"
|
||||||
:min="1"
|
:min="1"
|
||||||
|
@ -79,7 +86,7 @@
|
||||||
v-model="threadGroup.rampUpTime"
|
v-model="threadGroup.rampUpTime"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_seconds')"/>
|
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,7 +119,7 @@
|
||||||
@change="calculateChart(threadGroup)"
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_seconds')"/>
|
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -137,6 +144,7 @@ const TARGET_LEVEL = "TargetLevel";
|
||||||
const RAMP_UP = "RampUp";
|
const RAMP_UP = "RampUp";
|
||||||
const STEPS = "Steps";
|
const STEPS = "Steps";
|
||||||
const DURATION = "duration";
|
const DURATION = "duration";
|
||||||
|
const UNIT = "unit";
|
||||||
const RPS_LIMIT = "rpsLimit";
|
const RPS_LIMIT = "rpsLimit";
|
||||||
const RPS_LIMIT_ENABLE = "rpsLimitEnable";
|
const RPS_LIMIT_ENABLE = "rpsLimitEnable";
|
||||||
const THREAD_TYPE = "threadType";
|
const THREAD_TYPE = "threadType";
|
||||||
|
@ -196,11 +204,10 @@ export default {
|
||||||
this.threadGroups[i].iterateRampUp = item.value;
|
this.threadGroups[i].iterateRampUp = item.value;
|
||||||
break;
|
break;
|
||||||
case DURATION:
|
case DURATION:
|
||||||
if (item.unit) {
|
|
||||||
this.threadGroups[i].duration = item.value;
|
this.threadGroups[i].duration = item.value;
|
||||||
} else {
|
break;
|
||||||
this.threadGroups[i].duration = item.value * 60;
|
case UNIT:
|
||||||
}
|
this.threadGroups[i].unit = item.value;
|
||||||
break;
|
break;
|
||||||
case STEPS:
|
case STEPS:
|
||||||
this.threadGroups[i].step = item.value;
|
this.threadGroups[i].step = item.value;
|
||||||
|
@ -364,7 +371,7 @@ export default {
|
||||||
if (j === 0) {
|
if (j === 0) {
|
||||||
seriesData.data.push([0, 0]);
|
seriesData.data.push([0, 0]);
|
||||||
}
|
}
|
||||||
if (j > tg.rampUpTime) {
|
if (j >= tg.rampUpTime) {
|
||||||
xAxis.push(tg.duration);
|
xAxis.push(tg.duration);
|
||||||
|
|
||||||
seriesData.data.push([j, tg.threadNumber]);
|
seriesData.data.push([j, tg.threadNumber]);
|
||||||
|
@ -475,7 +482,7 @@ export default {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
handler.options.series[0].data.push([0, 0]);
|
handler.options.series[0].data.push([0, 0]);
|
||||||
}
|
}
|
||||||
if (i > handler.rampUpTime) {
|
if (i >= handler.rampUpTime) {
|
||||||
handler.options.xAxis.data.push(handler.duration);
|
handler.options.xAxis.data.push(handler.duration);
|
||||||
|
|
||||||
handler.options.series[0].data.push([i, handler.threadNumber]);
|
handler.options.series[0].data.push([i, handler.threadNumber]);
|
||||||
|
@ -506,6 +513,18 @@ export default {
|
||||||
}
|
}
|
||||||
this.calculateTotalChart();
|
this.calculateTotalChart();
|
||||||
},
|
},
|
||||||
|
getUnitLabel(tg) {
|
||||||
|
if (tg.unit === 'S') {
|
||||||
|
return this.$t('schedule.cron.seconds');
|
||||||
|
}
|
||||||
|
if (tg.unit === 'M') {
|
||||||
|
return this.$t('schedule.cron.minutes');
|
||||||
|
}
|
||||||
|
if (tg.unit === 'H') {
|
||||||
|
return this.$t('schedule.cron.hours');
|
||||||
|
}
|
||||||
|
return this.$t('schedule.cron.seconds');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
report: {
|
report: {
|
||||||
|
|
|
@ -467,7 +467,8 @@ export default {
|
||||||
let items = {
|
let items = {
|
||||||
name: name,
|
name: name,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: d
|
data: d,
|
||||||
|
smooth: true
|
||||||
};
|
};
|
||||||
let seriesArrayNames = seriesArray.map(m => m.name);
|
let seriesArrayNames = seriesArray.map(m => m.name);
|
||||||
if (seriesArrayNames.includes(name)) {
|
if (seriesArrayNames.includes(name)) {
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
<el-table :data="granularityData">
|
<el-table :data="granularityData">
|
||||||
<el-table-column property="start" :label="$t('load_test.duration')">
|
<el-table-column property="start" :label="$t('load_test.duration')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span>{{ scope.row.start }} - {{ scope.row.end }}</span>
|
<span>{{ scope.row.start }}S - {{ scope.row.end }}S</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="granularity" :label="$t('load_test.granularity')"/>
|
<el-table-column property="granularity" :label="$t('load_test.granularity')"/>
|
||||||
|
|
|
@ -47,10 +47,17 @@
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
v-model="threadGroup.duration"
|
v-model="threadGroup.duration"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="172800"
|
:max="99999"
|
||||||
@change="calculateChart(threadGroup)"
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio-group v-model="threadGroup.unit">
|
||||||
|
<el-radio label="S">{{ $t('schedule.cron.seconds') }}</el-radio>
|
||||||
|
<el-radio label="M">{{ $t('schedule.cron.minutes') }}</el-radio>
|
||||||
|
<el-radio label="H">{{ $t('schedule.cron.hours') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<br>
|
<br>
|
||||||
<el-form-item :label="$t('load_test.rps_limit')">
|
<el-form-item :label="$t('load_test.rps_limit')">
|
||||||
<el-switch v-model="threadGroup.rpsLimitEnable" @change="calculateTotalChart()"/>
|
<el-switch v-model="threadGroup.rpsLimitEnable" @change="calculateTotalChart()"/>
|
||||||
|
@ -74,7 +81,7 @@
|
||||||
@change="calculateChart(threadGroup)"
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_minutes')">
|
<el-form-item :label="$t('load_test.ramp_up_time_minutes', [getUnitLabel(threadGroup)])">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
:min="1"
|
:min="1"
|
||||||
|
@ -92,9 +99,10 @@
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
:min="1"
|
:min="1"
|
||||||
v-model="threadGroup.rampUpTime"
|
v-model="threadGroup.rampUpTime"
|
||||||
|
@change="calculateChart(threadGroup)"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_seconds')"/>
|
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -127,7 +135,7 @@
|
||||||
v-model="threadGroup.iterateRampUp"
|
v-model="threadGroup.iterateRampUp"
|
||||||
size="mini"/>
|
size="mini"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('load_test.ramp_up_time_seconds')"/>
|
<el-form-item :label="$t('load_test.ramp_up_time_seconds', [getUnitLabel(threadGroup)])"/>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -153,6 +161,7 @@ const RAMP_UP = "RampUp";
|
||||||
const ITERATE_RAMP_UP = "iterateRampUpTime";
|
const ITERATE_RAMP_UP = "iterateRampUpTime";
|
||||||
const STEPS = "Steps";
|
const STEPS = "Steps";
|
||||||
const DURATION = "duration";
|
const DURATION = "duration";
|
||||||
|
const UNIT = "unit";
|
||||||
const RPS_LIMIT = "rpsLimit";
|
const RPS_LIMIT = "rpsLimit";
|
||||||
const RPS_LIMIT_ENABLE = "rpsLimitEnable";
|
const RPS_LIMIT_ENABLE = "rpsLimitEnable";
|
||||||
const HOLD = "Hold";
|
const HOLD = "Hold";
|
||||||
|
@ -252,11 +261,10 @@ export default {
|
||||||
this.threadGroups[i].iterateRampUp = item.value;
|
this.threadGroups[i].iterateRampUp = item.value;
|
||||||
break;
|
break;
|
||||||
case DURATION:
|
case DURATION:
|
||||||
if (item.unit) {
|
|
||||||
this.threadGroups[i].duration = item.value;
|
this.threadGroups[i].duration = item.value;
|
||||||
} else {
|
break;
|
||||||
this.threadGroups[i].duration = item.value * 60;
|
case UNIT:
|
||||||
}
|
this.threadGroups[i].unit = item.value;
|
||||||
break;
|
break;
|
||||||
case STEPS:
|
case STEPS:
|
||||||
this.threadGroups[i].step = item.value;
|
this.threadGroups[i].step = item.value;
|
||||||
|
@ -289,6 +297,7 @@ export default {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
this.$set(this.threadGroups[i], "unit", this.threadGroups[i].unit || 'S');
|
||||||
this.$set(this.threadGroups[i], "threadType", this.threadGroups[i].threadType || 'DURATION');
|
this.$set(this.threadGroups[i], "threadType", this.threadGroups[i].threadType || 'DURATION');
|
||||||
this.$set(this.threadGroups[i], "iterateNum", this.threadGroups[i].iterateNum || 1);
|
this.$set(this.threadGroups[i], "iterateNum", this.threadGroups[i].iterateNum || 1);
|
||||||
this.$set(this.threadGroups[i], "iterateRampUp", this.threadGroups[i].iterateRampUp || 10);
|
this.$set(this.threadGroups[i], "iterateRampUp", this.threadGroups[i].iterateRampUp || 10);
|
||||||
|
@ -402,7 +411,7 @@ export default {
|
||||||
if (j === 0) {
|
if (j === 0) {
|
||||||
seriesData.data.push([0, 0]);
|
seriesData.data.push([0, 0]);
|
||||||
}
|
}
|
||||||
if (j > tg.rampUpTime) {
|
if (j >= tg.rampUpTime) {
|
||||||
xAxis.push(tg.duration);
|
xAxis.push(tg.duration);
|
||||||
|
|
||||||
seriesData.data.push([j, tg.threadNumber]);
|
seriesData.data.push([j, tg.threadNumber]);
|
||||||
|
@ -519,7 +528,7 @@ export default {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
handler.options.series[0].data.push([0, 0]);
|
handler.options.series[0].data.push([0, 0]);
|
||||||
}
|
}
|
||||||
if (i > handler.rampUpTime) {
|
if (i >= handler.rampUpTime) {
|
||||||
handler.options.xAxis.data.push(handler.duration);
|
handler.options.xAxis.data.push(handler.duration);
|
||||||
|
|
||||||
handler.options.series[0].data.push([i, handler.threadNumber]);
|
handler.options.series[0].data.push([i, handler.threadNumber]);
|
||||||
|
@ -575,6 +584,18 @@ export default {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
getUnitLabel(tg) {
|
||||||
|
if (tg.unit === 'S') {
|
||||||
|
return this.$t('schedule.cron.seconds');
|
||||||
|
}
|
||||||
|
if (tg.unit === 'M') {
|
||||||
|
return this.$t('schedule.cron.minutes');
|
||||||
|
}
|
||||||
|
if (tg.unit === 'H') {
|
||||||
|
return this.$t('schedule.cron.hours');
|
||||||
|
}
|
||||||
|
return this.$t('schedule.cron.seconds');
|
||||||
|
},
|
||||||
convertProperty() {
|
convertProperty() {
|
||||||
/// todo:下面4个属性是jmeter ConcurrencyThreadGroup plugin的属性,这种硬编码不太好吧,在哪能转换这种属性?
|
/// todo:下面4个属性是jmeter ConcurrencyThreadGroup plugin的属性,这种硬编码不太好吧,在哪能转换这种属性?
|
||||||
let result = [];
|
let result = [];
|
||||||
|
@ -584,7 +605,8 @@ export default {
|
||||||
{key: TARGET_LEVEL, value: this.threadGroups[i].threadNumber},
|
{key: TARGET_LEVEL, value: this.threadGroups[i].threadNumber},
|
||||||
{key: RAMP_UP, value: this.threadGroups[i].rampUpTime},
|
{key: RAMP_UP, value: this.threadGroups[i].rampUpTime},
|
||||||
{key: STEPS, value: this.threadGroups[i].step},
|
{key: STEPS, value: this.threadGroups[i].step},
|
||||||
{key: DURATION, value: this.threadGroups[i].duration, unit: 'S'},
|
{key: DURATION, value: this.threadGroups[i].duration, unit: this.threadGroups[i].unit},
|
||||||
|
{key: UNIT, value: this.threadGroups[i].unit},
|
||||||
{key: RPS_LIMIT, value: this.threadGroups[i].rpsLimit},
|
{key: RPS_LIMIT, value: this.threadGroups[i].rpsLimit},
|
||||||
{key: RPS_LIMIT_ENABLE, value: this.threadGroups[i].rpsLimitEnable},
|
{key: RPS_LIMIT_ENABLE, value: this.threadGroups[i].rpsLimitEnable},
|
||||||
{key: HOLD, value: this.threadGroups[i].duration - this.threadGroups[i].rampUpTime},
|
{key: HOLD, value: this.threadGroups[i].duration - this.threadGroups[i].rampUpTime},
|
||||||
|
|
|
@ -31,6 +31,7 @@ export function findThreadGroup(jmxContent, handler) {
|
||||||
tg.enabled = tg.attributes.enabled;
|
tg.enabled = tg.attributes.enabled;
|
||||||
tg.tgType = tg.name;
|
tg.tgType = tg.name;
|
||||||
tg.threadType = 'DURATION';
|
tg.threadType = 'DURATION';
|
||||||
|
tg.unit = 'S';
|
||||||
})
|
})
|
||||||
return threadGroups;
|
return threadGroups;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,214 @@
|
||||||
<template>
|
<template>
|
||||||
<ms-container>
|
<ms-container>
|
||||||
<ms-main-container>
|
<el-header height="0">
|
||||||
<el-row :gutter="20">
|
<div style="float: right">
|
||||||
<el-col :span="15">
|
<div v-if="tipsType==='1'">
|
||||||
<el-row>
|
🤔️ 天凉了,保温杯买了吗?
|
||||||
<related-test-plan-list ref="relatedTestPlanList"/>
|
</div>
|
||||||
</el-row>
|
<div v-else-if="tipsType==='2'">
|
||||||
<el-row>
|
😔 觉得MeterSphere不好用就来
|
||||||
<review-list :title="$t('test_track.review.my_review')" ref="caseReviewList"/>
|
<el-link href="https://github.com/metersphere/metersphere/issues" target="_blank" style="color: black"
|
||||||
</el-row>
|
type="primary">https://github.com/metersphere/metersphere/issues
|
||||||
|
</el-link>
|
||||||
|
吐个槽吧!
|
||||||
|
</div>
|
||||||
|
<div v-else-if="tipsType==='3'">
|
||||||
|
😄 觉得MeterSphere好用就来
|
||||||
|
<el-link href="https://github.com/metersphere/metersphere" target="_blank" style="color: black"
|
||||||
|
type="primary">https://github.com/metersphere/metersphere
|
||||||
|
</el-link>
|
||||||
|
点个star吧!
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
😊 MeterSphere温馨提醒 —— 多喝热水哟!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<ms-main-container v-loading="result.loading">
|
||||||
|
<el-row :gutter="0"></el-row>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="square">
|
||||||
|
<case-count-card :track-count-data="trackCountData" class="track-card"/>
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="9">
|
<el-col :span="6">
|
||||||
<test-case-side-list :title="$t('test_track.home.recent_test')" ref="testCaseRecentList"/>
|
<div class="square">
|
||||||
|
<relevance-case-card :relevance-count-data="relevanceCountData" class="track-card"/>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<div class="square">
|
||||||
|
<case-maintenance :case-option="caseOption" class="track-card"/>
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="12">
|
||||||
|
<bug-count-card class="track-card"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<ms-failure-test-case-list class="track-card"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="12">
|
||||||
|
<review-list class="track-card"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<ms-running-task-list class="track-card"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
</ms-main-container>
|
</ms-main-container>
|
||||||
</ms-container>
|
</ms-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import RelatedTestPlanList from "./components/RelatedTestPlanList";
|
|
||||||
import TestCaseSideList from "./components/TestCaseSideList";
|
|
||||||
import MsContainer from "../../common/components/MsContainer";
|
|
||||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
|
||||||
import ReviewList from "./components/ReviewList";
|
|
||||||
|
|
||||||
|
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
|
||||||
|
import MsContainer from "@/business/components/common/components/MsContainer";
|
||||||
|
import CaseCountCard from "@/business/components/track/home/components/CaseCountCard";
|
||||||
|
import RelevanceCaseCard from "@/business/components/track/home/components/RelevanceCaseCard";
|
||||||
|
import {getCurrentProjectID} from "@/common/js/utils";
|
||||||
|
import CaseMaintenance from "@/business/components/track/home/components/CaseMaintenance";
|
||||||
|
import {COUNT_NUMBER, COUNT_NUMBER_SHALLOW} from "@/common/js/constants";
|
||||||
|
import BugCountCard from "@/business/components/track/home/components/BugCountCard";
|
||||||
|
import ReviewList from "@/business/components/track/home/components/ReviewList";
|
||||||
|
import MsRunningTaskList from "@/business/components/api/homepage/components/RunningTaskList";
|
||||||
|
import MsFailureTestCaseList from "@/business/components/api/homepage/components/FailureTestCaseList";
|
||||||
|
|
||||||
|
require('echarts/lib/component/legend');
|
||||||
export default {
|
export default {
|
||||||
name: "TrackHome",
|
name: "TrackHome",
|
||||||
components: {MsMainContainer, MsContainer, TestCaseSideList, RelatedTestPlanList, ReviewList},
|
components: {
|
||||||
watch: {
|
ReviewList,
|
||||||
'$route'(to, from) {
|
BugCountCard,
|
||||||
if (to.path.indexOf('/track/home') > -1) {
|
RelevanceCaseCard,
|
||||||
this.innitData();
|
CaseCountCard,
|
||||||
|
MsMainContainer,
|
||||||
|
MsContainer,
|
||||||
|
CaseMaintenance,
|
||||||
|
MsRunningTaskList,
|
||||||
|
MsFailureTestCaseList
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tipsType: "1",
|
||||||
|
result: {},
|
||||||
|
trackCountData: {},
|
||||||
|
relevanceCountData: {},
|
||||||
|
caseOption: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.checkTipsType();
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkTipsType() {
|
||||||
|
let random = Math.floor(Math.random() * (4 - 1 + 1)) + 1;
|
||||||
|
this.tipsType = random + "";
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
let selectProjectId = getCurrentProjectID();
|
||||||
|
|
||||||
|
this.$get("/track/count/" + selectProjectId, response => {
|
||||||
|
this.trackCountData = response.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$get("/track/relevance/count/" + selectProjectId, response => {
|
||||||
|
this.relevanceCountData = response.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$get("/track/case/bar/" + selectProjectId, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.setBarOption(data);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setBarOption(data) {
|
||||||
|
let xAxis = [];
|
||||||
|
data.map(d => {
|
||||||
|
if (!xAxis.includes(d.xAxis)) {
|
||||||
|
xAxis.push(d.xAxis);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let yAxis1 = data.filter(d => d.groupName === 'FUNCTIONCASE').map(d => d.yAxis);
|
||||||
|
let yAxis2 = data.filter(d => d.groupName === 'RELEVANCECASE').map(d => d.yAxis);
|
||||||
|
let option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: xAxis
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ["功能用例数", "关联用例数"],
|
||||||
|
orient: 'vertical',
|
||||||
|
right: '80',
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: "功能用例数",
|
||||||
|
data: yAxis1,
|
||||||
|
type: 'bar',
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: this.$store.state.theme.theme ? this.$store.state.theme.theme : COUNT_NUMBER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
{
|
||||||
innitData() {
|
name: "关联用例数",
|
||||||
this.$refs.relatedTestPlanList.initTableData();
|
data: yAxis2,
|
||||||
this.$refs.testCaseRecentList.initTableData();
|
type: 'bar',
|
||||||
this.$refs.caseReviewList.initTableData();
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: this.$store.state.theme.theme ? this.$store.state.theme.theme : COUNT_NUMBER_SHALLOW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
this.caseOption = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.square {
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
.ms-main-container >>> .el-table {
|
.rectangle {
|
||||||
cursor: pointer;
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-row {
|
.el-row {
|
||||||
padding-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-card {
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
<template>
|
||||||
|
<el-card class="table-card" v-loading="result.loading" body-style="padding:10px;">
|
||||||
|
<div slot="header">
|
||||||
|
<span class="title">
|
||||||
|
遗留缺陷统计
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="150px">
|
||||||
|
<div class="main-number-show">
|
||||||
|
<span class="count-number">
|
||||||
|
{{ bugTotalSize }}
|
||||||
|
</span>
|
||||||
|
<span style="color: #6C317C;">
|
||||||
|
{{ $t('api_test.home_page.unit_of_measurement') }}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
占比
|
||||||
|
<span class="rage">
|
||||||
|
{{rage}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-aside>
|
||||||
|
<el-table border :data="tableData" class="adjust-table table-content" height="300">
|
||||||
|
<el-table-column prop="index" label="序号"
|
||||||
|
width="60" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="planName" label="测试计划名称"
|
||||||
|
width="130" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="createTime" :label="$t('commons.create_time')" width="180" show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="status"
|
||||||
|
column-key="status"
|
||||||
|
:label="$t('test_track.plan.plan_status')"
|
||||||
|
width="100"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span @click.stop="clickt = 'stop'">
|
||||||
|
<plan-status-table-item :value="scope.row.status"/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="caseSize" label="用例数"
|
||||||
|
width="80" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="bugSize" label="缺陷数"
|
||||||
|
width="80" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="passRage" label="通过率"
|
||||||
|
width="80" show-overflow-tooltip/>
|
||||||
|
</el-table>
|
||||||
|
</el-container>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {getCurrentProjectID} from "@/common/js/utils";
|
||||||
|
import PlanStatusTableItem from "@/business/components/track/common/tableItems/plan/PlanStatusTableItem";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "BugCountCard",
|
||||||
|
components: {
|
||||||
|
PlanStatusTableItem
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData: [],
|
||||||
|
result: {},
|
||||||
|
bugTotalSize: 0,
|
||||||
|
rage: '0%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.result = this.$get("/track/bug/count/" + getCurrentProjectID(), res => {
|
||||||
|
let data = res.data;
|
||||||
|
this.tableData = data.list;
|
||||||
|
this.bugTotalSize = data.bugTotalSize;
|
||||||
|
this.rage = data.rage;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.el-card /deep/ .el-card__header {
|
||||||
|
border-bottom: 0px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-aside {
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-number {
|
||||||
|
font-family: 'ArialMT', 'Arial', sans-serif;
|
||||||
|
font-size: 33px;
|
||||||
|
color: var(--count_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rage {
|
||||||
|
font-family: 'ArialMT', 'Arial', sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
|
color: var(--count_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-number-show {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 7px;
|
||||||
|
border-color: var(--count_number_shallow);
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-number-show {
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,191 @@
|
||||||
|
<template>
|
||||||
|
<el-card class="table-card" v-loading="result.loading" body-style="padding:10px;">
|
||||||
|
<div slot="header" >
|
||||||
|
<span class="title">
|
||||||
|
用例数量统计
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="120px">
|
||||||
|
<div class="main-number-show">
|
||||||
|
<span class="count-number">
|
||||||
|
{{trackCountData.allCaseCountNumber}}
|
||||||
|
</span>
|
||||||
|
<span style="color: #6C317C;">
|
||||||
|
{{$t('api_test.home_page.unit_of_measurement')}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding-left: 0px;padding-right: 0px;">
|
||||||
|
<div style="width: 200px;margin:0 auto">
|
||||||
|
|
||||||
|
<el-row align="center">
|
||||||
|
<el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">
|
||||||
|
<div class="count-info-div" v-html="trackCountData.p0CountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">
|
||||||
|
<div class="count-info-div" v-html="trackCountData.p1CountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">
|
||||||
|
<div class="count-info-div" v-html="trackCountData.p2CountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="padding: 5px;">
|
||||||
|
<div class="count-info-div" v-html="trackCountData.p3CountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<!-- <el-row align="right" style="margin-left: 20px" class="hidden-xl-only">-->
|
||||||
|
<!-- <el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">-->
|
||||||
|
<!-- <div class="count-info-div" v-html="trackCountData.p0CountStr"></div>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">-->
|
||||||
|
<!-- <div class="count-info-div" v-html="trackCountData.p1CountStr"></div>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="6" style="padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">-->
|
||||||
|
<!-- <div class="count-info-div" v-html="trackCountData.p2CountStr"></div>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- <el-col :span="6" style="padding: 5px;">-->
|
||||||
|
<!-- <div class="count-info-div" v-html="trackCountData.p3CountStr"></div>-->
|
||||||
|
<!-- </el-col>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
|
</div>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
|
||||||
|
<el-container class="detail-container">
|
||||||
|
<el-header style="height:20px;padding: 0px;margin-bottom: 10px;">
|
||||||
|
<el-row>
|
||||||
|
<el-col>
|
||||||
|
{{$t('api_test.home_page.api_details_card.this_week_add')}}
|
||||||
|
<el-link type="info" @click="redirectPage('thisWeekCount')" target="_blank" style="color: #000000">{{trackCountData.thisWeekAddedCount}}
|
||||||
|
</el-link>
|
||||||
|
{{$t('api_test.home_page.unit_of_measurement')}}
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-header>
|
||||||
|
<el-main style="padding: 5px;margin-top: 10px">
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="60%" class="count-number-show" style="margin-bottom: 0px;margin-top: 0px">
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="30%">
|
||||||
|
评审率:
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding: 0px 0px 0px 0px; line-height: 100px; text-align: center;">
|
||||||
|
<span class="count-number">
|
||||||
|
{{trackCountData.reviewRage}}
|
||||||
|
</span>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding: 5px">
|
||||||
|
<el-card class="no-shadow-card" body-style="padding-left:5px;padding-right:5px">
|
||||||
|
<main>
|
||||||
|
<el-row>
|
||||||
|
<el-col>
|
||||||
|
<span class="default-property">
|
||||||
|
{{$t('api_test.home_page.detail_card.running')}}
|
||||||
|
{{"\xa0\xa0"}}
|
||||||
|
<el-link type="info" @click="redirectPage('Underway')" target="_blank" style="color: #000000">
|
||||||
|
{{trackCountData.prepareCount}}
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
<el-col style="margin-top: 5px;">
|
||||||
|
<span class="default-property">
|
||||||
|
{{$t('api_test.home_page.detail_card.not_started')}}
|
||||||
|
{{"\xa0\xa0"}}
|
||||||
|
<el-link type="info" @click="redirectPage('Prepare')" target="_blank" style="color: #000000">
|
||||||
|
{{trackCountData.passCount}}
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
<el-col style="margin-top: 5px;">
|
||||||
|
<span class="main-property">
|
||||||
|
{{$t('api_test.home_page.detail_card.finished')}}
|
||||||
|
{{"\xa0\xa0"}}
|
||||||
|
<el-link type="info" @click="redirectPage('Completed')" target="_blank" style="color: #000000">
|
||||||
|
{{trackCountData.unPassCount}}
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</main>
|
||||||
|
</el-card>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "CaseCountCard",
|
||||||
|
props:{
|
||||||
|
trackCountData: {},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
redirectPage(clickType){
|
||||||
|
this.$emit("redirectPage","api","api",clickType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.el-aside {
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.count-number{
|
||||||
|
font-family:'ArialMT', 'Arial', sans-serif;
|
||||||
|
font-size:33px;
|
||||||
|
color: var(--count_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-number-show {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 7px;
|
||||||
|
border-color: var(--count_number_shallow);
|
||||||
|
border-radius:50%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-number-show{
|
||||||
|
margin:20px auto;
|
||||||
|
}
|
||||||
|
.detail-container{
|
||||||
|
margin-top: 30px
|
||||||
|
}
|
||||||
|
.no-shadow-card{
|
||||||
|
-webkit-box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
.default-property{
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
.main-property{
|
||||||
|
color: #F39021;
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card /deep/ .el-card__header {
|
||||||
|
border-bottom: 0px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-info-div{
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
.count-info-div >>>p{
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<el-card class="table-card" v-loading="result.loading" body-style="padding:10px;">
|
||||||
|
<div slot="header">
|
||||||
|
<span class="title">
|
||||||
|
用例维护人分布
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-container>
|
||||||
|
<ms-chart ref="chart1" :options="caseOption" :autoresize="true" style="width: 100%;height: 340px"></ms-chart>
|
||||||
|
</el-container>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsChart from "@/business/components/common/chart/MsChart";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CaseMaintenance",
|
||||||
|
components: {MsChart},
|
||||||
|
props: {
|
||||||
|
caseOption: {}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.no-shadow-card{
|
||||||
|
-webkit-box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card /deep/ .el-card__header {
|
||||||
|
border-bottom: 0px solid #EBEEF5;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,165 @@
|
||||||
|
<template>
|
||||||
|
<el-card class="table-card" v-loading="result.loading" body-style="padding:10px;">
|
||||||
|
<div slot="header" >
|
||||||
|
<span class="title">
|
||||||
|
关联用例数量统计
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="120px">
|
||||||
|
<div class="main-number-show">
|
||||||
|
<span class="count-number">
|
||||||
|
{{relevanceCountData.allRelevanceCaseCount}}
|
||||||
|
</span>
|
||||||
|
<span style="color: #6C317C;">
|
||||||
|
{{$t('api_test.home_page.unit_of_measurement')}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding-left: 0px;padding-right: 0px;">
|
||||||
|
<div style="width: 300px;margin:0 auto">
|
||||||
|
|
||||||
|
<el-row align="center">
|
||||||
|
<el-col :span="6" style="width:90px;padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">
|
||||||
|
<div class="count-info-div" v-html="relevanceCountData.apiCaseCountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="width:90px;padding: 5px;border-right-style: solid;border-right-width: 1px;border-right-color: #ECEEF4;">
|
||||||
|
<div class="count-info-div" v-html="relevanceCountData.scenarioCaseStr"></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="width:90px;padding: 5px;">
|
||||||
|
<div class="count-info-div" v-html="relevanceCountData.performanceCaseCountStr"></div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
|
||||||
|
<el-container class="detail-container">
|
||||||
|
<el-header style="height:20px;padding: 0px;margin-bottom: 10px;">
|
||||||
|
<el-row>
|
||||||
|
<el-col>
|
||||||
|
{{$t('api_test.home_page.api_details_card.this_week_add')}}
|
||||||
|
<el-link type="info" @click="redirectPage('thisWeekCount')" target="_blank" style="color: #000000">{{relevanceCountData.thisWeekAddedCount}}
|
||||||
|
</el-link>
|
||||||
|
{{$t('api_test.home_page.unit_of_measurement')}}
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-header>
|
||||||
|
<el-main style="padding: 5px;margin-top: 10px">
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="60%" class="count-number-show" style="margin-bottom: 0px;margin-top: 0px">
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="30%">
|
||||||
|
覆盖率:
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding: 0px 0px 0px 0px; line-height: 100px; text-align: center;">
|
||||||
|
<span class="count-number">
|
||||||
|
{{relevanceCountData.coverageRage}}
|
||||||
|
</span>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-aside>
|
||||||
|
<el-main style="padding: 5px">
|
||||||
|
<el-card class="no-shadow-card" body-style="padding-left:5px;padding-right:5px">
|
||||||
|
<main>
|
||||||
|
<el-row>
|
||||||
|
<el-col>
|
||||||
|
<span class="default-property">
|
||||||
|
未覆盖
|
||||||
|
{{"\xa0\xa0"}}
|
||||||
|
<el-link type="info" @click="redirectPage('Underway')" target="_blank" style="color: #000000">
|
||||||
|
{{relevanceCountData.uncoverageCount}}
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
<el-col style="margin-top: 5px;">
|
||||||
|
<span class="main-property">
|
||||||
|
已覆盖
|
||||||
|
{{"\xa0\xa0"}}
|
||||||
|
<el-link type="info" @click="redirectPage('Prepare')" target="_blank" style="color: #000000">
|
||||||
|
{{relevanceCountData.coverageCount}}
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</main>
|
||||||
|
</el-card>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "RelevanceCaseCard",
|
||||||
|
props:{
|
||||||
|
relevanceCountData:{},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
redirectPage(clickType){
|
||||||
|
this.$emit("redirectPage","api","api",clickType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.el-aside {
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.count-number{
|
||||||
|
font-family:'ArialMT', 'Arial', sans-serif;
|
||||||
|
font-size:33px;
|
||||||
|
color: var(--count_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-number-show {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 7px;
|
||||||
|
border-color: var(--count_number_shallow);
|
||||||
|
border-radius:50%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-number-show{
|
||||||
|
margin:20px auto;
|
||||||
|
}
|
||||||
|
.detail-container{
|
||||||
|
margin-top: 30px
|
||||||
|
}
|
||||||
|
.no-shadow-card{
|
||||||
|
-webkit-box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
box-shadow: 0 0px 0px 0 rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
.default-property{
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
.main-property{
|
||||||
|
color: #F39021;
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card /deep/ .el-card__header {
|
||||||
|
border-bottom: 0px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-info-div{
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
.count-info-div >>>p{
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<home-base-component :title="$t('test_track.review.my_review')" v-loading>
|
<el-card class="table-card" v-loading="result.loading" body-style="padding:10px;">
|
||||||
<template slot="header-area">
|
<div slot="header">
|
||||||
<div style="float: right">
|
<span class="title">
|
||||||
|
遗留缺陷统计
|
||||||
|
</span>
|
||||||
<ms-table-button :is-tester-permission="true" v-if="!showMyCreator" icon="el-icon-view"
|
<ms-table-button :is-tester-permission="true" v-if="!showMyCreator" icon="el-icon-view"
|
||||||
:content="$t('test_track.review.my_create')" @click="searchMyCreator"/>
|
:content="$t('test_track.review.my_create')" @click="searchMyCreator" style="float: right"/>
|
||||||
<ms-table-button :is-tester-permission="true" v-if="showMyCreator" icon="el-icon-view"
|
<ms-table-button :is-tester-permission="true" v-if="showMyCreator" icon="el-icon-view"
|
||||||
:content="$t('test_track.review.reviewed_by_me')" @click="searchMyCreator"/>
|
:content="$t('test_track.review.reviewed_by_me')" @click="searchMyCreator" style="float: right"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
|
||||||
<el-table
|
<el-table
|
||||||
class="adjust-table"
|
class="adjust-table"
|
||||||
border
|
border
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
</home-base-component>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -120,5 +120,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.el-card /deep/ .el-card__header {
|
||||||
|
border-bottom: 0px solid #EBEEF5;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4c33b9c3b12a83da6d9bd2740262c6c8baaab819
|
Subproject commit b2571e06e8b211821409115cc2c4a7c52cbac1db
|
|
@ -50,11 +50,23 @@ const IsReadOnly = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Theme = {
|
||||||
|
state: {
|
||||||
|
theme: undefined
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
setTheme(state, value) {
|
||||||
|
state.theme = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
api: API,
|
api: API,
|
||||||
common: Common,
|
common: Common,
|
||||||
switch: Switch,
|
switch: Switch,
|
||||||
isReadOnly: IsReadOnly,
|
isReadOnly: IsReadOnly,
|
||||||
|
theme: Theme
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,7 @@ body {
|
||||||
/*--color: #2c2a48;*/
|
/*--color: #2c2a48;*/
|
||||||
/*--color_shallow: #595591;*/
|
/*--color_shallow: #595591;*/
|
||||||
--color: '';
|
--color: '';
|
||||||
|
--primary_color: '';
|
||||||
--color_shallow: '';
|
--color_shallow: '';
|
||||||
--count_number: '';
|
--count_number: '';
|
||||||
--count_number_shallow: '';
|
--count_number_shallow: '';
|
||||||
|
|
|
@ -173,3 +173,4 @@ export const ORIGIN_COLOR = '#2c2a48';
|
||||||
export const ORIGIN_COLOR_SHALLOW = '#595591';
|
export const ORIGIN_COLOR_SHALLOW = '#595591';
|
||||||
export const COUNT_NUMBER = '#6C317C';
|
export const COUNT_NUMBER = '#6C317C';
|
||||||
export const COUNT_NUMBER_SHALLOW = '#CDB9D2';
|
export const COUNT_NUMBER_SHALLOW = '#CDB9D2';
|
||||||
|
export const PRIMARY_COLOR = '#783887';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {
|
||||||
COUNT_NUMBER_SHALLOW,
|
COUNT_NUMBER_SHALLOW,
|
||||||
LicenseKey,
|
LicenseKey,
|
||||||
ORIGIN_COLOR,
|
ORIGIN_COLOR,
|
||||||
ORIGIN_COLOR_SHALLOW,
|
ORIGIN_COLOR_SHALLOW, PRIMARY_COLOR,
|
||||||
PROJECT_ID,
|
PROJECT_ID,
|
||||||
REFRESH_SESSION_USER_URL,
|
REFRESH_SESSION_USER_URL,
|
||||||
ROLE_ADMIN,
|
ROLE_ADMIN,
|
||||||
|
@ -354,19 +354,19 @@ export function objToStrMap(obj) {
|
||||||
return strMap;
|
return strMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getColor() {
|
export function setColor(a, b, c, d, e) {
|
||||||
return localStorage.getItem('color');
|
// 顶部菜单背景色
|
||||||
}
|
|
||||||
|
|
||||||
export function setColor(a, b, c, d) {
|
|
||||||
document.body.style.setProperty('--color', a);
|
document.body.style.setProperty('--color', a);
|
||||||
document.body.style.setProperty('--color_shallow', b);
|
document.body.style.setProperty('--color_shallow', b);
|
||||||
|
// 首页颜色
|
||||||
document.body.style.setProperty('--count_number', c);
|
document.body.style.setProperty('--count_number', c);
|
||||||
document.body.style.setProperty('--count_number_shallow', d);
|
document.body.style.setProperty('--count_number_shallow', d);
|
||||||
|
// 主颜色
|
||||||
|
document.body.style.setProperty('--primary_color', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setOriginColor() {
|
export function setDefaultTheme() {
|
||||||
setColor(ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW, COUNT_NUMBER, COUNT_NUMBER_SHALLOW);
|
setColor(ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW, COUNT_NUMBER, COUNT_NUMBER_SHALLOW, PRIMARY_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function publicKeyEncrypt(input, publicKey) {
|
export function publicKeyEncrypt(input, publicKey) {
|
||||||
|
|
|
@ -481,7 +481,7 @@ export default {
|
||||||
delete_file: "The file already exists, please delete the file with the same name first!",
|
delete_file: "The file already exists, please delete the file with the same name first!",
|
||||||
thread_num: 'Concurrent users:',
|
thread_num: 'Concurrent users:',
|
||||||
input_thread_num: 'Please enter the number of threads',
|
input_thread_num: 'Please enter the number of threads',
|
||||||
duration: 'Duration time (seconds)',
|
duration: 'Duration time',
|
||||||
granularity: 'Aggregation time (seconds)',
|
granularity: 'Aggregation time (seconds)',
|
||||||
input_duration: 'Please enter a duration',
|
input_duration: 'Please enter a duration',
|
||||||
rps_limit: 'RPS Limit:',
|
rps_limit: 'RPS Limit:',
|
||||||
|
|
|
@ -478,14 +478,14 @@ export default {
|
||||||
delete_file: "文件已存在,请先删除同名文件!",
|
delete_file: "文件已存在,请先删除同名文件!",
|
||||||
thread_num: '并发用户数:',
|
thread_num: '并发用户数:',
|
||||||
input_thread_num: '请输入线程数',
|
input_thread_num: '请输入线程数',
|
||||||
duration: '压测时长(秒)',
|
duration: '压测时长',
|
||||||
granularity: '聚合时间(秒)',
|
granularity: '聚合时间(秒)',
|
||||||
input_duration: '请输入时长',
|
input_duration: '请输入时长',
|
||||||
rps_limit: 'RPS上限:',
|
rps_limit: 'RPS上限:',
|
||||||
input_rps_limit: '请输入限制',
|
input_rps_limit: '请输入限制',
|
||||||
ramp_up_time_within: '在',
|
ramp_up_time_within: '在',
|
||||||
ramp_up_time_minutes: '秒内,分',
|
ramp_up_time_minutes: '{0}内,分',
|
||||||
ramp_up_time_seconds: '秒内增加并发用户',
|
ramp_up_time_seconds: '{0}内增加并发用户',
|
||||||
iterate_num: '迭代次数 (次): ',
|
iterate_num: '迭代次数 (次): ',
|
||||||
by_iteration: '按迭代次数',
|
by_iteration: '按迭代次数',
|
||||||
by_duration: '按持续时间',
|
by_duration: '按持续时间',
|
||||||
|
|
|
@ -478,7 +478,7 @@ export default {
|
||||||
delete_file: "文件已存在,請先刪除同名文件!",
|
delete_file: "文件已存在,請先刪除同名文件!",
|
||||||
thread_num: '並發用戶數:',
|
thread_num: '並發用戶數:',
|
||||||
input_thread_num: '請輸入線程數',
|
input_thread_num: '請輸入線程數',
|
||||||
duration: '壓測時長(秒)',
|
duration: '壓測時長',
|
||||||
granularity: '聚合時間(秒)',
|
granularity: '聚合時間(秒)',
|
||||||
input_duration: '請輸入時長',
|
input_duration: '請輸入時長',
|
||||||
rps_limit: 'RPS上限:',
|
rps_limit: 'RPS上限:',
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {publicKeyEncrypt, saveLocalStorage} from '@/common/js/utils';
|
import {publicKeyEncrypt, saveLocalStorage} from '@/common/js/utils';
|
||||||
import {DEFAULT_LANGUAGE} from "@/common/js/constants";
|
import {DEFAULT_LANGUAGE, PRIMARY_COLOR} from "@/common/js/constants";
|
||||||
|
|
||||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||||
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
|
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
|
||||||
|
@ -91,6 +91,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
|
this.$get('/system/theme', res => {
|
||||||
|
this.color = res.data ? res.data : PRIMARY_COLOR;
|
||||||
|
document.body.style.setProperty('--primary_color', this.color);
|
||||||
|
})
|
||||||
this.result = this.$get("/isLogin").then(response => {
|
this.result = this.$get("/isLogin").then(response => {
|
||||||
|
|
||||||
if (display.default !== undefined) {
|
if (display.default !== undefined) {
|
||||||
|
@ -230,7 +234,7 @@ export default {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-bottom: 75px;
|
margin-bottom: 75px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #843697;
|
color: var(--primary_color);
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -243,18 +247,18 @@ export default {
|
||||||
|
|
||||||
.btn > .submit {
|
.btn > .submit {
|
||||||
border-radius: 70px;
|
border-radius: 70px;
|
||||||
border-color: #8B479B;
|
border-color: var(--primary_color);
|
||||||
background-color: #8B479B;
|
background-color: var(--primary_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn > .submit:hover {
|
.btn > .submit:hover {
|
||||||
border-color: rgba(139, 71, 155, 0.9);
|
border-color: var(--primary_color);
|
||||||
background-color: rgba(139, 71, 155, 0.9);
|
background-color: var(--primary_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn > .submit:active {
|
.btn > .submit:active {
|
||||||
border-color: rgba(139, 71, 155, 0.8);
|
border-color: var(--primary_color);
|
||||||
background-color: rgba(139, 71, 155, 0.8);
|
background-color: var(--primary_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-form-item:first-child {
|
.el-form-item:first-child {
|
||||||
|
@ -262,13 +266,13 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-radio__input.is-checked .el-radio__inner {
|
/deep/ .el-radio__input.is-checked .el-radio__inner {
|
||||||
background-color: #783887;
|
background-color: var(--primary_color);
|
||||||
background: #783887;
|
background: var(--primary_color);
|
||||||
border-color: #783887;
|
border-color: var(--primary_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-radio__input.is-checked + .el-radio__label {
|
/deep/ .el-radio__input.is-checked + .el-radio__label {
|
||||||
color: #783887;
|
color: var(--primary_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-input__inner {
|
/deep/ .el-input__inner {
|
||||||
|
@ -284,7 +288,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .el-input__inner:focus {
|
/deep/ .el-input__inner:focus {
|
||||||
border: 1px solid #783887 !important;
|
border: 1px solid var(--primary_color) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
|
|
Loading…
Reference in New Issue