diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java index bfe5e65b55..7181b1fb24 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java @@ -5,6 +5,7 @@ import io.metersphere.controller.request.BaseQueryRequest; import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.request.testcase.QueryTestCaseRequest; import io.metersphere.track.request.testcase.TestCaseBatchRequest; +import io.metersphere.track.response.TrackCountResult; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -48,4 +49,15 @@ public interface ExtTestCaseMapper { int checkIsHave(@Param("caseId") String caseId, @Param("workspaceIds") Set workspaceIds); List selectIds(@Param("request") BaseQueryRequest condition); + + /** + * 按照用例等级统计 + * @param projectId 项目ID + * @return 统计结果 + */ + List countPriority(@Param("projectId") String projectId); + + long countCreatedThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp); + + List countStatus(@Param("projectId") String projectId); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml index 6e746b0b81..ed890ad122 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml @@ -319,4 +319,18 @@ + + + + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/track/controller/TrackController.java b/backend/src/main/java/io/metersphere/track/controller/TrackController.java new file mode 100644 index 0000000000..c3d2981b78 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/controller/TrackController.java @@ -0,0 +1,53 @@ +package io.metersphere.track.controller; + + +import io.metersphere.commons.constants.RoleConstants; +import io.metersphere.track.response.TrackCountResult; +import io.metersphere.track.response.TrackStatisticsDTO; +import io.metersphere.track.service.TrackService; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresRoles; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.text.DecimalFormat; +import java.util.List; + +@RestController +@RequestMapping("/track") +@RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER, RoleConstants.ORG_ADMIN}, logical = Logical.OR) +public class TrackController { + + @Resource + private TrackService trackService; + + @GetMapping("/count/{projectId}") + public TrackStatisticsDTO getTrackCount(@PathVariable String projectId) { + TrackStatisticsDTO statistics = new TrackStatisticsDTO(); + + List priorityResults = trackService.countPriority(projectId); + statistics.countPriority(priorityResults); + + long size = trackService.countCreatedThisWeek(projectId); + statistics.setThisWeekAddedCount(size); + + List statusResults = trackService.countStatus(projectId); + statistics.countStatus(statusResults); + + long total = statistics.getPrepareCount() + statistics.getPassCount() + statistics.getUnPassCount(); + if (total != 0) { + float reviewed = (float) (statistics.getPassCount() + statistics.getUnPassCount()) * 100 / total; + DecimalFormat df = new DecimalFormat("0.0"); + statistics.setReviewRage(df.format(reviewed) + "%"); + } + + statistics.setP0CountStr("P0  

" + statistics.getP0CaseCountNumber()); + statistics.setP1CountStr("P1  

" + statistics.getP1CaseCountNumber()); + statistics.setP2CountStr("P2  

" + statistics.getP2CaseCountNumber()); + statistics.setP3CountStr("P3  

" + statistics.getP3CaseCountNumber()); + return statistics; + } +} diff --git a/backend/src/main/java/io/metersphere/track/request/testcase/CasePriority.java b/backend/src/main/java/io/metersphere/track/request/testcase/CasePriority.java new file mode 100644 index 0000000000..e450b44945 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/request/testcase/CasePriority.java @@ -0,0 +1,8 @@ +package io.metersphere.track.request.testcase; + +public class CasePriority { + public static final String P0 = "P0"; + public static final String P1 = "P1"; + public static final String P2 = "P2"; + public static final String P3 = "P3"; +} diff --git a/backend/src/main/java/io/metersphere/track/response/TrackCountResult.java b/backend/src/main/java/io/metersphere/track/response/TrackCountResult.java new file mode 100644 index 0000000000..14e2add524 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/response/TrackCountResult.java @@ -0,0 +1,19 @@ +package io.metersphere.track.response; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TrackCountResult { + + /** + * 分组统计字段 + */ + private String groupField; + /** + * 数据统计 + */ + private long countNumber; +} diff --git a/backend/src/main/java/io/metersphere/track/response/TrackStatisticsDTO.java b/backend/src/main/java/io/metersphere/track/response/TrackStatisticsDTO.java new file mode 100644 index 0000000000..6b58ecd8b7 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/response/TrackStatisticsDTO.java @@ -0,0 +1,143 @@ +package io.metersphere.track.response; + +import io.metersphere.commons.constants.TestReviewCaseStatus; +import io.metersphere.track.request.testcase.CasePriority; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * 用例数量统计数据 + */ +@Getter +@Setter +public class TrackStatisticsDTO { + + /** + * 用例总计 + */ + private long allCaseCountNumber = 0; + + /** + * P0登记用例总计 + */ + private long p0CaseCountNumber = 0; + + /** + * P1登记用例总计 + */ + private long p1CaseCountNumber = 0; + + /** + * P2登记用例总计 + */ + private long p2CaseCountNumber = 0; + + /** + * P3登记用例总计 + */ + private long p3CaseCountNumber = 0; + + private String p0CountStr = ""; + private String p1CountStr = ""; + private String p2CountStr = ""; + private String p3CountStr = ""; + + /** + * 关联用例数量统计 + */ + private long relevanceCaseCount = 0; + + /** + * 接口用例数量统计 + */ + private long apiCaseCount = 0; + + /** + * 场景用例数量统计 + */ + private long scenarioCaseCount = 0; + + /** + * 性能用例数量统计 + */ + private long performanceCaseCount = 0; + + + private String apiCaseCountStr = ""; + private String scenarioCaseStr = ""; + private String performanceCaseCountStr = ""; + + /** + * 本周新增数量 + */ + private long thisWeekAddedCount = 0; + /** + * 未覆盖 + */ + private long uncoverageCount = 0; + /** + * 已覆盖 + */ + private long coverageCount = 0; + /** + * 覆盖率 + */ + private String coverageRage = " 0%"; + /** + * 评审率 + */ + private String reviewRage = " 0%"; + /** + * 未评审 + */ + private long prepareCount = 0; + /** + * 已通过 + */ + private long passCount = 0; + /** + * 未通过 + */ + private long unPassCount = 0; + + + /** + * 按照 Priority 统计 + * @param trackCountResults 统计结果 + */ + public void countPriority(List trackCountResults) { + for (TrackCountResult countResult : trackCountResults) { + switch (countResult.getGroupField().toUpperCase()){ + case CasePriority.P0: + this.p0CaseCountNumber += countResult.getCountNumber(); + break; + case CasePriority.P1: + this.p1CaseCountNumber += countResult.getCountNumber(); + break; + case CasePriority.P2: + this.p2CaseCountNumber += countResult.getCountNumber(); + break; + case CasePriority.P3: + this.p3CaseCountNumber += countResult.getCountNumber(); + break; + default: + break; + } + this.allCaseCountNumber += countResult.getCountNumber(); + } + } + + public void countStatus(List statusResults) { + for (TrackCountResult countResult : statusResults) { + if(TestReviewCaseStatus.Prepare.name().equals(countResult.getGroupField())){ + this.prepareCount += countResult.getCountNumber(); + }else if(TestReviewCaseStatus.Pass.name().equals(countResult.getGroupField())){ + this.passCount += countResult.getCountNumber(); + }else if(TestReviewCaseStatus.UnPass.name().equals(countResult.getGroupField())){ + this.unPassCount += countResult.getCountNumber(); + } + } + } +} diff --git a/backend/src/main/java/io/metersphere/track/service/TrackService.java b/backend/src/main/java/io/metersphere/track/service/TrackService.java new file mode 100644 index 0000000000..6cf219ec8b --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/service/TrackService.java @@ -0,0 +1,40 @@ +package io.metersphere.track.service; + +import io.metersphere.base.mapper.ext.ExtTestCaseMapper; +import io.metersphere.commons.utils.DateUtils; +import io.metersphere.track.response.TrackCountResult; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Service +@Transactional(rollbackFor = Exception.class) +public class TrackService { + + @Resource + private ExtTestCaseMapper extTestCaseMapper; + + public List countPriority(String projectId) { + return extTestCaseMapper.countPriority(projectId); + } + + public long countCreatedThisWeek(String projectId) { + Map startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date()); + + Date firstTime = startAndEndDateInWeek.get("firstTime"); + Date lastTime = startAndEndDateInWeek.get("lastTime"); + + if (firstTime == null || lastTime == null) { + return 0; + } else { + return extTestCaseMapper.countCreatedThisWeek(projectId, firstTime.getTime(), lastTime.getTime()); + } + } + + public List countStatus(String projectId) { + return extTestCaseMapper.countStatus(projectId); + } +} diff --git a/frontend/src/business/components/track/home/TrackHome.vue b/frontend/src/business/components/track/home/TrackHome.vue index 3061221b30..dfb5f4aaee 100644 --- a/frontend/src/business/components/track/home/TrackHome.vue +++ b/frontend/src/business/components/track/home/TrackHome.vue @@ -1,17 +1,44 @@ diff --git a/frontend/src/business/components/track/home/components/CaseCountCard.vue b/frontend/src/business/components/track/home/components/CaseCountCard.vue new file mode 100644 index 0000000000..b70cf1c8f2 --- /dev/null +++ b/frontend/src/business/components/track/home/components/CaseCountCard.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/frontend/src/business/components/track/home/components/RelevanceCaseCard.vue b/frontend/src/business/components/track/home/components/RelevanceCaseCard.vue new file mode 100644 index 0000000000..ec437a0472 --- /dev/null +++ b/frontend/src/business/components/track/home/components/RelevanceCaseCard.vue @@ -0,0 +1,191 @@ + + + + +