refactor(测试计划): 优化测试计划报告
This commit is contained in:
parent
02a237af85
commit
21fbfee0b4
|
@ -1,15 +1,12 @@
|
|||
package io.metersphere.plan.domain;
|
||||
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TestPlanReport implements Serializable {
|
||||
|
@ -43,12 +40,12 @@ public class TestPlanReport implements Serializable {
|
|||
@Schema(description = "触发类型")
|
||||
private String triggerMode;
|
||||
|
||||
@Schema(description = "执行状态;未执行, 执行中, 已停止, 已完成;", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "执行状态: 未执行, 执行中, 已停止, 已完成;", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan_report.exec_status.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{test_plan_report.exec_status.length_range}", groups = {Created.class, Updated.class})
|
||||
private String execStatus;
|
||||
|
||||
@Schema(description = "结果状态;成功, 失败, 阻塞, 误报")
|
||||
@Schema(description = "结果状态: 成功, 失败, 阻塞, 误报")
|
||||
private String resultStatus;
|
||||
|
||||
@Schema(description = "通过阈值", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -59,6 +56,19 @@ public class TestPlanReport implements Serializable {
|
|||
@Schema(description = "通过率")
|
||||
private Long passRate;
|
||||
|
||||
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan_report.project_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{test_plan_report.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "是否是集成报告", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{test_plan_report.integrated.not_blank}", groups = {Created.class})
|
||||
private Boolean integrated;
|
||||
|
||||
@Schema(description = "是否删除", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{test_plan_report.deleted.not_blank}", groups = {Created.class})
|
||||
private Boolean deleted;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
|
@ -73,7 +83,10 @@ public class TestPlanReport implements Serializable {
|
|||
execStatus("exec_status", "execStatus", "VARCHAR", false),
|
||||
resultStatus("result_status", "resultStatus", "VARCHAR", false),
|
||||
passThreshold("pass_threshold", "passThreshold", "VARCHAR", false),
|
||||
passRate("pass_rate", "passRate", "DECIMAL", false);
|
||||
passRate("pass_rate", "passRate", "DECIMAL", false),
|
||||
projectId("project_id", "projectId", "VARCHAR", false),
|
||||
integrated("integrated", "integrated", "BIT", false),
|
||||
deleted("deleted", "deleted", "BIT", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -903,6 +903,196 @@ public class TestPlanReportExample {
|
|||
addCriterion("pass_rate not between", value1, value2, "passRate");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNull() {
|
||||
addCriterion("project_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNotNull() {
|
||||
addCriterion("project_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdEqualTo(String value) {
|
||||
addCriterion("project_id =", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotEqualTo(String value) {
|
||||
addCriterion("project_id <>", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThan(String value) {
|
||||
addCriterion("project_id >", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("project_id >=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThan(String value) {
|
||||
addCriterion("project_id <", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("project_id <=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLike(String value) {
|
||||
addCriterion("project_id like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotLike(String value) {
|
||||
addCriterion("project_id not like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIn(List<String> values) {
|
||||
addCriterion("project_id in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotIn(List<String> values) {
|
||||
addCriterion("project_id not in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdBetween(String value1, String value2) {
|
||||
addCriterion("project_id between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
||||
addCriterion("project_id not between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedIsNull() {
|
||||
addCriterion("integrated is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedIsNotNull() {
|
||||
addCriterion("integrated is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedEqualTo(Boolean value) {
|
||||
addCriterion("integrated =", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedNotEqualTo(Boolean value) {
|
||||
addCriterion("integrated <>", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedGreaterThan(Boolean value) {
|
||||
addCriterion("integrated >", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("integrated >=", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedLessThan(Boolean value) {
|
||||
addCriterion("integrated <", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("integrated <=", value, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedIn(List<Boolean> values) {
|
||||
addCriterion("integrated in", values, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedNotIn(List<Boolean> values) {
|
||||
addCriterion("integrated not in", values, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("integrated between", value1, value2, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andIntegratedNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("integrated not between", value1, value2, "integrated");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedIsNull() {
|
||||
addCriterion("deleted is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedIsNotNull() {
|
||||
addCriterion("deleted is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedEqualTo(Boolean value) {
|
||||
addCriterion("deleted =", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedNotEqualTo(Boolean value) {
|
||||
addCriterion("deleted <>", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedGreaterThan(Boolean value) {
|
||||
addCriterion("deleted >", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("deleted >=", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedLessThan(Boolean value) {
|
||||
addCriterion("deleted <", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("deleted <=", value, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedIn(List<Boolean> values) {
|
||||
addCriterion("deleted in", values, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedNotIn(List<Boolean> values) {
|
||||
addCriterion("deleted not in", values, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("deleted between", value1, value2, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andDeletedNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("deleted not between", value1, value2, "deleted");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -2,9 +2,8 @@ package io.metersphere.plan.mapper;
|
|||
|
||||
import io.metersphere.plan.domain.TestPlanReport;
|
||||
import io.metersphere.plan.domain.TestPlanReportExample;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface TestPlanReportMapper {
|
||||
long countByExample(TestPlanReportExample example);
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
<result column="result_status" jdbcType="VARCHAR" property="resultStatus" />
|
||||
<result column="pass_threshold" jdbcType="VARCHAR" property="passThreshold" />
|
||||
<result column="pass_rate" jdbcType="DECIMAL" property="passRate" />
|
||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="integrated" jdbcType="BIT" property="integrated" />
|
||||
<result column="deleted" jdbcType="BIT" property="deleted" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -75,7 +78,7 @@
|
|||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, test_plan_id, `name`, create_user, create_time, start_time, end_time, trigger_mode,
|
||||
exec_status, result_status, pass_threshold, pass_rate
|
||||
exec_status, result_status, pass_threshold, pass_rate, project_id, integrated, deleted
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.plan.domain.TestPlanReportExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -111,12 +114,14 @@
|
|||
insert into test_plan_report (id, test_plan_id, `name`,
|
||||
create_user, create_time, start_time,
|
||||
end_time, trigger_mode, exec_status,
|
||||
result_status, pass_threshold, pass_rate
|
||||
result_status, pass_threshold, pass_rate,
|
||||
project_id, integrated, deleted
|
||||
)
|
||||
values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{startTime,jdbcType=BIGINT},
|
||||
#{endTime,jdbcType=BIGINT}, #{triggerMode,jdbcType=VARCHAR}, #{execStatus,jdbcType=VARCHAR},
|
||||
#{resultStatus,jdbcType=VARCHAR}, #{passThreshold,jdbcType=VARCHAR}, #{passRate,jdbcType=DECIMAL}
|
||||
#{resultStatus,jdbcType=VARCHAR}, #{passThreshold,jdbcType=VARCHAR}, #{passRate,jdbcType=DECIMAL},
|
||||
#{projectId,jdbcType=VARCHAR}, #{integrated,jdbcType=BIT}, #{deleted,jdbcType=BIT}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.plan.domain.TestPlanReport">
|
||||
|
@ -158,6 +163,15 @@
|
|||
<if test="passRate != null">
|
||||
pass_rate,
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id,
|
||||
</if>
|
||||
<if test="integrated != null">
|
||||
integrated,
|
||||
</if>
|
||||
<if test="deleted != null">
|
||||
deleted,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -196,6 +210,15 @@
|
|||
<if test="passRate != null">
|
||||
#{passRate,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
#{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="integrated != null">
|
||||
#{integrated,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="deleted != null">
|
||||
#{deleted,jdbcType=BIT},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.plan.domain.TestPlanReportExample" resultType="java.lang.Long">
|
||||
|
@ -243,6 +266,15 @@
|
|||
<if test="record.passRate != null">
|
||||
pass_rate = #{record.passRate,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="record.projectId != null">
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.integrated != null">
|
||||
integrated = #{record.integrated,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.deleted != null">
|
||||
deleted = #{record.deleted,jdbcType=BIT},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -261,7 +293,10 @@
|
|||
exec_status = #{record.execStatus,jdbcType=VARCHAR},
|
||||
result_status = #{record.resultStatus,jdbcType=VARCHAR},
|
||||
pass_threshold = #{record.passThreshold,jdbcType=VARCHAR},
|
||||
pass_rate = #{record.passRate,jdbcType=DECIMAL}
|
||||
pass_rate = #{record.passRate,jdbcType=DECIMAL},
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
integrated = #{record.integrated,jdbcType=BIT},
|
||||
deleted = #{record.deleted,jdbcType=BIT}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -302,6 +337,15 @@
|
|||
<if test="passRate != null">
|
||||
pass_rate = #{passRate,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="integrated != null">
|
||||
integrated = #{integrated,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="deleted != null">
|
||||
deleted = #{deleted,jdbcType=BIT},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -317,20 +361,25 @@
|
|||
exec_status = #{execStatus,jdbcType=VARCHAR},
|
||||
result_status = #{resultStatus,jdbcType=VARCHAR},
|
||||
pass_threshold = #{passThreshold,jdbcType=VARCHAR},
|
||||
pass_rate = #{passRate,jdbcType=DECIMAL}
|
||||
pass_rate = #{passRate,jdbcType=DECIMAL},
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
integrated = #{integrated,jdbcType=BIT},
|
||||
deleted = #{deleted,jdbcType=BIT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into test_plan_report
|
||||
(id, test_plan_id, `name`, create_user, create_time, start_time, end_time, trigger_mode,
|
||||
exec_status, result_status, pass_threshold, pass_rate)
|
||||
exec_status, result_status, pass_threshold, pass_rate, project_id, integrated,
|
||||
deleted)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.testPlanId,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR},
|
||||
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.startTime,jdbcType=BIGINT},
|
||||
#{item.endTime,jdbcType=BIGINT}, #{item.triggerMode,jdbcType=VARCHAR}, #{item.execStatus,jdbcType=VARCHAR},
|
||||
#{item.resultStatus,jdbcType=VARCHAR}, #{item.passThreshold,jdbcType=VARCHAR},
|
||||
#{item.passRate,jdbcType=DECIMAL})
|
||||
#{item.passRate,jdbcType=DECIMAL}, #{item.projectId,jdbcType=VARCHAR}, #{item.integrated,jdbcType=BIT},
|
||||
#{item.deleted,jdbcType=BIT})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -379,6 +428,15 @@
|
|||
<if test="'pass_rate'.toString() == column.value">
|
||||
#{item.passRate,jdbcType=DECIMAL}
|
||||
</if>
|
||||
<if test="'project_id'.toString() == column.value">
|
||||
#{item.projectId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'integrated'.toString() == column.value">
|
||||
#{item.integrated,jdbcType=BIT}
|
||||
</if>
|
||||
<if test="'deleted'.toString() == column.value">
|
||||
#{item.deleted,jdbcType=BIT}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
|
|
|
@ -77,6 +77,9 @@ CREATE TABLE IF NOT EXISTS test_plan_report(
|
|||
`result_status` VARCHAR(50) DEFAULT '-' COMMENT '结果状态: 成功, 失败, 阻塞, 误报' ,
|
||||
`pass_threshold` VARCHAR(100) NOT NULL COMMENT '通过阈值' ,
|
||||
`pass_rate` DECIMAL COMMENT '通过率' ,
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目id' ,
|
||||
`integrated` BIT NOT NULL DEFAULT 0 COMMENT '是否是集成报告' ,
|
||||
`deleted` BIT NOT NULL DEFAULT 0 COMMENT '是否删除' ,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '测试计划报告';
|
||||
|
||||
|
@ -87,6 +90,9 @@ CREATE INDEX idx_create_time ON test_plan_report(create_time);
|
|||
CREATE INDEX idx_exec_status ON test_plan_report(exec_status);
|
||||
CREATE INDEX idx_result_status ON test_plan_report(result_status);
|
||||
CREATE INDEX idx_pass_rate ON test_plan_report(pass_rate);
|
||||
CREATE INDEX idx_project_id ON test_plan_report(project_id);
|
||||
CREATE INDEX idx_integrated ON test_plan_report(integrated);
|
||||
CREATE INDEX idx_deleted ON test_plan_report(deleted);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS test_plan_report_summary(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID' ,
|
||||
|
|
|
@ -48,14 +48,14 @@ public class ApiReportLogService {
|
|||
return dto;
|
||||
}
|
||||
|
||||
public void updateLog(String id) {
|
||||
public LogDTO updateLog(String id) {
|
||||
ApiReport apiReport = apiReportMapper.selectByPrimaryKey(id);
|
||||
Project project = projectMapper.selectByPrimaryKey(apiReport.getProjectId());
|
||||
LogDTO dto = new LogDTO(
|
||||
apiReport.getProjectId(),
|
||||
project.getOrganizationId(),
|
||||
apiReport.getId(),
|
||||
apiReport.getUpdateUser(),
|
||||
null,
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.API_REPORT,
|
||||
apiReport.getName());
|
||||
|
@ -63,7 +63,7 @@ public class ApiReportLogService {
|
|||
dto.setPath("/api/report/case/rename/" + apiReport.getId() + "/" + apiReport.getName());
|
||||
dto.setMethod(HttpMethodConstants.GET.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(apiReport));
|
||||
operationLogService.add(dto);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public void batchDeleteLog(List<String> ids, String userId, String projectId) {
|
||||
|
|
|
@ -30,7 +30,7 @@ public class OperationLogModule {
|
|||
public static final String API_TEST_MANAGEMENT_RECYCLE = "API_TEST_MANAGEMENT_RECYCLE";
|
||||
|
||||
public static final String API_REPORT = "API_TEST_REPORT_CASE";
|
||||
public static final String API_TEST_REPORT_SCENARIO = "API_TEST_REPORT_SCENARIO";
|
||||
public static final String API_TEST_REPORT_SCENARIO = "API_TEST_REPORT_SCENARIO";
|
||||
public static final String AUTH_TITLE = "AUTH_TITLE";
|
||||
public static final String PROJECT_ENVIRONMENT_SETTING = "PROJECT_ENVIRONMENT_SETTING";
|
||||
public static final String PROJECT_PROJECT_MANAGER = "PROJECT_PROJECT_MANAGER";
|
||||
|
@ -170,4 +170,6 @@ public class OperationLogModule {
|
|||
public static final String SETTING_ORGANIZATION_TASK_CENTER = "SETTING_ORGANIZATION_TASK_CENTER";
|
||||
//项目任务中心:PROJECT_MANAGEMENT_TASK_CENTER
|
||||
public static final String PROJECT_MANAGEMENT_TASK_CENTER = "PROJECT_MANAGEMENT_TASK_CENTER";
|
||||
|
||||
public static final String TEST_PLAN_REPORT = "TEST_PLAN_REPORT";
|
||||
}
|
||||
|
|
|
@ -4,26 +4,28 @@ import com.github.pagehelper.Page;
|
|||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportBatchRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportDeleteRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportEditRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportPageRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanReportPageResponse;
|
||||
import io.metersphere.plan.service.TestPlanManagementService;
|
||||
import io.metersphere.plan.service.TestPlanReportLogService;
|
||||
import io.metersphere.plan.service.TestPlanReportNoticeService;
|
||||
import io.metersphere.plan.service.TestPlanReportService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.log.annotation.Log;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.notice.annotation.SendNotice;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.security.CheckOwner;
|
||||
import io.metersphere.system.utils.PageUtils;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -33,43 +35,46 @@ import java.util.List;
|
|||
@Tag(name = "测试计划-报告")
|
||||
public class TestPlanReportController {
|
||||
|
||||
@Resource
|
||||
private TestPlanManagementService testPlanManagementService;
|
||||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
@Resource
|
||||
private TestPlanManagementService testPlanManagementService;
|
||||
@Resource
|
||||
private TestPlanReportService testPlanReportService;
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "测试计划-报告-表格分页查询")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public Pager<List<TestPlanReportPageResponse>> page(@Validated @RequestBody TestPlanReportPageRequest request) {
|
||||
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpr.create_time desc");
|
||||
return PageUtils.setPageInfo(page, testPlanReportService.page(request));
|
||||
}
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "测试计划-报告-表格分页查询")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public Pager<List<TestPlanReportPageResponse>> page(@Validated @RequestBody TestPlanReportPageRequest request) {
|
||||
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpr.create_time desc");
|
||||
return PageUtils.setPageInfo(page, testPlanReportService.page(request));
|
||||
}
|
||||
|
||||
@PostMapping("/rename")
|
||||
@Operation(summary = "测试计划-报告-重命名")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public void rename(@Validated @RequestBody TestPlanReportEditRequest request) {
|
||||
testPlanReportService.rename(request);
|
||||
}
|
||||
@PostMapping("/rename/{id}")
|
||||
@Operation(summary = "测试计划-报告-重命名")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getId()", resourceType = "test_plan_report")
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#id)", msClass = TestPlanReportLogService.class)
|
||||
public void rename(@PathVariable String id, @RequestBody Object name) {
|
||||
testPlanReportService.rename(id, name.toString());
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
@Operation(summary = "测试计划-报告-删除")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_DELETE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public void delete(@Validated @RequestBody TestPlanReportDeleteRequest request) {
|
||||
testPlanReportService.delete(request);
|
||||
}
|
||||
@GetMapping("/delete/{id}")
|
||||
@Operation(summary = "测试计划-报告-删除")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_DELETE)
|
||||
@CheckOwner(resourceId = "#id", resourceType = "test_plan_report")
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = TestPlanReportLogService.class)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.TEST_PLAN_REPORT_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getDto(#id)", targetClass = TestPlanReportNoticeService.class)
|
||||
public void delete(@PathVariable String id) {
|
||||
testPlanReportService.delete(id);
|
||||
}
|
||||
|
||||
@PostMapping("/batch-delete")
|
||||
@Operation(summary = "测试计划-报告-批量删除")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_DELETE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public void batchDelete(@Validated @RequestBody TestPlanReportBatchRequest request) {
|
||||
testPlanReportService.batchDelete(request);
|
||||
}
|
||||
@PostMapping("/batch-delete")
|
||||
@Operation(summary = "测试计划-报告-批量删除")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_REPORT_READ_DELETE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public void batchDelete(@Validated @RequestBody TestPlanReportBatchRequest request) {
|
||||
testPlanReportService.batchDelete(request, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,7 @@ import lombok.EqualsAndHashCode;
|
|||
@EqualsAndHashCode(callSuper = false)
|
||||
public class TestPlanReportBatchRequest extends TableBatchRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.project_id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "类型", allowableValues = {"ALL: 全部", "TEST_PLAN: 独立", "GROUP: 聚合"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.type.not_blank}")
|
||||
private String type;
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.project_id.not_blank}")
|
||||
private String projectId;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,7 @@ import lombok.EqualsAndHashCode;
|
|||
@EqualsAndHashCode(callSuper = false)
|
||||
public class TestPlanReportPageRequest extends BasePageRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.project_id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "类型", allowableValues = {"ALL: 全部", "TEST_PLAN: 独立", "GROUP: 聚合"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.type.not_blank}")
|
||||
private String type;
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan.project_id.not_blank}")
|
||||
private String projectId;
|
||||
}
|
||||
|
|
|
@ -8,27 +8,29 @@ import lombok.EqualsAndHashCode;
|
|||
@EqualsAndHashCode(callSuper = false)
|
||||
public class TestPlanReportPageResponse {
|
||||
|
||||
@Schema(description = "报告ID")
|
||||
private String id;
|
||||
@Schema(description = "报告名称")
|
||||
private String name;
|
||||
@Schema(description = "计划名称")
|
||||
private String planName;
|
||||
@Schema(description = "计划通过阈值")
|
||||
private String planPassThreshold;
|
||||
@Schema(description = "触发方式")
|
||||
private String triggerMode;
|
||||
@Schema(description = "执行状态")
|
||||
private String executeStatus;
|
||||
@Schema(description = "执行结果")
|
||||
private String resultStatus;
|
||||
@Schema(description = "通过率")
|
||||
private Double passRate;
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
@Schema(description = "创建人名称")
|
||||
private String createUserName;
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
@Schema(description = "报告ID")
|
||||
private String id;
|
||||
@Schema(description = "报告名称")
|
||||
private String name;
|
||||
@Schema(description = "计划名称")
|
||||
private String planName;
|
||||
@Schema(description = "计划通过阈值")
|
||||
private String planPassThreshold;
|
||||
@Schema(description = "触发方式")
|
||||
private String triggerMode;
|
||||
@Schema(description = "执行状态")
|
||||
private String execStatus;
|
||||
@Schema(description = "执行结果")
|
||||
private String resultStatus;
|
||||
@Schema(description = "通过率")
|
||||
private Double passRate;
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
@Schema(description = "创建人名称")
|
||||
private String createUserName;
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
@Schema(description = "是否是集合报告")
|
||||
private boolean integrated;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,33 @@
|
|||
package io.metersphere.plan.mapper;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlanReport;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportBatchRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportPageRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanReportPageResponse;
|
||||
import io.metersphere.system.dto.sdk.ApiReportMessageDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtTestPlanReportMapper {
|
||||
|
||||
/**
|
||||
* 分页获取计划列表
|
||||
* @param request 分页请求参数
|
||||
* @return 计划列表
|
||||
*/
|
||||
List<TestPlanReportPageResponse> list(@Param("request") TestPlanReportPageRequest request, @Param("sort") String sort);
|
||||
/**
|
||||
* 分页获取计划列表
|
||||
*
|
||||
* @param request 分页请求参数
|
||||
* @return 计划列表
|
||||
*/
|
||||
List<TestPlanReportPageResponse> list(@Param("request") TestPlanReportPageRequest request);
|
||||
|
||||
/**
|
||||
* 根据页面参数获取批量操作的报告ID
|
||||
* @param request 请求参数
|
||||
* @return 报告ID集合
|
||||
*/
|
||||
List<String> getReportBatchIdsByParam(@Param("request")TestPlanReportBatchRequest request);
|
||||
/**
|
||||
* 根据页面参数获取批量操作的报告ID
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @return 报告ID集合
|
||||
*/
|
||||
List<String> getReportBatchIdsByParam(@Param("request") TestPlanReportBatchRequest request);
|
||||
|
||||
List<TestPlanReport> selectReportByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<ApiReportMessageDTO> getNoticeList(@Param("ids") List<String> subList);
|
||||
}
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
<mapper namespace="io.metersphere.plan.mapper.ExtTestPlanReportMapper">
|
||||
<select id="list" resultType="io.metersphere.plan.dto.response.TestPlanReportPageResponse">
|
||||
select tpr.id as id, tpr.name as name, tp.name as planName, tpr.pass_threshold planPassThreshold,
|
||||
tpr.trigger_mode as triggerMode, tpr.exec_status as executeStatus, tpr.result_status as resultStatus,
|
||||
tpr.pass_rate passRate, tpr.create_user createUser, tpr.create_time createTime
|
||||
tpr.trigger_mode as triggerMode, tpr.exec_status , tpr.result_status as resultStatus,
|
||||
tpr.pass_rate passRate, tpr.create_user createUser, tpr.create_time createTime, tpr.integrated
|
||||
from test_plan_report tpr
|
||||
join test_plan tp on tpr.test_plan_id = tp.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
<if test="sort != null and sort != ''">
|
||||
order by ${sort}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getReportBatchIdsByParam" resultType="java.lang.String">
|
||||
|
@ -18,14 +15,24 @@
|
|||
join test_plan tp on tpr.test_plan_id = tp.id
|
||||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
<select id="selectReportByIds" resultType="io.metersphere.plan.domain.TestPlanReport">
|
||||
select * from test_plan_report where id in
|
||||
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="getNoticeList" resultType="io.metersphere.system.dto.sdk.ApiReportMessageDTO">
|
||||
select id, name from test_plan_report where id in
|
||||
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
tpr.deleted = 0
|
||||
<if test="request.projectId != null and request.projectId != ''">
|
||||
and tp.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.type != null and request.type != '' and request.type != 'ALL'">
|
||||
and tp.type = #{request.type}
|
||||
and tpr.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and tpr.name like concat('%', #{request.keyword},'%')
|
||||
|
@ -44,13 +51,23 @@
|
|||
<foreach collection="request.filter.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='integrated'">
|
||||
and tpr.integrated in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
<choose>
|
||||
<when test="value == 'true'">1</when>
|
||||
<when test="value == 'false'">0</when>
|
||||
<otherwise>0</otherwise>
|
||||
</choose>
|
||||
</foreach>
|
||||
</when>
|
||||
<!-- 触发方式 -->
|
||||
<when test="key == 'triggerMode'">
|
||||
and tpr.trigger_mode in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<!-- 执行状态 -->
|
||||
<when test="key == 'executeStatus'">
|
||||
<when test="key == 'execStatus'">
|
||||
and tpr.exec_status in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlanReport;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanReportMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanReportMapper;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.log.aspect.OperationLogAspect;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class TestPlanReportLogService {
|
||||
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
@Resource
|
||||
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||
@Resource
|
||||
private TestPlanReportMapper testPlanReportMapper;
|
||||
|
||||
|
||||
public LogDTO deleteLog(String id) {
|
||||
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(id);
|
||||
Project project = projectMapper.selectByPrimaryKey(report.getProjectId());
|
||||
LogDTO dto = new LogDTO(
|
||||
report.getProjectId(),
|
||||
project.getOrganizationId(),
|
||||
report.getId(),
|
||||
null,
|
||||
OperationLogType.DELETE.name(),
|
||||
OperationLogModule.TEST_PLAN_REPORT,
|
||||
report.getName());
|
||||
|
||||
dto.setPath(OperationLogAspect.getPath());
|
||||
dto.setMethod(HttpMethodConstants.GET.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(report));
|
||||
return dto;
|
||||
}
|
||||
|
||||
public LogDTO updateLog(String id) {
|
||||
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(id);
|
||||
Project project = projectMapper.selectByPrimaryKey(report.getProjectId());
|
||||
LogDTO dto = new LogDTO(
|
||||
report.getProjectId(),
|
||||
project.getOrganizationId(),
|
||||
report.getId(),
|
||||
null,
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.TEST_PLAN_REPORT,
|
||||
report.getName());
|
||||
|
||||
dto.setPath(OperationLogAspect.getPath());
|
||||
dto.setMethod(HttpMethodConstants.GET.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(report));
|
||||
return dto;
|
||||
}
|
||||
|
||||
public void batchDeleteLog(List<String> ids, String userId, String projectId) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
List<TestPlanReport> reports = extTestPlanReportMapper.selectReportByIds(ids);
|
||||
List<LogDTO> logs = new ArrayList<>();
|
||||
reports.forEach(report -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
projectId,
|
||||
project.getOrganizationId(),
|
||||
report.getId(),
|
||||
userId,
|
||||
OperationLogType.DELETE.name(),
|
||||
OperationLogModule.TEST_PLAN_REPORT,
|
||||
report.getName());
|
||||
|
||||
dto.setPath(OperationLogAspect.getPath());
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(report));
|
||||
logs.add(dto);
|
||||
});
|
||||
operationLogService.batchAdd(logs);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlanReport;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanReportMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanReportMapper;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.SubListUtils;
|
||||
import io.metersphere.system.domain.User;
|
||||
import io.metersphere.system.dto.sdk.ApiReportMessageDTO;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.service.CommonNoticeSendService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class TestPlanReportNoticeService {
|
||||
|
||||
@Resource
|
||||
private TestPlanReportMapper testPlanReportMapper;
|
||||
@Resource
|
||||
private CommonNoticeSendService commonNoticeSendService;
|
||||
@Resource
|
||||
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||
|
||||
public ApiReportMessageDTO getDto(String id) {
|
||||
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(id);
|
||||
ApiReportMessageDTO reportMessageDTO = new ApiReportMessageDTO();
|
||||
reportMessageDTO.setId(report.getId());
|
||||
reportMessageDTO.setName(report.getName());
|
||||
return reportMessageDTO;
|
||||
}
|
||||
|
||||
public void batchSendNotice(List<String> ids, User user, String projectId, String event) {
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
SubListUtils.dealForSubList(ids, 100, (subList) -> {
|
||||
List<ApiReportMessageDTO> noticeLists = extTestPlanReportMapper.getNoticeList(subList);
|
||||
List<Map> resources = new ArrayList<>(JSON.parseArray(JSON.toJSONString(noticeLists), Map.class));
|
||||
commonNoticeSendService.sendNotice(NoticeConstants.TaskType.TEST_PLAN_REPORT_TASK, event, resources, user, projectId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.domain.TestPlanReport;
|
||||
import io.metersphere.plan.domain.TestPlanReportExample;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportBatchRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportDeleteRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportEditRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanReportPageRequest;
|
||||
import io.metersphere.plan.dto.response.TestPlanReportPageResponse;
|
||||
import io.metersphere.plan.mapper.*;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanReportMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanReportMapper;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.SubListUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.domain.User;
|
||||
import io.metersphere.system.mapper.UserMapper;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.service.UserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
@ -21,115 +25,105 @@ import java.util.Map;
|
|||
@Service
|
||||
public class TestPlanReportService {
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@Resource
|
||||
private TestPlanReportMapper testPlanReportMapper;
|
||||
@Resource
|
||||
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||
@Resource
|
||||
private TestPlanReportSummaryMapper testPlanReportSummaryMapper;
|
||||
@Resource
|
||||
private TestPlanReportFunctionCaseMapper testPlanReportFunctionCaseMapper;
|
||||
@Resource
|
||||
private TestPlanReportBugMapper testPlanReportBugMapper;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@Resource
|
||||
private TestPlanReportMapper testPlanReportMapper;
|
||||
@Resource
|
||||
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||
@Resource
|
||||
private TestPlanReportLogService testPlanReportLogService;
|
||||
@Resource
|
||||
private TestPlanReportNoticeService testPlanReportNoticeService;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
/**
|
||||
* 分页查询报告列表
|
||||
* @param request 分页请求参数
|
||||
* @return 报告列表
|
||||
*/
|
||||
public List<TestPlanReportPageResponse> page(TestPlanReportPageRequest request) {
|
||||
List<TestPlanReportPageResponse> reportList = extTestPlanReportMapper.list(request, request.getSortString());
|
||||
if (CollectionUtils.isEmpty(reportList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> distinctUserIds = reportList.stream().map(TestPlanReportPageResponse::getCreateUser).distinct().toList();
|
||||
Map<String, String> userMap = userService.getUserMapByIds(distinctUserIds);
|
||||
reportList.forEach(report -> report.setCreateUserName(userMap.get(report.getCreateUser())));
|
||||
return reportList;
|
||||
}
|
||||
/**
|
||||
* 分页查询报告列表
|
||||
*
|
||||
* @param request 分页请求参数
|
||||
* @return 报告列表
|
||||
*/
|
||||
public List<TestPlanReportPageResponse> page(TestPlanReportPageRequest request) {
|
||||
List<TestPlanReportPageResponse> reportList = extTestPlanReportMapper.list(request);
|
||||
if (CollectionUtils.isEmpty(reportList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> distinctUserIds = reportList.stream().map(TestPlanReportPageResponse::getCreateUser).distinct().toList();
|
||||
Map<String, String> userMap = userService.getUserMapByIds(distinctUserIds);
|
||||
reportList.forEach(report -> report.setCreateUserName(userMap.get(report.getCreateUser())));
|
||||
return reportList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 报告重命名
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void rename(TestPlanReportEditRequest request) {
|
||||
checkReport(request.getId());
|
||||
TestPlanReport report = new TestPlanReport();
|
||||
report.setId(request.getId());
|
||||
report.setName(request.getName());
|
||||
testPlanReportMapper.updateByPrimaryKeySelective(report);
|
||||
}
|
||||
/**
|
||||
* 报告重命名
|
||||
*/
|
||||
public void rename(String id, String name) {
|
||||
TestPlanReport report = checkReport(id);
|
||||
report.setName(name);
|
||||
testPlanReportMapper.updateByPrimaryKeySelective(report);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个报告
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void delete(TestPlanReportDeleteRequest request) {
|
||||
checkReport(request.getId());
|
||||
testPlanReportMapper.deleteByPrimaryKey(request.getId());
|
||||
// 删除报告内容的关联资源表
|
||||
cleanReportAssociateResource(List.of(request.getId()));
|
||||
}
|
||||
/**
|
||||
* 删除单个报告
|
||||
*/
|
||||
public void delete(String id) {
|
||||
TestPlanReport report = checkReport(id);
|
||||
report.setDeleted(true);
|
||||
testPlanReportMapper.updateByPrimaryKeySelective(report);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量参数报告
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void batchDelete(TestPlanReportBatchRequest request) {
|
||||
List<String> batchIds = getBatchIds(request);
|
||||
if (CollectionUtils.isNotEmpty(batchIds)) {
|
||||
TestPlanReportExample example = new TestPlanReportExample();
|
||||
example.createCriteria().andIdIn(batchIds);
|
||||
testPlanReportMapper.deleteByExample(example);
|
||||
// 删除报告内容的关联资源表
|
||||
cleanReportAssociateResource(batchIds);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 批量参数报告
|
||||
*
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void batchDelete(TestPlanReportBatchRequest request, String userId) {
|
||||
List<String> batchIds = getBatchIds(request);
|
||||
User user = userMapper.selectByPrimaryKey(userId);
|
||||
if (CollectionUtils.isNotEmpty(batchIds)) {
|
||||
SubListUtils.dealForSubList(batchIds, 500, subList -> {
|
||||
TestPlanReportExample example = new TestPlanReportExample();
|
||||
example.createCriteria().andIdIn(subList);
|
||||
TestPlanReport testPlanReport = new TestPlanReport();
|
||||
testPlanReport.setDeleted(true);
|
||||
testPlanReportMapper.updateByExampleSelective(testPlanReport, example);
|
||||
|
||||
/**
|
||||
* 清理报告关联的资源
|
||||
* @param reportIds 报告ID集合
|
||||
*/
|
||||
public void cleanReportAssociateResource(List<String> reportIds) {
|
||||
// TODO: 删除报告关联的统计, 用例, 缺陷
|
||||
TestPlanReportSummaryExample summaryExample = new TestPlanReportSummaryExample();
|
||||
summaryExample.createCriteria().andTestPlanReportIdIn(reportIds);
|
||||
testPlanReportSummaryMapper.deleteByExample(summaryExample);
|
||||
TestPlanReportFunctionCaseExample functionCaseExample = new TestPlanReportFunctionCaseExample();
|
||||
functionCaseExample.createCriteria().andTestPlanReportIdIn(reportIds);
|
||||
testPlanReportFunctionCaseMapper.deleteByExample(functionCaseExample);
|
||||
TestPlanReportBugExample bugExample = new TestPlanReportBugExample();
|
||||
bugExample.createCriteria().andTestPlanReportIdIn(reportIds);
|
||||
testPlanReportBugMapper.deleteByExample(bugExample);
|
||||
}
|
||||
testPlanReportLogService.batchDeleteLog(subList, userId, request.getProjectId());
|
||||
testPlanReportNoticeService.batchSendNotice(subList, user, request.getProjectId(), NoticeConstants.Event.DELETE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过请求参数获取批量操作的ID集合
|
||||
* @param request 请求参数
|
||||
* @return ID集合
|
||||
*/
|
||||
private List<String> getBatchIds(TestPlanReportBatchRequest request) {
|
||||
if (request.isSelectAll()) {
|
||||
List<String> batchIds = extTestPlanReportMapper.getReportBatchIdsByParam(request);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
batchIds.removeIf(id -> request.getExcludeIds().contains(id));
|
||||
}
|
||||
return batchIds;
|
||||
} else {
|
||||
return request.getSelectIds();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验报告是否存在
|
||||
* @param id 报告ID
|
||||
*/
|
||||
private void checkReport(String id) {
|
||||
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(id);
|
||||
if (testPlanReport == null) {
|
||||
throw new MSException(Translator.get("test_plan_report_not_exist"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 通过请求参数获取批量操作的ID集合
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @return ID集合
|
||||
*/
|
||||
private List<String> getBatchIds(TestPlanReportBatchRequest request) {
|
||||
if (request.isSelectAll()) {
|
||||
List<String> batchIds = extTestPlanReportMapper.getReportBatchIdsByParam(request);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
batchIds.removeIf(id -> request.getExcludeIds().contains(id));
|
||||
}
|
||||
return batchIds;
|
||||
} else {
|
||||
return request.getSelectIds();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验报告是否存在
|
||||
*
|
||||
* @param id 报告ID
|
||||
*/
|
||||
private TestPlanReport checkReport(String id) {
|
||||
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(id);
|
||||
if (testPlanReport == null) {
|
||||
throw new MSException(Translator.get("test_plan_report_not_exist"));
|
||||
}
|
||||
return testPlanReport;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,144 +28,137 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
@AutoConfigureMockMvc
|
||||
public class TestPlanReportControllerTests extends BaseTest {
|
||||
|
||||
private static final String LIST_PLAN_REPORT = "/test-plan/report/page";
|
||||
private static final String RENAME_PLAN_REPORT = "/test-plan/report/rename";
|
||||
private static final String DELETE_PLAN_REPORT = "/test-plan/report/delete";
|
||||
private static final String BATCH_DELETE_PLAN_REPORT = "/test-plan/report/batch-delete";
|
||||
private static final String GEN_AND_SHARE = "/test-plan/report/share/gen";
|
||||
private static final String GET_SHARE_INFO = "/test-plan/report/share/get";
|
||||
private static final String GET_SHARE_TIME = "/test-plan/report/share/get-share-time";
|
||||
private static final String LIST_PLAN_REPORT = "/test-plan/report/page";
|
||||
private static final String RENAME_PLAN_REPORT = "/test-plan/report/rename";
|
||||
private static final String DELETE_PLAN_REPORT = "/test-plan/report/delete";
|
||||
private static final String BATCH_DELETE_PLAN_REPORT = "/test-plan/report/batch-delete";
|
||||
private static final String GEN_AND_SHARE = "/test-plan/report/share/gen";
|
||||
private static final String GET_SHARE_INFO = "/test-plan/report/share/get";
|
||||
private static final String GET_SHARE_TIME = "/test-plan/report/share/get-share-time";
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@Sql(scripts = {"/dml/init_test_plan_report.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
void tesPagePlanReportSuccess() throws Exception {
|
||||
TestPlanReportPageRequest request = new TestPlanReportPageRequest();
|
||||
request.setProjectId("100001100001");
|
||||
request.setType("ALL");
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(10);
|
||||
request.setKeyword("1");
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(LIST_PLAN_REPORT, request);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
// 返回值不为空
|
||||
Assertions.assertNotNull(pageData);
|
||||
// 返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
|
||||
// 返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
|
||||
// 返回值中取出第一条数据, 并判断是否包含关键字default
|
||||
TestPlanReportPageResponse report = JSON.parseArray(JSON.toJSONString(pageData.getList()), TestPlanReportPageResponse.class).get(0);
|
||||
Assertions.assertTrue(StringUtils.contains(report.getName(), request.getKeyword()));
|
||||
// 覆盖排序, 及数据为空
|
||||
request.setSort(Map.of("tpr.create_time", "asc"));
|
||||
request.setKeyword("oasis");
|
||||
this.requestPost(LIST_PLAN_REPORT, request);
|
||||
}
|
||||
@Test
|
||||
@Order(1)
|
||||
@Sql(scripts = {"/dml/init_test_plan_report.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
void tesPagePlanReportSuccess() throws Exception {
|
||||
TestPlanReportPageRequest request = new TestPlanReportPageRequest();
|
||||
request.setProjectId("100001100001");
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(10);
|
||||
request.setKeyword("1");
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(LIST_PLAN_REPORT, request);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
// 返回值不为空
|
||||
Assertions.assertNotNull(pageData);
|
||||
// 返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
|
||||
// 返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
|
||||
// 返回值中取出第一条数据, 并判断是否包含关键字default
|
||||
TestPlanReportPageResponse report = JSON.parseArray(JSON.toJSONString(pageData.getList()), TestPlanReportPageResponse.class).get(0);
|
||||
Assertions.assertTrue(StringUtils.contains(report.getName(), request.getKeyword()));
|
||||
// 覆盖排序, 及数据为空
|
||||
request.setSort(Map.of("tpr.create_time", "asc"));
|
||||
request.setKeyword("oasis");
|
||||
this.requestPost(LIST_PLAN_REPORT, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void testPagePlanReportError() throws Exception {
|
||||
// 必填参数有误
|
||||
TestPlanReportPageRequest request = new TestPlanReportPageRequest();
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(10);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
// 页码有误
|
||||
request.setProjectId("100001100001");
|
||||
request.setType("ALL");
|
||||
request.setCurrent(0);
|
||||
request.setPageSize(10);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
// 页数有误
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(1);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
}
|
||||
@Test
|
||||
@Order(2)
|
||||
void testPagePlanReportError() throws Exception {
|
||||
// 必填参数有误
|
||||
TestPlanReportPageRequest request = new TestPlanReportPageRequest();
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(10);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
// 页码有误
|
||||
request.setProjectId("100001100001");
|
||||
request.setCurrent(0);
|
||||
request.setPageSize(10);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
// 页数有误
|
||||
request.setCurrent(1);
|
||||
request.setPageSize(1);
|
||||
this.requestPost(LIST_PLAN_REPORT, request, status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
void testRenamePlanReportSuccess() throws Exception {
|
||||
TestPlanReportEditRequest request = new TestPlanReportEditRequest();
|
||||
request.setId("test-plan-report-id-1");
|
||||
request.setName("oasis");
|
||||
request.setProjectId("100001100001");
|
||||
this.requestPostWithOk(RENAME_PLAN_REPORT, request);
|
||||
}
|
||||
@Test
|
||||
@Order(3)
|
||||
void testRenamePlanReportSuccess() throws Exception {
|
||||
this.requestPostWithOk(RENAME_PLAN_REPORT + "/test-plan-report-id-1", "oasis");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
void testRenamePlanReportError() throws Exception {
|
||||
TestPlanReportEditRequest request = new TestPlanReportEditRequest();
|
||||
request.setId("test-plan-report-id-x");
|
||||
request.setName("oasis");
|
||||
request.setProjectId("100001100001");
|
||||
this.requestPost(RENAME_PLAN_REPORT, request, status().is5xxServerError());
|
||||
}
|
||||
@Test
|
||||
@Order(4)
|
||||
void testRenamePlanReportError() throws Exception {
|
||||
TestPlanReportEditRequest request = new TestPlanReportEditRequest();
|
||||
request.setId("test-plan-report-id-x");
|
||||
request.setName("oasis");
|
||||
request.setProjectId("100001100001");
|
||||
this.requestPost(RENAME_PLAN_REPORT, request, status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
void testSharePlanReport() throws Exception {
|
||||
TestPlanReportShareRequest shareRequest = new TestPlanReportShareRequest();
|
||||
shareRequest.setReportId("test-plan-report-id-1");
|
||||
shareRequest.setProjectId("100001100001");
|
||||
shareRequest.setShareType(ShareInfoType.TEST_PLAN_SHARE_REPORT.name());
|
||||
this.requestPost(GEN_AND_SHARE, shareRequest);
|
||||
shareRequest.setLang(Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
MvcResult mvcResult = this.requestPost(GEN_AND_SHARE, shareRequest).andReturn();
|
||||
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder sortHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||
TestPlanShareInfo shareInfo = JSON.parseObject(JSON.toJSONString(sortHolder.getData()), TestPlanShareInfo.class);
|
||||
Assertions.assertNotNull(shareInfo);
|
||||
this.requestGet(GET_SHARE_INFO + "/" + shareInfo.getId());
|
||||
}
|
||||
@Test
|
||||
@Order(5)
|
||||
void testSharePlanReport() throws Exception {
|
||||
TestPlanReportShareRequest shareRequest = new TestPlanReportShareRequest();
|
||||
shareRequest.setReportId("test-plan-report-id-1");
|
||||
shareRequest.setProjectId("100001100001");
|
||||
shareRequest.setShareType(ShareInfoType.TEST_PLAN_SHARE_REPORT.name());
|
||||
this.requestPost(GEN_AND_SHARE, shareRequest);
|
||||
shareRequest.setLang(Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
MvcResult mvcResult = this.requestPost(GEN_AND_SHARE, shareRequest).andReturn();
|
||||
String sortData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder sortHolder = JSON.parseObject(sortData, ResultHolder.class);
|
||||
TestPlanShareInfo shareInfo = JSON.parseObject(JSON.toJSONString(sortHolder.getData()), TestPlanShareInfo.class);
|
||||
Assertions.assertNotNull(shareInfo);
|
||||
this.requestGet(GET_SHARE_INFO + "/" + shareInfo.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
void testGetShareInfo() throws Exception {
|
||||
// 报告被删除
|
||||
this.requestGet(GET_SHARE_INFO + "/share-1");
|
||||
// 分享链接未找到
|
||||
this.requestGet(GET_SHARE_INFO + "/share-2", status().is5xxServerError());
|
||||
}
|
||||
@Test
|
||||
@Order(6)
|
||||
void testGetShareInfo() throws Exception {
|
||||
// 报告被删除
|
||||
this.requestGet(GET_SHARE_INFO + "/share-1");
|
||||
// 分享链接未找到
|
||||
this.requestGet(GET_SHARE_INFO + "/share-2", status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
void testGetShareTime() throws Exception {
|
||||
this.requestGet(GET_SHARE_TIME + "/100001100001");
|
||||
this.requestGet(GET_SHARE_TIME + "/100001100002");
|
||||
}
|
||||
@Test
|
||||
@Order(7)
|
||||
void testGetShareTime() throws Exception {
|
||||
this.requestGet(GET_SHARE_TIME + "/100001100001");
|
||||
this.requestGet(GET_SHARE_TIME + "/100001100002");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
void testDeletePlanReport() throws Exception {
|
||||
TestPlanReportDeleteRequest request = new TestPlanReportDeleteRequest();
|
||||
request.setId("test-plan-report-id-1");
|
||||
request.setProjectId("100001100001");
|
||||
this.requestPostWithOk(DELETE_PLAN_REPORT, request);
|
||||
}
|
||||
@Test
|
||||
@Order(8)
|
||||
void testDeletePlanReport() throws Exception {
|
||||
TestPlanReportDeleteRequest request = new TestPlanReportDeleteRequest();
|
||||
request.setId("test-plan-report-id-1");
|
||||
request.setProjectId("100001100001");
|
||||
this.requestGet(DELETE_PLAN_REPORT + "/test-plan-report-id-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(9)
|
||||
void testBatchDeletePlanReport() throws Exception {
|
||||
TestPlanReportBatchRequest request = new TestPlanReportBatchRequest();
|
||||
request.setProjectId("100001100001");
|
||||
request.setType("ALL");
|
||||
// 勾选部分, 并删除
|
||||
request.setSelectAll(false);
|
||||
request.setSelectIds(List.of("test-plan-report-id-2"));
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
// 全选并排除所有, 为空
|
||||
request.setSelectAll(true);
|
||||
request.setExcludeIds(List.of("test-plan-report-id-3", "test-plan-report-id-4"));
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
// 全选不排除
|
||||
request.setExcludeIds(null);
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
}
|
||||
@Test
|
||||
@Order(9)
|
||||
void testBatchDeletePlanReport() throws Exception {
|
||||
TestPlanReportBatchRequest request = new TestPlanReportBatchRequest();
|
||||
request.setProjectId("100001100001");
|
||||
// 勾选部分, 并删除
|
||||
request.setSelectAll(false);
|
||||
request.setSelectIds(List.of("test-plan-report-id-2"));
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
// 全选并排除所有, 为空
|
||||
request.setSelectAll(true);
|
||||
request.setExcludeIds(List.of("test-plan-report-id-3", "test-plan-report-id-4"));
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
// 全选不排除
|
||||
request.setExcludeIds(null);
|
||||
this.requestPostWithOk(BATCH_DELETE_PLAN_REPORT, request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ INSERT INTO `test_plan`(`id`, `num`, `project_id`, `group_id`, `module_id`, `nam
|
|||
VALUES ('test-plan-id-for992', 100003, '100001100001', 'NONE', '1', '测试一下计划-992', 'PREPARED', 'TEST_PLAN', NULL, CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '11');
|
||||
|
||||
-- 计划报告测试数据
|
||||
INSERT INTO `test_plan_report`(`id`, `test_plan_id`, `name`, `create_user`, `create_time`, `start_time`, `end_time`, `trigger_mode`, `exec_status`, `result_status`, `pass_threshold`, `pass_rate`) VALUES
|
||||
('test-plan-report-id-1', 'test-plan-id-for991', '测试一下计划报告1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00),
|
||||
('test-plan-report-id-2', 'test-plan-id-for991', '测试一下计划报告1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00),
|
||||
('test-plan-report-id-3', 'test-plan-id-for992', '测试一下计划报告3', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00),
|
||||
('test-plan-report-id-4', 'test-plan-id-for992', '测试一下计划报告4', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00);
|
||||
INSERT INTO `test_plan_report`(`id`, `test_plan_id`, `name`, `create_user`, `create_time`, `start_time`, `end_time`, `trigger_mode`, `exec_status`, `result_status`, `pass_threshold`, `pass_rate`, `project_id`, `integrated`, `deleted`) VALUES
|
||||
('test-plan-report-id-1', 'test-plan-id-for991', '测试一下计划报告1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', 'SUCCESS', '99.99', 100.00, '100001100001', 0, 0),
|
||||
('test-plan-report-id-2', 'test-plan-id-for991', '测试一下计划报告1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001', 0, 0),
|
||||
('test-plan-report-id-3', 'test-plan-id-for992', '测试一下计划报告3', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001',1, 0),
|
||||
('test-plan-report-id-4', 'test-plan-id-for992', '测试一下计划报告4', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001', 1, 0);
|
||||
|
||||
-- 计划报告分享信息
|
||||
INSERT INTO project_application (`project_id`, `type`, `type_value`) VALUES
|
||||
('100001100001', 'TEST_PLAN_SHARE_REPORT', '1D');
|
||||
('100001100001', 'TEST_PLAN_SHARE_REPORT', '1D');
|
||||
INSERT INTO `share_info`(`id`, `create_time`, `create_user`, `update_time`, `share_type`, `custom_data`, `lang`, `project_id`) VALUES
|
||||
('share-1', CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, 'TEST_PLAN_SHARE_REPORT', 0x31303531363635363936353436383137, 'zh_CN', '100001100001');
|
||||
('share-1', CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, 'TEST_PLAN_SHARE_REPORT', 0x31303531363635363936353436383137, 'zh_CN', '100001100001');
|
|
@ -1,8 +1,8 @@
|
|||
// 报告列表
|
||||
export const PlanReportListUrl = '/api/report/scenario/page';
|
||||
export const PlanReportListUrl = '/test-plan/report/page';
|
||||
// 报告重命名
|
||||
export const PlanReportRenameUrl = '/api/report/scenario/rename';
|
||||
export const PlanReportRenameUrl = '/test-plan/report/rename';
|
||||
// 删除报告
|
||||
export const PlanDeleteUrl = '/api/report/scenario/delete';
|
||||
export const PlanDeleteUrl = '/test-plan/report/delete';
|
||||
// 批量删除报告
|
||||
export const PlanBatchDeleteUrl = '/api/report/scenario/batch/delete';
|
||||
export const PlanBatchDeleteUrl = '/test-plan/report/batch-delete';
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
// 模板展示字段icon
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
export enum ReportEnum {
|
||||
API_SCENARIO_REPORT = 'API_SCENARIO_REPORT',
|
||||
API_REPORT = 'API_REPORT',
|
||||
|
@ -86,23 +89,35 @@ export const ReportStatus = {
|
|||
},
|
||||
};
|
||||
|
||||
export const PlanReportStatus = {
|
||||
export const PlanReportStatus: Record<string, any> = {
|
||||
[ReportStatusEnum.EXEC_STATUS]: {
|
||||
STOPPED: {
|
||||
key: 'STOPPED',
|
||||
icon: 'icon-icon_block_filled',
|
||||
statusText: t('report.stopped'),
|
||||
label: 'report.stop',
|
||||
color: '!var(--color-text-input-border)',
|
||||
},
|
||||
RUNNING: {
|
||||
key: 'RUNNING',
|
||||
icon: 'icon-icon_testing',
|
||||
statusText: t('report.status.running'),
|
||||
label: 'report.inExecution',
|
||||
color: '!text-[rgb(var(--link-6))]',
|
||||
},
|
||||
PENDING: {
|
||||
key: 'PENDING',
|
||||
icon: 'icon-icon_wait',
|
||||
statusText: t('report.status.pending'),
|
||||
label: 'report.queuing',
|
||||
color: '!text-[rgb(var(--link-6))]',
|
||||
},
|
||||
COMPLETED: {
|
||||
key: 'COMPLETED',
|
||||
icon: 'icon-icon_succeed_colorful',
|
||||
statusText: t('report.completed'),
|
||||
label: 'report.successful',
|
||||
},
|
||||
},
|
||||
[ReportStatusEnum.REPORT_STATUS]: {
|
||||
SUCCESS: {
|
||||
|
@ -113,10 +128,6 @@ export const PlanReportStatus = {
|
|||
icon: 'icon-icon_close_colorful',
|
||||
label: 'report.failure',
|
||||
},
|
||||
FAKE_ERROR: {
|
||||
icon: 'icon-icon_warning_colorful',
|
||||
label: 'report.falseAlarm',
|
||||
},
|
||||
},
|
||||
};
|
||||
export default {};
|
||||
|
|
|
@ -7,6 +7,7 @@ export enum FilterSlotNameEnum {
|
|||
CASE_MANAGEMENT_BUG_STATE = 'CASE_MANAGEMENT_BUG_STATE', // 缺陷状态
|
||||
API_TEST_API_REQUEST_METHODS = 'API_TEST_API_REQUEST_METHODS', // 接口测试请求方式
|
||||
API_TEST_API_REQUEST_API_STATUS = 'API_TEST_API_REQUEST_API_STATUS', // 接口测试接口状态
|
||||
TEST_PLAN_REPORT_EXEC_STATUS = 'TEST_PLAN_REPORT_EXEC_STATUS',
|
||||
}
|
||||
|
||||
export enum FilterRemoteMethodsEnum {
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
<template>
|
||||
<MsColorLine :color-data="colorData" :height="props.height" :radius="props.radius">
|
||||
<!-- TODO 这个页面还得根据实际业务调整-->
|
||||
<template #popoverContent>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="pr-[8px] text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.progress') }}</td>
|
||||
<td class="font-medium text-[var(--color-text-1)]">
|
||||
{{ progress }}
|
||||
<span> ({{ `${props.detail.passCount + props.detail.unPassCount}/${props.detail.caseCount}` }}) </span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--success-6))]"></div>
|
||||
<div>{{ t('caseManagement.caseReview.pass') }}</div>
|
||||
</td>
|
||||
<td class="popover-value-td">
|
||||
{{ props.detail.passCount }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--danger-6))]"></div>
|
||||
<div>{{ t('caseManagement.caseReview.fail') }}</div>
|
||||
</td>
|
||||
<td class="popover-value-td">
|
||||
{{ props.detail.unPassCount }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--warning-6))]"></div>
|
||||
<div>{{ t('caseManagement.caseReview.reReview') }}</div>
|
||||
</td>
|
||||
<td class="popover-value-td">
|
||||
{{ props.detail.reReviewedCount }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="popover-label-td">
|
||||
<div class="mb-[2px] mr-[4px] h-[6px] w-[6px] rounded-full bg-[rgb(var(--link-6))]"></div>
|
||||
<div>{{ t('caseManagement.caseReview.reviewing') }}</div>
|
||||
</td>
|
||||
<td class="popover-value-td">
|
||||
{{ props.detail.underReviewedCount }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
</MsColorLine>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MsColorLine from '@/components/pure/ms-color-line/index.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const props = defineProps<{
|
||||
detail: {
|
||||
passCount: number;
|
||||
unPassCount: number;
|
||||
reReviewedCount: number;
|
||||
underReviewedCount: number;
|
||||
caseCount: number;
|
||||
[key: string]: any;
|
||||
};
|
||||
height: string;
|
||||
radius?: string;
|
||||
}>();
|
||||
const { t } = useI18n();
|
||||
|
||||
const colorData = computed(() => {
|
||||
return [
|
||||
{
|
||||
percentage: 100,
|
||||
color: 'var(--color-text-n8)',
|
||||
},
|
||||
];
|
||||
// TODO 实际业务调整
|
||||
// return [
|
||||
// {
|
||||
// percentage: (props.detail.passCount / props.detail.caseCount) * 100,
|
||||
// color: 'rgb(var(--success-6))',
|
||||
// },
|
||||
// {
|
||||
// percentage: (props.detail.unPassCount / props.detail.caseCount) * 100,
|
||||
// color: 'rgb(var(--danger-6))',
|
||||
// },
|
||||
// {
|
||||
// percentage: (props.detail.reReviewedCount / props.detail.caseCount) * 100,
|
||||
// color: 'rgb(var(--warning-6))',
|
||||
// },
|
||||
// {
|
||||
// percentage: (props.detail.underReviewedCount / props.detail.caseCount) * 100,
|
||||
// color: 'rgb(var(--link-6))',
|
||||
// },
|
||||
// ];
|
||||
});
|
||||
const progress = computed(() => {
|
||||
const result = ((props.detail.passCount + props.detail.unPassCount) / props.detail.caseCount) * 100;
|
||||
return `${Number.isNaN(result) ? 0 : result.toFixed(2)}%`;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.popover-label-td {
|
||||
@apply flex items-center;
|
||||
|
||||
padding: 8px 8px 0 0;
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
.popover-value-td {
|
||||
@apply font-medium;
|
||||
|
||||
padding-top: 8px;
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
</style>
|
|
@ -32,69 +32,7 @@
|
|||
>{{ characterLimit(record.name) }}</div
|
||||
>
|
||||
</template>
|
||||
<!-- 报告类型 -->
|
||||
<template #integrated="{ record }">
|
||||
<MsTag theme="light" :type="record.integrated ? 'primary' : undefined">
|
||||
{{ record.integrated ? t('report.collection') : t('report.independent') }}
|
||||
</MsTag>
|
||||
</template>
|
||||
<template #integratedFilter="{ columnConfig }">
|
||||
<TableFilter
|
||||
v-model:visible="reportTypeVisible"
|
||||
v-model:status-filters="integratedFiltersMap[showType]"
|
||||
:title="(columnConfig.title as string)"
|
||||
:list="reportTypeList"
|
||||
@search="initData()"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<MsTag theme="light" :type="item.value === 'INTEGRATED' ? 'primary' : undefined">
|
||||
{{ item.value === 'INTEGRATED' ? t('report.collection') : t('report.independent') }}
|
||||
</MsTag>
|
||||
</template>
|
||||
</TableFilter>
|
||||
</template>
|
||||
<!-- 报告触发方式筛选 -->
|
||||
<template #triggerModeFilter="{ columnConfig }">
|
||||
<a-trigger
|
||||
v-model:popup-visible="triggerModeFilterVisible"
|
||||
trigger="click"
|
||||
@popup-visible-change="handleFilterHidden"
|
||||
>
|
||||
<a-button
|
||||
type="text"
|
||||
class="arco-btn-text--secondary p-[8px_4px]"
|
||||
@click.stop="triggerModeFilterVisible = true"
|
||||
>
|
||||
<div class="font-medium">
|
||||
{{ t(columnConfig.title as string) }}
|
||||
</div>
|
||||
<icon-down :class="triggerModeFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<div class="arco-table-filters-content">
|
||||
<div class="ml-[6px] flex items-center justify-start px-[6px] py-[2px]">
|
||||
<a-checkbox-group
|
||||
v-model:model-value="triggerModeListFiltersMaps[showType]"
|
||||
direction="vertical"
|
||||
size="small"
|
||||
>
|
||||
<a-checkbox v-for="(key, value) of TriggerModeLabel" :key="key" :value="value">
|
||||
<div class="font-medium">{{ t(key) }}</div>
|
||||
</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
<div class="filter-button">
|
||||
<a-button size="mini" class="mr-[8px]" @click="resetTriggerModeFilter">
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||
{{ t('system.orgTemplate.confirm') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-trigger>
|
||||
</template>
|
||||
|
||||
<!-- 通过率 -->
|
||||
<template #passRateColumn>
|
||||
<div class="flex items-center text-[var(--color-text-3)]">
|
||||
|
@ -108,95 +46,22 @@
|
|||
</div>
|
||||
</template>
|
||||
<template #passRate="{ record }">
|
||||
<div class="mr-[8px] w-[100px]">
|
||||
<passRateLine :detail="record" height="5px" />
|
||||
</div>
|
||||
<div class="text-[var(--color-text-1)]">
|
||||
{{ `${record.passRate | 0}%` }}
|
||||
</div>
|
||||
</template>
|
||||
<!-- 报告结果筛选 -->
|
||||
<template #statusFilter="{ columnConfig }">
|
||||
<a-trigger
|
||||
v-model:popup-visible="statusFilterVisible"
|
||||
trigger="click"
|
||||
@popup-visible-change="handleFilterHidden"
|
||||
>
|
||||
<a-button type="text" class="arco-btn-text--secondary p-[8px_4px]" @click.stop="statusFilterVisible = true">
|
||||
<div class="font-medium">
|
||||
{{ t(columnConfig.title as string) }}
|
||||
</div>
|
||||
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<div class="arco-table-filters-content">
|
||||
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||
<a-checkbox-group
|
||||
v-model:model-value="statusListFiltersMap[showType]"
|
||||
direction="vertical"
|
||||
size="small"
|
||||
>
|
||||
<a-checkbox v-for="key of statusFilters" :key="key" :value="key">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.REPORT_STATUS" :status="key" />
|
||||
</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
<div class="filter-button">
|
||||
<a-button size="mini" class="mr-[8px]" @click="resetStatusFilter">
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||
{{ t('system.orgTemplate.confirm') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-trigger>
|
||||
</template>
|
||||
<!-- 执行状态筛选 -->
|
||||
<template #execStatusFilter="{ columnConfig }">
|
||||
<a-trigger
|
||||
v-model:popup-visible="execStatusFilterVisible"
|
||||
trigger="click"
|
||||
@popup-visible-change="handleExecStatusFilterHidden"
|
||||
>
|
||||
<a-button
|
||||
type="text"
|
||||
class="arco-btn-text--secondary p-[8px_4px]"
|
||||
@click.stop="execStatusFilterVisible = true"
|
||||
>
|
||||
<div class="font-medium">
|
||||
{{ t(columnConfig.title as string) }}
|
||||
</div>
|
||||
<icon-down :class="execStatusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<div class="arco-table-filters-content">
|
||||
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||
<a-checkbox-group
|
||||
v-model:model-value="statusListFiltersMap[showType]"
|
||||
direction="vertical"
|
||||
size="small"
|
||||
>
|
||||
<a-checkbox v-for="key of execStatusFilters" :key="key" :value="key">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.EXEC_STATUS" :status="key" />
|
||||
</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
<div class="filter-button">
|
||||
<a-button size="mini" class="mr-[8px]" @click="resetExecStatusFilter">
|
||||
{{ t('common.reset') }}
|
||||
</a-button>
|
||||
<a-button type="primary" size="mini" @click="handleExecStatusFilterHidden(false)">
|
||||
{{ t('system.orgTemplate.confirm') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-trigger>
|
||||
<template #resultStatus="{ record }">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.REPORT_STATUS" :status="record.resultStatus" />
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.REPORT_STATUS" :status="record.status" />
|
||||
<template #execStatus="{ record }">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.EXEC_STATUS" :status="record.execStatus" />
|
||||
</template>
|
||||
<template #[FilterSlotNameEnum.TEST_PLAN_REPORT_EXEC_STATUS]="{ filterContent }">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.EXEC_STATUS" :status="filterContent.value" />
|
||||
</template>
|
||||
<template #[FilterSlotNameEnum.TEST_PLAN_STATUS_FILTER]="{ filterContent }">
|
||||
<ExecutionStatus :module-type="ReportStatusEnum.REPORT_STATUS" :status="filterContent.value" />
|
||||
</template>
|
||||
<template #triggerMode="{ record }">
|
||||
<span>{{ t(TriggerModeLabel[record.triggerMode as keyof typeof TriggerModeLabel]) }}</span>
|
||||
|
@ -225,9 +90,6 @@
|
|||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
|
||||
import passRateLine from '@/views/test-plan/report/component/passRateLine.vue';
|
||||
import ExecutionStatus from '@/views/test-plan/report/component/reportStatus.vue';
|
||||
|
||||
import { reportBathDelete, reportDelete, reportList, reportRename } from '@/api/modules/test-plan/report';
|
||||
|
@ -241,6 +103,7 @@
|
|||
import { BatchApiParams } from '@/models/common';
|
||||
import { PlanReportStatus, ReportStatusEnum, TriggerModeLabel } from '@/enums/reportEnum';
|
||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||
import { FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||
|
||||
const { openModal } = useModal();
|
||||
|
||||
|
@ -248,16 +111,47 @@
|
|||
const tableStore = useTableStore();
|
||||
const { t } = useI18n();
|
||||
const keyword = ref<string>('');
|
||||
const statusFilterVisible = ref(false);
|
||||
const execStatusFilterVisible = ref(false);
|
||||
|
||||
const triggerModeFilterVisible = ref(false);
|
||||
|
||||
const triggerModeListFilters = ref<string[]>([]);
|
||||
|
||||
type ReportShowType = 'All' | 'INDEPENDENT' | 'INTEGRATED';
|
||||
const showType = ref<ReportShowType>('All');
|
||||
|
||||
const executeResultOptions = computed(() => {
|
||||
return Object.keys(PlanReportStatus[ReportStatusEnum.EXEC_STATUS]).map((key) => {
|
||||
return {
|
||||
value: key,
|
||||
label: PlanReportStatus[ReportStatusEnum.EXEC_STATUS][key].statusText,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const statusResultOptions = computed(() => {
|
||||
return Object.keys(PlanReportStatus[ReportStatusEnum.REPORT_STATUS]).map((key) => {
|
||||
return {
|
||||
value: key,
|
||||
label: PlanReportStatus[ReportStatusEnum.REPORT_STATUS][key].statusText,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const triggerModeOptions = computed(() => {
|
||||
return Object.keys(TriggerModeLabel).map((key) => {
|
||||
return {
|
||||
value: key,
|
||||
label: t(TriggerModeLabel[key as keyof typeof TriggerModeLabel]),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const integratedFilters = computed(() => {
|
||||
if (showType.value === 'All') {
|
||||
return undefined;
|
||||
}
|
||||
if (showType.value === 'INTEGRATED') {
|
||||
return [true];
|
||||
}
|
||||
return [false];
|
||||
});
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: 'report.name',
|
||||
|
@ -286,22 +180,13 @@
|
|||
showDrag: true,
|
||||
columnSelectorDisabled: true,
|
||||
},
|
||||
{
|
||||
title: 'report.type',
|
||||
slotName: 'integrated',
|
||||
dataIndex: 'integrated',
|
||||
titleSlotName: 'integratedFilter',
|
||||
width: 150,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'report.execStatus',
|
||||
dataIndex: 'execStatus',
|
||||
slotName: 'execStatus',
|
||||
titleSlotName: 'execStatusFilter',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
sorter: true,
|
||||
filterConfig: {
|
||||
options: executeResultOptions.value,
|
||||
filterSlotName: FilterSlotNameEnum.TEST_PLAN_REPORT_EXEC_STATUS,
|
||||
},
|
||||
showInTable: true,
|
||||
width: 200,
|
||||
|
@ -310,13 +195,17 @@
|
|||
|
||||
{
|
||||
title: 'report.result',
|
||||
dataIndex: 'status',
|
||||
slotName: 'status',
|
||||
dataIndex: 'resultStatus',
|
||||
slotName: 'resultStatus',
|
||||
titleSlotName: 'statusFilter',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
sorter: true,
|
||||
},
|
||||
filterConfig: {
|
||||
options: statusResultOptions.value,
|
||||
filterSlotName: FilterSlotNameEnum.TEST_PLAN_STATUS_FILTER,
|
||||
},
|
||||
showInTable: true,
|
||||
width: 200,
|
||||
showDrag: true,
|
||||
|
@ -333,13 +222,11 @@
|
|||
dataIndex: 'triggerMode',
|
||||
slotName: 'triggerMode',
|
||||
showInTable: true,
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
sorter: true,
|
||||
},
|
||||
width: 150,
|
||||
showDrag: true,
|
||||
titleSlotName: 'triggerModeFilter',
|
||||
filterConfig: {
|
||||
options: triggerModeOptions.value,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'report.operator',
|
||||
|
@ -400,72 +287,12 @@
|
|||
}),
|
||||
rename
|
||||
);
|
||||
// 全部过滤条件
|
||||
const allListFilters = ref<string[]>([]);
|
||||
const independentListFilters = ref<string[]>([]);
|
||||
const integratedListFilters = ref<string[]>([]);
|
||||
|
||||
const statusListFiltersMap = ref<Record<string, string[]>>({
|
||||
All: allListFilters.value,
|
||||
INDEPENDENT: independentListFilters.value,
|
||||
INTEGRATED: integratedListFilters.value,
|
||||
});
|
||||
|
||||
const allTriggerModeFilters = ref<string[]>([]);
|
||||
const independentTriggerModeFilters = ref<string[]>([]);
|
||||
const integratedTriggerModeFilters = ref<string[]>([]);
|
||||
const triggerModeListFiltersMaps = ref<Record<string, string[]>>({
|
||||
All: allTriggerModeFilters.value,
|
||||
INDEPENDENT: independentTriggerModeFilters.value,
|
||||
INTEGRATED: integratedTriggerModeFilters.value,
|
||||
});
|
||||
// 全部过滤条件
|
||||
const allIntegratedFilters = ref<string[]>([]);
|
||||
const independentIntegratedFilters = ref<string[]>([]);
|
||||
const integratedIntegratedFilters = ref<string[]>([]);
|
||||
|
||||
const reportTypeVisible = ref<boolean>(false);
|
||||
|
||||
const integratedFiltersMap = ref<Record<string, string[]>>({
|
||||
All: allIntegratedFilters.value,
|
||||
INDEPENDENT: independentIntegratedFilters.value,
|
||||
INTEGRATED: integratedIntegratedFilters.value,
|
||||
});
|
||||
|
||||
const reportTypeList = ref([
|
||||
{
|
||||
value: 'INDEPENDENT',
|
||||
label: t('report.independent'),
|
||||
},
|
||||
{
|
||||
value: 'INTEGRATED',
|
||||
label: t('report.collection'),
|
||||
},
|
||||
]);
|
||||
|
||||
const integratedFilters = computed(() => {
|
||||
if (showType.value === 'All') {
|
||||
if (integratedFiltersMap.value[showType.value].length === 1) {
|
||||
return integratedFiltersMap.value[showType.value].includes('INDEPENDENT') ? [false] : [true];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
if (showType.value === 'INTEGRATED') {
|
||||
return [true];
|
||||
}
|
||||
return [false];
|
||||
});
|
||||
|
||||
function initData() {
|
||||
setLoadListParams({
|
||||
keyword: keyword.value,
|
||||
projectId: appStore.currentProjectId,
|
||||
|
||||
filter: {
|
||||
status: statusListFiltersMap.value[showType.value],
|
||||
integrated: integratedFilters.value,
|
||||
triggerMode: triggerModeListFiltersMaps.value[showType.value],
|
||||
},
|
||||
filter: { ...propsRes.value.filter, integrated: integratedFilters.value },
|
||||
});
|
||||
loadList();
|
||||
}
|
||||
|
@ -493,11 +320,7 @@
|
|||
...params,
|
||||
selectIds: params?.selectedIds || [],
|
||||
condition: {
|
||||
filter: {
|
||||
status: statusListFiltersMap.value[showType.value],
|
||||
integrated: integratedFilters.value,
|
||||
triggerMode: triggerModeListFilters.value,
|
||||
},
|
||||
filter: { ...propsRes.value.filter, integrated: integratedFilters.value },
|
||||
keyword: keyword.value,
|
||||
},
|
||||
projectId: appStore.currentProjectId,
|
||||
|
@ -561,51 +384,13 @@
|
|||
initData();
|
||||
});
|
||||
|
||||
const statusFilters = computed(() => {
|
||||
return Object.keys(PlanReportStatus[ReportStatusEnum.REPORT_STATUS]) || [];
|
||||
});
|
||||
|
||||
const execStatusFilters = computed(() => {
|
||||
return Object.keys(PlanReportStatus[ReportStatusEnum.EXEC_STATUS]) || [];
|
||||
});
|
||||
|
||||
function handleFilterHidden(val: boolean) {
|
||||
if (!val) {
|
||||
triggerModeFilterVisible.value = false;
|
||||
statusFilterVisible.value = false;
|
||||
initData();
|
||||
}
|
||||
}
|
||||
|
||||
function handleExecStatusFilterHidden(val: boolean) {
|
||||
if (!val) {
|
||||
triggerModeFilterVisible.value = false;
|
||||
execStatusFilterVisible.value = false;
|
||||
initData();
|
||||
}
|
||||
}
|
||||
|
||||
function resetTriggerModeFilter() {
|
||||
triggerModeFilterVisible.value = false;
|
||||
triggerModeListFilters.value = [];
|
||||
initData();
|
||||
}
|
||||
|
||||
function resetStatusFilter() {
|
||||
statusFilterVisible.value = false;
|
||||
statusListFiltersMap.value[showType.value] = [];
|
||||
initData();
|
||||
}
|
||||
|
||||
function resetExecStatusFilter() {
|
||||
execStatusFilterVisible.value = false;
|
||||
statusListFiltersMap.value[showType.value] = [];
|
||||
initData();
|
||||
}
|
||||
|
||||
function changeShowType(val: string | number | boolean) {
|
||||
showType.value = val as ReportShowType;
|
||||
resetSelector();
|
||||
console.log(propsRes.value);
|
||||
propsRes.value.filter = {
|
||||
integrated: integratedFilters.value,
|
||||
};
|
||||
initData();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,13 +32,8 @@
|
|||
icon: 'icon-icon_close_colorful',
|
||||
label: 'report.failure',
|
||||
},
|
||||
FAKE_ERROR: {
|
||||
icon: 'icon-icon_warning_colorful',
|
||||
label: 'report.fake.error',
|
||||
},
|
||||
DEFAULT: {
|
||||
icon: 'icon-icon_block_filled',
|
||||
label: 'report.status.pending',
|
||||
label: '-',
|
||||
color: '!text-[var(--color-text-input-border)]',
|
||||
},
|
||||
},
|
||||
|
@ -58,9 +53,9 @@
|
|||
label: 'report.status.pending',
|
||||
color: '!text-[var(--color-text-input-border)]',
|
||||
},
|
||||
DEFAULT: {
|
||||
COMPLETED: {
|
||||
icon: 'icon-icon_wait',
|
||||
label: 'report.status.pending',
|
||||
label: 'report.completed',
|
||||
color: '!text-[var(--color-text-input-border)]',
|
||||
},
|
||||
},
|
||||
|
|
|
@ -31,4 +31,5 @@ export default {
|
|||
'report.execStatus': 'Execution status',
|
||||
'report.plan.name': 'Plan Name',
|
||||
'report.passRate': 'Pass rate',
|
||||
'report.completed': 'Completed',
|
||||
};
|
||||
|
|
|
@ -31,5 +31,6 @@ export default {
|
|||
'report.execStatus': '执行状态',
|
||||
'report.plan.name': '计划名称',
|
||||
'report.passRate': '通过率',
|
||||
'report.passRateTip': 'TODO待补充文案',
|
||||
'report.passRateTip': '测试计划报告通过率',
|
||||
'report.completed': '已完成',
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue