diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlan.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlan.java index 8c2d36df0b..08bd4a9219 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlan.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlan.java @@ -8,68 +8,167 @@ import jakarta.validation.constraints.Size; import lombok.Data; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; @Data public class TestPlan implements Serializable { - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan.id.not_blank}", groups = {Updated.class}) @Size(min = 1, max = 50, message = "{test_plan.id.length_range}", groups = {Created.class, Updated.class}) private String id; - @Schema(description = "测试计划所属项目", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "num") + private Long num; + + @Schema(description = "测试计划所属项目", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan.project_id.not_blank}", groups = {Created.class}) @Size(min = 1, max = 50, message = "{test_plan.project_id.length_range}", groups = {Created.class, Updated.class}) private String projectId; - @Schema(description = "测试计划父ID;测试计划要改为树结构。最上层的为root,其余则是父节点ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan.parent_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{test_plan.parent_id.length_range}", groups = {Created.class, Updated.class}) - private String parentId; + @Schema(description = "测试计划组ID;默认为none.只关联type为group的测试计划", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.group_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{test_plan.group_id.length_range}", groups = {Created.class, Updated.class}) + private String groupId; - @Schema(description = "测试计划名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "测试计划模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.module_id.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 50, message = "{test_plan.module_id.length_range}", groups = {Created.class, Updated.class}) + private String moduleId; + + @Schema(description = "测试计划名称", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan.name.not_blank}", groups = {Created.class}) @Size(min = 1, max = 255, message = "{test_plan.name.length_range}", groups = {Created.class, Updated.class}) private String name; - @Schema(description = "测试计划状态;进行中/未开始/已完成/已结束/已归档", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "测试计划状态;未开始,进行中,已完成,已归档", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "{test_plan.status.not_blank}", groups = {Created.class}) @Size(min = 1, max = 20, message = "{test_plan.status.length_range}", groups = {Created.class, Updated.class}) private String status; - @Schema(description = "测试阶段", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan.stage.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 30, message = "{test_plan.stage.length_range}", groups = {Created.class, Updated.class}) - private String stage; + @Schema(description = "数据类型;测试计划组(group)/测试计划(testPlan)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.type.not_blank}", groups = {Created.class}) + @Size(min = 1, max = 30, message = "{test_plan.type.length_range}", groups = {Created.class, Updated.class}) + private String type; - @Schema(description = "标签") - private String tags; + @Schema(description = "标签") + private List tags; - @Schema(description = "创建时间") + @Schema(description = "创建时间") private Long createTime; - @Schema(description = "创建人") + @Schema(description = "创建人") private String createUser; - @Schema(description = "更新时间") + @Schema(description = "更新时间") private Long updateTime; - @Schema(description = "更新人") + @Schema(description = "更新人") private String updateUser; - @Schema(description = "计划开始时间") + @Schema(description = "计划开始时间") private Long plannedStartTime; - @Schema(description = "计划结束时间") + @Schema(description = "计划结束时间") private Long plannedEndTime; - @Schema(description = "实际开始时间") + @Schema(description = "实际开始时间") private Long actualStartTime; - @Schema(description = "实际结束时间") + @Schema(description = "实际结束时间") private Long actualEndTime; - @Schema(description = "描述") + @Schema(description = "描述;描述") private String description; private static final long serialVersionUID = 1L; + + public enum Column { + id("id", "id", "VARCHAR", false), + num("num", "num", "BIGINT", false), + projectId("project_id", "projectId", "VARCHAR", false), + groupId("group_id", "groupId", "VARCHAR", false), + moduleId("module_id", "moduleId", "VARCHAR", false), + name("name", "name", "VARCHAR", true), + status("status", "status", "VARCHAR", true), + type("type", "type", "VARCHAR", true), + tags("tags", "tags", "VARCHAR", false), + createTime("create_time", "createTime", "BIGINT", false), + createUser("create_user", "createUser", "VARCHAR", false), + updateTime("update_time", "updateTime", "BIGINT", false), + updateUser("update_user", "updateUser", "VARCHAR", false), + plannedStartTime("planned_start_time", "plannedStartTime", "BIGINT", false), + plannedEndTime("planned_end_time", "plannedEndTime", "BIGINT", false), + actualStartTime("actual_start_time", "actualStartTime", "BIGINT", false), + actualEndTime("actual_end_time", "actualEndTime", "BIGINT", false), + description("description", "description", "VARCHAR", false); + + private static final String BEGINNING_DELIMITER = "`"; + + private static final String ENDING_DELIMITER = "`"; + + private final String column; + + private final boolean isColumnNameDelimited; + + private final String javaProperty; + + private final String jdbcType; + + public String value() { + return this.column; + } + + public String getValue() { + return this.column; + } + + public String getJavaProperty() { + return this.javaProperty; + } + + public String getJdbcType() { + return this.jdbcType; + } + + Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) { + this.column = column; + this.javaProperty = javaProperty; + this.jdbcType = jdbcType; + this.isColumnNameDelimited = isColumnNameDelimited; + } + + public String desc() { + return this.getEscapedColumnName() + " DESC"; + } + + public String asc() { + return this.getEscapedColumnName() + " ASC"; + } + + public static Column[] excludes(Column ... excludes) { + ArrayList columns = new ArrayList<>(Arrays.asList(Column.values())); + if (excludes != null && excludes.length > 0) { + columns.removeAll(new ArrayList<>(Arrays.asList(excludes))); + } + return columns.toArray(new Column[]{}); + } + + public static Column[] all() { + return Column.values(); + } + + public String getEscapedColumnName() { + if (this.isColumnNameDelimited) { + return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString(); + } else { + return this.column; + } + } + + public String getAliasedEscapedColumnName() { + return this.getEscapedColumnName(); + } + } } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfig.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfig.java index 312a4d1bad..b9f0f90262 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfig.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfig.java @@ -1,38 +1,109 @@ 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.NotNull; -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 TestPlanConfig implements Serializable { - @Schema(description = "测试计划ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_config.test_plan_id.not_blank}", groups = {Updated.class}) + @Schema(description = "测试计划ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan_config.test_plan_id.not_blank}", groups = {Created.class}) @Size(min = 1, max = 50, message = "{test_plan_config.test_plan_id.length_range}", groups = {Created.class, Updated.class}) private String testPlanId; - @Schema(description = "是否自定更新功能用例状态", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_config.automatic_status_update.not_blank}", groups = {Created.class}) + @Schema(description = "是否自定更新功能用例状态", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "{test_plan_config.automatic_status_update.not_blank}", groups = {Created.class}) private Boolean automaticStatusUpdate; - @Schema(description = "是否允许重复添加用例", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_config.repeat_case.not_blank}", groups = {Created.class}) + @Schema(description = "是否允许重复添加用例", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "{test_plan_config.repeat_case.not_blank}", groups = {Created.class}) private Boolean repeatCase; - @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "{test_plan_config.pass_threshold.not_blank}", groups = {Created.class}) - private Integer passThreshold; + private Double passThreshold; - @Schema(description = "运行模式", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_config.run_mode_config.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 65535, message = "{test_plan_config.run_mode_config.length_range}", groups = {Created.class, Updated.class}) + @Schema(description = "运行模式") private String runModeConfig; private static final long serialVersionUID = 1L; + + public enum Column { + testPlanId("test_plan_id", "testPlanId", "VARCHAR", false), + automaticStatusUpdate("automatic_status_update", "automaticStatusUpdate", "BIT", false), + repeatCase("repeat_case", "repeatCase", "BIT", false), + passThreshold("pass_threshold", "passThreshold", "DOUBLE", false), + runModeConfig("run_mode_config", "runModeConfig", "LONGVARCHAR", false); + + private static final String BEGINNING_DELIMITER = "`"; + + private static final String ENDING_DELIMITER = "`"; + + private final String column; + + private final boolean isColumnNameDelimited; + + private final String javaProperty; + + private final String jdbcType; + + public String value() { + return this.column; + } + + public String getValue() { + return this.column; + } + + public String getJavaProperty() { + return this.javaProperty; + } + + public String getJdbcType() { + return this.jdbcType; + } + + Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) { + this.column = column; + this.javaProperty = javaProperty; + this.jdbcType = jdbcType; + this.isColumnNameDelimited = isColumnNameDelimited; + } + + public String desc() { + return this.getEscapedColumnName() + " DESC"; + } + + public String asc() { + return this.getEscapedColumnName() + " ASC"; + } + + public static Column[] excludes(Column ... excludes) { + ArrayList columns = new ArrayList<>(Arrays.asList(Column.values())); + if (excludes != null && excludes.length > 0) { + columns.removeAll(new ArrayList<>(Arrays.asList(excludes))); + } + return columns.toArray(new Column[]{}); + } + + public static Column[] all() { + return Column.values(); + } + + public String getEscapedColumnName() { + if (this.isColumnNameDelimited) { + return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString(); + } else { + return this.column; + } + } + + public String getAliasedEscapedColumnName() { + return this.getEscapedColumnName(); + } + } } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfigExample.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfigExample.java index 5f88051b69..374e906d60 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfigExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanConfigExample.java @@ -304,52 +304,52 @@ public class TestPlanConfigExample { return (Criteria) this; } - public Criteria andPassThresholdEqualTo(Integer value) { + public Criteria andPassThresholdEqualTo(Double value) { addCriterion("pass_threshold =", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdNotEqualTo(Integer value) { + public Criteria andPassThresholdNotEqualTo(Double value) { addCriterion("pass_threshold <>", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdGreaterThan(Integer value) { + public Criteria andPassThresholdGreaterThan(Double value) { addCriterion("pass_threshold >", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdGreaterThanOrEqualTo(Integer value) { + public Criteria andPassThresholdGreaterThanOrEqualTo(Double value) { addCriterion("pass_threshold >=", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdLessThan(Integer value) { + public Criteria andPassThresholdLessThan(Double value) { addCriterion("pass_threshold <", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdLessThanOrEqualTo(Integer value) { + public Criteria andPassThresholdLessThanOrEqualTo(Double value) { addCriterion("pass_threshold <=", value, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdIn(List values) { + public Criteria andPassThresholdIn(List values) { addCriterion("pass_threshold in", values, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdNotIn(List values) { + public Criteria andPassThresholdNotIn(List values) { addCriterion("pass_threshold not in", values, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdBetween(Integer value1, Integer value2) { + public Criteria andPassThresholdBetween(Double value1, Double value2) { addCriterion("pass_threshold between", value1, value2, "passThreshold"); return (Criteria) this; } - public Criteria andPassThresholdNotBetween(Integer value1, Integer value2) { + public Criteria andPassThresholdNotBetween(Double value1, Double value2) { addCriterion("pass_threshold not between", value1, value2, "passThreshold"); return (Criteria) this; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanExample.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanExample.java index 5f1b1bc9b7..41cfa4d4ea 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanExample.java @@ -64,19 +64,50 @@ public class TestPlanExample { } protected abstract static class GeneratedCriteria { + protected List tagsCriteria; + + protected List allCriteria; + protected List criteria; protected GeneratedCriteria() { super(); criteria = new ArrayList(); + tagsCriteria = new ArrayList(); + } + + public List getTagsCriteria() { + return tagsCriteria; + } + + protected void addTagsCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + tagsCriteria.add(new Criterion(condition, value, "io.metersphere.handler.ListTypeHandler")); + allCriteria = null; + } + + protected void addTagsCriterion(String condition, List value1, List value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + tagsCriteria.add(new Criterion(condition, value1, value2, "io.metersphere.handler.ListTypeHandler")); + allCriteria = null; } public boolean isValid() { - return criteria.size() > 0; + return criteria.size() > 0 + || tagsCriteria.size() > 0; } public List getAllCriteria() { - return criteria; + if (allCriteria == null) { + allCriteria = new ArrayList(); + allCriteria.addAll(criteria); + allCriteria.addAll(tagsCriteria); + } + return allCriteria; } public List getCriteria() { @@ -88,6 +119,7 @@ public class TestPlanExample { throw new RuntimeException("Value for condition cannot be null"); } criteria.add(new Criterion(condition)); + allCriteria = null; } protected void addCriterion(String condition, Object value, String property) { @@ -95,6 +127,7 @@ public class TestPlanExample { throw new RuntimeException("Value for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value)); + allCriteria = null; } protected void addCriterion(String condition, Object value1, Object value2, String property) { @@ -102,6 +135,7 @@ public class TestPlanExample { throw new RuntimeException("Between values for " + property + " cannot be null"); } criteria.add(new Criterion(condition, value1, value2)); + allCriteria = null; } public Criteria andIdIsNull() { @@ -174,6 +208,66 @@ public class TestPlanExample { return (Criteria) this; } + public Criteria andNumIsNull() { + addCriterion("num is null"); + return (Criteria) this; + } + + public Criteria andNumIsNotNull() { + addCriterion("num is not null"); + return (Criteria) this; + } + + public Criteria andNumEqualTo(Long value) { + addCriterion("num =", value, "num"); + return (Criteria) this; + } + + public Criteria andNumNotEqualTo(Long value) { + addCriterion("num <>", value, "num"); + return (Criteria) this; + } + + public Criteria andNumGreaterThan(Long value) { + addCriterion("num >", value, "num"); + return (Criteria) this; + } + + public Criteria andNumGreaterThanOrEqualTo(Long value) { + addCriterion("num >=", value, "num"); + return (Criteria) this; + } + + public Criteria andNumLessThan(Long value) { + addCriterion("num <", value, "num"); + return (Criteria) this; + } + + public Criteria andNumLessThanOrEqualTo(Long value) { + addCriterion("num <=", value, "num"); + return (Criteria) this; + } + + public Criteria andNumIn(List values) { + addCriterion("num in", values, "num"); + return (Criteria) this; + } + + public Criteria andNumNotIn(List values) { + addCriterion("num not in", values, "num"); + return (Criteria) this; + } + + public Criteria andNumBetween(Long value1, Long value2) { + addCriterion("num between", value1, value2, "num"); + return (Criteria) this; + } + + public Criteria andNumNotBetween(Long value1, Long value2) { + addCriterion("num not between", value1, value2, "num"); + return (Criteria) this; + } + public Criteria andProjectIdIsNull() { addCriterion("project_id is null"); return (Criteria) this; @@ -244,73 +338,143 @@ public class TestPlanExample { return (Criteria) this; } - public Criteria andParentIdIsNull() { - addCriterion("parent_id is null"); + public Criteria andGroupIdIsNull() { + addCriterion("group_id is null"); return (Criteria) this; } - public Criteria andParentIdIsNotNull() { - addCriterion("parent_id is not null"); + public Criteria andGroupIdIsNotNull() { + addCriterion("group_id is not null"); return (Criteria) this; } - public Criteria andParentIdEqualTo(String value) { - addCriterion("parent_id =", value, "parentId"); + public Criteria andGroupIdEqualTo(String value) { + addCriterion("group_id =", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdNotEqualTo(String value) { - addCriterion("parent_id <>", value, "parentId"); + public Criteria andGroupIdNotEqualTo(String value) { + addCriterion("group_id <>", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdGreaterThan(String value) { - addCriterion("parent_id >", value, "parentId"); + public Criteria andGroupIdGreaterThan(String value) { + addCriterion("group_id >", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdGreaterThanOrEqualTo(String value) { - addCriterion("parent_id >=", value, "parentId"); + public Criteria andGroupIdGreaterThanOrEqualTo(String value) { + addCriterion("group_id >=", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdLessThan(String value) { - addCriterion("parent_id <", value, "parentId"); + public Criteria andGroupIdLessThan(String value) { + addCriterion("group_id <", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdLessThanOrEqualTo(String value) { - addCriterion("parent_id <=", value, "parentId"); + public Criteria andGroupIdLessThanOrEqualTo(String value) { + addCriterion("group_id <=", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdLike(String value) { - addCriterion("parent_id like", value, "parentId"); + public Criteria andGroupIdLike(String value) { + addCriterion("group_id like", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdNotLike(String value) { - addCriterion("parent_id not like", value, "parentId"); + public Criteria andGroupIdNotLike(String value) { + addCriterion("group_id not like", value, "groupId"); return (Criteria) this; } - public Criteria andParentIdIn(List values) { - addCriterion("parent_id in", values, "parentId"); + public Criteria andGroupIdIn(List values) { + addCriterion("group_id in", values, "groupId"); return (Criteria) this; } - public Criteria andParentIdNotIn(List values) { - addCriterion("parent_id not in", values, "parentId"); + public Criteria andGroupIdNotIn(List values) { + addCriterion("group_id not in", values, "groupId"); return (Criteria) this; } - public Criteria andParentIdBetween(String value1, String value2) { - addCriterion("parent_id between", value1, value2, "parentId"); + public Criteria andGroupIdBetween(String value1, String value2) { + addCriterion("group_id between", value1, value2, "groupId"); return (Criteria) this; } - public Criteria andParentIdNotBetween(String value1, String value2) { - addCriterion("parent_id not between", value1, value2, "parentId"); + public Criteria andGroupIdNotBetween(String value1, String value2) { + addCriterion("group_id not between", value1, value2, "groupId"); + return (Criteria) this; + } + + public Criteria andModuleIdIsNull() { + addCriterion("module_id is null"); + return (Criteria) this; + } + + public Criteria andModuleIdIsNotNull() { + addCriterion("module_id is not null"); + return (Criteria) this; + } + + public Criteria andModuleIdEqualTo(String value) { + addCriterion("module_id =", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdNotEqualTo(String value) { + addCriterion("module_id <>", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdGreaterThan(String value) { + addCriterion("module_id >", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdGreaterThanOrEqualTo(String value) { + addCriterion("module_id >=", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdLessThan(String value) { + addCriterion("module_id <", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdLessThanOrEqualTo(String value) { + addCriterion("module_id <=", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdLike(String value) { + addCriterion("module_id like", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdNotLike(String value) { + addCriterion("module_id not like", value, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdIn(List values) { + addCriterion("module_id in", values, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdNotIn(List values) { + addCriterion("module_id not in", values, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdBetween(String value1, String value2) { + addCriterion("module_id between", value1, value2, "moduleId"); + return (Criteria) this; + } + + public Criteria andModuleIdNotBetween(String value1, String value2) { + addCriterion("module_id not between", value1, value2, "moduleId"); return (Criteria) this; } @@ -454,73 +618,73 @@ public class TestPlanExample { return (Criteria) this; } - public Criteria andStageIsNull() { - addCriterion("stage is null"); + public Criteria andTypeIsNull() { + addCriterion("`type` is null"); return (Criteria) this; } - public Criteria andStageIsNotNull() { - addCriterion("stage is not null"); + public Criteria andTypeIsNotNull() { + addCriterion("`type` is not null"); return (Criteria) this; } - public Criteria andStageEqualTo(String value) { - addCriterion("stage =", value, "stage"); + public Criteria andTypeEqualTo(String value) { + addCriterion("`type` =", value, "type"); return (Criteria) this; } - public Criteria andStageNotEqualTo(String value) { - addCriterion("stage <>", value, "stage"); + public Criteria andTypeNotEqualTo(String value) { + addCriterion("`type` <>", value, "type"); return (Criteria) this; } - public Criteria andStageGreaterThan(String value) { - addCriterion("stage >", value, "stage"); + public Criteria andTypeGreaterThan(String value) { + addCriterion("`type` >", value, "type"); return (Criteria) this; } - public Criteria andStageGreaterThanOrEqualTo(String value) { - addCriterion("stage >=", value, "stage"); + public Criteria andTypeGreaterThanOrEqualTo(String value) { + addCriterion("`type` >=", value, "type"); return (Criteria) this; } - public Criteria andStageLessThan(String value) { - addCriterion("stage <", value, "stage"); + public Criteria andTypeLessThan(String value) { + addCriterion("`type` <", value, "type"); return (Criteria) this; } - public Criteria andStageLessThanOrEqualTo(String value) { - addCriterion("stage <=", value, "stage"); + public Criteria andTypeLessThanOrEqualTo(String value) { + addCriterion("`type` <=", value, "type"); return (Criteria) this; } - public Criteria andStageLike(String value) { - addCriterion("stage like", value, "stage"); + public Criteria andTypeLike(String value) { + addCriterion("`type` like", value, "type"); return (Criteria) this; } - public Criteria andStageNotLike(String value) { - addCriterion("stage not like", value, "stage"); + public Criteria andTypeNotLike(String value) { + addCriterion("`type` not like", value, "type"); return (Criteria) this; } - public Criteria andStageIn(List values) { - addCriterion("stage in", values, "stage"); + public Criteria andTypeIn(List values) { + addCriterion("`type` in", values, "type"); return (Criteria) this; } - public Criteria andStageNotIn(List values) { - addCriterion("stage not in", values, "stage"); + public Criteria andTypeNotIn(List values) { + addCriterion("`type` not in", values, "type"); return (Criteria) this; } - public Criteria andStageBetween(String value1, String value2) { - addCriterion("stage between", value1, value2, "stage"); + public Criteria andTypeBetween(String value1, String value2) { + addCriterion("`type` between", value1, value2, "type"); return (Criteria) this; } - public Criteria andStageNotBetween(String value1, String value2) { - addCriterion("stage not between", value1, value2, "stage"); + public Criteria andTypeNotBetween(String value1, String value2) { + addCriterion("`type` not between", value1, value2, "type"); return (Criteria) this; } @@ -534,63 +698,63 @@ public class TestPlanExample { return (Criteria) this; } - public Criteria andTagsEqualTo(String value) { - addCriterion("tags =", value, "tags"); + public Criteria andTagsEqualTo(List value) { + addTagsCriterion("tags =", value, "tags"); return (Criteria) this; } - public Criteria andTagsNotEqualTo(String value) { - addCriterion("tags <>", value, "tags"); + public Criteria andTagsNotEqualTo(List value) { + addTagsCriterion("tags <>", value, "tags"); return (Criteria) this; } - public Criteria andTagsGreaterThan(String value) { - addCriterion("tags >", value, "tags"); + public Criteria andTagsGreaterThan(List value) { + addTagsCriterion("tags >", value, "tags"); return (Criteria) this; } - public Criteria andTagsGreaterThanOrEqualTo(String value) { - addCriterion("tags >=", value, "tags"); + public Criteria andTagsGreaterThanOrEqualTo(List value) { + addTagsCriterion("tags >=", value, "tags"); return (Criteria) this; } - public Criteria andTagsLessThan(String value) { - addCriterion("tags <", value, "tags"); + public Criteria andTagsLessThan(List value) { + addTagsCriterion("tags <", value, "tags"); return (Criteria) this; } - public Criteria andTagsLessThanOrEqualTo(String value) { - addCriterion("tags <=", value, "tags"); + public Criteria andTagsLessThanOrEqualTo(List value) { + addTagsCriterion("tags <=", value, "tags"); return (Criteria) this; } - public Criteria andTagsLike(String value) { - addCriterion("tags like", value, "tags"); + public Criteria andTagsLike(List value) { + addTagsCriterion("tags like", value, "tags"); return (Criteria) this; } - public Criteria andTagsNotLike(String value) { - addCriterion("tags not like", value, "tags"); + public Criteria andTagsNotLike(List value) { + addTagsCriterion("tags not like", value, "tags"); return (Criteria) this; } - public Criteria andTagsIn(List values) { - addCriterion("tags in", values, "tags"); + public Criteria andTagsIn(List> values) { + addTagsCriterion("tags in", values, "tags"); return (Criteria) this; } - public Criteria andTagsNotIn(List values) { - addCriterion("tags not in", values, "tags"); + public Criteria andTagsNotIn(List> values) { + addTagsCriterion("tags not in", values, "tags"); return (Criteria) this; } - public Criteria andTagsBetween(String value1, String value2) { - addCriterion("tags between", value1, value2, "tags"); + public Criteria andTagsBetween(List value1, List value2) { + addTagsCriterion("tags between", value1, value2, "tags"); return (Criteria) this; } - public Criteria andTagsNotBetween(String value1, String value2) { - addCriterion("tags not between", value1, value2, "tags"); + public Criteria andTagsNotBetween(List value1, List value2) { + addTagsCriterion("tags not between", value1, value2, "tags"); return (Criteria) this; } diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipal.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipal.java deleted file mode 100644 index 93a370529d..0000000000 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipal.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.metersphere.plan.domain; - -import io.metersphere.validation.groups.Created; -import io.metersphere.validation.groups.Updated; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; -import java.io.Serializable; -import lombok.Data; - -@Data -public class TestPlanPrincipal implements Serializable { - @Schema(description = "测试计划ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_principal.test_plan_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{test_plan_principal.test_plan_id.length_range}", groups = {Created.class, Updated.class}) - private String testPlanId; - - @Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotBlank(message = "{test_plan_principal.user_id.not_blank}", groups = {Created.class}) - @Size(min = 1, max = 50, message = "{test_plan_principal.user_id.length_range}", groups = {Created.class, Updated.class}) - private String userId; - - private static final long serialVersionUID = 1L; -} \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipalExample.java b/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipalExample.java deleted file mode 100644 index 4dd2b6ee8a..0000000000 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/domain/TestPlanPrincipalExample.java +++ /dev/null @@ -1,340 +0,0 @@ -package io.metersphere.plan.domain; - -import java.util.ArrayList; -import java.util.List; - -public class TestPlanPrincipalExample { - protected String orderByClause; - - protected boolean distinct; - - protected List oredCriteria; - - public TestPlanPrincipalExample() { - oredCriteria = new ArrayList(); - } - - public void setOrderByClause(String orderByClause) { - this.orderByClause = orderByClause; - } - - public String getOrderByClause() { - return orderByClause; - } - - public void setDistinct(boolean distinct) { - this.distinct = distinct; - } - - public boolean isDistinct() { - return distinct; - } - - public List getOredCriteria() { - return oredCriteria; - } - - public void or(Criteria criteria) { - oredCriteria.add(criteria); - } - - public Criteria or() { - Criteria criteria = createCriteriaInternal(); - oredCriteria.add(criteria); - return criteria; - } - - public Criteria createCriteria() { - Criteria criteria = createCriteriaInternal(); - if (oredCriteria.size() == 0) { - oredCriteria.add(criteria); - } - return criteria; - } - - protected Criteria createCriteriaInternal() { - Criteria criteria = new Criteria(); - return criteria; - } - - public void clear() { - oredCriteria.clear(); - orderByClause = null; - distinct = false; - } - - protected abstract static class GeneratedCriteria { - protected List criteria; - - protected GeneratedCriteria() { - super(); - criteria = new ArrayList(); - } - - public boolean isValid() { - return criteria.size() > 0; - } - - public List getAllCriteria() { - return criteria; - } - - public List getCriteria() { - return criteria; - } - - protected void addCriterion(String condition) { - if (condition == null) { - throw new RuntimeException("Value for condition cannot be null"); - } - criteria.add(new Criterion(condition)); - } - - protected void addCriterion(String condition, Object value, String property) { - if (value == null) { - throw new RuntimeException("Value for " + property + " cannot be null"); - } - criteria.add(new Criterion(condition, value)); - } - - protected void addCriterion(String condition, Object value1, Object value2, String property) { - if (value1 == null || value2 == null) { - throw new RuntimeException("Between values for " + property + " cannot be null"); - } - criteria.add(new Criterion(condition, value1, value2)); - } - - public Criteria andTestPlanIdIsNull() { - addCriterion("test_plan_id is null"); - return (Criteria) this; - } - - public Criteria andTestPlanIdIsNotNull() { - addCriterion("test_plan_id is not null"); - return (Criteria) this; - } - - public Criteria andTestPlanIdEqualTo(String value) { - addCriterion("test_plan_id =", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdNotEqualTo(String value) { - addCriterion("test_plan_id <>", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdGreaterThan(String value) { - addCriterion("test_plan_id >", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdGreaterThanOrEqualTo(String value) { - addCriterion("test_plan_id >=", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdLessThan(String value) { - addCriterion("test_plan_id <", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdLessThanOrEqualTo(String value) { - addCriterion("test_plan_id <=", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdLike(String value) { - addCriterion("test_plan_id like", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdNotLike(String value) { - addCriterion("test_plan_id not like", value, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdIn(List values) { - addCriterion("test_plan_id in", values, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdNotIn(List values) { - addCriterion("test_plan_id not in", values, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdBetween(String value1, String value2) { - addCriterion("test_plan_id between", value1, value2, "testPlanId"); - return (Criteria) this; - } - - public Criteria andTestPlanIdNotBetween(String value1, String value2) { - addCriterion("test_plan_id not between", value1, value2, "testPlanId"); - return (Criteria) this; - } - - public Criteria andUserIdIsNull() { - addCriterion("user_id is null"); - return (Criteria) this; - } - - public Criteria andUserIdIsNotNull() { - addCriterion("user_id is not null"); - return (Criteria) this; - } - - public Criteria andUserIdEqualTo(String value) { - addCriterion("user_id =", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdNotEqualTo(String value) { - addCriterion("user_id <>", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdGreaterThan(String value) { - addCriterion("user_id >", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdGreaterThanOrEqualTo(String value) { - addCriterion("user_id >=", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdLessThan(String value) { - addCriterion("user_id <", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdLessThanOrEqualTo(String value) { - addCriterion("user_id <=", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdLike(String value) { - addCriterion("user_id like", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdNotLike(String value) { - addCriterion("user_id not like", value, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdIn(List values) { - addCriterion("user_id in", values, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdNotIn(List values) { - addCriterion("user_id not in", values, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdBetween(String value1, String value2) { - addCriterion("user_id between", value1, value2, "userId"); - return (Criteria) this; - } - - public Criteria andUserIdNotBetween(String value1, String value2) { - addCriterion("user_id not between", value1, value2, "userId"); - return (Criteria) this; - } - } - - public static class Criteria extends GeneratedCriteria { - - protected Criteria() { - super(); - } - } - - public static class Criterion { - private String condition; - - private Object value; - - private Object secondValue; - - private boolean noValue; - - private boolean singleValue; - - private boolean betweenValue; - - private boolean listValue; - - private String typeHandler; - - public String getCondition() { - return condition; - } - - public Object getValue() { - return value; - } - - public Object getSecondValue() { - return secondValue; - } - - public boolean isNoValue() { - return noValue; - } - - public boolean isSingleValue() { - return singleValue; - } - - public boolean isBetweenValue() { - return betweenValue; - } - - public boolean isListValue() { - return listValue; - } - - public String getTypeHandler() { - return typeHandler; - } - - protected Criterion(String condition) { - super(); - this.condition = condition; - this.typeHandler = null; - this.noValue = true; - } - - protected Criterion(String condition, Object value, String typeHandler) { - super(); - this.condition = condition; - this.value = value; - this.typeHandler = typeHandler; - if (value instanceof List) { - this.listValue = true; - } else { - this.singleValue = true; - } - } - - protected Criterion(String condition, Object value) { - this(condition, value, null); - } - - protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { - super(); - this.condition = condition; - this.value = value; - this.secondValue = secondValue; - this.typeHandler = typeHandler; - this.betweenValue = true; - } - - protected Criterion(String condition, Object value, Object secondValue) { - this(condition, value, secondValue, null); - } - } -} \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.java b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.java index bf4682d5c7..f2e217bf13 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.java @@ -33,4 +33,8 @@ public interface TestPlanConfigMapper { int updateByPrimaryKeyWithBLOBs(TestPlanConfig record); int updateByPrimaryKey(TestPlanConfig record); + + int batchInsert(@Param("list") List list); + + int batchInsertSelective(@Param("list") List list, @Param("selective") TestPlanConfig.Column ... selective); } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.xml index 99d3b261c7..1dfd0eb81c 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanConfigMapper.xml @@ -5,7 +5,7 @@ - + @@ -126,7 +126,7 @@ insert into test_plan_config (test_plan_id, automatic_status_update, repeat_case, pass_threshold, run_mode_config) values (#{testPlanId,jdbcType=VARCHAR}, #{automaticStatusUpdate,jdbcType=BIT}, #{repeatCase,jdbcType=BIT}, - #{passThreshold,jdbcType=INTEGER}, #{runModeConfig,jdbcType=LONGVARCHAR}) + #{passThreshold,jdbcType=DOUBLE}, #{runModeConfig,jdbcType=LONGVARCHAR}) insert into test_plan_config @@ -158,7 +158,7 @@ #{repeatCase,jdbcType=BIT}, - #{passThreshold,jdbcType=INTEGER}, + #{passThreshold,jdbcType=DOUBLE}, #{runModeConfig,jdbcType=LONGVARCHAR}, @@ -184,7 +184,7 @@ repeat_case = #{record.repeatCase,jdbcType=BIT}, - pass_threshold = #{record.passThreshold,jdbcType=INTEGER}, + pass_threshold = #{record.passThreshold,jdbcType=DOUBLE}, run_mode_config = #{record.runModeConfig,jdbcType=LONGVARCHAR}, @@ -199,7 +199,7 @@ set test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT}, repeat_case = #{record.repeatCase,jdbcType=BIT}, - pass_threshold = #{record.passThreshold,jdbcType=INTEGER}, + pass_threshold = #{record.passThreshold,jdbcType=DOUBLE}, run_mode_config = #{record.runModeConfig,jdbcType=LONGVARCHAR} @@ -210,7 +210,7 @@ set test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT}, repeat_case = #{record.repeatCase,jdbcType=BIT}, - pass_threshold = #{record.passThreshold,jdbcType=INTEGER} + pass_threshold = #{record.passThreshold,jdbcType=DOUBLE} @@ -225,7 +225,7 @@ repeat_case = #{repeatCase,jdbcType=BIT}, - pass_threshold = #{passThreshold,jdbcType=INTEGER}, + pass_threshold = #{passThreshold,jdbcType=DOUBLE}, run_mode_config = #{runModeConfig,jdbcType=LONGVARCHAR}, @@ -237,7 +237,7 @@ update test_plan_config set automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT}, repeat_case = #{repeatCase,jdbcType=BIT}, - pass_threshold = #{passThreshold,jdbcType=INTEGER}, + pass_threshold = #{passThreshold,jdbcType=DOUBLE}, run_mode_config = #{runModeConfig,jdbcType=LONGVARCHAR} where test_plan_id = #{testPlanId,jdbcType=VARCHAR} @@ -245,7 +245,47 @@ update test_plan_config set automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT}, repeat_case = #{repeatCase,jdbcType=BIT}, - pass_threshold = #{passThreshold,jdbcType=INTEGER} + pass_threshold = #{passThreshold,jdbcType=DOUBLE} where test_plan_id = #{testPlanId,jdbcType=VARCHAR} + + insert into test_plan_config + (test_plan_id, automatic_status_update, repeat_case, pass_threshold, run_mode_config + ) + values + + (#{item.testPlanId,jdbcType=VARCHAR}, #{item.automaticStatusUpdate,jdbcType=BIT}, + #{item.repeatCase,jdbcType=BIT}, #{item.passThreshold,jdbcType=DOUBLE}, #{item.runModeConfig,jdbcType=LONGVARCHAR} + ) + + + + insert into test_plan_config ( + + ${column.escapedColumnName} + + ) + values + + ( + + + #{item.testPlanId,jdbcType=VARCHAR} + + + #{item.automaticStatusUpdate,jdbcType=BIT} + + + #{item.repeatCase,jdbcType=BIT} + + + #{item.passThreshold,jdbcType=DOUBLE} + + + #{item.runModeConfig,jdbcType=LONGVARCHAR} + + + ) + + \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.java b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.java index e11acc9957..ea30b8fa2c 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.java +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.java @@ -27,4 +27,8 @@ public interface TestPlanMapper { int updateByPrimaryKeySelective(TestPlan record); int updateByPrimaryKey(TestPlan record); + + int batchInsert(@Param("list") List list); + + int batchInsertSelective(@Param("list") List list, @Param("selective") TestPlan.Column ... selective); } \ No newline at end of file diff --git a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.xml index a121034ab0..e4ea2345a7 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/plan/mapper/TestPlanMapper.xml @@ -3,12 +3,14 @@ + - + + - - + + @@ -43,6 +45,25 @@ + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} + + + and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} and #{criterion.secondValue,typeHandler=io.metersphere.handler.ListTypeHandler} + + + and ${criterion.condition} + + #{listItem,typeHandler=io.metersphere.handler.ListTypeHandler} + + + + @@ -72,14 +93,33 @@ + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} + + + and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} and #{criterion.secondValue,typeHandler=io.metersphere.handler.ListTypeHandler} + + + and ${criterion.condition} + + #{listItem,typeHandler=io.metersphere.handler.ListTypeHandler} + + + + - id, project_id, parent_id, `name`, `status`, stage, tags, create_time, create_user, - update_time, update_user, planned_start_time, planned_end_time, actual_start_time, + id, num, project_id, group_id, module_id, `name`, `status`, `type`, tags, create_time, + create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time, actual_end_time, description - select - - distinct - - - from test_plan_principal - - - - - order by ${orderByClause} - - - - delete from test_plan_principal - where test_plan_id = #{testPlanId,jdbcType=VARCHAR} - and user_id = #{userId,jdbcType=VARCHAR} - - - delete from test_plan_principal - - - - - - insert into test_plan_principal (test_plan_id, user_id) - values (#{testPlanId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}) - - - insert into test_plan_principal - - - test_plan_id, - - - user_id, - - - - - #{testPlanId,jdbcType=VARCHAR}, - - - #{userId,jdbcType=VARCHAR}, - - - - - - update test_plan_principal - - - test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, - - - user_id = #{record.userId,jdbcType=VARCHAR}, - - - - - - - - update test_plan_principal - set test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}, - user_id = #{record.userId,jdbcType=VARCHAR} - - - - - \ No newline at end of file diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql index 1d9aa3d894..dec16c2f2c 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/ddl/V3.0.0_3__test_plan.sql @@ -1,7 +1,7 @@ -- set innodb lock wait timeout SET SESSION innodb_lock_wait_timeout = 7200; -CREATE TABLE test_plan_module +CREATE TABLE IF NOT EXISTS test_plan_module ( `id` VARCHAR(50) NOT NULL COMMENT 'ID', `project_id` VARCHAR(50) NOT NULL COMMENT '项目名称', @@ -24,11 +24,13 @@ CREATE UNIQUE INDEX uq_name_project_parent ON test_plan_module (project_id, name CREATE TABLE IF NOT EXISTS test_plan ( `id` VARCHAR(50) NOT NULL COMMENT 'ID', + `num` BIGINT COMMENT 'num', `project_id` VARCHAR(50) NOT NULL COMMENT '测试计划所属项目', - `parent_id` VARCHAR(50) NOT NULL COMMENT '测试计划父ID;测试计划要改为树结构。最上层的为root,其余则是父节点ID', + `group_id` VARCHAR(50) NOT NULL COMMENT '测试计划组ID;默认为none.只关联type为group的测试计划', + `module_id` VARCHAR(50) NOT NULL COMMENT '测试计划模块ID', `name` VARCHAR(255) NOT NULL COMMENT '测试计划名称', - `status` VARCHAR(20) NOT NULL COMMENT '测试计划状态;进行中/未开始/已完成/已结束/已归档', - `stage` VARCHAR(30) NOT NULL COMMENT '测试阶段', + `status` VARCHAR(20) NOT NULL COMMENT '测试计划状态;未开始,进行中,已完成,已归档', + `type` VARCHAR(30) NOT NULL COMMENT '数据类型;测试计划组(group)/测试计划(testPlan)', `tags` VARCHAR(500) COMMENT '标签', `create_time` BIGINT NOT NULL COMMENT '创建时间', `create_user` VARCHAR(50) NOT NULL COMMENT '创建人', @@ -38,16 +40,28 @@ CREATE TABLE IF NOT EXISTS test_plan `planned_end_time` BIGINT COMMENT '计划结束时间', `actual_start_time` BIGINT COMMENT '实际开始时间', `actual_end_time` BIGINT COMMENT '实际结束时间', - `description` VARCHAR(2000) COMMENT '描述', + `description` VARCHAR(2000) COMMENT '描述', PRIMARY KEY (id) -) ENGINE = InnoDB - DEFAULT CHARSET = utf8mb4 - COLLATE = utf8mb4_general_ci COMMENT = '测试计划'; +) COMMENT = '测试计划'; - -CREATE INDEX idx_parent_id ON test_plan (project_id); +CREATE INDEX idx_group_id ON test_plan (group_id); +CREATE INDEX idx_project_id ON test_plan (project_id); CREATE INDEX idx_create_user ON test_plan (create_user); CREATE INDEX idx_status ON test_plan (status); +CREATE UNIQUE INDEX uq_name_project ON test_plan (project_id, name); +CREATE INDEX idx_module_id ON test_plan (module_id); + + +CREATE TABLE IF NOT EXISTS test_plan_config +( + `test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID', + `run_mode_config` TEXT COMMENT '运行模式', + `automatic_status_update` BIT NOT NULL DEFAULT 0 COMMENT '是否自定更新功能用例状态', + `repeat_case` BIT NOT NULL DEFAULT 0 COMMENT '是否允许重复添加用例', + `pass_threshold` DOUBLE NOT NULL DEFAULT 100 COMMENT '测试计划通过阈值;0-100', + PRIMARY KEY (test_plan_id) +) COMMENT = '测试计划配置'; + -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; \ No newline at end of file diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql index 099cdb9640..7004a7ffad 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql @@ -43,6 +43,8 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'PROJECT_TEST_PLAN_MODULE:READ'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'member', 'PROJECT_TEST_PLAN:READ'); -- 组织管理员权限 INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'org_admin', 'ORGANIZATION_USER_ROLE:READ'); @@ -196,6 +198,14 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN_MODULE:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN_MODULE:READ+DELETE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+ADD'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+UPDATE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+DELETE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+EXECUTE'); -- 项目成员权限 INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_BASE_INFO:READ'); @@ -306,6 +316,14 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN_MODULE:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN_MODULE:READ+DELETE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+ADD'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+UPDATE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+DELETE'); +INSERT INTO user_role_permission (id, role_id, permission_id) +VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+EXECUTE'); -- 初始化当前站点配置 INSERT into system_parameter values('base.url', 'http://127.0.0.1:8081', 'text'); -- 初始化prometheus站点配置 diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/FunctionCaseExecuteStatus.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/FunctionCaseExecuteStatus.java new file mode 100644 index 0000000000..ec992f2d12 --- /dev/null +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/FunctionCaseExecuteStatus.java @@ -0,0 +1,9 @@ +package io.metersphere.sdk.constants; + +/** + * 功能用例执行状态 + */ +public enum FunctionCaseExecuteStatus { + //未开始,成功,失败,阻塞 + PENDING, SUCCESS, ERROR, BLOCK +} diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ModuleConstants.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ModuleConstants.java index 28c66112c3..de4489e906 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ModuleConstants.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ModuleConstants.java @@ -19,4 +19,9 @@ public class ModuleConstants { public static final String NODE_TYPE_GITLAB = "Gitlab"; public static final String NODE_PROTOCOL_HTTP = "HTTP"; + + /* 模块数量统计相关key */ + public static final String MODULE_COUNT_ALL = "all"; + public static final String MODULE_COUNT_MY = "my"; + /* 模块数量统计相关key end*/ } diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java new file mode 100644 index 0000000000..8fe940ec3e --- /dev/null +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/TestPlanConstants.java @@ -0,0 +1,21 @@ +package io.metersphere.sdk.constants; + +public class TestPlanConstants { + //测试计划类型-测试计划 + public static final String TEST_PLAN_TYPE_PLAN = "TEST_PLAN"; + //测试计划类型-测试计划组 + public static final String TEST_PLAN_TYPE_GROUP = "GROUP"; + //测试计划组默认ID + public static final String TEST_PLAN_DEFAULT_GROUP_ID = "none"; + + //测试计划状态-未开始 + public static final String TEST_PLAN_STATUS_PREPARED = "PREPARED"; + + //测试计划状态-进行中 + public static final String TEST_PLAN_STATUS_UNDERWAY = "UNDERWAY"; + //测试计划状态-已完成 + public static final String TEST_PLAN_STATUS_COMPLETED = "COMPLETED"; + //测试计划状态-已归档 + public static final String TEST_PLAN_STATUS_ARCHIVED = "ARCHIVED"; + +} diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/file/MinioRepository.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/file/MinioRepository.java index 219ccbbdd6..795cf9f7e6 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/file/MinioRepository.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/file/MinioRepository.java @@ -71,7 +71,7 @@ public class MinioRepository implements FileRepository { private String getPath(FileRequest request) { String folder = request.getFolder(); if (!StringUtils.startsWithAny(folder, "system", "project", "organization")) { - throw new MSException("file.folder.error"); + throw new MSException("folder.error"); } return StringUtils.join(folder, "/", request.getFileName()); } diff --git a/backend/framework/sdk/src/main/resources/i18n/plan.properties b/backend/framework/sdk/src/main/resources/i18n/plan.properties index cbb7c5d16e..67f67c4d9d 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan.properties @@ -1,75 +1,82 @@ -test_plan.id.not_blank= -test_plan.project_id.length_range= -test_plan.project_id.not_blank= -test_plan.parent_id.length_range= -test_plan.parent_id.not_blank= -test_plan.name.length_range= -test_plan.name.not_blank= -test_plan.status.length_range= -test_plan.status.not_blank= -test_plan.stage.length_range= -test_plan.stage.not_blank= -test_plan.create_user.length_range= -test_plan.create_user.not_blank= -test_plan_report.id.not_blank= -test_plan_report.test_plan_id.length_range= -test_plan_report.test_plan_id.not_blank= -test_plan_report.name.length_range= -test_plan_report.name.not_blank= -test_plan_report.create_user.length_range= -test_plan_report.create_user.not_blank= -test_plan_ui_scenario.id.not_blank= -test_plan_ui_scenario.test_plan_id.length_range= -test_plan_ui_scenario.test_plan_id.not_blank= -test_plan_ui_scenario.ui_scenario_id.length_range= -test_plan_ui_scenario.ui_scenario_id.not_blank= -test_plan_ui_scenario.create_user.length_range= -test_plan_ui_scenario.create_user.not_blank= -test_plan_function_case.id.not_blank= -test_plan_function_case.plan_id.length_range= -test_plan_function_case.plan_id.not_blank= -test_plan_function_case.function_case_id.length_range= -test_plan_function_case.function_case_id.not_blank= -test_plan_function_case.create_user.length_range= -test_plan_function_case.create_user.not_blank= -test_plan_api_scenario.id.not_blank= -test_plan_api_scenario.test_plan_id.length_range= -test_plan_api_scenario.test_plan_id.not_blank= -test_plan_api_scenario.create_user.length_range= -test_plan_api_scenario.create_user.not_blank= -test_plan_follow.test_plan_id.not_blank= -test_plan_follow.user_id.not_blank= -test_plan_api_case.id.not_blank= -test_plan_api_case.test_plan_id.length_range= -test_plan_api_case.test_plan_id.not_blank= -test_plan_api_case.api_case_id.length_range= -test_plan_api_case.api_case_id.not_blank= -test_plan_api_case.create_user.length_range= -test_plan_api_case.create_user.not_blank= -test_plan_config.test_plan_id.not_blank= -test_plan_config.automatic_status_update.length_range= -test_plan_config.automatic_status_update.not_blank= -test_plan_config.repeat_case.length_range= -test_plan_config.repeat_case.not_blank= -test_plan_config.pass_threshold.length_range= -test_plan_config.pass_threshold.not_blank= -test_plan_load_case.id.not_blank= -test_plan_load_case.test_plan_id.length_range= -test_plan_load_case.test_plan_id.not_blank= -test_plan_load_case.load_case_id.length_range= -test_plan_load_case.load_case_id.not_blank= -test_plan_load_case.create_user.length_range= -test_plan_load_case.create_user.not_blank= -test_plan_execute_record_blob.test_plan_execute_record.not_blank= -test_plan_execute_record.id.not_blank= -test_plan_execute_record.test_plan_id.length_range= -test_plan_execute_record.test_plan_id.not_blank= -test_plan_execute_record.name.length_range= -test_plan_execute_record.name.not_blank= -test_plan_execute_record.status.length_range= -test_plan_execute_record.status.not_blank= -test_plan_principal.test_plan_id.not_blank= -test_plan_principal.user_id.not_blank= -test_plan_report_content.id.not_blank= -test_plan_report_content.test_plan_report_id.length_range= -test_plan_report_content.test_plan_report_id.not_blank= \ No newline at end of file +test_plan.id.not_blank=测试计划id不能为空 +test_plan.project_id.length_range=测试计划所属项目id长度过长 +test_plan.project_id.not_blank=测试计划所属项目id不能为空 +test_plan.module_id.not_blank=测试计划模块ID不能为空 +test_plan.parent_id.length_range=测试计划父id长度过长 +test_plan.parent_id.not_blank=测试计划父id不能为空 +test_plan.name.length_range=测试计划名称长度过长 +test_plan.name.not_blank=测试计划名称不能为空 +test_plan.name.exist=测试计划名称已存在 +test_plan.too_many=测试计划数量不能超过{0}个 +test_plan.status.length_range=测试计划状态长度过长 +test_plan.status.not_blank=测试计划状态不能为空 +test_plan.stage.length_range=测试计划阶段长度过长 +test_plan.stage.not_blank=测试计划阶段不能为空 +test_plan.create_user.length_range=测试计划创建人长度过长 +test_plan.create_user.not_blank=测试计划创建人不能为空 +test_plan_report.id.not_blank=测试计划报告id不能为空 +test_plan_report.test_plan_id.length_range=测试计划id长度过长 +test_plan_report.test_plan_id.not_blank=测试计划id不能为空 +test_plan_report.name.length_range=测试计划报告名称长度过长 +test_plan_report.name.not_blank=测试计划报告名称不能为空 +test_plan_report.create_user.length_range=测试计划报告创建人长度过长 +test_plan_report.create_user.not_blank=测试计划报告创建人不能为空 +test_plan_ui_scenario.id.not_blank=测试计划ui用例id不能为空 +test_plan_ui_scenario.test_plan_id.length_range=测试计划ui用例的测试计划id长度过长 +test_plan_ui_scenario.test_plan_id.not_blank=测试计划ui用例的测试计划id不能为空 +test_plan_ui_scenario.ui_scenario_id.length_range=测试计划ui用例的ui用例id长度过长 +test_plan_ui_scenario.ui_scenario_id.not_blank=测试计划ui用例的ui用例id不能为空 +test_plan_ui_scenario.create_user.length_range=测试计划ui用例创建人长度过长 +test_plan_ui_scenario.create_user.not_blank=测试计划ui用例创建人不能为空 +test_plan_function_case.id.not_blank=测试计划功能用例id不能为空 +test_plan_function_case.test_plan_id.length_range=测试计划功能用例的测试计划id长度过长 +test_plan_function_case.test_plan_id.not_blank=测试计划功能用例的测试计划id不能为空 +test_plan_function_case.function_case_id.length_range=测试计划功能用例的功能用例id长度过长 +test_plan_function_case.function_case_id.not_blank=测试计划功能用例的功能用例id不能为空 +test_plan_function_case.create_user.length_range=测试计划功能用例创建人长度过长 +test_plan_function_case.create_user.not_blank=测试计划功能用例创建人不能为空 +test_plan_api_scenario.id.not_blank=测试计划api场景id不能为空 +test_plan_api_scenario.test_plan_id.length_range=测试计划id长度过长 +test_plan_api_scenario.test_plan_id.not_blank=测试计划id不能为空 +test_plan_api_scenario.api_scenario_id.length_range=测试计划api场景的api场景id长度过长 +test_plan_api_scenario.api_scenario_id.not_blank=测试计划api场景的api场景id不能为空 +test_plan_api_scenario.create_user.length_range=测试计划api场景创建人长度过长 +test_plan_api_scenario.create_user.not_blank=测试计划api场景创建人不能为空 +test_plan_follow.test_plan_id.not_blan=测试计划id不能为空 +test_plan_follow.user_id.not_blank=用户id不能为空 +test_plan_api_case.id.not_blank=测试计划api用例id不能为空 +test_plan_api_case.test_plan_id.length_range=测试计划api用例的测试计划id长度过长 +test_plan_api_case.test_plan_id.not_blank=测试计划api用例的测试计划id不能为空 +test_plan_api_case.api_case_id.length_range=测试计划api用例的api用例id长度过长 +test_plan_api_case.api_case_id.not_blank=测试计划api用例的api用例id不能为空 +test_plan_api_case.create_user.length_range=测试计划api用例创建人长度过长 +test_plan_api_case.create_user.not_blank=测试计划api用例创建人不能为空 +test_plan_config.test_plan_id.not_blank=测试计划id不能为空 +test_plan_config.automatic_status_update.length_range=自动状态更新长度过长 +test_plan_config.automatic_status_update.not_blank=自动状态更新不能为空 +test_plan_config.repeat_case.length_range=重复用例长度过长 +test_plan_config.repeat_case.not_blank=重复用例不能为空 +test_plan_config.pass_threshold.length_range=通过阈值长度过长 +test_plan_config.pass_threshold.not_blank=通过阈值不能为空 +test_plan_load_case.id.not_blank=测试计划性能用例id不能为空 +test_plan_load_case.test_plan_id.length_range=测试计划性能用例的测试计划id长度过长 +test_plan_load_case.test_plan_id.not_blank=测试计划性能用例的测试计划id不能为空 +test_plan_load_case.load_case_id.length_range=测试计划性能用例的性能用例id长度过长 +test_plan_load_case.load_case_id.not_blank=测试计划性能用例的性能用例id不能为空 +test_plan_load_case.create_user.length_range=测试计划性能用例创建人长度过长 +test_plan_load_case.create_user.not_blank=测试计划性能用例创建人不能为空 +test_plan_execute_record_blob.test_plan_execute_record.not_blank=测试计划执行记录不能为空 +test_plan_execute_record.id.not_blank=测试计划执行记录id不能为空 +test_plan_execute_record.test_plan_id.length_range=测试计划id长度过长 +test_plan_execute_record.test_plan_id.not_blank=测试计划id不能为空 +test_plan_execute_record.name.length_range=测试计划执行记录名称长度过长 +test_plan_execute_record.name.not_blank=测试计划执行记录名称不能为空 +test_plan_execute_record.status.length_range=测试计划执行记录状态长度过长 +test_plan_execute_record.status.not_blank=测试计划执行记录状态不能为空 +test_plan_principal.test_plan_id.not_blank=测试计划id不能为空 +test_plan_principal.user_id.not_blank=用户id不能为空 +test_plan_report_content.id.not_blank=测试计划报告内容id不能为空 +test_plan_report_content.test_plan_report_id.length_range=测试计划报告id长度过长 +test_plan_report_content.test_plan_report_id.not_blank=测试计划报告id不能为空 +log.delete.test_plan=删除测试计划 +log.delete.test_plan_group=删除测试计划组 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties index ae82577304..9821e5f23a 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties @@ -1,10 +1,13 @@ test_plan.id.not_blank=Test plan id cannot be empty test_plan.project_id.length_range=Test plan project id length too long test_plan.project_id.not_blank=Test plan project id cannot be empty +test_plan.module_id.not_blank=Test plan module id cannot be empty test_plan.parent_id.length_range=Test plan parent id length too long test_plan.parent_id.not_blank=Test plan parent id cannot be empty test_plan.name.length_range=Test plan name length too long test_plan.name.not_blank=Test plan name cannot be empty +test_plan.name.exist=Test plan name exist +test_plan.too_many=Test plan cannot larger than {0} test_plan.status.length_range=Test plan status length too long test_plan.status.not_blank=Test plan status cannot be empty test_plan.stage.length_range=Test plan stage length too long @@ -74,4 +77,6 @@ test_plan_principal.test_plan_id.not_blank=Test plan principal test plan id cann test_plan_principal.user_id.not_blank=Test plan principal user id cannot be empty test_plan_report_content.id.not_blank=Test plan report content id cannot be empty test_plan_report_content.test_plan_report_id.length_range=Test plan report content test plan report id length too long -test_plan_report_content.test_plan_report_id.not_blank=Test plan report content test plan report id cannot be empty \ No newline at end of file +test_plan_report_content.test_plan_report_id.not_blank=Test plan report content test plan report id cannot be empty +log.delete.test_plan=Test plan deleted +log.delete.test_plan_group=Test plan group deleted \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties index f431b4b922..67f67c4d9d 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties @@ -1,77 +1,82 @@ -test_plan.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan.project_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6240\u5C5E\u9879\u76EEID\u957F\u5EA6\u8FC7\u957F -test_plan.project_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6240\u5C5E\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A -test_plan.parent_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u7236ID\u957F\u5EA6\u8FC7\u957F -test_plan.parent_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u7236ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan.name.length_range=\u6D4B\u8BD5\u8BA1\u5212\u540D\u79F0\u957F\u5EA6\u8FC7\u957F -test_plan.name.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A -test_plan.status.length_range=\u6D4B\u8BD5\u8BA1\u5212\u72B6\u6001\u957F\u5EA6\u8FC7\u957F -test_plan.status.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A -test_plan.stage.length_range=\u6D4B\u8BD5\u8BA1\u5212\u9636\u6BB5\u957F\u5EA6\u8FC7\u957F -test_plan.stage.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u9636\u6BB5\u4E0D\u80FD\u4E3A\u7A7A -test_plan.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544AID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_report.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report.name.length_range=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544A\u540D\u79F0\u957F\u5EA6\u8FC7\u957F -test_plan_report.name.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544A\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544A\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_report.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544A\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_ui_scenario.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_ui_scenario.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_ui_scenario.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_ui_scenario.ui_scenario_id.length_range=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u7684UI\u7528\u4F8BID\u957F\u5EA6\u8FC7\u957F -test_plan_ui_scenario.ui_scenario_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u7684UI\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_ui_scenario.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_ui_scenario.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212UI\u7528\u4F8B\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_function_case.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_function_case.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_function_case.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_function_case.function_case_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u7684\u529F\u80FD\u7528\u4F8BID\u957F\u5EA6\u8FC7\u957F -test_plan_function_case.function_case_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u7684\u529F\u80FD\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_function_case.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_function_case.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u529F\u80FD\u7528\u4F8B\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_scenario.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u573A\u666FID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_scenario.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_api_scenario.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_scenario.api_scenario_id.length_range=\u6D4B\u8BD5\u8BA1\u5212Api\u573A\u666F\u7684Api\u573A\u666FID\u957F\u5EA6\u8FC7\u957F -test_plan_api_scenario.api_scenario_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212Api\u573A\u666F\u7684Api\u573A\u666FID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_scenario.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212API\u573A\u666F\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_api_scenario.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u573A\u666F\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_follow.test_plan_id.not_blan=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_follow.user_id.not_blank=\u7528\u6237ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_case.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_case.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_api_case.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_case.api_case_id.length_range=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u7684API\u7528\u4F8BID\u957F\u5EA6\u8FC7\u957F -test_plan_api_case.api_case_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u7684API\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_api_case.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_api_case.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212API\u7528\u4F8B\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_config.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_config.automatic_status_update.length_range=\u81EA\u52A8\u72B6\u6001\u66F4\u65B0\u957F\u5EA6\u8FC7\u957F -test_plan_config.automatic_status_update.not_blank=\u81EA\u52A8\u72B6\u6001\u66F4\u65B0\u4E0D\u80FD\u4E3A\u7A7A -test_plan_config.repeat_case.length_range=\u91CD\u590D\u7528\u4F8B\u957F\u5EA6\u8FC7\u957F -test_plan_config.repeat_case.not_blank=\u91CD\u590D\u7528\u4F8B\u4E0D\u80FD\u4E3A\u7A7A -test_plan_config.pass_threshold.length_range=\u901A\u8FC7\u9608\u503C\u957F\u5EA6\u8FC7\u957F -test_plan_config.pass_threshold.not_blank=\u901A\u8FC7\u9608\u503C\u4E0D\u80FD\u4E3A\u7A7A -test_plan_load_case.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_load_case.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_load_case.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u7684\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_load_case.load_case_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u7684\u6027\u80FD\u7528\u4F8BID\u957F\u5EA6\u8FC7\u957F -test_plan_load_case.load_case_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u7684\u6027\u80FD\u7528\u4F8BID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_load_case.create_user.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u521B\u5EFA\u4EBA\u957F\u5EA6\u8FC7\u957F -test_plan_load_case.create_user.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6027\u80FD\u7528\u4F8B\u521B\u5EFA\u4EBA\u4E0D\u80FD\u4E3A\u7A7A -test_plan_execute_record_blob.test_plan_execute_record.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55\u4E0D\u80FD\u4E3A\u7A7A -test_plan_execute_record.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_execute_record.test_plan_id.length_range=\u6D4B\u8BD5\u8BA1\u5212ID\u957F\u5EA6\u8FC7\u957F -test_plan_execute_record.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_execute_record.name.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55\u540D\u79F0\u957F\u5EA6\u8FC7\u957F -test_plan_execute_record.name.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A -test_plan_execute_record.status.length_range=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55\u72B6\u6001\u957F\u5EA6\u8FC7\u957F -test_plan_execute_record.status.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u6267\u884C\u8BB0\u5F55\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A -test_plan_principal.test_plan_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_principal.user_id.not_blank=\u7528\u6237ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report_content.id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544A\u5185\u5BB9ID\u4E0D\u80FD\u4E3A\u7A7A -test_plan_report_content.test_plan_report_id.length_range=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544AID\u957F\u5EA6\u8FC7\u957F -test_plan_report_content.test_plan_report_id.not_blank=\u6D4B\u8BD5\u8BA1\u5212\u62A5\u544AID\u4E0D\u80FD\u4E3A\u7A7A \ No newline at end of file +test_plan.id.not_blank=测试计划id不能为空 +test_plan.project_id.length_range=测试计划所属项目id长度过长 +test_plan.project_id.not_blank=测试计划所属项目id不能为空 +test_plan.module_id.not_blank=测试计划模块ID不能为空 +test_plan.parent_id.length_range=测试计划父id长度过长 +test_plan.parent_id.not_blank=测试计划父id不能为空 +test_plan.name.length_range=测试计划名称长度过长 +test_plan.name.not_blank=测试计划名称不能为空 +test_plan.name.exist=测试计划名称已存在 +test_plan.too_many=测试计划数量不能超过{0}个 +test_plan.status.length_range=测试计划状态长度过长 +test_plan.status.not_blank=测试计划状态不能为空 +test_plan.stage.length_range=测试计划阶段长度过长 +test_plan.stage.not_blank=测试计划阶段不能为空 +test_plan.create_user.length_range=测试计划创建人长度过长 +test_plan.create_user.not_blank=测试计划创建人不能为空 +test_plan_report.id.not_blank=测试计划报告id不能为空 +test_plan_report.test_plan_id.length_range=测试计划id长度过长 +test_plan_report.test_plan_id.not_blank=测试计划id不能为空 +test_plan_report.name.length_range=测试计划报告名称长度过长 +test_plan_report.name.not_blank=测试计划报告名称不能为空 +test_plan_report.create_user.length_range=测试计划报告创建人长度过长 +test_plan_report.create_user.not_blank=测试计划报告创建人不能为空 +test_plan_ui_scenario.id.not_blank=测试计划ui用例id不能为空 +test_plan_ui_scenario.test_plan_id.length_range=测试计划ui用例的测试计划id长度过长 +test_plan_ui_scenario.test_plan_id.not_blank=测试计划ui用例的测试计划id不能为空 +test_plan_ui_scenario.ui_scenario_id.length_range=测试计划ui用例的ui用例id长度过长 +test_plan_ui_scenario.ui_scenario_id.not_blank=测试计划ui用例的ui用例id不能为空 +test_plan_ui_scenario.create_user.length_range=测试计划ui用例创建人长度过长 +test_plan_ui_scenario.create_user.not_blank=测试计划ui用例创建人不能为空 +test_plan_function_case.id.not_blank=测试计划功能用例id不能为空 +test_plan_function_case.test_plan_id.length_range=测试计划功能用例的测试计划id长度过长 +test_plan_function_case.test_plan_id.not_blank=测试计划功能用例的测试计划id不能为空 +test_plan_function_case.function_case_id.length_range=测试计划功能用例的功能用例id长度过长 +test_plan_function_case.function_case_id.not_blank=测试计划功能用例的功能用例id不能为空 +test_plan_function_case.create_user.length_range=测试计划功能用例创建人长度过长 +test_plan_function_case.create_user.not_blank=测试计划功能用例创建人不能为空 +test_plan_api_scenario.id.not_blank=测试计划api场景id不能为空 +test_plan_api_scenario.test_plan_id.length_range=测试计划id长度过长 +test_plan_api_scenario.test_plan_id.not_blank=测试计划id不能为空 +test_plan_api_scenario.api_scenario_id.length_range=测试计划api场景的api场景id长度过长 +test_plan_api_scenario.api_scenario_id.not_blank=测试计划api场景的api场景id不能为空 +test_plan_api_scenario.create_user.length_range=测试计划api场景创建人长度过长 +test_plan_api_scenario.create_user.not_blank=测试计划api场景创建人不能为空 +test_plan_follow.test_plan_id.not_blan=测试计划id不能为空 +test_plan_follow.user_id.not_blank=用户id不能为空 +test_plan_api_case.id.not_blank=测试计划api用例id不能为空 +test_plan_api_case.test_plan_id.length_range=测试计划api用例的测试计划id长度过长 +test_plan_api_case.test_plan_id.not_blank=测试计划api用例的测试计划id不能为空 +test_plan_api_case.api_case_id.length_range=测试计划api用例的api用例id长度过长 +test_plan_api_case.api_case_id.not_blank=测试计划api用例的api用例id不能为空 +test_plan_api_case.create_user.length_range=测试计划api用例创建人长度过长 +test_plan_api_case.create_user.not_blank=测试计划api用例创建人不能为空 +test_plan_config.test_plan_id.not_blank=测试计划id不能为空 +test_plan_config.automatic_status_update.length_range=自动状态更新长度过长 +test_plan_config.automatic_status_update.not_blank=自动状态更新不能为空 +test_plan_config.repeat_case.length_range=重复用例长度过长 +test_plan_config.repeat_case.not_blank=重复用例不能为空 +test_plan_config.pass_threshold.length_range=通过阈值长度过长 +test_plan_config.pass_threshold.not_blank=通过阈值不能为空 +test_plan_load_case.id.not_blank=测试计划性能用例id不能为空 +test_plan_load_case.test_plan_id.length_range=测试计划性能用例的测试计划id长度过长 +test_plan_load_case.test_plan_id.not_blank=测试计划性能用例的测试计划id不能为空 +test_plan_load_case.load_case_id.length_range=测试计划性能用例的性能用例id长度过长 +test_plan_load_case.load_case_id.not_blank=测试计划性能用例的性能用例id不能为空 +test_plan_load_case.create_user.length_range=测试计划性能用例创建人长度过长 +test_plan_load_case.create_user.not_blank=测试计划性能用例创建人不能为空 +test_plan_execute_record_blob.test_plan_execute_record.not_blank=测试计划执行记录不能为空 +test_plan_execute_record.id.not_blank=测试计划执行记录id不能为空 +test_plan_execute_record.test_plan_id.length_range=测试计划id长度过长 +test_plan_execute_record.test_plan_id.not_blank=测试计划id不能为空 +test_plan_execute_record.name.length_range=测试计划执行记录名称长度过长 +test_plan_execute_record.name.not_blank=测试计划执行记录名称不能为空 +test_plan_execute_record.status.length_range=测试计划执行记录状态长度过长 +test_plan_execute_record.status.not_blank=测试计划执行记录状态不能为空 +test_plan_principal.test_plan_id.not_blank=测试计划id不能为空 +test_plan_principal.user_id.not_blank=用户id不能为空 +test_plan_report_content.id.not_blank=测试计划报告内容id不能为空 +test_plan_report_content.test_plan_report_id.length_range=测试计划报告id长度过长 +test_plan_report_content.test_plan_report_id.not_blank=测试计划报告id不能为空 +log.delete.test_plan=删除测试计划 +log.delete.test_plan_group=删除测试计划组 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties index ec4666c3d8..8b131cf376 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties @@ -1,77 +1,82 @@ -test_plan.id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan.project_id.length_range=\u6E2C\u8A66\u8A08\u5283\u6240\u5C6C\u9805\u76EEID\u9577\u5EA6\u904E\u9577 -test_plan.project_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u6240\u5C6C\u9805\u76EEID\u4E0D\u80FD\u70BA\u7A7A -test_plan.parent_id.length_range=\u6E2C\u8A66\u8A08\u5283\u7236ID\u9577\u5EA6\u904E\u9577 -test_plan.parent_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u7236ID\u4E0D\u80FD\u70BA\u7A7A -test_plan.name.length_range=\u6E2C\u8A66\u8A08\u5283\u540D\u7A31\u9577\u5EA6\u904E\u9577 -test_plan.name.not_blank=\u6E2C\u8A66\u8A08\u5283\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A -test_plan.status.length_range=\u6E2C\u8A66\u8A08\u5283\u72C0\u614B\u9577\u5EA6\u904E\u9577 -test_plan.status.not_blank=\u6E2C\u8A66\u8A08\u5283\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A -test_plan.stage.length_range=\u6E2C\u8A66\u8A08\u5283\u968E\u6BB5\u9577\u5EA6\u904E\u9577 -test_plan.stage.not_blank=\u6E2C\u8A66\u8A08\u5283\u968E\u6BB5\u4E0D\u80FD\u70BA\u7A7A -test_plan.create_user.length_range=\u6E2C\u8A66\u8A08\u5283\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_report.id.not_blank=\u6E2C\u8A66\u8A08\u5283\u5831\u544AID\u4E0D\u80FD\u70BA\u7A7A -test_plan_report.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_report.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_report.name.length_range=\u6E2C\u8A66\u8A08\u5283\u5831\u544A\u540D\u7A31\u9577\u5EA6\u904E\u9577 -test_plan_report.name.not_blank=\u6E2C\u8A66\u8A08\u5283\u5831\u544A\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A -test_plan_report.create_user.length_range=\u6E2C\u8A66\u8A08\u5283\u5831\u544A\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_report.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283\u5831\u544A\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_ui_scenario.id.not_blank=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_ui_scenario.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_ui_scenario.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_ui_scenario.ui_scenario_id.length_range=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u7684UI\u7528\u4F8BID\u9577\u5EA6\u904E\u9577 -test_plan_ui_scenario.ui_scenario_id.not_blank=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u7684UI\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_ui_scenario.create_user.length_range=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_ui_scenario.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283UI\u7528\u4F8B\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_function_case.id.not_blank=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_function_case.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_function_case.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_function_case.function_case_id.length_range=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u7684\u529F\u80FD\u7528\u4F8BID\u9577\u5EA6\u904E\u9577 -test_plan_function_case.function_case_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u7684\u529F\u80FD\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_function_case.create_user.length_range=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_function_case.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283\u529F\u80FD\u7528\u4F8B\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_scenario.id.not_blank=\u6E2C\u8A66\u8A08\u5283API\u5834\u666FID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_scenario.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_api_scenario.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_scenario.api_scenario_id.length_range=\u6E2C\u8A66\u8A08\u5283Api\u5834\u666F\u7684Api\u5834\u666FID\u9577\u5EA6\u904E\u9577 -test_plan_api_scenario.api_scenario_id.not_blank=\u6E2C\u8A66\u8A08\u5283Api\u5834\u666F\u7684Api\u5834\u666FID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_scenario.create_user.length_range=\u6E2C\u8A66\u8A08\u5283API\u5834\u666F\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_api_scenario.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283API\u5834\u666F\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_follow.test_plan_id.not_blan=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_follow.user_id.not_blank=\u7528\u6236ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_case.id.not_blank=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_case.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_api_case.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_case.api_case_id.length_range=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u7684API\u7528\u4F8BID\u9577\u5EA6\u904E\u9577 -test_plan_api_case.api_case_id.not_blank=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u7684API\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_api_case.create_user.length_range=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_api_case.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283API\u7528\u4F8B\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_config.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_config.automatic_status_update.length_range=\u81EA\u52D5\u72C0\u614B\u66F4\u65B0\u9577\u5EA6\u904E\u9577 -test_plan_config.automatic_status_update.not_blank=\u81EA\u52D5\u72C0\u614B\u66F4\u65B0\u4E0D\u80FD\u70BA\u7A7A -test_plan_config.repeat_case.length_range=\u91CD\u8907\u7528\u4F8B\u9577\u5EA6\u904E\u9577 -test_plan_config.repeat_case.not_blank=\u91CD\u8907\u7528\u4F8B\u4E0D\u80FD\u70BA\u7A7A -test_plan_config.pass_threshold.length_range=\u901A\u904E\u95BE\u503C\u9577\u5EA6\u904E\u9577 -test_plan_config.pass_threshold.not_blank=\u901A\u904E\u95BE\u503C\u4E0D\u80FD\u70BA\u7A7A -test_plan_load_case.id.not_blank=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_load_case.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_load_case.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u7684\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_load_case.load_case_id.length_range=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u7684\u6027\u80FD\u7528\u4F8BID\u9577\u5EA6\u904E\u9577 -test_plan_load_case.load_case_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u7684\u6027\u80FD\u7528\u4F8BID\u4E0D\u80FD\u70BA\u7A7A -test_plan_load_case.create_user.length_range=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u5275\u5EFA\u4EBA\u9577\u5EA6\u904E\u9577 -test_plan_load_case.create_user.not_blank=\u6E2C\u8A66\u8A08\u5283\u6027\u80FD\u7528\u4F8B\u5275\u5EFA\u4EBA\u4E0D\u80FD\u70BA\u7A7A -test_plan_execute_record_blob.test_plan_execute_record.not_blank=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304\u4E0D\u80FD\u70BA\u7A7A -test_plan_execute_record.id.not_blank=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_execute_record.test_plan_id.length_range=\u6E2C\u8A66\u8A08\u5283ID\u9577\u5EA6\u904E\u9577 -test_plan_execute_record.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_execute_record.name.length_range=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304\u540D\u7A31\u9577\u5EA6\u904E\u9577 -test_plan_execute_record.name.not_blank=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A -test_plan_execute_record.status.length_range=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304\u72C0\u614B\u9577\u5EA6\u904E\u9577 -test_plan_execute_record.status.not_blank=\u6E2C\u8A66\u8A08\u5283\u57F7\u884C\u8A18\u9304\u72C0\u614B\u4E0D\u80FD\u70BA\u7A7A -test_plan_principal.test_plan_id.not_blank=\u6E2C\u8A66\u8A08\u5283ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_principal.user_id.not_blank=\u7528\u6236ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_report_content.id.not_blank=\u6E2C\u8A66\u8A08\u5283\u5831\u544A\u5167\u5BB9ID\u4E0D\u80FD\u70BA\u7A7A -test_plan_report_content.test_plan_report_id.length_range=\u6E2C\u8A66\u8A08\u5283\u5831\u544AID\u9577\u5EA6\u904E\u9577 -test_plan_report_content.test_plan_report_id.not_blank=\u6E2C\u8A66\u8A08\u5283\u5831\u544AID\u4E0D\u80FD\u70BA\u7A7A \ No newline at end of file +test_plan.id.not_blank=測試計劃id不能為空 +test_plan.project_id.length_range=測試計劃所屬項目id長度過長 +test_plan.project_id.not_blank=測試計劃所屬項目id不能為空 +test_plan.module_id.not_blank=測試計劃模塊ID不能為空 +test_plan.parent_id.length_range=測試計劃父id長度過長 +test_plan.parent_id.not_blank=測試計劃父id不能為空 +test_plan.name.length_range=測試計劃名稱長度過長 +test_plan.name.not_blank=測試計劃名稱不能為空 +test_plan.name.exist=測試計劃名稱已存在 +test_plan.too_many=測試計劃數量不能超過{0}個 +test_plan.status.length_range=測試計劃狀態長度過長 +test_plan.status.not_blank=測試計劃狀態不能為空 +test_plan.stage.length_range=測試計劃階段長度過長 +test_plan.stage.not_blank=測試計劃階段不能為空 +test_plan.create_user.length_range=測試計劃創建人長度過長 +test_plan.create_user.not_blank=測試計劃創建人不能為空 +test_plan_report.id.not_blank=測試計劃報告id不能為空 +test_plan_report.test_plan_id.length_range=測試計劃id長度過長 +test_plan_report.test_plan_id.not_blank=測試計劃id不能為空 +test_plan_report.name.length_range=測試計劃報告名稱長度過長 +test_plan_report.name.not_blank=測試計劃報告名稱不能為空 +test_plan_report.create_user.length_range=測試計劃報告創建人長度過長 +test_plan_report.create_user.not_blank=測試計劃報告創建人不能為空 +test_plan_ui_scenario.id.not_blank=測試計劃ui用例id不能為空 +test_plan_ui_scenario.test_plan_id.length_range=測試計劃ui用例的測試計劃id長度過長 +test_plan_ui_scenario.test_plan_id.not_blank=測試計劃ui用例的測試計劃id不能為空 +test_plan_ui_scenario.ui_scenario_id.length_range=測試計劃ui用例的ui用例id長度過長 +test_plan_ui_scenario.ui_scenario_id.not_blank=測試計劃ui用例的ui用例id不能為空 +test_plan_ui_scenario.create_user.length_range=測試計劃ui用例創建人長度過長 +test_plan_ui_scenario.create_user.not_blank=測試計劃ui用例創建人不能為空 +test_plan_function_case.id.not_blank=測試計劃功能用例id不能為空 +test_plan_function_case.test_plan_id.length_range=測試計劃功能用例的測試計劃id長度過長 +test_plan_function_case.test_plan_id.not_blank=測試計劃功能用例的測試計劃id不能為空 +test_plan_function_case.function_case_id.length_range=測試計劃功能用例的功能用例id長度過長 +test_plan_function_case.function_case_id.not_blank=測試計劃功能用例的功能用例id不能為空 +test_plan_function_case.create_user.length_range=測試計劃功能用例創建人長度過長 +test_plan_function_case.create_user.not_blank=測試計劃功能用例創建人不能為空 +test_plan_api_scenario.id.not_blank=測試計劃api場景id不能為空 +test_plan_api_scenario.test_plan_id.length_range=測試計劃id長度過長 +test_plan_api_scenario.test_plan_id.not_blank=測試計劃id不能為空 +test_plan_api_scenario.api_scenario_id.length_range=測試計劃api場景的api場景id長度過長 +test_plan_api_scenario.api_scenario_id.not_blank=測試計劃api場景的api場景id不能為空 +test_plan_api_scenario.create_user.length_range=測試計劃api場景創建人長度過長 +test_plan_api_scenario.create_user.not_blank=測試計劃api場景創建人不能為空 +test_plan_follow.test_plan_id.not_blan=測試計劃id不能為空 +test_plan_follow.user_id.not_blank=用戶id不能為空 +test_plan_api_case.id.not_blank=測試計劃api用例id不能為空 +test_plan_api_case.test_plan_id.length_range=測試計劃api用例的測試計劃id長度過長 +test_plan_api_case.test_plan_id.not_blank=測試計劃api用例的測試計劃id不能為空 +test_plan_api_case.api_case_id.length_range=測試計劃api用例的api用例id長度過長 +test_plan_api_case.api_case_id.not_blank=測試計劃api用例的api用例id不能為空 +test_plan_api_case.create_user.length_range=測試計劃api用例創建人長度過長 +test_plan_api_case.create_user.not_blank=測試計劃api用例創建人不能為空 +test_plan_config.test_plan_id.not_blank=測試計劃id不能為空 +test_plan_config.automatic_status_update.length_range=自動狀態更新長度過長 +test_plan_config.automatic_status_update.not_blank=自動狀態更新不能為空 +test_plan_config.repeat_case.length_range=重複用例長度過長 +test_plan_config.repeat_case.not_blank=重複用例不能為空 +test_plan_config.pass_threshold.length_range=通過閾值長度過長 +test_plan_config.pass_threshold.not_blank=通過閾值不能為空 +test_plan_load_case.id.not_blank=測試計劃性能用例id不能為空 +test_plan_load_case.test_plan_id.length_range=測試計劃性能用例的測試計劃id長度過長 +test_plan_load_case.test_plan_id.not_blank=測試計劃性能用例的測試計劃id不能為空 +test_plan_load_case.load_case_id.length_range=測試計劃性能用例的性能用例id長度過長 +test_plan_load_case.load_case_id.not_blank=測試計劃性能用例的性能用例id不能為空 +test_plan_load_case.create_user.length_range=測試計劃性能用例創建人長度過長 +test_plan_load_case.create_user.not_blank=測試計劃性能用例創建人不能為空 +test_plan_execute_record_blob.test_plan_execute_record.not_blank=測試計劃執行記錄不能為空 +test_plan_execute_record.id.not_blank=測試計劃執行記錄id不能為空 +test_plan_execute_record.test_plan_id.length_range=測試計劃id長度過長 +test_plan_execute_record.test_plan_id.not_blank=測試計劃id不能為空 +test_plan_execute_record.name.length_range=測試計劃執行記錄名稱長度過長 +test_plan_execute_record.name.not_blank=測試計劃執行記錄名稱不能為空 +test_plan_execute_record.status.length_range=測試計劃執行記錄狀態長度過長 +test_plan_execute_record.status.not_blank=測試計劃執行記錄狀態不能為空 +test_plan_principal.test_plan_id.not_blank=測試計劃id不能為空 +test_plan_principal.user_id.not_blank=用戶id不能為空 +test_plan_report_content.id.not_blank=測試計劃報告內容id不能為空 +test_plan_report_content.test_plan_report_id.length_range=測試計劃報告id長度過長 +test_plan_report_content.test_plan_report_id.not_blank=測試計劃報告id不能為空 +log.delete.test_plan=刪除測試計劃 +log.delete.test_plan_group=刪除測試計劃組 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/project.properties b/backend/framework/sdk/src/main/resources/i18n/project.properties index 18ead8249e..c2979b6891 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project.properties @@ -444,9 +444,9 @@ latest.file.not.exist=最新文件不存在 file.not.jar=不是jar文件 change.jar.enable=修改了jar文件的启用状态 file.name.exist=文件名已存在 -file.log.delete_module=模块下的所有数据全部被删除 +log.delete_module=模块下的所有数据全部被删除 file.module.root=根目录 -file.folder.error=文件夹不合法 +folder.error=文件夹不合法 file.log.move_to=移动到 file.log.change_file_module=文件进行了移动 file.log.next=之后 diff --git a/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties index 3bfdfe9ee6..cb2d0e9d9a 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties @@ -480,9 +480,9 @@ latest.file.not.exist=New version file note exist file.not.jar=Not jar file change.jar.enable=Change jar file enable file.name.exist=File name already exists -file.log.delete_module=has be deleted +log.delete_module=has be deleted file.module.root=root module -file.folder.error=File folder error +folder.error=File folder error file.log.move_to=move to file.log.change_file_module=File has be moved file.log.next=next diff --git a/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties index b2ca4f821a..0afbb06a68 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties @@ -479,9 +479,9 @@ latest.file.not.exist=最新文件不存在 file.not.jar=不是jar文件 change.jar.enable=修改了jar文件的启用状态 file.name.exist=文件名已存在 -file.log.delete_module=模块下的所有数据全部被删除 +log.delete_module=模块下的所有数据全部被删除 file.module.root=根目录 -file.folder.error=文件夹不合法 +folder.error=文件夹不合法 file.log.move_to=移动到 file.log.change_file_module=文件进行了移动 file.log.next=之后 diff --git a/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties index a38b423743..e7f2e17384 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties @@ -480,9 +480,9 @@ latest.file.not.exist=最新文件不存在 file.not.jar=不是jar文件 change.jar.enable=修改了jar文件的啟用狀態 file.name.exist=文件名已存在 -file.log.delete_module=模塊下的所有數據全部被刪除 +log.delete_module=模塊下的所有數據全部被刪除 file.module.root=根目錄 -file.folder.error=文件夾不合法 +folder.error=文件夾不合法 file.log.move_to=移動到 file.log.change_file_module=文件進行了移動 file.log.next=之後 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleLogService.java index a4a6583e68..6a46306281 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleLogService.java @@ -85,7 +85,7 @@ public class ApiDebugModuleLogService { .method(HttpMethodConstants.GET.name()) .path(DELETE + "/%s") .sourceId(item.getId()) - .content(item.getName() + " " + Translator.get("file.log.delete_module")) + .content(item.getName() + " " + Translator.get("log.delete_module")) .createUser(operator) .build().getLogDTO(); dtos.add(dto); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionModuleLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionModuleLogService.java index f5f4dc0f93..ca3f576439 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionModuleLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionModuleLogService.java @@ -86,7 +86,7 @@ public class ApiDefinitionModuleLogService { .method(HttpMethodConstants.GET.name()) .path(DELETE + "/%s") .sourceId(item.getId()) - .content(item.getName() + " " + Translator.get("file.log.delete_module")) + .content(item.getName() + " " + Translator.get("log.delete_module")) .createUser(operator) .build().getLogDTO(); dtoList.add(dto); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleLogService.java index 4a1ad490d9..7d40342142 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioModuleLogService.java @@ -85,7 +85,7 @@ public class ApiScenarioModuleLogService { .method(HttpMethodConstants.GET.name()) .path(DELETE + "/%s") .sourceId(item.getId()) - .content(item.getName() + " " + Translator.get("file.log.delete_module")) + .content(item.getName() + " " + Translator.get("log.delete_module")) .createUser(operator) .build().getLogDTO(); dtoList.add(dto); diff --git a/backend/services/bug-management/src/test/resources/dml/init_bug_relation_case.sql b/backend/services/bug-management/src/test/resources/dml/init_bug_relation_case.sql index b0f843daf7..6488c5873d 100644 --- a/backend/services/bug-management/src/test/resources/dml/init_bug_relation_case.sql +++ b/backend/services/bug-management/src/test/resources/dml/init_bug_relation_case.sql @@ -8,5 +8,7 @@ VALUES ('wx_test_id_1', 'wx_1', 'bug_id_1', 'FUNCTIONAL', null, null, 'admin', U ('wx_test_id_2', 'wx_2', 'bug_id_1', 'FUNCTIONAL', 'test-plan-id', 'bug_relate_case', 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000), ('wx_test_id_3', 'wx_3', 'bug_id_2', 'FUNCTIONAL', null, null, 'admin', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000); -INSERT INTO `test_plan` (`id`,`project_id`,`parent_id`,`name`,`status`,`stage`,`create_time`,`create_user`) -VALUES('test-plan-id','wx_test','3','cececec','3','4',UNIX_TIMESTAMP() * 1000,'admin'); \ No newline at end of file +INSERT INTO `test_plan` (`id`, `project_id`, `group_id`, `module_id`, `type`, `name`, `status`, `create_time`, + `create_user`) +VALUES ('test-plan-id', 'wx_test', 'none', 'root', 'TEST_PLAN', 'cececec', 'PREPARED', UNIX_TIMESTAMP() * 1000, + 'admin'); \ No newline at end of file diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/FileMetadataService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/FileMetadataService.java index 80c610ee69..10cbf17717 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/FileMetadataService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/FileMetadataService.java @@ -280,8 +280,6 @@ public class FileMetadataService { } } - private static final String FILE_MODULE_COUNT_ALL = "all"; - private String uploadFile(FileMetadata fileMetadata, MultipartFile file) throws Exception { FileRequest uploadFileRequest = new FileRequest(); uploadFileRequest.setFileName(fileMetadata.getId()); @@ -414,8 +412,6 @@ public class FileMetadataService { } } - private static final String FILE_MODULE_COUNT_MY = "my"; - /** * 重新上传 */ @@ -466,8 +462,8 @@ public class FileMetadataService { long allCount = extFileMetadataMapper.fileCount(myFileCountDTO); myFileCountDTO.setOperator(operator); long myFileCount = extFileMetadataMapper.fileCount(myFileCountDTO); - moduleCountMap.put(FILE_MODULE_COUNT_MY, myFileCount); - moduleCountMap.put(FILE_MODULE_COUNT_ALL, allCount); + moduleCountMap.put(ModuleConstants.MODULE_COUNT_MY, myFileCount); + moduleCountMap.put(ModuleConstants.MODULE_COUNT_ALL, allCount); return moduleCountMap; } diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/FileModuleLogService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/FileModuleLogService.java index 93c56097db..81460a6132 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/FileModuleLogService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/FileModuleLogService.java @@ -105,9 +105,9 @@ public class FileModuleLogService { .type(OperationLogType.DELETE.name()) .module(OperationLogModule.PROJECT_FILE_MANAGEMENT) .method(HttpMethodConstants.GET.name()) - .path("/project/file-module/delete/%s") + .path("/project/file-module/delete") .sourceId(deleteModule.getId()) - .content(deleteModule.getName() + " " + Translator.get("file.log.delete_module")) + .content(deleteModule.getName() + " " + Translator.get("log.delete_module")) .originalValue(JSON.toJSONBytes(deleteModule)) .createUser(operator) .build().getLogDTO(); diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java index 49cfc203fd..1b4e70ed4d 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java @@ -31,10 +31,9 @@ import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.service.CommonProjectService; import io.metersphere.system.uid.IDGenerator; +import io.metersphere.system.utils.CheckLogModel; import io.metersphere.system.utils.Pager; import jakarta.annotation.Resource; -import lombok.AllArgsConstructor; -import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.junit.jupiter.api.*; @@ -2479,11 +2478,3 @@ public class FileManagementControllerTests extends BaseTest { } } } - -@Data -@AllArgsConstructor -class CheckLogModel { - private String resourceId; - private OperationLogType operationType; - private String url; -} diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileRepositoryControllerTest.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileRepositoryControllerTest.java index 4788d6b3a1..30e32f8240 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileRepositoryControllerTest.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileRepositoryControllerTest.java @@ -22,10 +22,9 @@ import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.service.CommonProjectService; import io.metersphere.system.uid.IDGenerator; +import io.metersphere.system.utils.CheckLogModel; import io.metersphere.system.utils.Pager; import jakarta.annotation.Resource; -import lombok.AllArgsConstructor; -import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.junit.jupiter.api.*; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -68,7 +67,7 @@ public class FileRepositoryControllerTest extends BaseTest { @Resource private CommonProjectService commonProjectService; - private static List LOG_CHECK_LIST = new ArrayList<>(); + private static List LOG_CHECK_LIST = new ArrayList<>(); @BeforeEach public void initTestData() { @@ -167,7 +166,7 @@ public class FileRepositoryControllerTest extends BaseTest { repositoryId = rh.getData().toString(); this.checkFileRepository(repositoryId, createRequest.getProjectId(), createRequest.getName(), createRequest.getPlatform(), createRequest.getUrl(), createRequest.getToken(), createRequest.getUserName()); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(repositoryId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) + new CheckLogModel(repositoryId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) ); //测试获取详情 @@ -213,7 +212,7 @@ public class FileRepositoryControllerTest extends BaseTest { rh = JSON.parseObject(returnStr, ResultHolder.class); this.checkFileRepository(rh.getData().toString(), createRequest.getProjectId(), createRequest.getName(), createRequest.getPlatform(), createRequest.getUrl(), createRequest.getToken(), createRequest.getUserName()); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(rh.getData().toString(), OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) + new CheckLogModel(rh.getData().toString(), OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) ); //参数测试: 没有url @@ -288,7 +287,7 @@ public class FileRepositoryControllerTest extends BaseTest { this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_UPDATE, createRequest); this.checkFileRepository(repositoryId, project.getId(), "GITEA存储库改个名字", ModuleConstants.NODE_TYPE_GITEA, GITEA_URL, GITEA_TOKEN, null); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(repositoryId, OperationLogType.UPDATE, FileManagementRequestUtils.URL_FILE_REPOSITORY_UPDATE) + new CheckLogModel(repositoryId, OperationLogType.UPDATE, FileManagementRequestUtils.URL_FILE_REPOSITORY_UPDATE) ); //修改用户名 FileModuleRepository updateModel = new FileModuleRepository(); @@ -344,7 +343,7 @@ public class FileRepositoryControllerTest extends BaseTest { this.requestGetWithOk(String.format(FileManagementRequestUtils.URL_MODULE_DELETE, repositoryId)); this.checkRepositoryDeleted(repositoryId); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(repositoryId, OperationLogType.DELETE, FileManagementRequestUtils.URL_MODULE_DELETE) + new CheckLogModel(repositoryId, OperationLogType.DELETE, FileManagementRequestUtils.URL_MODULE_DELETE) ); //重新添加 @@ -360,7 +359,7 @@ public class FileRepositoryControllerTest extends BaseTest { repositoryId = rh.getData().toString(); this.checkFileRepository(repositoryId, createRequest.getProjectId(), createRequest.getName(), createRequest.getPlatform(), createRequest.getUrl(), createRequest.getToken(), createRequest.getUserName()); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(repositoryId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) + new CheckLogModel(repositoryId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_CREATE) ); } @@ -410,7 +409,7 @@ public class FileRepositoryControllerTest extends BaseTest { String fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString(); this.checkRepositoryFile(fileId, request); LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(fileId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD) + new CheckLogModel(fileId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD) ); getFileMessage(fileId); fileList.add(fileId); @@ -661,7 +660,7 @@ public class FileRepositoryControllerTest extends BaseTest { this.requestPostWithOk(FileManagementRequestUtils.URL_FILE_DELETE, fileBatchProcessRequest); for (String fileId : fileList) { LOG_CHECK_LIST.add( - new RepositoryCheckLogModel(fileId, OperationLogType.DELETE, FileManagementRequestUtils.URL_FILE_DELETE) + new CheckLogModel(fileId, OperationLogType.DELETE, FileManagementRequestUtils.URL_FILE_DELETE) ); this.checkRepositoryFileDeleted(fileId); } @@ -671,7 +670,7 @@ public class FileRepositoryControllerTest extends BaseTest { @Order(100) public void testLog() throws Exception { Thread.sleep(5000); - for (RepositoryCheckLogModel checkLogModel : LOG_CHECK_LIST) { + for (CheckLogModel checkLogModel : LOG_CHECK_LIST) { if (org.apache.commons.lang3.StringUtils.isEmpty(checkLogModel.getUrl())) { this.checkLog(checkLogModel.getResourceId(), checkLogModel.getOperationType()); } else { @@ -717,12 +716,4 @@ public class FileRepositoryControllerTest extends BaseTest { ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); return JSON.parseArray(JSON.toJSONString(resultHolder.getData()), String.class); } -} - -@Data -@AllArgsConstructor -class RepositoryCheckLogModel { - private String resourceId; - private OperationLogType operationType; - private String url; } \ No newline at end of file diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/table/TableBatchProcessDTO.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/table/TableBatchProcessDTO.java index 0914dda48c..1977fa2011 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/table/TableBatchProcessDTO.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/table/TableBatchProcessDTO.java @@ -8,6 +8,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import lombok.Data; +import java.util.ArrayList; import java.util.List; @Data @@ -20,7 +21,7 @@ public class TableBatchProcessDTO { private List< @NotBlank(message = "{id must not be blank}", groups = {Created.class, Updated.class}) String - > selectIds; + > selectIds = new ArrayList<>(); @Schema(description = "是否选择所有数据") private boolean selectAll; diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/utils/CheckLogModel.java b/backend/services/system-setting/src/test/java/io/metersphere/system/utils/CheckLogModel.java new file mode 100644 index 0000000000..c322432db8 --- /dev/null +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/utils/CheckLogModel.java @@ -0,0 +1,27 @@ +package io.metersphere.system.utils; + +import io.metersphere.system.log.constants.OperationLogType; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +@Data +public class CheckLogModel { + private String resourceId; + private OperationLogType operationType; + private String url; + + + public CheckLogModel(String resourceId, OperationLogType operationType, String url) { + this.resourceId = resourceId; + this.operationType = operationType; + this.url = formatLogUrl(url); + } + + private String formatLogUrl(String url) { + if (StringUtils.endsWith(url, "/%s")) { + return StringUtils.substring(url, 0, url.length() - 3); + } else { + return url; + } + } +} \ No newline at end of file diff --git a/backend/services/system-setting/src/test/resources/dml/init_aspect.sql b/backend/services/system-setting/src/test/resources/dml/init_aspect.sql index 256bd23532..184478a05f 100644 --- a/backend/services/system-setting/src/test/resources/dml/init_aspect.sql +++ b/backend/services/system-setting/src/test/resources/dml/init_aspect.sql @@ -40,8 +40,12 @@ VALUES ('aspect_gyq_api_one', 'api_test','HTTP', 'POST','api/test','test-api-sta INSERT INTO api_scenario(id, name, priority, status, last_report_status, last_report_id, num, pos, version_id, ref_id, project_id, module_id, description, tags, create_user, create_time, delete_time, delete_user, update_user, update_time) VALUES ('aspect_gyq_api_scenario_one', 'api_scenario', 'p1', 'test-api-status', null, null,1000001, 1,'v1.10', 'aspect_gyq_api_scenario_one','100001100001', 'test_module', null,null,'admin', UNIX_TIMESTAMP() * 1000,null,null,'admin', UNIX_TIMESTAMP() * 1000); -INSERT INTO test_plan(id, project_id, parent_id, name, status, stage, tags, create_time, create_user, update_time, update_user, planned_start_time, planned_end_time, actual_start_time, actual_end_time, description) -VALUES ('aspect_gyq_test_plan_one','100001100001', 'NONE', 'test_plan', 'test-api-status', 'Smock', null, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 2000, UNIX_TIMESTAMP() * 3000 ,UNIX_TIMESTAMP() * 2000, UNIX_TIMESTAMP() * 3000,null); +INSERT INTO test_plan(id, project_id, group_id, module_id, name, status, type, tags, create_time, create_user, + update_time, update_user, planned_start_time, planned_end_time, actual_start_time, + actual_end_time, description) +VALUES ('aspect_gyq_test_plan_one', '100001100001', 'none', 'root', 'test_plan', 'PREPARED', 'TEST_PLAN', null, + UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 2000, + UNIX_TIMESTAMP() * 3000, UNIX_TIMESTAMP() * 2000, UNIX_TIMESTAMP() * 3000, null); INSERT INTO case_review(id, num, name, module_id, project_id, status, review_pass_rule, pos, start_time, end_time, tags, description, create_time, create_user, update_time, update_user) VALUES ('aspect_gyq_case_review_one','10001','case_review','module_id', '100001100001','PREPARED','SINGLE','0', null, null, null, null, UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin'); diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java index d7abb99397..f6d5891713 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java @@ -1,41 +1,116 @@ package io.metersphere.plan.controller; -import io.metersphere.plan.dto.TestPlanDTO; +import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; +import io.metersphere.plan.dto.request.TestPlanCreateRequest; +import io.metersphere.plan.dto.request.TestPlanTableRequest; +import io.metersphere.plan.dto.response.TestPlanResponse; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanService; -import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.constants.HttpMethodConstants; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.security.CheckOwner; +import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.SessionUtils; -import io.metersphere.validation.groups.Created; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.constraints.NotBlank; -import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/test-plan") +@Tag(name = "测试计划") public class TestPlanController { @Resource private TestPlanService testPlanService; + @Resource + private TestPlanManagementService testPlanManagementService; + + @PostMapping("/page") + @Operation(summary = "测试计划-表格分页查询") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public Pager> page(@Validated @RequestBody TestPlanTableRequest request) { + return testPlanManagementService.page(request); + } + + @GetMapping("/getCount/{id}") + @Operation(summary = "测试计划-获取统计数据") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) + @CheckOwner(resourceId = "#id", resourceType = "test_plan") + public TestPlanResponse getCount(@PathVariable String id) { + return testPlanService.getCount(id); + } + + + @PostMapping("/module/count") + @Operation(summary = "测试计划-模块统计") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public Map moduleCount(@Validated @RequestBody TestPlanTableRequest request) { + return testPlanManagementService.moduleCount(request); + } + @PostMapping("/add") - public TestPlanDTO addUser(@Validated({Created.class}) @RequestBody TestPlanDTO testPlan) { - testPlan.setCreateUser(SessionUtils.getUserId()); - testPlan.setUpdateUser(SessionUtils.getUserId()); - return testPlanService.add(testPlan); + @Operation(summary = "测试计划-创建测试计划") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public String add(@Validated @RequestBody TestPlanCreateRequest testPlan) { + return testPlanService.add(testPlan, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name()); } - @PostMapping("/delete/batch") - public void deleteBatch(@RequestBody List idList) { - if (CollectionUtils.isEmpty(idList)) { - throw new MSException("The ids cannot be empty!"); - } - testPlanService.batchDelete(idList); - } @GetMapping("/delete/{id}") + @Operation(summary = "测试计划-删除测试计划") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_DELETE) + @CheckOwner(resourceId = "#id", resourceType = "test_plan") public void delete(@NotBlank @PathVariable String id) { - testPlanService.delete(id); + testPlanService.delete(id, SessionUtils.getUserId(), "/test-plan/delete", HttpMethodConstants.GET.name()); } + + + @PostMapping(value = "/batch-delete") + @Operation(summary = "测试计划-批量删除") + @RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE) + @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + public void delete(@Validated @RequestBody TestPlanBatchProcessRequest request) throws Exception { + testPlanService.delete(request, SessionUtils.getUserId(), "/test-plan/batch-delete", HttpMethodConstants.POST.name()); + } + + /* + todo 更新接口(具体字段未确定) + @PostMapping(value = "/update") + @Operation(summary = "项目管理-文件管理-修改文件") + @RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE) + @CheckOwner(resourceId = "#request.getId()", resourceType = "file_metadata") + public void update(@Validated @RequestBody FileUpdateRequest request) throws Exception { + } + */ + + + //todo 关注测试计划接口 + + //todo 取消关注测试计划接口 + + /* + todo 归档测试计划 + ·归档时要确定测试计划是完成状态 + ·归档时所有数据要备份一套新的(包括各种用例的基本信息)。 + ·关于环境:但是在查看归档内容的时候所属环境展示什么?只展示名字吗? + ·关于用例:那么是要在测试计划里能查看到用例的具体信息吗? 不归档的测试计划能查看吗? + ·功能用例里涉及到评审相关的也要备份吗? + ·功能用例里关联的其他自动化用例信息也要备份吗? + ·缺陷的整个流转过程也是要备份吗? + ·关于报告: + ·备份到什么程度?还需要在报告列表中展示这些报告吗? + ·每个用例调试出来的报告要备份吗?全部都备份? + ·执行记录呢也要完全备份吗? + ·归档的测试计划从哪里看?在测试计划列表中混合着展示吗?还是提供一个单独的按钮/页面/模块单独展示这些归档了的东西? + */ } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanDTO.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanDTO.java deleted file mode 100644 index d96cfca523..0000000000 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.metersphere.plan.dto; - -import io.metersphere.plan.domain.TestPlan; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -@EqualsAndHashCode(callSuper = true) -@Data -public class TestPlanDTO extends TestPlan { - @Schema(description = "测试计划责任人", requiredMode = Schema.RequiredMode.NOT_REQUIRED) - private List principals; - - @Schema(description = "测试计划关注人") - private List followers; - - @Schema(description = "是否自定更新功能用例状态", requiredMode = Schema.RequiredMode.REQUIRED) - private boolean automaticStatusUpdate; - - @Schema(description = "是否允许重复添加用例", requiredMode = Schema.RequiredMode.REQUIRED) - private boolean repeatCase; - - @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) - private int passThreshold = 100; -} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java new file mode 100644 index 0000000000..933c084bae --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/TestPlanQueryConditions.java @@ -0,0 +1,37 @@ +package io.metersphere.plan.dto; + +import io.metersphere.sdk.constants.TestPlanConstants; +import io.metersphere.system.dto.sdk.BaseCondition; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +/** + * 测试计划条件查询 + */ +@Data +@NoArgsConstructor +public class TestPlanQueryConditions { + //模块ID + private List moduleIds; + + //项目ID + private String projectId; + + //测试计划所属GroupId + private String groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID; + + //查询条件 + private BaseCondition condition = new BaseCondition(); + + //隐藏的测试计划ID + public List hiddenIds = new ArrayList<>(); + + public TestPlanQueryConditions(List moduleIds,String projectId,BaseCondition condition){ + this.moduleIds = moduleIds; + this.projectId = projectId; + this.condition = condition; + } +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanBatchProcessRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanBatchProcessRequest.java new file mode 100644 index 0000000000..1f282cb6b7 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanBatchProcessRequest.java @@ -0,0 +1,22 @@ +package io.metersphere.plan.dto.request; + +import io.metersphere.system.dto.table.TableBatchProcessDTO; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = false) +public class TestPlanBatchProcessRequest extends TableBatchProcessDTO { + + @Schema(description = "项目ID") + @NotBlank(message = "{id must not be blank}") + private String projectId; + + @Schema(description = "模块ID") + private List moduleIds; + +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java new file mode 100644 index 0000000000..3697317701 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanCreateRequest.java @@ -0,0 +1,65 @@ +package io.metersphere.plan.dto.request; + +import io.metersphere.sdk.constants.ModuleConstants; +import io.metersphere.sdk.constants.TestPlanConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; + +@Data +public class TestPlanCreateRequest { + @Schema(description = "测试计划所属项目", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.project_id.not_blank}") + @Size(min = 1, max = 50, message = "{test_plan.project_id.length_range}") + private String projectId; + + @Schema(description = "测试计划组ID;测试计划要改为树结构。最上层的为root,其余则是父节点ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.parent_id.not_blank}") + @Size(min = 1, max = 50, message = "{test_plan.parent_id.length_range}") + private String groupId = TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID; + + @Schema(description = "测试计划名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.name.not_blank}") + @Size(min = 1, max = 255, message = "{test_plan.name.length_range}") + private String name; + + + @Schema(description = "测试计划模块ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{test_plan.module_id.not_blank}") + @Size(min = 1, max = 50, message = "{test_plan.parent_id.length_range}") + private String moduleId = ModuleConstants.DEFAULT_NODE_ID; + + @Schema(description = "计划开始时间") + private Long plannedStartTime; + + @Schema(description = "计划结束时间") + private Long plannedEndTime; + + @Schema(description = "标签") + private LinkedHashSet< + @NotBlank + String> tags; + + @Schema(description = "描述") + private String description; + + @Schema(description = "是否自定更新功能用例状态", requiredMode = Schema.RequiredMode.REQUIRED) + private boolean automaticStatusUpdate; + + @Schema(description = "是否允许重复添加用例", requiredMode = Schema.RequiredMode.REQUIRED) + private boolean repeatCase; + + @Schema(description = "测试计划通过阈值;0-100", requiredMode = Schema.RequiredMode.REQUIRED) + @Max(value = 100, message = "{test_plan.pass_threshold.max}") + private double passThreshold = 100; + + public List getTags() { + return tags == null ? null : new ArrayList<>(tags); + } +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java new file mode 100644 index 0000000000..2337b21f88 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java @@ -0,0 +1,25 @@ +package io.metersphere.plan.dto.request; + +import io.metersphere.system.dto.sdk.BasePageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = false) +public class TestPlanTableRequest extends BasePageRequest { + @Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)") + private List moduleIds; + + @Schema(description = "项目ID") + @NotBlank(message = "{id must not be blank}") + private String projectId; + + public TestPlanTableRequest() { + this.setCurrent(1); + this.setPageSize(5); + } +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java new file mode 100644 index 0000000000..81b12ad496 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/response/TestPlanResponse.java @@ -0,0 +1,41 @@ +package io.metersphere.plan.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class TestPlanResponse { + //:ID、计划名称、计划状态、测试进度、通过率、用例数、定时任务、bug数、创建人、创建时间、模块 + @Schema(description = "测试计划ID") + private String id; + @Schema(description = "测试计划编号") + private long num; + @Schema(description = "名称") + private String name; + @Schema(description = "状态") + private String status; + @Schema(description = "测试进度") + private String testProgress; + @Schema(description = "通过率") + private String passRate; + @Schema(description = "功能用例数") + private long functionalCaseCount = -1; + @Schema(description = "接口用例数") + private long apiCaseCount = -1; + @Schema(description = "接口场景数") + private long apiScenarioCount = -1; + @Schema(description = "Bug数量") + private long bugCount = -1; + @Schema(description = "定时任务") + private String schedule; + @Schema(description = "创建人") + private String createUser; + @Schema(description = "创建时间") + private String createTime; + @Schema(description = "模块") + private String moduleName; + @Schema(description = "模块Id") + private String moduleId; + @Schema(description = "类型(测试计划组/测试计划)") + private String type; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java index f8156ea485..ce679e8a81 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.java @@ -1,11 +1,21 @@ package io.metersphere.plan.mapper; +import io.metersphere.plan.dto.TestPlanQueryConditions; +import io.metersphere.plan.dto.response.TestPlanResponse; +import io.metersphere.project.dto.ModuleCountDTO; import org.apache.ibatis.annotations.Param; import java.util.List; public interface ExtTestPlanMapper { - List selectByParentId(String parentId); + List selectByGroupId(String parentId); + + List selectByGroupIdList(@Param("list") List parentTestPlanId); + + List selectByConditions(TestPlanQueryConditions testPlanQueryConditions); + + List selectIdByConditions(TestPlanQueryConditions testPlanQueryConditions); + + List countModuleIdByKeywordAndFileType(TestPlanQueryConditions testPlanQueryConditions); - List selectByParentIdList(@Param("list") List parentTestPlanId); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml index 2e25d30d1d..faad1c0174 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanMapper.xml @@ -2,13 +2,70 @@ - + SELECT id FROM test_plan WHERE group_id = #{parentId} - + SELECT id FROM test_plan WHERE group_id IN #{item} + + + + + + + + t.group_id = #{groupId} + + AND t.project_id = #{projectId} + + + AND t.name like concat('%', #{condition.keyword}, '%') + + + AND t.module_id IN + + #{item} + + + + AND t.id NOT IN + + #{item} + + + + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java index d53a83175d..37986b66da 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java @@ -25,4 +25,6 @@ public interface ExtTestPlanModuleMapper { List selectIdsByProjectId(String projectId); List selectChildrenIdsSortByPos(String parentId); + + String selectNameById(String id); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml index 0ee559ed4d..e4c7d716f8 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml @@ -63,4 +63,9 @@ WHERE parent_id = #{0} ORDER BY pos ASC + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java new file mode 100644 index 0000000000..e2f4ab3a13 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanLogService.java @@ -0,0 +1,98 @@ +package io.metersphere.plan.service; + +import io.metersphere.plan.domain.TestPlan; +import io.metersphere.project.domain.Project; +import io.metersphere.project.mapper.ProjectMapper; +import io.metersphere.sdk.constants.TestPlanConstants; +import io.metersphere.sdk.util.JSON; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.dto.builder.LogDTOBuilder; +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.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional(rollbackFor = Exception.class) +public class TestPlanLogService { + + private String logModule = OperationLogModule.TEST_PLAN; + + @Resource + private ProjectMapper projectMapper; + @Resource + private OperationLogService operationLogService; + + public void saveAddLog(TestPlan module, String operator, String requestUrl, String requestMethod) { + Project project = projectMapper.selectByPrimaryKey(module.getProjectId()); + LogDTO dto = LogDTOBuilder.builder() + .projectId(module.getProjectId()) + .organizationId(project.getOrganizationId()) + .type(OperationLogType.ADD.name()) + .module(logModule) + .method(requestMethod) + .path(requestUrl) + .sourceId(module.getId()) + .content(module.getName()) + .originalValue(JSON.toJSONBytes(module)) + .createUser(operator) + .build().getLogDTO(); + operationLogService.add(dto); + } + + public void saveUpdateLog(TestPlan oldTestPlan, TestPlan newTestPlan, String projectId, String operator, String requestUrl, String requestMethod) { + Project project = projectMapper.selectByPrimaryKey(projectId); + LogDTO dto = LogDTOBuilder.builder() + .projectId(projectId) + .organizationId(project.getOrganizationId()) + .type(OperationLogType.UPDATE.name()) + .module(logModule) + .method(requestMethod) + .path(requestUrl) + .sourceId(newTestPlan.getId()) + .content(newTestPlan.getName()) + .originalValue(JSON.toJSONBytes(oldTestPlan)) + .modifiedValue(JSON.toJSONBytes(newTestPlan)) + .createUser(operator) + .build().getLogDTO(); + operationLogService.add(dto); + } + + public void saveDeleteLog(TestPlan deleteTestPlan, List testPlanItemList, String operator, String requestUrl, String requestMethod) { + Project project = projectMapper.selectByPrimaryKey(deleteTestPlan.getProjectId()); + LogDTO dto = LogDTOBuilder.builder() + .projectId(deleteTestPlan.getProjectId()) + .organizationId(project.getOrganizationId()) + .type(OperationLogType.DELETE.name()) + .module(logModule) + .method(requestMethod) + .path(requestUrl) + .sourceId(deleteTestPlan.getId()) + .content(this.generateTestPlanDeleteContent(deleteTestPlan, testPlanItemList)) + .originalValue(JSON.toJSONBytes(deleteTestPlan)) + .createUser(operator) + .build().getLogDTO(); + operationLogService.add(dto); + } + + private String generateTestPlanDeleteContent(TestPlan deleteTestPlan, List testPlanItemList) { + StringBuilder content = new StringBuilder(); + if(StringUtils.equals(deleteTestPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)){ + content.append(Translator.get("log.delete.test_plan_group")).append(":").append(deleteTestPlan.getName()).append(StringUtils.SPACE); + } + if(CollectionUtils.isNotEmpty(testPlanItemList)){ + List testPlanNameList = testPlanItemList.stream().map(TestPlan::getName).toList(); + String testPlanNamesString = StringUtils.join(testPlanNameList,","); + content.append(Translator.get("log.delete.test_plan")).append(":").append(testPlanNamesString).append(StringUtils.SPACE); + } + return content.toString(); + } + +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java new file mode 100644 index 0000000000..5cad541976 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java @@ -0,0 +1,51 @@ +package io.metersphere.plan.service; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.metersphere.plan.dto.TestPlanQueryConditions; +import io.metersphere.plan.dto.request.TestPlanTableRequest; +import io.metersphere.plan.dto.response.TestPlanResponse; +import io.metersphere.plan.mapper.ExtTestPlanMapper; +import io.metersphere.project.dto.ModuleCountDTO; +import io.metersphere.system.utils.PageUtils; +import io.metersphere.system.utils.Pager; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +@Service +@Transactional(rollbackFor = Exception.class) +public class TestPlanManagementService { + @Resource + private ExtTestPlanMapper extTestPlanMapper; + @Resource + private TestPlanModuleService testPlanModuleService; + + public Map moduleCount(TestPlanTableRequest request) { + //查出每个模块节点下的资源数量。 不需要按照模块进行筛选 + TestPlanQueryConditions testPlanQueryConditions = new TestPlanQueryConditions(null, request.getProjectId(), request); + List moduleCountDTOList = extTestPlanMapper.countModuleIdByKeywordAndFileType(testPlanQueryConditions); + Map moduleCountMap = testPlanModuleService.getModuleCountMap(request.getProjectId(), moduleCountDTOList); + + return moduleCountMap; + } + + public Pager> page(TestPlanTableRequest request) { + Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), + StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "t.update_time desc"); + return PageUtils.setPageInfo(page, this.getTableList(request)); + } + + private List getTableList(TestPlanTableRequest request) { + List testPlanResponses = extTestPlanMapper.selectByConditions(new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request)); + testPlanResponses.forEach(item -> { + item.setModuleName(testPlanModuleService.getNameById(item.getModuleId())); + //todo 定时任务相关信息处理 + }); + return testPlanResponses; + } +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleLogService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleLogService.java index c6229048ae..af9b1cd1a8 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleLogService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleLogService.java @@ -73,7 +73,7 @@ public class TestPlanModuleLogService { .method(requestMethod) .path(requestUrl) .sourceId(deleteModule.getId()) - .content(deleteModule.getName() + " " + Translator.get("file.log.delete_module")) + .content(deleteModule.getName() + " " + Translator.get("log.delete_module")) .originalValue(JSON.toJSONBytes(deleteModule)) .createUser(operator) .build().getLogDTO(); diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java index 0ccbc0036f..852ccf338f 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanModuleService.java @@ -1,5 +1,6 @@ package io.metersphere.plan.service; +import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanModuleCreateRequest; import io.metersphere.plan.dto.request.TestPlanModuleUpdateRequest; import io.metersphere.plan.mapper.ExtTestPlanModuleMapper; @@ -43,6 +44,8 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP protected SqlSessionFactory sqlSessionFactory; @Resource private TestPlanModuleLogService testPlanModuleLogService; + @Resource + private TestPlanService testPlanService; public List getTree(String projectId) { List fileModuleList = extTestPlanModuleMapper.selectBaseByProjectId(projectId); @@ -128,7 +131,7 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP public void update(TestPlanModuleUpdateRequest request, String userId,String requestUrl,String requestMethod) { TestPlanModule module = testPlanModuleMapper.selectByPrimaryKey(request.getId()); if (module == null) { - throw new MSException("file_module.not.exist"); + throw new MSException("module.not.exist"); } TestPlanModule updateModule = new TestPlanModule(); updateModule.setId(request.getId()); @@ -144,25 +147,29 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP } - public void deleteModule(String deleteId, String currentUser,String requestUrl,String requestMethod) { + public void deleteModule(String deleteId, String operator, String requestUrl, String requestMethod) { TestPlanModule deleteModule = testPlanModuleMapper.selectByPrimaryKey(deleteId); if (deleteModule != null) { - this.deleteModule(Collections.singletonList(deleteId)); + this.deleteModule(Collections.singletonList(deleteId), operator, requestUrl, requestMethod); //记录日志 - testPlanModuleLogService.saveDeleteLog(deleteModule, currentUser,requestUrl,requestMethod); + testPlanModuleLogService.saveDeleteLog(deleteModule, operator, requestUrl, requestMethod); } } - public void deleteModule(List deleteIds) { + + public void deleteModule(List deleteIds, String operator, String requestUrl, String requestMethod) { if (CollectionUtils.isEmpty(deleteIds)) { return; } extTestPlanModuleMapper.deleteByIds(deleteIds); - //todo:删除测试计划 + TestPlanBatchProcessRequest request = new TestPlanBatchProcessRequest(); + request.setModuleIds(deleteIds); + request.setSelectAll(true); + testPlanService.delete(request, operator, requestUrl, requestMethod); List childrenIds = extTestPlanModuleMapper.selectChildrenIdsByParentIds(deleteIds); if (CollectionUtils.isNotEmpty(childrenIds)) { - deleteModule(childrenIds); + deleteModule(childrenIds, operator, requestUrl, requestMethod); } } @@ -227,7 +234,7 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP public void deleteResources(String projectId) { List fileModuleIdList = extTestPlanModuleMapper.selectIdsByProjectId(projectId); if (CollectionUtils.isNotEmpty(fileModuleIdList)) { - this.deleteModule(fileModuleIdList); + this.deleteModule(fileModuleIdList, "SCHEDULE", "none", "none"); } } @@ -247,4 +254,7 @@ public class TestPlanModuleService extends ModuleTreeService implements CleanupP } } + public String getNameById(String id) { + return extTestPlanModuleMapper.selectNameById(id); + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java deleted file mode 100644 index c56f1d6fea..0000000000 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.metersphere.plan.service; - -import io.metersphere.plan.domain.TestPlanPrincipal; -import io.metersphere.plan.mapper.TestPlanPrincipalMapper; -import jakarta.annotation.Resource; -import org.apache.ibatis.session.ExecutorType; -import org.apache.ibatis.session.SqlSession; -import org.apache.ibatis.session.SqlSessionFactory; -import org.mybatis.spring.SqlSessionUtils; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Service -@Transactional(rollbackFor = Exception.class) -public class TestPlanPrincipalService { - - @Resource - private SqlSessionFactory sqlSessionFactory; - - public void batchSave(List testPlanPrincipalList) { - SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); - TestPlanPrincipalMapper testPlanPrincipalMapper = sqlSession.getMapper(TestPlanPrincipalMapper.class); - try { - int insertIndex = 0; - for (TestPlanPrincipal testPlanPrincipal : testPlanPrincipalList) { - testPlanPrincipalMapper.insert(testPlanPrincipal); - insertIndex++; - if (insertIndex % 50 == 0) { - sqlSession.flushStatements(); - } - } - sqlSession.flushStatements(); - } finally { - SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); - } - } -} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java index ecabc3861b..6524fd94b6 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java @@ -1,39 +1,49 @@ package io.metersphere.plan.service; -import io.metersphere.plan.domain.*; -import io.metersphere.plan.dto.TestPlanDTO; +import io.metersphere.plan.domain.TestPlan; +import io.metersphere.plan.domain.TestPlanConfig; +import io.metersphere.plan.domain.TestPlanExample; +import io.metersphere.plan.dto.TestPlanQueryConditions; +import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; +import io.metersphere.plan.dto.request.TestPlanCreateRequest; +import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.mapper.ExtTestPlanMapper; import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanMapper; +import io.metersphere.sdk.constants.ApplicationNumScope; +import io.metersphere.sdk.constants.ModuleConstants; +import io.metersphere.sdk.constants.TestPlanConstants; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.domain.TestPlanModuleExample; +import io.metersphere.system.mapper.TestPlanModuleMapper; import io.metersphere.system.uid.IDGenerator; +import io.metersphere.system.uid.NumGenerator; import jakarta.annotation.Resource; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import java.util.ArrayList; import java.util.List; @Service @Transactional(rollbackFor = Exception.class) public class TestPlanService { + private static final long MAX_TEST_PLAN_SIZE = 999; @Resource private TestPlanMapper testPlanMapper; @Resource private ExtTestPlanMapper extTestPlanMapper; @Resource private TestPlanConfigMapper testPlanConfigMapper; - + @Resource + private TestPlanLogService testPlanLogService; + @Resource + private TestPlanModuleMapper testPlanModuleMapper; @Resource private TestPlanConfigService testPlanConfigService; - @Resource - private TestPlanPrincipalService testPlanPrincipalService; + @Resource private TestPlanFollowerService testPlanFollowerService; @Resource @@ -47,103 +57,134 @@ public class TestPlanService { @Resource private TestPlanFunctionCaseService testPlanFunctionCaseService; - public TestPlanDTO add(@NotNull TestPlanDTO testPlanCreateRequest) { - if (StringUtils.equals(testPlanCreateRequest.getParentId(), testPlanCreateRequest.getId())) { - throw new MSException("The parent test plan cannot be the same as the current test plan!"); + public void checkModule(String moduleId) { + if (!StringUtils.equals(moduleId, ModuleConstants.DEFAULT_NODE_ID)) { + TestPlanModuleExample example = new TestPlanModuleExample(); + example.createCriteria().andIdEqualTo(moduleId); + if (testPlanModuleMapper.countByExample(example) == 0) { + throw new MSException("module.not.exist"); + } } + } - if (StringUtils.isBlank(testPlanCreateRequest.getId())) { - testPlanCreateRequest.setId(IDGenerator.nextStr()); - } - testPlanCreateRequest.setCreateTime(System.currentTimeMillis()); - testPlanCreateRequest.setUpdateTime(System.currentTimeMillis()); + public String add(TestPlanCreateRequest testPlanCreateRequest, String operator, String requestUrl, String requestMethod) { + //检查模块的合法性 + this.checkModule(testPlanCreateRequest.getModuleId()); - TestPlan testPlan = new TestPlan(); - BeanUtils.copyBean(testPlan, testPlanCreateRequest); - testPlanMapper.insert(testPlan); + TestPlan createTestPlan = new TestPlan(); + BeanUtils.copyBean(createTestPlan, testPlanCreateRequest); + this.validateTestPlan(createTestPlan); + + createTestPlan.setId(IDGenerator.nextStr()); + long operateTime = System.currentTimeMillis(); + createTestPlan.setNum(NumGenerator.nextNum(testPlanCreateRequest.getProjectId(), ApplicationNumScope.TEST_PLAN)); + createTestPlan.setCreateUser(operator); + createTestPlan.setUpdateUser(operator); + createTestPlan.setCreateTime(operateTime); + createTestPlan.setUpdateTime(operateTime); + createTestPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED); + createTestPlan.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN); + testPlanMapper.insert(createTestPlan); TestPlanConfig testPlanConfig = new TestPlanConfig(); - testPlanConfig.setTestPlanId(testPlan.getId()); + testPlanConfig.setTestPlanId(createTestPlan.getId()); testPlanConfig.setAutomaticStatusUpdate(testPlanCreateRequest.isAutomaticStatusUpdate()); testPlanConfig.setRepeatCase(testPlanCreateRequest.isRepeatCase()); testPlanConfig.setPassThreshold(testPlanCreateRequest.getPassThreshold()); testPlanConfigMapper.insert(testPlanConfig); - if (CollectionUtils.isNotEmpty(testPlanCreateRequest.getFollowers())) { - List testPlanFollowerList = new ArrayList<>(); - for (String follower : testPlanCreateRequest.getFollowers()) { - TestPlanFollower testPlanFollower = new TestPlanFollower(); - testPlanFollower.setTestPlanId(testPlan.getId()); - testPlanFollower.setUserId(follower); - testPlanFollowerList.add(testPlanFollower); - } - testPlanFollowerService.batchSave(testPlanFollowerList); - } + testPlanLogService.saveAddLog(createTestPlan, operator, requestUrl, requestMethod); - if (CollectionUtils.isNotEmpty(testPlanCreateRequest.getPrincipals())) { - List testPlanPrincipalList = new ArrayList<>(); - for (String principal : testPlanCreateRequest.getPrincipals()) { - TestPlanPrincipal testPlanPrincipal = new TestPlanPrincipal(); - testPlanPrincipal.setTestPlanId(testPlan.getId()); - testPlanPrincipal.setUserId(principal); - testPlanPrincipalList.add(testPlanPrincipal); - } - testPlanPrincipalService.batchSave(testPlanPrincipalList); - } - return testPlanCreateRequest; + return createTestPlan.getId(); } - public void batchDelete(List idList) { + private void validateTestPlan(TestPlan testPlan) { + if (StringUtils.isBlank(testPlan.getName())) { + throw new MSException(Translator.get("test_plan.name.not_blank")); + } TestPlanExample example = new TestPlanExample(); - example.createCriteria().andIdIn(idList); - testPlanMapper.deleteByExample(example); + if (StringUtils.isBlank(testPlan.getId())) { - this.cascadeDelete(idList); + TestPlanExample.Criteria criteria = example.createCriteria(); + //测试计划第一层的数据还不能超过1000个 + criteria.andGroupIdEqualTo(TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID); + if (testPlanMapper.countByExample(example) >= MAX_TEST_PLAN_SIZE) { + throw new MSException(Translator.getWithArgs("test_plan.too_many", MAX_TEST_PLAN_SIZE)); + } + example.clear(); + example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()); + if (testPlanMapper.countByExample(example) > 0) { + throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); + } + } else { + example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()).andIdNotEqualTo(testPlan.getId()); + if (testPlanMapper.countByExample(example) > 0) { + throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName()); + } + } } - public void delete(@NotBlank String id) { + public void delete(String id, String operator, String requestUrl, String requestMethod) { + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id); + testPlanMapper.deleteByPrimaryKey(id); + //级联删除 + this.cascadeDeleteTestPlan(id); TestPlanExample example = new TestPlanExample(); - example.createCriteria().andIdEqualTo(id); - testPlanMapper.deleteByExample(example); - this.cascadeDelete(id); + example.createCriteria().andGroupIdEqualTo(id); + List testPlanItemList = testPlanMapper.selectByExample(example); + testPlanItemList.forEach(item -> this.cascadeDeleteTestPlan(item.getId())); + //记录日志 + testPlanLogService.saveDeleteLog(testPlan, testPlanItemList, operator, requestUrl, requestMethod); } - public void deleteByParentId(String parentTestPlanId) { - List childrenTestPlanIdList = extTestPlanMapper.selectByParentId(parentTestPlanId); - if (CollectionUtils.isNotEmpty(childrenTestPlanIdList)) { - this.batchDelete(childrenTestPlanIdList); + public void delete(TestPlanBatchProcessRequest request, String operator, String requestUrl, String requestMethod) { + List deleteIdList = request.getSelectIds(); + if (request.isSelectAll()) { + TestPlanQueryConditions testPlanQueryConditions = new TestPlanQueryConditions(request.getModuleIds(), request.getProjectId(), request.getCondition()); + testPlanQueryConditions.setHiddenIds(request.getExcludeIds()); + deleteIdList = extTestPlanMapper.selectIdByConditions(testPlanQueryConditions); } + deleteIdList.forEach(testPlanId -> { + this.delete(testPlanId, operator, requestUrl, requestMethod); + }); } - @Validated - public void deleteBatchByParentId(List parentTestPlanId) { - List childrenTestPlanIdList = extTestPlanMapper.selectByParentIdList(parentTestPlanId); - if (CollectionUtils.isNotEmpty(childrenTestPlanIdList)) { - this.batchDelete(childrenTestPlanIdList); - } - } - - private void cascadeDelete(String id) { - //删除子计划 - this.deleteByParentId(id); + //删除测试计划以及其他的级联数据 + private void cascadeDeleteTestPlan(String testPlanId) { + testPlanMapper.deleteByPrimaryKey(testPlanId); //删除当前计划对应的资源 - this.testPlanConfigService.delete(id); - this.testPlanFunctionCaseService.deleteByTestPlanId(id); - this.testPlanApiCaseService.deleteByTestPlanId(id); - this.testPlanApiScenarioService.deleteByTestPlanId(id); - this.testPlanUiScenarioService.deleteByTestPlanId(id); - this.testPlanLoadCaseService.deleteByTestPlanId(id); + /* + todo + this.testPlanConfigService.delete(testPlanId); + this.testPlanFunctionCaseService.deleteByTestPlanId(testPlanId); + this.testPlanApiCaseService.deleteByTestPlanId(testPlanId); + this.testPlanApiScenarioService.deleteByTestPlanId(testPlanId); + this.testPlanUiScenarioService.deleteByTestPlanId(testPlanId); + this.testPlanLoadCaseService.deleteByTestPlanId(testPlanId); + 删除计划的关注者 + 删除计划报告 + 删除计划定时任务 + */ + } - private void cascadeDelete(List idList) { - //删除子计划 - this.deleteBatchByParentId(idList); - //删除当前计划对应的资源 - this.testPlanConfigService.deleteBatch(idList); - this.testPlanFunctionCaseService.deleteBatchByTestPlanId(idList); - this.testPlanApiCaseService.deleteBatchByTestPlanId(idList); - this.testPlanApiScenarioService.deleteBatchByTestPlanId(idList); - this.testPlanUiScenarioService.deleteBatchByTestPlanId(idList); - this.testPlanLoadCaseService.deleteBatchByTestPlanId(idList); + public TestPlan getById(String id) { + return testPlanMapper.selectByPrimaryKey(id); + } + + + public TestPlanResponse getCount(String id) { + TestPlanResponse response = new TestPlanResponse(); + response.setId(id); + /* + todo 统计:测试进度、通过率、用例数、Bug数量(这些比较慢的查询,是否需要另开接口查询) + Q:测试计划组需要查询这些数据吗? + */ + response.setFunctionalCaseCount(0); + response.setApiCaseCount(0); + response.setApiScenarioCount(0); + response.setPassRate("3.14%"); + response.setTestProgress("15.92%"); + return response; } } diff --git a/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml b/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml index 87bddf678c..ef171f023d 100644 --- a/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml +++ b/backend/services/test-plan/src/main/resources/testPlanGeneratorConfig.xml @@ -54,25 +54,29 @@ - - - - - + +
+ +
+