refactor(测试跟踪): 优化首页样式及展示面板
This commit is contained in:
parent
ef3a211e19
commit
202e85f23f
|
@ -351,15 +351,15 @@ export default {
|
||||||
test_rate: "Test Rate",
|
test_rate: "Test Rate",
|
||||||
tested_case: "Tested Case",
|
tested_case: "Tested Case",
|
||||||
review_progress: "Review Progress",
|
review_progress: "Review Progress",
|
||||||
case_count: "Statistics of the number of use cases",
|
case_count: "Statistics of cases",
|
||||||
relevance_case: "Related Case",
|
relevance_case: "Statistics of related cases",
|
||||||
case_maintenance: "Use case person responsible distribution",
|
case_maintenance: "Statistics of case maintenance",
|
||||||
bug_count: "Statistics of test plan remaining defects",
|
bug_count: "Statistics of test plan unclosed bugs",
|
||||||
case_review: "Use case review",
|
case_review: "Use case review",
|
||||||
review_rate: "Reviewed",
|
review_rate: "Reviewed",
|
||||||
coverage: "Coverage",
|
coverage: "Coverage",
|
||||||
function_case_count: "Functional Case Count",
|
function_case_count: "Functional Case",
|
||||||
relevance_case_count: "Related Case Count",
|
relevance_case_count: "Related Case",
|
||||||
serial_number: "Index",
|
serial_number: "Index",
|
||||||
test_plan_name: "Plan Name",
|
test_plan_name: "Plan Name",
|
||||||
case_size: "Case Count",
|
case_size: "Case Count",
|
||||||
|
|
|
@ -66,11 +66,19 @@ public class IssuesRequest extends BaseQueryRequest {
|
||||||
private List<String> exportIds;
|
private List<String> exportIds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 本周遗留缺陷
|
* 本周测试计划遗留缺陷
|
||||||
*/
|
*/
|
||||||
private Boolean thisWeekUnClosedIssue = false;
|
private Boolean thisWeekUnClosedTestPlanIssue = false;
|
||||||
/**
|
/**
|
||||||
* 本周遗留缺陷ID
|
* 测试计划遗留的缺陷
|
||||||
*/
|
*/
|
||||||
private List<String> thisWeekUncloseIds;
|
private Boolean unClosedTestPlanIssue = false;
|
||||||
|
/**
|
||||||
|
* 测试计划关联所有缺陷
|
||||||
|
*/
|
||||||
|
private Boolean allTestPlanIssue = false;
|
||||||
|
/**
|
||||||
|
* 过滤缺陷ID
|
||||||
|
*/
|
||||||
|
private List<String> filterIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,4 +48,6 @@ public interface ExtIssuesMapper {
|
||||||
Long getThisWeekIssueCount(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
Long getThisWeekIssueCount(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
||||||
|
|
||||||
List<String> getTestPlanThisWeekIssue(String projectId);
|
List<String> getTestPlanThisWeekIssue(String projectId);
|
||||||
|
|
||||||
|
List<String> getTestPlanIssue(String projectId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,15 @@
|
||||||
and tp.project_id = #{projectId}
|
and tp.project_id = #{projectId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getTestPlanIssue" resultType="java.lang.String">
|
||||||
|
select distinct tci.issues_id
|
||||||
|
from test_plan_test_case tptc
|
||||||
|
join test_plan tp on tp.id = tptc.plan_id
|
||||||
|
join test_case_issues tci on tptc.id = tci.resource_id
|
||||||
|
join issues on tci.issues_id = issues.id
|
||||||
|
where tptc.is_del != 1 and tp.project_id = #{projectId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="getIssueCustomFields" resultType="io.metersphere.xpack.track.dto.IssuesDao">
|
<select id="getIssueCustomFields" resultType="io.metersphere.xpack.track.dto.IssuesDao">
|
||||||
select cfi.field_id as fieldId,
|
select cfi.field_id as fieldId,
|
||||||
cf.type fieldType,
|
cf.type fieldType,
|
||||||
|
@ -247,9 +256,9 @@
|
||||||
#{value}
|
#{value}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
<if test="request.thisWeekUnClosedIssue and request.thisWeekUncloseIds != null and request.thisWeekUncloseIds.size() > 0">
|
<if test="request.filterIds != null and request.filterIds.size() > 0">
|
||||||
and issues.id in
|
and issues.id in
|
||||||
<foreach collection="request.thisWeekUncloseIds" item="value" separator="," open="(" close=")">
|
<foreach collection="request.filterIds" item="value" separator="," open="(" close=")">
|
||||||
#{value}
|
#{value}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.metersphere.constants;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
public enum IssueStatus {
|
||||||
|
status_new("new", "new"),
|
||||||
|
status_resolved("resolved", "resolved"),
|
||||||
|
status_closed("closed", "closed"),
|
||||||
|
status_active("active", "active"),
|
||||||
|
status_delete("delete", "delete"),
|
||||||
|
status_in_progress("in_progress", "in_progress"),
|
||||||
|
status_rejected("rejected", "rejected"),
|
||||||
|
status_upcoming("upcoming", "upcoming"),
|
||||||
|
status_reopened("reopened", "reopened");
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String i18nKey;
|
||||||
|
|
||||||
|
IssueStatus(String name, String i18nKey) {
|
||||||
|
this.name = name;
|
||||||
|
this.i18nKey = i18nKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getI18nKey() {
|
||||||
|
return i18nKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IssueStatus getEnumByName(String name) {
|
||||||
|
IssueStatus[] issueStatus = IssueStatus.values();
|
||||||
|
for (int i = 0; i < issueStatus.length; i++) {
|
||||||
|
if (StringUtils.equals(issueStatus[i].getName(), name)) {
|
||||||
|
return issueStatus[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,9 +48,7 @@ public class IssuesController {
|
||||||
@PostMapping("/list/{goPage}/{pageSize}")
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_ISSUE_READ)
|
||||||
public Pager<List<IssuesDao>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody IssuesRequest request) {
|
public Pager<List<IssuesDao>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody IssuesRequest request) {
|
||||||
if (request.getThisWeekUnClosedIssue()) {
|
issuesService.setFilterIds(request);
|
||||||
issuesService.setThisWeekUnclosedIds(request);
|
|
||||||
}
|
|
||||||
Page<List<Issues>> page = PageHelper.startPage(goPage, pageSize, true);
|
Page<List<Issues>> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
return PageUtils.setPageInfo(page, issuesService.list(request));
|
return PageUtils.setPageInfo(page, issuesService.list(request));
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,6 @@ public class TrackController {
|
||||||
statistics.setReviewPassRage(df.format(reviewPass) + "%");
|
statistics.setReviewPassRage(df.format(reviewPass) + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import lombok.Setter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -21,4 +22,5 @@ public class BugStatistics {
|
||||||
private String unClosedRage;
|
private String unClosedRage;
|
||||||
private String bugCaseRage;
|
private String bugCaseRage;
|
||||||
private List<TestPlanBugCount> list = new ArrayList<>();
|
private List<TestPlanBugCount> list = new ArrayList<>();
|
||||||
|
private Map<String, Integer> chartData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package io.metersphere.dto;
|
package io.metersphere.dto;
|
||||||
|
|
||||||
import io.metersphere.excel.converter.TestReviewCaseStatus;
|
import io.metersphere.excel.converter.TestReviewCaseStatus;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.request.testcase.TrackCount;
|
import io.metersphere.request.testcase.TrackCount;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用例数量统计数据
|
* 用例数量统计数据
|
||||||
|
@ -107,33 +110,31 @@ public class TrackStatisticsDTO {
|
||||||
*/
|
*/
|
||||||
private long unPassCount = 0;
|
private long unPassCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 面板数据
|
||||||
|
*/
|
||||||
|
private Map<String, Integer> chartData;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照 Priority 统计
|
* 按照 Priority 统计
|
||||||
* @param trackCountResults 统计结果
|
* @param trackCountResults 统计结果
|
||||||
*/
|
*/
|
||||||
public void countPriority(List<TrackCountResult> trackCountResults) {
|
public void countPriority(List<TrackCountResult> trackCountResults) {
|
||||||
|
Map<String, Integer> chartData = new HashMap<>();
|
||||||
for (TrackCountResult countResult : trackCountResults) {
|
for (TrackCountResult countResult : trackCountResults) {
|
||||||
if (StringUtils.isNotBlank(countResult.getGroupField())) {
|
if (StringUtils.isNotBlank(countResult.getGroupField())) {
|
||||||
switch (countResult.getGroupField().toUpperCase()){
|
Integer count = chartData.get(countResult.getGroupField());
|
||||||
case TrackCount.P0:
|
if (count == null) {
|
||||||
this.p0CaseCountNumber += countResult.getCountNumber();
|
chartData.put(countResult.getGroupField(), (int) countResult.getCountNumber());
|
||||||
break;
|
} else {
|
||||||
case TrackCount.P1:
|
count += (int) countResult.getCountNumber();
|
||||||
this.p1CaseCountNumber += countResult.getCountNumber();
|
chartData.put(countResult.getGroupField(), count);
|
||||||
break;
|
|
||||||
case TrackCount.P2:
|
|
||||||
this.p2CaseCountNumber += countResult.getCountNumber();
|
|
||||||
break;
|
|
||||||
case TrackCount.P3:
|
|
||||||
this.p3CaseCountNumber += countResult.getCountNumber();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.allCaseCountNumber += countResult.getCountNumber();
|
this.allCaseCountNumber += countResult.getCountNumber();
|
||||||
}
|
}
|
||||||
|
this.chartData = chartData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void countStatus(List<TrackCountResult> statusResults) {
|
public void countStatus(List<TrackCountResult> statusResults) {
|
||||||
|
@ -149,24 +150,38 @@ public class TrackStatisticsDTO {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void countRelevance(List<TrackCountResult> relevanceResults) {
|
public void countRelevance(List<TrackCountResult> relevanceResults) {
|
||||||
|
Map<String, Integer> chartData = new HashMap<>();
|
||||||
for (TrackCountResult countResult : relevanceResults) {
|
for (TrackCountResult countResult : relevanceResults) {
|
||||||
switch (countResult.getGroupField()){
|
if (StringUtils.equalsIgnoreCase(TrackCount.TESTCASE, countResult.getGroupField())) {
|
||||||
case TrackCount.TESTCASE:
|
Integer count = chartData.get(Translator.get("api_case"));
|
||||||
this.apiCaseCount += countResult.getCountNumber();
|
if (count == null) {
|
||||||
this.allRelevanceCaseCount += countResult.getCountNumber();
|
chartData.put(Translator.get("api_case"), (int) countResult.getCountNumber());
|
||||||
break;
|
} else {
|
||||||
case TrackCount.PERFORMANCE:
|
count += (int) countResult.getCountNumber();
|
||||||
this.performanceCaseCount += countResult.getCountNumber();
|
chartData.put(Translator.get("api_case"), count);
|
||||||
this.allRelevanceCaseCount += countResult.getCountNumber();
|
|
||||||
break;
|
|
||||||
case TrackCount.AUTOMATION:
|
|
||||||
this.scenarioCaseCount += countResult.getCountNumber();
|
|
||||||
this.allRelevanceCaseCount += countResult.getCountNumber();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (StringUtils.equalsIgnoreCase(TrackCount.PERFORMANCE, countResult.getGroupField())) {
|
||||||
|
Integer count = chartData.get(Translator.get("performance_case"));
|
||||||
|
if (count == null) {
|
||||||
|
chartData.put(Translator.get("performance_case"), (int) countResult.getCountNumber());
|
||||||
|
} else {
|
||||||
|
count += (int) countResult.getCountNumber();
|
||||||
|
chartData.put(Translator.get("performance_case"), count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.equalsIgnoreCase(TrackCount.AUTOMATION, countResult.getGroupField())) {
|
||||||
|
Integer count = chartData.get(Translator.get("scenario_case"));
|
||||||
|
if (count == null) {
|
||||||
|
chartData.put(Translator.get("scenario_case"), (int) countResult.getCountNumber());
|
||||||
|
} else {
|
||||||
|
count += (int) countResult.getCountNumber();
|
||||||
|
chartData.put(Translator.get("scenario_case"), count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.allRelevanceCaseCount += countResult.getCountNumber();
|
||||||
|
}
|
||||||
|
this.chartData = chartData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void countCoverage(List<TrackCountResult> coverageResults) {
|
public void countCoverage(List<TrackCountResult> coverageResults) {
|
||||||
|
|
|
@ -1456,16 +1456,26 @@ public class IssuesService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThisWeekUnclosedIds(IssuesRequest request) {
|
public void setFilterIds(IssuesRequest request) {
|
||||||
List<String> issueIds = extIssuesMapper.getTestPlanThisWeekIssue(request.getProjectId());
|
List<String> issueIds = new ArrayList<>();
|
||||||
|
if (request.getThisWeekUnClosedTestPlanIssue()) {
|
||||||
|
issueIds = extIssuesMapper.getTestPlanThisWeekIssue(request.getProjectId());
|
||||||
|
} else if (request.getAllTestPlanIssue() || request.getUnClosedTestPlanIssue()) {
|
||||||
|
issueIds = extIssuesMapper.getTestPlanIssue(request.getProjectId());
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> statusMap = customFieldIssuesService.getIssueStatusMap(issueIds, request.getProjectId());
|
Map<String, String> statusMap = customFieldIssuesService.getIssueStatusMap(issueIds, request.getProjectId());
|
||||||
if (MapUtils.isEmpty(statusMap)) {
|
if (MapUtils.isEmpty(statusMap)) {
|
||||||
request.setThisWeekUncloseIds(issueIds);
|
request.setFilterIds(issueIds);
|
||||||
} else {
|
} else {
|
||||||
|
if (request.getThisWeekUnClosedTestPlanIssue() || request.getUnClosedTestPlanIssue()) {
|
||||||
List<String> unClosedIds = issueIds.stream()
|
List<String> unClosedIds = issueIds.stream()
|
||||||
.filter(id -> !StringUtils.equals(statusMap.getOrDefault(id, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY), "closed"))
|
.filter(id -> !StringUtils.equals(statusMap.getOrDefault(id, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY), "closed"))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
request.setThisWeekUncloseIds(unClosedIds);
|
request.setFilterIds(unClosedIds);
|
||||||
|
} else {
|
||||||
|
request.setFilterIds(issueIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.metersphere.base.domain.CustomField;
|
||||||
import io.metersphere.base.domain.TestPlan;
|
import io.metersphere.base.domain.TestPlan;
|
||||||
import io.metersphere.base.domain.TestPlanExample;
|
import io.metersphere.base.domain.TestPlanExample;
|
||||||
import io.metersphere.base.mapper.TestPlanMapper;
|
import io.metersphere.base.mapper.TestPlanMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
|
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||||
import io.metersphere.commons.utils.DateUtils;
|
import io.metersphere.commons.utils.DateUtils;
|
||||||
|
import io.metersphere.constants.IssueStatus;
|
||||||
|
import io.metersphere.constants.SystemCustomField;
|
||||||
import io.metersphere.dto.BugStatistics;
|
import io.metersphere.dto.BugStatistics;
|
||||||
import io.metersphere.dto.TestPlanBugCount;
|
import io.metersphere.dto.TestPlanBugCount;
|
||||||
import io.metersphere.dto.TestPlanDTOWithMetric;
|
import io.metersphere.dto.TestPlanDTOWithMetric;
|
||||||
import io.metersphere.dto.TrackCountResult;
|
import io.metersphere.dto.TrackCountResult;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.plan.dto.ChartsData;
|
import io.metersphere.plan.dto.ChartsData;
|
||||||
import io.metersphere.plan.service.TestPlanService;
|
import io.metersphere.plan.service.TestPlanService;
|
||||||
import io.metersphere.xpack.track.dto.IssuesDao;
|
import io.metersphere.xpack.track.dto.IssuesDao;
|
||||||
|
@ -37,6 +43,8 @@ public class TrackService {
|
||||||
@Resource
|
@Resource
|
||||||
private CustomFieldIssuesService customFieldIssuesService;
|
private CustomFieldIssuesService customFieldIssuesService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private BaseCustomFieldService baseCustomFieldService;
|
||||||
|
@Resource
|
||||||
private TestPlanService testPlanService;
|
private TestPlanService testPlanService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -110,27 +118,21 @@ public class TrackService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BugStatistics getBugStatistics(String projectId) {
|
public BugStatistics getBugStatistics(String projectId) {
|
||||||
|
List<TestPlanBugCount> list = new ArrayList<>();
|
||||||
|
BugStatistics bugStatistics = new BugStatistics();
|
||||||
TestPlanExample example = new TestPlanExample();
|
TestPlanExample example = new TestPlanExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId);
|
example.createCriteria().andProjectIdEqualTo(projectId);
|
||||||
List<TestPlan> plans = testPlanMapper.selectByExample(example);
|
List<TestPlan> plans = testPlanMapper.selectByExample(example);
|
||||||
List<TestPlanBugCount> list = new ArrayList<>();
|
List<String> planIds = plans.stream().map(TestPlan::getId).collect(Collectors.toList());
|
||||||
BugStatistics bugStatistics = new BugStatistics();
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
int totalUnClosedPlanBugSize = 0;
|
int totalUnClosedPlanBugSize = 0;
|
||||||
int totalPlanBugSize = 0;
|
int totalPlanBugSize = 0;
|
||||||
int newCount = 0;
|
|
||||||
int resolvedCount = 0;
|
|
||||||
int rejectedCount = 0;
|
|
||||||
int unKnownCount = 0;
|
|
||||||
int thisWeekCount = 0;
|
int thisWeekCount = 0;
|
||||||
|
Map<String, Integer> bugStatusMap = getPlanBugStatusSize(planIds, projectId);
|
||||||
for (TestPlan plan : plans) {
|
for (TestPlan plan : plans) {
|
||||||
Map<String, Integer> bugSizeMap = getPlanBugSize(plan.getId(), projectId);
|
Map<String, Integer> bugSizeMap = getPlanBugSize(plan.getId(), projectId);
|
||||||
int planBugSize = bugSizeMap.get("total");
|
int planBugSize = bugSizeMap.get("total");
|
||||||
int unClosedPlanBugSize = bugSizeMap.get("unClosed");
|
int unClosedPlanBugSize = bugSizeMap.get("unClosed");
|
||||||
newCount += bugSizeMap.get("newCount");
|
|
||||||
resolvedCount += bugSizeMap.get("resolvedCount");
|
|
||||||
rejectedCount += bugSizeMap.get("rejectedCount");
|
|
||||||
unKnownCount += bugSizeMap.get("unKnownCount");
|
|
||||||
thisWeekCount += bugSizeMap.get("thisWeekCount");
|
thisWeekCount += bugSizeMap.get("thisWeekCount");
|
||||||
totalUnClosedPlanBugSize += unClosedPlanBugSize;
|
totalUnClosedPlanBugSize += unClosedPlanBugSize;
|
||||||
totalPlanBugSize += planBugSize;
|
totalPlanBugSize += planBugSize;
|
||||||
|
@ -138,7 +140,6 @@ public class TrackService {
|
||||||
if (unClosedPlanBugSize == 0) {
|
if (unClosedPlanBugSize == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestPlanBugCount testPlanBug = new TestPlanBugCount();
|
TestPlanBugCount testPlanBug = new TestPlanBugCount();
|
||||||
testPlanBug.setIndex(index++);
|
testPlanBug.setIndex(index++);
|
||||||
testPlanBug.setPlanName(plan.getName());
|
testPlanBug.setPlanName(plan.getName());
|
||||||
|
@ -158,12 +159,8 @@ public class TrackService {
|
||||||
float rage = totalPlanBugSize == 0 ? 0 : (float) totalUnClosedPlanBugSize * 100 / totalPlanBugSize;
|
float rage = totalPlanBugSize == 0 ? 0 : (float) totalUnClosedPlanBugSize * 100 / totalPlanBugSize;
|
||||||
DecimalFormat df = new DecimalFormat("0.0");
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
bugStatistics.setUnClosedRage(df.format(rage) + "%");
|
bugStatistics.setUnClosedRage(df.format(rage) + "%");
|
||||||
|
|
||||||
bugStatistics.setNewCount(newCount);
|
|
||||||
bugStatistics.setResolvedCount(resolvedCount);
|
|
||||||
bugStatistics.setRejectedCount(rejectedCount);
|
|
||||||
bugStatistics.setUnKnownCount(unKnownCount);
|
|
||||||
bugStatistics.setThisWeekCount(thisWeekCount);
|
bugStatistics.setThisWeekCount(thisWeekCount);
|
||||||
|
bugStatistics.setChartData(bugStatusMap);
|
||||||
return bugStatistics;
|
return bugStatistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,13 +174,11 @@ public class TrackService {
|
||||||
Map<String, String> statusMap = customFieldIssuesService.getIssueStatusMap(issueIds, projectId);
|
Map<String, String> statusMap = customFieldIssuesService.getIssueStatusMap(issueIds, projectId);
|
||||||
Map<String, Integer> bugSizeMap = new HashMap<>();
|
Map<String, Integer> bugSizeMap = new HashMap<>();
|
||||||
bugSizeMap.put("total", issueIds.size());
|
bugSizeMap.put("total", issueIds.size());
|
||||||
|
|
||||||
// 缺陷是否有状态
|
// 缺陷是否有状态
|
||||||
List<String> unClosedIds;
|
List<String> unClosedIds;
|
||||||
if (MapUtils.isEmpty(statusMap)) {
|
if (MapUtils.isEmpty(statusMap)) {
|
||||||
unClosedIds = issueIds;
|
unClosedIds = issueIds;
|
||||||
bugSizeMap.put("unClosed", issueIds.size());
|
bugSizeMap.put("unClosed", issueIds.size());
|
||||||
bugSizeMap.put("newCount", issueIds.size());
|
|
||||||
} else {
|
} else {
|
||||||
unClosedIds = issueIds.stream()
|
unClosedIds = issueIds.stream()
|
||||||
.filter(id -> !StringUtils.equals(statusMap.getOrDefault(id, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY), "closed"))
|
.filter(id -> !StringUtils.equals(statusMap.getOrDefault(id, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY), "closed"))
|
||||||
|
@ -196,29 +191,59 @@ public class TrackService {
|
||||||
thisWeekCount = extIssuesMapper.getThisWeekIssueCount(unClosedIds, projectId).intValue();
|
thisWeekCount = extIssuesMapper.getThisWeekIssueCount(unClosedIds, projectId).intValue();
|
||||||
}
|
}
|
||||||
bugSizeMap.put("thisWeekCount", thisWeekCount);
|
bugSizeMap.put("thisWeekCount", thisWeekCount);
|
||||||
// 如果没有严重程度字段
|
return bugSizeMap;
|
||||||
int newCount = 0;
|
|
||||||
int resolvedCount = 0;
|
|
||||||
int rejectedCount = 0;
|
|
||||||
int unKnownCount = 0;
|
|
||||||
for (String unClosedId : unClosedIds) {
|
|
||||||
String status = statusMap.getOrDefault(unClosedId, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY);
|
|
||||||
if (StringUtils.equalsIgnoreCase(status, "new")) {
|
|
||||||
newCount += 1;
|
|
||||||
} else if (StringUtils.equalsIgnoreCase(status, "resolved")) {
|
|
||||||
resolvedCount += 1;
|
|
||||||
} else if (StringUtils.equalsIgnoreCase(status, "rejected")) {
|
|
||||||
rejectedCount += 1;
|
|
||||||
} else {
|
|
||||||
unKnownCount += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bugSizeMap.put("newCount", newCount);
|
private Map<String, Integer> getPlanBugStatusSize(List<String> planIds, String projectId) {
|
||||||
bugSizeMap.put("resolvedCount", resolvedCount);
|
CustomField customField = baseCustomFieldService.getCustomFieldByName(projectId, SystemCustomField.ISSUE_STATUS);
|
||||||
bugSizeMap.put("rejectedCount", rejectedCount);
|
JSONArray statusArray = JSONArray.parseArray(customField.getOptions());
|
||||||
bugSizeMap.put("unKnownCount", unKnownCount);
|
Map<String, Integer> bugStatusMap = new HashMap<>();
|
||||||
return bugSizeMap;
|
if (CollectionUtils.isNotEmpty(planIds)) {
|
||||||
|
planIds.forEach(planId -> {
|
||||||
|
List<String> issueIds = extTestCaseMapper.getTestPlanBug(planId);
|
||||||
|
Map<String, String> statusMap = customFieldIssuesService.getIssueStatusMap(issueIds, projectId);
|
||||||
|
if (MapUtils.isEmpty(statusMap)) {
|
||||||
|
Integer count = bugStatusMap.get(Translator.get("new"));
|
||||||
|
if (count == null) {
|
||||||
|
bugStatusMap.put(Translator.get("new"), issueIds.size());
|
||||||
|
} else {
|
||||||
|
count += issueIds.size();
|
||||||
|
bugStatusMap.put(Translator.get("new"), count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<String> unClosedIds = issueIds.stream()
|
||||||
|
.filter(id -> !StringUtils.equals(statusMap.getOrDefault(id, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY), "closed"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
for (String unClosedId : unClosedIds) {
|
||||||
|
String status = statusMap.getOrDefault(unClosedId, StringUtils.EMPTY).replaceAll("\"", StringUtils.EMPTY);
|
||||||
|
IssueStatus statusEnum = IssueStatus.getEnumByName(status);
|
||||||
|
if (statusEnum != null) {
|
||||||
|
Integer count = bugStatusMap.get(Translator.get(statusEnum.getI18nKey()));
|
||||||
|
if (count == null) {
|
||||||
|
bugStatusMap.put(Translator.get(statusEnum.getI18nKey()), 1);
|
||||||
|
} else {
|
||||||
|
count += 1;
|
||||||
|
bugStatusMap.put(Translator.get(statusEnum.getI18nKey()), count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statusArray.forEach(item -> {
|
||||||
|
JSONObject statusObj = (JSONObject) item;
|
||||||
|
if (StringUtils.equals(status, statusObj.get("value").toString())) {
|
||||||
|
Integer count = bugStatusMap.get(statusObj.get("text").toString());
|
||||||
|
if (count == null) {
|
||||||
|
bugStatusMap.put(statusObj.get("text").toString(), 1);
|
||||||
|
} else {
|
||||||
|
count += 1;
|
||||||
|
bugStatusMap.put(statusObj.get("text").toString(), count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return bugStatusMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAllUnClosedBugSize(String projectId) {
|
private int getAllUnClosedBugSize(String projectId) {
|
||||||
|
|
|
@ -63,6 +63,16 @@ can_not_be_null=Can not be null
|
||||||
excel_field_not_exist=Not exist
|
excel_field_not_exist=Not exist
|
||||||
options_not_exist=Incorrect option value
|
options_not_exist=Incorrect option value
|
||||||
format_error=Format error
|
format_error=Format error
|
||||||
|
# issue status
|
||||||
|
new=new
|
||||||
|
resolved=resolved
|
||||||
|
closed=closed
|
||||||
|
active=active
|
||||||
|
delete=delete
|
||||||
|
in_progress=in_progress
|
||||||
|
rejected=rejected
|
||||||
|
upcoming=upcoming
|
||||||
|
reopened=reopened
|
||||||
#project
|
#project
|
||||||
project_name_is_null=Project name cannot be null
|
project_name_is_null=Project name cannot be null
|
||||||
project_name_already_exists=The project name already exists
|
project_name_already_exists=The project name already exists
|
||||||
|
|
|
@ -40,6 +40,16 @@ can_not_be_null=不能为空
|
||||||
excel_field_not_exist=不存在该字段
|
excel_field_not_exist=不存在该字段
|
||||||
options_not_exist=选项值有误
|
options_not_exist=选项值有误
|
||||||
format_error=格式有误
|
format_error=格式有误
|
||||||
|
# issue status
|
||||||
|
new=新建
|
||||||
|
resolved=已解决
|
||||||
|
closed=已关闭
|
||||||
|
active=激活
|
||||||
|
delete=删除
|
||||||
|
in_progress=接受/处理
|
||||||
|
rejected=已拒绝
|
||||||
|
upcoming=待办
|
||||||
|
reopened=重新打开
|
||||||
#project
|
#project
|
||||||
project_name_is_null=项目名称不能为空
|
project_name_is_null=项目名称不能为空
|
||||||
project_name_already_exists=项目名称已存在
|
project_name_already_exists=项目名称已存在
|
||||||
|
|
|
@ -40,6 +40,16 @@ can_not_be_null=不能爲空
|
||||||
excel_field_not_exist=不存在該字段
|
excel_field_not_exist=不存在該字段
|
||||||
options_not_exist=選項值有誤
|
options_not_exist=選項值有誤
|
||||||
format_error=格式有誤
|
format_error=格式有誤
|
||||||
|
#issue status
|
||||||
|
new=新建
|
||||||
|
resolved=已解決
|
||||||
|
closed=已關閉
|
||||||
|
active=激活
|
||||||
|
delete=刪除
|
||||||
|
in_progress=接受/處理
|
||||||
|
rejected=已拒絕
|
||||||
|
upcoming=待辦
|
||||||
|
reopened=重新打開
|
||||||
#project
|
#project
|
||||||
project_name_is_null=項目名稱不能為空
|
project_name_is_null=項目名稱不能為空
|
||||||
project_name_already_exists=項目名稱已存在
|
project_name_already_exists=項目名稱已存在
|
||||||
|
|
|
@ -5,3 +5,8 @@ export const TEST_CASE_STATUS_MAP = {
|
||||||
'Completed': i18n.t('test_track.plan.plan_status_completed'),
|
'Completed': i18n.t('test_track.plan.plan_status_completed'),
|
||||||
'Trash': i18n.t('test_track.plan.plan_status_trash')
|
'Trash': i18n.t('test_track.plan.plan_status_trash')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DASHBOARD_CHART_COLOR = [
|
||||||
|
'#AA4FBF', '#FFD131', '#10CECE', '#4E83FD',
|
||||||
|
'#935AF6', '#50CEFB', '#FFA53D', '#62D256',
|
||||||
|
];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="background-color:#F5F6F7">
|
<div style="background-color:#F5F6F7; overflow: auto">
|
||||||
<ms-container>
|
<ms-container>
|
||||||
<ms-main-container style="overflow-y: hidden">
|
<ms-main-container style="padding: 0px">
|
||||||
<div class="track-home-layout">
|
<div class="track-home-layout">
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<el-row :gutter="16" style="margin-top: 16px">
|
<el-row :gutter="16" style="margin-top: 16px">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<bug-count-card />
|
<bug-count-card @redirectPage="redirectPage"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<case-maintenance />
|
<case-maintenance />
|
||||||
|
@ -22,19 +22,19 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row style="margin-top: 16px">
|
<el-row style="margin-top: 16px">
|
||||||
<el-col style="background-color: #FFFFFF;">
|
<el-col style="height: 369px; background-color: #FFFFFF;">
|
||||||
<ms-failure-test-case-list :select-function-case="true" @redirectPage="redirectPage"/>
|
<ms-failure-test-case-list :select-function-case="true" @redirectPage="redirectPage"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row style="margin-top: 16px">
|
<el-row style="margin-top: 16px">
|
||||||
<el-col style="background-color: #FFFFFF;">
|
<el-col style="height: 369px; background-color: #FFFFFF;">
|
||||||
<review-list/>
|
<review-list/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row style="margin-top: 16px">
|
<el-row style="margin-top: 16px">
|
||||||
<el-col style="background-color: #FFFFFF;">
|
<el-col style="height: 369px; background-color: #FFFFFF;">
|
||||||
<ms-running-task-list :call-from="'track_home'" @redirectPage="redirectPage"/>
|
<ms-running-task-list :call-from="'track_home'" @redirectPage="redirectPage"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -55,7 +55,6 @@ import BugCountCard from "./components/BugCountCard";
|
||||||
import ReviewList from "./components/ReviewList";
|
import ReviewList from "./components/ReviewList";
|
||||||
import MsRunningTaskList from "./components/RunningTaskList";
|
import MsRunningTaskList from "./components/RunningTaskList";
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
import {getUUID} from "metersphere-frontend/src/utils";
|
||||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
|
||||||
import MsFailureTestCaseList from "@/business/home/components/FailureTestCaseList";
|
import MsFailureTestCaseList from "@/business/home/components/FailureTestCaseList";
|
||||||
|
|
||||||
require('echarts/lib/component/legend');
|
require('echarts/lib/component/legend');
|
||||||
|
@ -76,11 +75,6 @@ export default {
|
||||||
return {
|
return {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
projectId() {
|
|
||||||
return getCurrentProjectID();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
redirectPage(page, dataType, selectType, title) {
|
redirectPage(page, dataType, selectType, title) {
|
||||||
//api页面跳转
|
//api页面跳转
|
||||||
|
@ -103,6 +97,8 @@ export default {
|
||||||
case "api":
|
case "api":
|
||||||
home = this.$router.resolve('/api/definition/' + uuid + "/" + dataType + "/" + selectType);
|
home = this.$router.resolve('/api/definition/' + uuid + "/" + dataType + "/" + selectType);
|
||||||
break;
|
break;
|
||||||
|
case "issue":
|
||||||
|
home = this.$router.resolve('/track/issue/' + uuid + "/" + dataType + "/" + selectType);
|
||||||
}
|
}
|
||||||
if (home) {
|
if (home) {
|
||||||
window.open(home.href, '_blank');
|
window.open(home.href, '_blank');
|
||||||
|
@ -193,4 +189,8 @@ export default {
|
||||||
color: #1F2329;
|
color: #1F2329;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.track-home-layout :deep(.el-card) {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" shadow="never" body-style="padding:10px 5px;">
|
<div class="dashboard-card">
|
||||||
<div slot="header">
|
<el-card shadow="never" class="box-card" style="height: 100%">
|
||||||
<span class="title">
|
<div slot="header" class="clearfix">
|
||||||
{{ $t('test_track.home.bug_count') }}
|
<span class="dashboard-title">{{ $t('test_track.home.bug_count') }}</span>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-loading="loading" element-loading-background="#FFFFFF">
|
<div v-loading="loading" element-loading-background="#FFFFFF">
|
||||||
<div v-show="loadError"
|
<div v-show="loadError"
|
||||||
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center;align-items: center">
|
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center; align-items: center">
|
||||||
<img style="height: 100px;width: 100px;"
|
<img style="height: 100px;width: 100px;"
|
||||||
src="/assets/figma/icon_load_error.svg"/>
|
src="/assets/figma/icon_load_error.svg"/>
|
||||||
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<div class="main-info">
|
<div class="main-info">
|
||||||
<bug-count-chart :bug-data="bugData" ref="countChart" @redirectPage="redirectPage"/>
|
<count-chart :chart-data="bugData.chartData" :main-title="chartMainTitle"
|
||||||
|
:week-count="bugData.thisWeekAddedCount" :chart-sub-link="chartRedirectLink" ref="countChart" @redirectPage="redirectPage"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="24" style="margin: 0">
|
<el-row :gutter="24" style="margin: 0">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
{{ $t('home.bug_dashboard.un_closed_count') }}
|
{{ $t('home.bug_dashboard.un_closed_count') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num">
|
<el-link class="addition-info-num" @click="redirectPage('unClosedRelatedTestPlan')">
|
||||||
{{ formatAmount(bugData.bugUnclosedCount) }}
|
{{ formatAmount(bugData.bugUnclosedCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
{{ $t('home.bug_dashboard.total_count') }}
|
{{ $t('home.bug_dashboard.total_count') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num">
|
<el-link class="addition-info-num" @click="redirectPage('AllRelatedTestPlan')">
|
||||||
{{ formatAmount(bugData.bugTotalCount) }}
|
{{ formatAmount(bugData.bugTotalCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,24 +59,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import bugCountChart from "@/business/home/components/chart/BugCountChart";
|
import countChart from "@/business/home/components/chart/CountChart";
|
||||||
import hoverCard from "@/business/home/components/card/HoverCard";
|
import hoverCard from "@/business/home/components/card/HoverCard";
|
||||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||||
import {getTrackBugCount} from "@/api/track";
|
import {getTrackBugCount} from "@/api/track";
|
||||||
import {formatNumber} from "@/api/track"
|
import {formatNumber} from "@/api/track"
|
||||||
|
import {getUUID} from "metersphere-frontend/src/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "BugCountCard",
|
name: "BugCountCard",
|
||||||
components: {bugCountChart, hoverCard},
|
components: {countChart, hoverCard},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
unClosedBugRangeToolTip: this.$t('home.bug_dashboard.un_closed_range_tips'),
|
unClosedBugRangeToolTip: this.$t('home.bug_dashboard.un_closed_range_tips'),
|
||||||
unClosedBugCaseRangeToolTip: this.$t('home.bug_dashboard.un_closed_bug_case_range_tips'),
|
unClosedBugCaseRangeToolTip: this.$t('home.bug_dashboard.un_closed_bug_case_range_tips'),
|
||||||
|
chartMainTitle: this.$t("home.bug_dashboard.un_closed_bug_count"),
|
||||||
|
chartRedirectLink: "/#/track/issue/" + getUUID() + "/" + getCurrentProjectID() + "/thisWeekUnClosedIssue",
|
||||||
bugData: {
|
bugData: {
|
||||||
bugCaseRage:" 0%",
|
bugCaseRage:" 0%",
|
||||||
bugTotalCount: 0,
|
bugTotalCount: 0,
|
||||||
|
@ -87,7 +91,8 @@ export default {
|
||||||
resolvedCount: 0,
|
resolvedCount: 0,
|
||||||
rejectedCount: 0,
|
rejectedCount: 0,
|
||||||
unKnownCount: 0,
|
unKnownCount: 0,
|
||||||
thisWeekCount: 0
|
thisWeekCount: 0,
|
||||||
|
chartData: {}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -114,7 +119,8 @@ export default {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
},
|
},
|
||||||
redirectPage(clickType) {
|
redirectPage(clickType) {
|
||||||
this.$emit("redirectPage", "testCase", "relationCase", clickType);
|
let currentProjectId = getCurrentProjectID();
|
||||||
|
this.$emit("redirectPage", "issue", currentProjectId, clickType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" shadow="never" body-style="padding: 10px 5px;">
|
<div class="dashboard-card">
|
||||||
<div slot="header">
|
<el-card shadow="never" class="box-card" style="height: 100%">
|
||||||
<span class="title">
|
<div slot="header" class="clearfix">
|
||||||
{{ $t('test_track.home.case_count') }}
|
<span class="dashboard-title">{{ $t('test_track.home.case_count') }}</span>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-loading="loading" element-loading-background="#FFFFFF">
|
<div v-loading="loading" element-loading-background="#FFFFFF">
|
||||||
<div v-show="loadError"
|
<div v-show="loadError"
|
||||||
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center;align-items: center">
|
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center; align-items: center">
|
||||||
<img style="height: 100px;width: 100px;"
|
<img style="height: 100px;width: 100px;"
|
||||||
src="/assets/figma/icon_load_error.svg"/>
|
src="/assets/figma/icon_load_error.svg"/>
|
||||||
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<div class="main-info">
|
<div class="main-info">
|
||||||
<case-count-chart :track-data="trackData" ref="countChart" @redirectPage="redirectPage"/>
|
<count-chart :chart-data="trackData.chartData" :main-title="chartMainTitle"
|
||||||
|
:week-count="trackData.thisWeekAddedCount" :chart-sub-link="chartRedirectLink" ref="countChart" @redirectPage="redirectPage"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="16" style="margin: 0">
|
<el-row :gutter="16" style="margin: 0">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
{{ $t('home.case_review_dashboard.not_review') }}
|
{{ $t('home.case_review_dashboard.not_review') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('notReviewed')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('notReviewed')">
|
||||||
{{ formatAmount(trackData.prepareCount) }}
|
{{ formatAmount(trackData.prepareCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
{{ $t('home.case_review_dashboard.finished_review') }}
|
{{ $t('home.case_review_dashboard.finished_review') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('reviewed')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('reviewed')">
|
||||||
{{ formatAmount(trackData.passCount + trackData.unPassCount) }}
|
{{ formatAmount(trackData.passCount + trackData.unPassCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
{{ $t("home.case_review_dashboard.not_pass") }}
|
{{ $t("home.case_review_dashboard.not_pass") }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('UnPass')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('UnPass')">
|
||||||
{{ formatAmount(trackData.unPassCount) }}
|
{{ formatAmount(trackData.unPassCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
{{ $t("home.case_review_dashboard.pass") }}
|
{{ $t("home.case_review_dashboard.pass") }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('Pass')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('Pass')">
|
||||||
{{ formatAmount(trackData.passCount) }}
|
{{ formatAmount(trackData.passCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,25 +95,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import caseCountChart from "@/business/home/components/chart/CaseCountChart";
|
import countChart from "@/business/home/components/chart/CountChart";
|
||||||
import hoverCard from "@/business/home/components/card/HoverCard";
|
import hoverCard from "@/business/home/components/card/HoverCard";
|
||||||
|
import {getUUID} from "metersphere-frontend/src/utils";
|
||||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||||
import {getTrackCount} from "@/api/track";
|
import {getTrackCount} from "@/api/track";
|
||||||
import {formatNumber} from "@/api/track"
|
import {formatNumber} from "@/api/track"
|
||||||
import {hasPermission} from "@/business/utils/sdk-utils";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CaseCountCard",
|
name: "CaseCountCard",
|
||||||
components: {caseCountChart, hoverCard},
|
components: {countChart, hoverCard},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
caseReviewRangeToolTip: this.$t('api_test.home_page.formula.review'),
|
caseReviewRangeToolTip: this.$t('api_test.home_page.formula.review'),
|
||||||
caseFinishedReviewPassRageToolTip: this.$t('home.dashboard.case_finished_review_pass_tip'),
|
caseFinishedReviewPassRageToolTip: this.$t('home.dashboard.case_finished_review_pass_tip'),
|
||||||
|
chartMainTitle: this.$t("home.case_review_dashboard.case_count"),
|
||||||
|
chartRedirectLink: "/#/track/case/all/" + getUUID() + "/case/thisWeekCount",
|
||||||
trackData: {
|
trackData: {
|
||||||
allCaseCountNumber: 0,
|
allCaseCountNumber: 0,
|
||||||
allRelevanceCaseCount: 0,
|
allRelevanceCaseCount: 0,
|
||||||
|
@ -135,7 +138,8 @@ export default {
|
||||||
scenarioCaseStr: "",
|
scenarioCaseStr: "",
|
||||||
thisWeekAddedCount: 0,
|
thisWeekAddedCount: 0,
|
||||||
unPassCount: 0,
|
unPassCount: 0,
|
||||||
uncoverageCount: 0
|
uncoverageCount: 0,
|
||||||
|
chartData: {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -163,9 +167,6 @@ export default {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
},
|
},
|
||||||
redirectPage(clickType) {
|
redirectPage(clickType) {
|
||||||
if (!hasPermission('PROJECT_TRACK_CASE:READ')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$emit("redirectPage", "testCase", "case", clickType);
|
this.$emit("redirectPage", "testCase", "case", clickType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" shadow="never" body-style="padding:10px;">
|
<div class="dashboard-card">
|
||||||
<div slot="header">
|
<el-card shadow="never" class="box-card" style="height: 100%">
|
||||||
<span class="title">
|
<div slot="header" class="clearfix">
|
||||||
{{ $t('test_track.home.case_maintenance') }}
|
<span class="dashboard-title">{{ $t('test_track.home.case_maintenance') }}</span>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-loading="loading" element-loading-background="#FFFFFF">
|
<div v-loading="loading" element-loading-background="#FFFFFF">
|
||||||
|
@ -15,11 +14,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<el-container>
|
<el-container>
|
||||||
<ms-chart ref="chart1" :options="caseOption" :autoresize="true" style="width: 100%;height: 323px"></ms-chart>
|
<ms-chart ref="chart1" :options="caseOption" :autoresize="true" style="width: 100%;height: 323px;"></ms-chart>
|
||||||
</el-container>
|
</el-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -88,12 +88,21 @@ export default {
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
grid: {
|
||||||
|
left: 0,
|
||||||
|
containLabel: true,
|
||||||
|
bottom: 24,
|
||||||
|
top: 60,
|
||||||
|
right: 24,
|
||||||
|
width: 600,
|
||||||
|
height: 250
|
||||||
|
},
|
||||||
legend: {
|
legend: {
|
||||||
itemWidth: 8,
|
itemWidth: 8,
|
||||||
itemHeight: 8,
|
itemHeight: 8,
|
||||||
data: [{icon: 'rect', name: this.$t('test_track.home.function_case_count')}, {icon: 'rect', name: this.$t('test_track.home.relevance_case_count')}],
|
data: [{icon: 'rect', name: this.$t('test_track.home.function_case_count')}, {icon: 'rect', name: this.$t('test_track.home.relevance_case_count')}],
|
||||||
orient: 'horizontal',
|
orient: 'horizontal',
|
||||||
left: '30',
|
left: '0',
|
||||||
top: '10'
|
top: '10'
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" shadow="never" v-loading="loading" body-style="padding:10px;">
|
<el-card class="table-card" shadow="never" v-loading="loading">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<span class="table-title">
|
<span class="table-title">
|
||||||
{{ $t('api_test.home_page.failed_case_list.title') }}
|
{{ $t('api_test.home_page.failed_case_list.title') }}
|
||||||
|
@ -14,8 +14,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<el-table :data="tableData" class="adjust-table table-content"
|
<el-table :data="tableData" class="adjust-table table-content"
|
||||||
:header-cell-style="{backgroundColor: '#F5F6F7'}" max-height="224px">
|
header-cell-class-name="home-table-cell" max-height="226px">
|
||||||
<el-table-column type="index" :label="$t('home.case.index')" show-overflow-tooltip/>
|
<el-table-column type="index" :label="$t('home.case.index')" width="100" show-overflow-tooltip/>
|
||||||
<el-table-column prop="caseName" :label="$t('home.case.case_name')">
|
<el-table-column prop="caseName" :label="$t('home.case.case_name')">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-link type="info" @click="redirect(row.caseType,row.id)"
|
<el-link type="info" @click="redirect(row.caseType,row.id)"
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card class="table-card" shadow="never" body-style="padding:10px 5px;">
|
<div class="dashboard-card">
|
||||||
<div slot="header">
|
<el-card shadow="never" class="box-card" style="height: 100%">
|
||||||
<span class="title">
|
<div slot="header" class="clearfix">
|
||||||
{{ $t('test_track.home.relevance_case') }}
|
<span class="dashboard-title">{{ $t('test_track.home.relevance_case') }}</span>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-loading="loading" element-loading-background="#FFFFFF">
|
<div v-loading="loading" element-loading-background="#FFFFFF">
|
||||||
<div v-show="loadError"
|
<div v-show="loadError"
|
||||||
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center;align-items: center">
|
style="width: 100%; height: 300px; display: flex; flex-direction: column; justify-content: center; align-items: center">
|
||||||
<img style="height: 100px;width: 100px;"
|
<img style="height: 100px;width: 100px;"
|
||||||
src="/assets/figma/icon_load_error.svg"/>
|
src="/assets/figma/icon_load_error.svg"/>
|
||||||
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
<span class="addition-info-title" style="color: #646A73">{{ $t("home.dashboard.public.load_error") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<div class="main-info">
|
<div class="main-info">
|
||||||
<relevance-count-chart :relevance-data="relevanceData" ref="countChart" @redirectPage="redirectPage"/>
|
<count-chart :chart-data="relevanceData.chartData" :main-title="chartMainTitle"
|
||||||
|
:week-count="relevanceData.thisWeekAddedCount" :chart-sub-link="chartRedirectLink" ref="countChart" @redirectPage="redirectPage"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="24" style="margin: 0">
|
<el-row :gutter="24" style="margin: 0">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
{{ $t('home.relevance_dashboard.not_cover') }}
|
{{ $t('home.relevance_dashboard.not_cover') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('uncoverage')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('uncoverage')">
|
||||||
{{ formatAmount(relevanceData.uncoverageCount) }}
|
{{ formatAmount(relevanceData.uncoverageCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
{{ $t('home.relevance_dashboard.cover') }}
|
{{ $t('home.relevance_dashboard.cover') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="common-amount">
|
<div class="common-amount">
|
||||||
<el-link class="addition-info-num" @click="redirectPage('coverage')" v-permission-disable="['PROJECT_TRACK_CASE:READ']">
|
<el-link class="addition-info-num" @click="redirectPage('coverage')">
|
||||||
{{ formatAmount(relevanceData.coverageCount) }}
|
{{ formatAmount(relevanceData.coverageCount) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,23 +59,27 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import relevanceCountChart from "@/business/home/components/chart/RelevanceCountChart";
|
import countChart from "@/business/home/components/chart/CountChart";
|
||||||
import hoverCard from "@/business/home/components/card/HoverCard";
|
import hoverCard from "@/business/home/components/card/HoverCard";
|
||||||
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
import {getCurrentProjectID} from "metersphere-frontend/src/utils/token";
|
||||||
import {getTrackRelevanceCount} from "@/api/track";
|
import {getTrackRelevanceCount} from "@/api/track";
|
||||||
import {formatNumber} from "@/api/track"
|
import {formatNumber} from "@/api/track"
|
||||||
|
import {getUUID} from "metersphere-frontend/src/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RelevanceCaseCard",
|
name: "RelevanceCaseCard",
|
||||||
components: {relevanceCountChart, hoverCard},
|
components: {countChart, hoverCard},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
coverRangeToolTip: this.$t('api_test.home_page.formula.testplan_coverage'),
|
coverRangeToolTip: this.$t('api_test.home_page.formula.testplan_coverage'),
|
||||||
|
chartMainTitle: this.$t("home.relevance_dashboard.relevance_case_count"),
|
||||||
|
chartRedirectLink: "/#/track/case/all/" + getUUID() + "/case/thisWeekRelevanceCount",
|
||||||
relevanceData: {
|
relevanceData: {
|
||||||
allCaseCountNumber: 0,
|
allCaseCountNumber: 0,
|
||||||
allRelevanceCaseCount: 0,
|
allRelevanceCaseCount: 0,
|
||||||
|
@ -97,7 +101,8 @@ export default {
|
||||||
scenarioCaseStr: "",
|
scenarioCaseStr: "",
|
||||||
thisWeekAddedCount: 0,
|
thisWeekAddedCount: 0,
|
||||||
unPassCount: 0,
|
unPassCount: 0,
|
||||||
uncoverageCount: 0
|
uncoverageCount: 0,
|
||||||
|
chartData: {}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<ms-table-button icon="" :class="!showMyCreator ? 'hover' : 'reviewedBtn'" :content="$t('test_track.review.reviewed_by_me')" @click="searchMyCreator('false')" style="border-color: #FFFFFF"/>
|
<ms-table-button icon="" :class="!showMyCreator ? 'hover reviewedBtn' : 'reviewedBtn'" :content="$t('test_track.review.reviewed_by_me')" @click="searchMyCreator('false')" style="border-color: #FFFFFF"/>
|
||||||
<ms-table-button icon="" :class="showMyCreator ? 'hover' : 'createBtn'" :content="$t('test_track.review.my_create')" @click="searchMyCreator('true')" style="border-color: #FFFFFF; margin-left: 3px"/>
|
<ms-table-button icon="" :class="showMyCreator ? 'hover createBtn' : 'createBtn'" :content="$t('test_track.review.my_create')" @click="searchMyCreator('true')" style="border-color: #FFFFFF; margin-left: 3px"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-loading="loading" element-loading-background="#FFFFFF">
|
<div v-loading="loading" element-loading-background="#FFFFFF">
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!loadError">
|
<div v-show="!loadError">
|
||||||
<el-table class="adjust-table" :data="tableData" @row-click="intoPlan"
|
<el-table class="adjust-table" :data="tableData" @row-click="intoPlan"
|
||||||
:header-cell-style="{backgroundColor: '#F5F6F7'}" max-height="224px">
|
header-cell-class-name="home-table-cell" max-height="226px">
|
||||||
<el-table-column type="index" :label="$t('home.table.index')" show-overflow-tooltip />
|
<el-table-column type="index" width="100" :label="$t('home.table.index')" show-overflow-tooltip />
|
||||||
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip />
|
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip />
|
||||||
<el-table-column prop="status" :label="$t('test_track.plan.plan_status')">
|
<el-table-column prop="status" :label="$t('test_track.plan.plan_status')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -146,26 +146,59 @@ export default {
|
||||||
border: 1px solid #BBBFC4;
|
border: 1px solid #BBBFC4;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
|
width: 182px;
|
||||||
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(button.el-button.el-button--mini.is-plain.hover) {
|
:deep(button.el-button.el-button--mini.is-plain.hover) {
|
||||||
background: rgba(120, 56, 135, 0.1);
|
background: rgba(120, 56, 135, 0.1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #783887;
|
color: #783887;
|
||||||
|
background-color: rgba(120, 56, 135, 0.1);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewedBtn.el-button--mini.is-plain:hover {
|
:deep(button.el-button.el-button--mini.is-plain.createBtn) {
|
||||||
|
width: 100px;
|
||||||
|
height: 24px;
|
||||||
|
position: relative;
|
||||||
|
left: 4px;
|
||||||
|
top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(button.el-button.el-button--mini.is-plain.reviewedBtn) {
|
||||||
|
width: 72px;
|
||||||
|
height: 24px;
|
||||||
|
position: relative;
|
||||||
|
left: 4px;
|
||||||
|
top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.reviewedBtn.el-button--mini.is-plain:hover) {
|
||||||
background: rgba(120, 56, 135, 0.1);
|
background: rgba(120, 56, 135, 0.1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #783887;
|
color: #783887;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.createBtn.el-button--mini.is-plain:hover {
|
:deep(.createBtn.el-button--mini.is-plain:hover) {
|
||||||
background: rgba(120, 56, 135, 0.1);
|
background: rgba(120, 56, 135, 0.1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #783887;
|
color: #783887;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(button.el-button.el-button--mini.is-plain span) {
|
||||||
|
font-family: 'PingFang SC';
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
position: relative;
|
||||||
|
right: 3px;
|
||||||
|
bottom: 8px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
:enable-selection="false"
|
:enable-selection="false"
|
||||||
:condition="condition"
|
:condition="condition"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:header-cell-style="{ backgroundColor: '#F5F6F7' }"
|
@refresh="search"
|
||||||
@refresh="search" max-height="224px">
|
header-cell-class-name="home-table-cell" max-height="226px">
|
||||||
<el-table-column type="index" :label="$t('home.table.index')" show-overflow-tooltip/>
|
<el-table-column type="index" width="100" :label="$t('home.table.index')" show-overflow-tooltip/>
|
||||||
<el-table-column prop="name" :label="$t('commons.name')">
|
<el-table-column prop="name" :label="$t('commons.name')">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<!-- 若为只读用户不可点击之后跳转-->
|
<!-- 若为只读用户不可点击之后跳转-->
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div v-show="!isHover" class="transition-box">
|
<div v-show="!isHover" class="transition-box">
|
||||||
<div style="margin:16px 0 0 16px">
|
<div style="margin:16px 0 0 16px">
|
||||||
<span class="addition-info-title"> {{ title }}</span>
|
<span class="addition-info-title"> {{ title }}</span>
|
||||||
<el-tooltip class="item" effect="light" :content="toolTip" placement="top-start">
|
<el-tooltip class="item" effect="dark" :content="toolTip" placement="top-start">
|
||||||
<img style="height: 14px;width: 14px;margin-left: 4px" src="/assets/figma/icon_question.svg"/>
|
<img style="height: 14px;width: 14px;margin-left: 4px" src="/assets/figma/icon_question.svg"/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<div class="common-amount" @mouseenter="isHover=true">
|
<div class="common-amount" @mouseenter="isHover=true">
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="reloadOver">
|
|
||||||
<el-row type="flex" justify="left" align="left">
|
|
||||||
<div style="height: 184px;width: 184px;margin-left: 30px;margin-right: 30px;">
|
|
||||||
<ms-chart :options="options"
|
|
||||||
:height="184"
|
|
||||||
:width="184"
|
|
||||||
:autoresize="true"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 总数统计 -->
|
|
||||||
<div style="margin: auto;width: 260px;padding-right: 30px">
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-new"/>
|
|
||||||
<span class="count-title">{{ $t('test_track.issue.status_new') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(bugData.newCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-resolved"/>
|
|
||||||
<span class="count-title">{{ $t('test_track.issue.status_resolved') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(bugData.resolvedCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-rejected"/>
|
|
||||||
<span class="count-title">{{ $t('test_track.issue.status_rejected') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(bugData.rejectedCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
|
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
|
||||||
import {formatNumber} from "@/api/track";
|
|
||||||
import {getCurrentProjectID} from "@/business/utils/sdk-utils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "CountChart",
|
|
||||||
components: {MsChart},
|
|
||||||
props: {
|
|
||||||
bugData: Object,
|
|
||||||
totalTime: Number,
|
|
||||||
isExport: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
reloadOver: true,
|
|
||||||
pieChartStyle: {
|
|
||||||
amountFontSize: 32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
reload() {
|
|
||||||
this.reloadOver = false;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.reloadOver = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTotal() {
|
|
||||||
let total = 0;
|
|
||||||
if (this.bugData.newCount) {
|
|
||||||
total += this.bugData.newCount;
|
|
||||||
}
|
|
||||||
if (this.bugData.resolvedCount) {
|
|
||||||
total += this.bugData.resolvedCount;
|
|
||||||
}
|
|
||||||
if (this.bugData.rejectedCount) {
|
|
||||||
total += this.bugData.rejectedCount;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
getAmount() {
|
|
||||||
let total = this.getTotal();
|
|
||||||
if (total > 999999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 20;
|
|
||||||
} else if (total > 99999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 22;
|
|
||||||
} else if (total > 9999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 24;
|
|
||||||
} else if (total > 999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 26;
|
|
||||||
} else {
|
|
||||||
this.pieChartStyle.amountFontSize = 32;
|
|
||||||
}
|
|
||||||
total = this.formatAmount(total);
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
formatAmount(param) {
|
|
||||||
return formatNumber(param);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
options() {
|
|
||||||
let protocolData = [{value: 0}];
|
|
||||||
let colorArr = ['#DEE0E3'];
|
|
||||||
if (this.getTotal() > 0) {
|
|
||||||
colorArr = ['#AA4FBF', '#14E1C6', '#FAD355',]
|
|
||||||
protocolData = [
|
|
||||||
{value: this.bugData.newCount, name: this.$t('test_track.issue.status_new')},
|
|
||||||
{value: this.bugData.resolvedCount, name: this.$t('test_track.issue.status_resolved')},
|
|
||||||
{value: this.bugData.rejectedCount, name: this.$t('test_track.issue.status_rejected')},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
let optionData = {
|
|
||||||
color: colorArr,
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: "{mainTitle|" + this.$t("home.bug_dashboard.un_closed_bug_count") + "}\n\n{number|" + this.getAmount() + "}\n\n",
|
|
||||||
subtext: this.$t("home.dashboard.public.this_week") + ": +" + this.bugData.thisWeekCount + " >",
|
|
||||||
top: "center",
|
|
||||||
left: "center",
|
|
||||||
textStyle: {
|
|
||||||
rich: {
|
|
||||||
mainTitle: {
|
|
||||||
color: '#646A73',
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
number: {
|
|
||||||
fontSize: this.pieChartStyle.amountFontSize,
|
|
||||||
fontWeight: 500,
|
|
||||||
fontStyle: "normal",
|
|
||||||
fontFamily: "PinfFang SC",
|
|
||||||
margin: "112px 0px 0px 2px0",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sublink: "/#/track/issue/" + getUUID() + "/" + getCurrentProjectID() + "/thisWeekUnClosedIssue",
|
|
||||||
subtextStyle: {
|
|
||||||
color: "#1F2329",
|
|
||||||
fontSize: 12,
|
|
||||||
width: 105,
|
|
||||||
ellipsis: '... >',
|
|
||||||
overflow: "truncate",
|
|
||||||
},
|
|
||||||
itemGap: -60,
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['75%', '96%'],
|
|
||||||
avoidLabelOverlap: false,
|
|
||||||
hoverAnimation: true,
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: "#FFF",
|
|
||||||
borderWidth: 3,
|
|
||||||
borderRadius: 1,
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: protocolData,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
return optionData;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
.count-row {
|
|
||||||
padding: 8px 0px 8px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-title {
|
|
||||||
color: #646A73;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-value {
|
|
||||||
color: #646A73;
|
|
||||||
float: right;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-rejected {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #FAD355;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-resolved {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #14E1C6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-new {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #AA4FBF;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,242 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="reloadOver">
|
|
||||||
<el-row type="flex" justify="left" align="left">
|
|
||||||
<div style="height: 184px;width: 184px;margin-left: 30px;margin-right: 30px;">
|
|
||||||
<ms-chart :options="options"
|
|
||||||
:height="184"
|
|
||||||
:width="184"
|
|
||||||
:autoresize="true"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 总数统计 -->
|
|
||||||
<div style="margin: auto;width: 260px;padding-right: 30px">
|
|
||||||
<div class="count-row">
|
|
||||||
<div>
|
|
||||||
<span class="ms-point-p0"/>
|
|
||||||
<span class="count-title">P0</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(trackData.p0CaseCountNumber) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-p1"/>
|
|
||||||
<span class="count-title">P1</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(trackData.p1CaseCountNumber) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-p2"/>
|
|
||||||
<span class="count-title">P2</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(trackData.p2CaseCountNumber) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-p3"/>
|
|
||||||
<span class="count-title">P3</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(trackData.p3CaseCountNumber) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
|
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
|
||||||
import {formatNumber} from "@/api/track";
|
|
||||||
import {hasPermission} from "@/business/utils/sdk-utils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "CaseCountChart",
|
|
||||||
components: {MsChart},
|
|
||||||
props: {
|
|
||||||
trackData: Object,
|
|
||||||
totalTime: Number,
|
|
||||||
isExport: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
reloadOver: true,
|
|
||||||
pieChartStyle: {
|
|
||||||
amountFontSize: 32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
reload() {
|
|
||||||
this.reloadOver = false;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.reloadOver = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTotal() {
|
|
||||||
let total = 0;
|
|
||||||
if (this.trackData.p0CaseCountNumber) {
|
|
||||||
total += this.trackData.p0CaseCountNumber;
|
|
||||||
}
|
|
||||||
if (this.trackData.p0CaseCountNumber) {
|
|
||||||
total += this.trackData.p1CaseCountNumber;
|
|
||||||
}
|
|
||||||
if (this.trackData.p0CaseCountNumber) {
|
|
||||||
total += this.trackData.p2CaseCountNumber;
|
|
||||||
}
|
|
||||||
if (this.trackData.p0CaseCountNumber) {
|
|
||||||
total += this.trackData.p3CaseCountNumber;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
getAmount() {
|
|
||||||
let total = this.getTotal();
|
|
||||||
if (total > 999999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 20;
|
|
||||||
} else if (total > 99999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 22;
|
|
||||||
} else if (total > 9999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 24;
|
|
||||||
} else if (total > 999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 26;
|
|
||||||
} else {
|
|
||||||
this.pieChartStyle.amountFontSize = 32;
|
|
||||||
}
|
|
||||||
total = this.formatAmount(total);
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
formatAmount(param) {
|
|
||||||
return formatNumber(param);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
options() {
|
|
||||||
let protocolData = [{value: 0}];
|
|
||||||
let colorArr = ['#DEE0E3'];
|
|
||||||
if (this.getTotal() > 0) {
|
|
||||||
colorArr = ['#F76964', '#FFD131', '#AA4FBF', '#10CECE']
|
|
||||||
protocolData = [
|
|
||||||
{value: this.trackData.p0CaseCountNumber, name: 'P0'},
|
|
||||||
{value: this.trackData.p1CaseCountNumber, name: 'P1'},
|
|
||||||
{value: this.trackData.p2CaseCountNumber, name: 'P2'},
|
|
||||||
{value: this.trackData.p3CaseCountNumber, name: 'P3'},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
let optionData = {
|
|
||||||
color: colorArr,
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: "{mainTitle|" + this.$t("home.case_review_dashboard.case_count") + "}\n\n{number|" + this.getAmount() + "}\n\n",
|
|
||||||
subtext: this.$t("home.dashboard.public.this_week") + ": +" + this.trackData.thisWeekAddedCount + " >",
|
|
||||||
top: "center",
|
|
||||||
left: "center",
|
|
||||||
textStyle: {
|
|
||||||
rich: {
|
|
||||||
mainTitle: {
|
|
||||||
color: '#646A73',
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
number: {
|
|
||||||
fontSize: this.pieChartStyle.amountFontSize,
|
|
||||||
fontWeight: 500,
|
|
||||||
fontStyle: "normal",
|
|
||||||
fontFamily: "PinfFang SC",
|
|
||||||
margin: "112px 0px 0px 2px0",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sublink: hasPermission('PROJECT_TRACK_CASE:READ') ? "/#/track/case/all/" + getUUID() + "/case/thisWeekCount" : '',
|
|
||||||
subtextStyle: {
|
|
||||||
color: "#1F2329",
|
|
||||||
fontSize: 12,
|
|
||||||
width: 105,
|
|
||||||
ellipsis: '...',
|
|
||||||
overflow: "truncate",
|
|
||||||
},
|
|
||||||
itemGap: -60,
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['70%', '96%'],
|
|
||||||
avoidLabelOverlap: false,
|
|
||||||
hoverAnimation: true,
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: "#FFF",
|
|
||||||
borderWidth: 3,
|
|
||||||
borderRadius: 1,
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: protocolData,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
return optionData;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.count-row {
|
|
||||||
padding: 8px 0px 8px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-title {
|
|
||||||
color: #646A73;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-value {
|
|
||||||
color: #646A73;
|
|
||||||
float: right;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-p0 {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #F76964;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-p1 {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #FFD131;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-p2 {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #AA4FBF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-p3 {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #14E1C6;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="reloadOver">
|
||||||
|
<el-row type="flex" justify="left" align="left">
|
||||||
|
<div style="height: 184px; width: 100%; margin-left: 30px; margin-right: 30px;">
|
||||||
|
<ms-chart :options="options"
|
||||||
|
:height="184"
|
||||||
|
width="100%"
|
||||||
|
:autoresize="true"/>
|
||||||
|
</div>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
|
||||||
|
import {formatNumber} from "@/api/track";
|
||||||
|
import {DASHBOARD_CHART_COLOR} from "@/business/constants/table-constants";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CountChart",
|
||||||
|
components: {MsChart},
|
||||||
|
props: {
|
||||||
|
chartData: Object,
|
||||||
|
weekCount: Number,
|
||||||
|
totalTime: Number,
|
||||||
|
mainTitle: String,
|
||||||
|
chartSubLink: String,
|
||||||
|
isExport: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
reloadOver: true,
|
||||||
|
pieChartStyle: {
|
||||||
|
amountFontSize: 32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.reload();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reload() {
|
||||||
|
this.reloadOver = false;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.reloadOver = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getTotal() {
|
||||||
|
let total = 0;
|
||||||
|
for (let name in this.chartData) {
|
||||||
|
total += this.chartData[name];
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
},
|
||||||
|
getAmount() {
|
||||||
|
let total = this.getTotal();
|
||||||
|
if (total > 999999999) {
|
||||||
|
this.pieChartStyle.amountFontSize = 20;
|
||||||
|
} else if (total > 99999999) {
|
||||||
|
this.pieChartStyle.amountFontSize = 22;
|
||||||
|
} else if (total > 9999999) {
|
||||||
|
this.pieChartStyle.amountFontSize = 24;
|
||||||
|
} else if (total > 999999) {
|
||||||
|
this.pieChartStyle.amountFontSize = 26;
|
||||||
|
} else {
|
||||||
|
this.pieChartStyle.amountFontSize = 32;
|
||||||
|
}
|
||||||
|
total = this.formatAmount(total);
|
||||||
|
return total;
|
||||||
|
},
|
||||||
|
formatAmount(param) {
|
||||||
|
return formatNumber(param);
|
||||||
|
},
|
||||||
|
getChartData(empty) {
|
||||||
|
let elementArr = [];
|
||||||
|
if (empty) {
|
||||||
|
for (let name in this.chartData) {
|
||||||
|
let element = {name: name, value: 0};
|
||||||
|
elementArr.push(element);
|
||||||
|
}
|
||||||
|
return elementArr;
|
||||||
|
} else {
|
||||||
|
for (let name in this.chartData) {
|
||||||
|
let element = {name: name, value: this.chartData[name]};
|
||||||
|
elementArr.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elementArr;
|
||||||
|
},
|
||||||
|
getChartColor(size, empty) {
|
||||||
|
let colorArr = [];
|
||||||
|
if (empty) {
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
colorArr.push("#DEE0E3");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
colorArr = DASHBOARD_CHART_COLOR.slice(0, size);
|
||||||
|
}
|
||||||
|
return colorArr;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
options() {
|
||||||
|
let dataIsNotEmpty = false;
|
||||||
|
let borderWidth = 0;
|
||||||
|
let elementArr = this.getChartData(true);
|
||||||
|
let colorArr = this.getChartColor(elementArr.length, true);
|
||||||
|
if (this.getTotal() > 0) {
|
||||||
|
borderWidth = 3;
|
||||||
|
dataIsNotEmpty = true;
|
||||||
|
elementArr = this.getChartData(false);
|
||||||
|
colorArr = this.getChartColor(elementArr.length, false);
|
||||||
|
}
|
||||||
|
let optionData = {
|
||||||
|
color: colorArr,
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
icon: "rect",
|
||||||
|
selectedMode: dataIsNotEmpty,
|
||||||
|
itemGap: 16,
|
||||||
|
left: '45%',
|
||||||
|
y: 'center',
|
||||||
|
itemHeight: 8,
|
||||||
|
itemWidth: 8, //修改icon图形大小
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: 0.1
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
align: 'right',
|
||||||
|
rich: {
|
||||||
|
protocol: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#646A73',
|
||||||
|
fontWeight: 400,
|
||||||
|
width: 50,
|
||||||
|
align: 'left',
|
||||||
|
lineHeight: 22,
|
||||||
|
},
|
||||||
|
num: {
|
||||||
|
fontSize: 14,
|
||||||
|
align: 'right',
|
||||||
|
lineHeight: 22,
|
||||||
|
color: '#646A73',
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: [0, 0, 0, 140]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: elementArr,
|
||||||
|
formatter: function (name) {
|
||||||
|
//通过name获取到数组对象中的单个对象
|
||||||
|
let singleData = elementArr.filter(function (item) {
|
||||||
|
return item.name === name
|
||||||
|
});
|
||||||
|
let value = singleData[0].value;
|
||||||
|
return [`{protocol|${name}}`, `{num|${value}}`].join("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: "{mainTitle|" + this.mainTitle + "}\n\n{number|" + this.getAmount() + "}\n\n",
|
||||||
|
subtext: this.$t("home.dashboard.public.this_week") + ": +" + formatNumber(this.weekCount) + " >",
|
||||||
|
top: "center",
|
||||||
|
left: "86px",
|
||||||
|
textAlign: 'center',
|
||||||
|
textStyle: {
|
||||||
|
rich: {
|
||||||
|
mainTitle: {
|
||||||
|
color: '#646A73',
|
||||||
|
fontSize: 12,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
number: {
|
||||||
|
fontSize: this.pieChartStyle.amountFontSize,
|
||||||
|
fontWeight: 500,
|
||||||
|
fontStyle: "normal",
|
||||||
|
fontFamily: "PinfFang SC",
|
||||||
|
margin: "112px 0px 0px 2px0",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sublink: this.chartSubLink,
|
||||||
|
subtextStyle: {
|
||||||
|
color: "#1F2329",
|
||||||
|
fontSize: 12,
|
||||||
|
width: 105,
|
||||||
|
ellipsis: '...',
|
||||||
|
overflow: "truncate",
|
||||||
|
},
|
||||||
|
itemGap: -60,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['70%', '96%'],
|
||||||
|
center: ['92px', '50%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
hoverAnimation: dataIsNotEmpty,
|
||||||
|
legendHoverLink: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
borderColor: "#FFF",
|
||||||
|
borderWidth: borderWidth,
|
||||||
|
borderRadius: 1,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: elementArr,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
return optionData;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,224 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="reloadOver">
|
|
||||||
<el-row type="flex" justify="left" align="left">
|
|
||||||
<div style="height: 184px;width: 184px;margin-left: 30px;margin-right: 30px;">
|
|
||||||
<ms-chart :options="options"
|
|
||||||
:height="184"
|
|
||||||
:width="184"
|
|
||||||
:autoresize="true"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 总数统计 -->
|
|
||||||
<div style="margin: auto;width: 260px;padding-right: 30px">
|
|
||||||
<div class="count-row">
|
|
||||||
<div>
|
|
||||||
<span class="ms-point-api"/>
|
|
||||||
<span class="count-title">{{ $t('home.relevance_dashboard.api_case') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(relevanceData.apiCaseCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-scenario"/>
|
|
||||||
<span class="count-title">{{ $t('home.relevance_dashboard.scenario_case') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(relevanceData.scenarioCaseCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="count-row">
|
|
||||||
<span class="ms-point-performance"/>
|
|
||||||
<span class="count-title">{{ $t('home.relevance_dashboard.performance_case') }}</span>
|
|
||||||
<span class="count-value">
|
|
||||||
{{ formatAmount(relevanceData.performanceCaseCount) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
|
|
||||||
import {getUUID} from "metersphere-frontend/src/utils";
|
|
||||||
import {formatNumber} from "@/api/track";
|
|
||||||
import {hasPermission} from "@/business/utils/sdk-utils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "RelevanceCountChart",
|
|
||||||
components: {MsChart},
|
|
||||||
props: {
|
|
||||||
relevanceData: Object,
|
|
||||||
totalTime: Number,
|
|
||||||
isExport: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
reloadOver: true,
|
|
||||||
pieChartStyle: {
|
|
||||||
amountFontSize: 32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
reload() {
|
|
||||||
this.reloadOver = false;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.reloadOver = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTotal() {
|
|
||||||
let total = 0;
|
|
||||||
if (this.relevanceData.apiCaseCount) {
|
|
||||||
total += this.relevanceData.apiCaseCount;
|
|
||||||
}
|
|
||||||
if (this.relevanceData.scenarioCaseCount) {
|
|
||||||
total += this.relevanceData.scenarioCaseCount;
|
|
||||||
}
|
|
||||||
if (this.relevanceData.performanceCaseCount) {
|
|
||||||
total += this.relevanceData.performanceCaseCount;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
getAmount() {
|
|
||||||
let total = this.getTotal();
|
|
||||||
if (total > 999999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 20;
|
|
||||||
} else if (total > 99999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 22;
|
|
||||||
} else if (total > 9999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 24;
|
|
||||||
} else if (total > 999999) {
|
|
||||||
this.pieChartStyle.amountFontSize = 26;
|
|
||||||
} else {
|
|
||||||
this.pieChartStyle.amountFontSize = 32;
|
|
||||||
}
|
|
||||||
total = this.formatAmount(total);
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
formatAmount(param) {
|
|
||||||
return formatNumber(param);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
options() {
|
|
||||||
let protocolData = [{value: 0}];
|
|
||||||
let colorArr = ['#DEE0E3'];
|
|
||||||
if (this.getTotal() > 0) {
|
|
||||||
colorArr = ['#AA4FBF', '#FFD131', '#10CECE', '#4261F6',]
|
|
||||||
protocolData = [
|
|
||||||
{value: this.relevanceData.apiCaseCount, name: this.$t('home.relevance_dashboard.api_case')},
|
|
||||||
{value: this.relevanceData.scenarioCaseCount, name: this.$t('home.relevance_dashboard.scenario_case')},
|
|
||||||
{value: this.relevanceData.performanceCaseCount, name: this.$t('home.relevance_dashboard.performance_case')}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
let optionData = {
|
|
||||||
color: colorArr,
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: "{mainTitle|" + this.$t("home.relevance_dashboard.relevance_case_count") + "}\n\n{number|" + this.getAmount() + "}\n\n",
|
|
||||||
subtext: this.$t("home.dashboard.public.this_week") + ": +" + this.relevanceData.thisWeekAddedCount + " >",
|
|
||||||
top: "center",
|
|
||||||
left: "center",
|
|
||||||
textStyle: {
|
|
||||||
rich: {
|
|
||||||
mainTitle: {
|
|
||||||
color: '#646A73',
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
number: {
|
|
||||||
fontSize: this.pieChartStyle.amountFontSize,
|
|
||||||
fontWeight: 500,
|
|
||||||
fontStyle: "normal",
|
|
||||||
fontFamily: "PinfFang SC",
|
|
||||||
margin: "112px 0px 0px 2px0",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sublink: hasPermission('PROJECT_TRACK_CASE:READ') ? "/#/track/case/all/" + getUUID() + "/case/thisWeekRelevanceCount" : "",
|
|
||||||
subtextStyle: {
|
|
||||||
color: "#1F2329",
|
|
||||||
fontSize: 12,
|
|
||||||
width: 105,
|
|
||||||
ellipsis: '...',
|
|
||||||
overflow: "truncate",
|
|
||||||
},
|
|
||||||
itemGap: -60,
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['70%', '96%'],
|
|
||||||
avoidLabelOverlap: false,
|
|
||||||
hoverAnimation: true,
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: "#FFF",
|
|
||||||
borderWidth: 3,
|
|
||||||
borderRadius: 1,
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: protocolData,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
return optionData;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
.count-row {
|
|
||||||
padding: 8px 0px 8px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-title {
|
|
||||||
color: #646A73;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count-value {
|
|
||||||
color: #646A73;
|
|
||||||
float: right;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-api {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #AA4FBF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-scenario {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #FFD131;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ms-point-performance {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
margin-right: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
background-color: #10CECE;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -381,7 +381,11 @@ export default {
|
||||||
},
|
},
|
||||||
getIssues() {
|
getIssues() {
|
||||||
if (this.dataSelectRange === 'thisWeekUnClosedIssue') {
|
if (this.dataSelectRange === 'thisWeekUnClosedIssue') {
|
||||||
this.page.condition.thisWeekUnClosedIssue = true;
|
this.page.condition.thisWeekUnClosedTestPlanIssue = true;
|
||||||
|
} else if (this.dataSelectRange === 'unClosedRelatedTestPlan') {
|
||||||
|
this.page.condition.unClosedTestPlanIssue = true;
|
||||||
|
} else if (this.dataSelectRange === 'AllRelatedTestPlan') {
|
||||||
|
this.page.condition.allTestPlanIssue = true;
|
||||||
}
|
}
|
||||||
this.page.condition.projectId = this.projectId;
|
this.page.condition.projectId = this.projectId;
|
||||||
this.page.condition.workspaceId= this.workspaceId;
|
this.page.condition.workspaceId= this.workspaceId;
|
||||||
|
|
|
@ -29,14 +29,14 @@ const message = {
|
||||||
},
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
public: {
|
public: {
|
||||||
this_week: "This week ",
|
this_week: "Week ",
|
||||||
load_error: "Loading failure",
|
load_error: "Loading failure",
|
||||||
no_data: "No data",
|
no_data: "No data",
|
||||||
},
|
},
|
||||||
case_finished_review_pass_tip: "Reviewed cases/All reviewed cases *100%"
|
case_finished_review_pass_tip: "Reviewed cases/All reviewed cases *100%"
|
||||||
},
|
},
|
||||||
case_review_dashboard: {
|
case_review_dashboard: {
|
||||||
case_count: "Case count",
|
case_count: "Case",
|
||||||
not_review: "Not reviewed",
|
not_review: "Not reviewed",
|
||||||
finished_review: "Reviewed",
|
finished_review: "Reviewed",
|
||||||
not_pass: "Not pass",
|
not_pass: "Not pass",
|
||||||
|
@ -46,18 +46,18 @@ const message = {
|
||||||
api_case: "Api case",
|
api_case: "Api case",
|
||||||
scenario_case: "Scenario case",
|
scenario_case: "Scenario case",
|
||||||
performance_case: "Performance case",
|
performance_case: "Performance case",
|
||||||
relevance_case_count: "Relevance case count",
|
relevance_case_count: "Relevance case",
|
||||||
not_cover: "Not cover",
|
not_cover: "Not cover",
|
||||||
cover: "Cover",
|
cover: "Cover",
|
||||||
},
|
},
|
||||||
bug_dashboard: {
|
bug_dashboard: {
|
||||||
un_closed_bug_count: "Unclosed bug count",
|
un_closed_bug_count: "Unclosed bug",
|
||||||
un_closed_range: "Unclosed bug range",
|
un_closed_range: "Unclosed bug rate",
|
||||||
un_closed_range_tips: "Unclosed bugs/all associated bugs *100%",
|
un_closed_range_tips: "Unclosed bugs/all associated bugs *100%",
|
||||||
un_closed_bug_case_range: "Unclosed bug case range",
|
un_closed_bug_case_range: "Unclosed bug case rate",
|
||||||
un_closed_bug_case_range_tips: "Unclosed bugs/all associated cases *100%",
|
un_closed_bug_case_range_tips: "Unclosed bugs/all associated cases *100%",
|
||||||
un_closed_count: "Unclosed bug count",
|
un_closed_count: "Unclosed bug",
|
||||||
total_count: "Bug total",
|
total_count: "All related bug",
|
||||||
case_count: "Case count",
|
case_count: "Case count",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue