diff --git a/backend/framework/domain/src/main/java/io/metersphere/project/domain/Project.java b/backend/framework/domain/src/main/java/io/metersphere/project/domain/Project.java index 9b028355bc..56a1bb6093 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/project/domain/Project.java +++ b/backend/framework/domain/src/main/java/io/metersphere/project/domain/Project.java @@ -1,16 +1,12 @@ package io.metersphere.project.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 Project implements Serializable { @@ -63,6 +59,10 @@ public class Project implements Serializable { @Schema(description = "模块设置") private String moduleSetting; + @Schema(description = "全部资源池", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "{project.all_resource_pool.not_blank}", groups = {Created.class}) + private Boolean allResourcePool; + private static final long serialVersionUID = 1L; public enum Column { @@ -79,7 +79,8 @@ public class Project implements Serializable { deleted("deleted", "deleted", "BIT", false), deleteUser("delete_user", "deleteUser", "VARCHAR", false), enable("enable", "enable", "BIT", true), - moduleSetting("module_setting", "moduleSetting", "VARCHAR", false); + moduleSetting("module_setting", "moduleSetting", "VARCHAR", false), + allResourcePool("all_resource_pool", "allResourcePool", "BIT", false); private static final String BEGINNING_DELIMITER = "`"; diff --git a/backend/framework/domain/src/main/java/io/metersphere/project/domain/ProjectExample.java b/backend/framework/domain/src/main/java/io/metersphere/project/domain/ProjectExample.java index d612f745e0..60fc8d524a 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/project/domain/ProjectExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/project/domain/ProjectExample.java @@ -1023,6 +1023,66 @@ public class ProjectExample { addCriterion("module_setting not between", value1, value2, "moduleSetting"); return (Criteria) this; } + + public Criteria andAllResourcePoolIsNull() { + addCriterion("all_resource_pool is null"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolIsNotNull() { + addCriterion("all_resource_pool is not null"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolEqualTo(Boolean value) { + addCriterion("all_resource_pool =", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolNotEqualTo(Boolean value) { + addCriterion("all_resource_pool <>", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolGreaterThan(Boolean value) { + addCriterion("all_resource_pool >", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolGreaterThanOrEqualTo(Boolean value) { + addCriterion("all_resource_pool >=", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolLessThan(Boolean value) { + addCriterion("all_resource_pool <", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolLessThanOrEqualTo(Boolean value) { + addCriterion("all_resource_pool <=", value, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolIn(List values) { + addCriterion("all_resource_pool in", values, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolNotIn(List values) { + addCriterion("all_resource_pool not in", values, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolBetween(Boolean value1, Boolean value2) { + addCriterion("all_resource_pool between", value1, value2, "allResourcePool"); + return (Criteria) this; + } + + public Criteria andAllResourcePoolNotBetween(Boolean value1, Boolean value2) { + addCriterion("all_resource_pool not between", value1, value2, "allResourcePool"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/framework/domain/src/main/java/io/metersphere/project/mapper/ProjectMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/project/mapper/ProjectMapper.xml index 11ba3ab492..b7a3948a1a 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/project/mapper/ProjectMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/project/mapper/ProjectMapper.xml @@ -16,6 +16,7 @@ + @@ -77,7 +78,7 @@ id, num, organization_id, `name`, description, create_time, update_time, update_user, - create_user, delete_time, deleted, delete_user, `enable`, module_setting + create_user, delete_time, deleted, delete_user, `enable`, module_setting, all_resource_pool @@ -263,6 +272,9 @@ module_setting = #{record.moduleSetting,jdbcType=VARCHAR}, + + all_resource_pool = #{record.allResourcePool,jdbcType=BIT}, + @@ -283,7 +295,8 @@ deleted = #{record.deleted,jdbcType=BIT}, delete_user = #{record.deleteUser,jdbcType=VARCHAR}, `enable` = #{record.enable,jdbcType=BIT}, - module_setting = #{record.moduleSetting,jdbcType=VARCHAR} + module_setting = #{record.moduleSetting,jdbcType=VARCHAR}, + all_resource_pool = #{record.allResourcePool,jdbcType=BIT} @@ -330,6 +343,9 @@ module_setting = #{moduleSetting,jdbcType=VARCHAR}, + + all_resource_pool = #{allResourcePool,jdbcType=BIT}, + where id = #{id,jdbcType=VARCHAR} @@ -347,20 +363,23 @@ deleted = #{deleted,jdbcType=BIT}, delete_user = #{deleteUser,jdbcType=VARCHAR}, `enable` = #{enable,jdbcType=BIT}, - module_setting = #{moduleSetting,jdbcType=VARCHAR} + module_setting = #{moduleSetting,jdbcType=VARCHAR}, + all_resource_pool = #{allResourcePool,jdbcType=BIT} where id = #{id,jdbcType=VARCHAR} insert into project (id, num, organization_id, `name`, description, create_time, update_time, update_user, - create_user, delete_time, deleted, delete_user, `enable`, module_setting) + create_user, delete_time, deleted, delete_user, `enable`, module_setting, all_resource_pool + ) values (#{item.id,jdbcType=VARCHAR}, #{item.num,jdbcType=BIGINT}, #{item.organizationId,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.description,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR}, #{item.deleteTime,jdbcType=BIGINT}, #{item.deleted,jdbcType=BIT}, #{item.deleteUser,jdbcType=VARCHAR}, - #{item.enable,jdbcType=BIT}, #{item.moduleSetting,jdbcType=VARCHAR}) + #{item.enable,jdbcType=BIT}, #{item.moduleSetting,jdbcType=VARCHAR}, #{item.allResourcePool,jdbcType=BIT} + ) @@ -415,6 +434,9 @@ #{item.moduleSetting,jdbcType=VARCHAR} + + #{item.allResourcePool,jdbcType=BIT} + ) diff --git a/backend/framework/domain/src/main/resources/migration/3.4.0/ddl/V3.4.0_2__ga_ddl.sql b/backend/framework/domain/src/main/resources/migration/3.4.0/ddl/V3.4.0_2__ga_ddl.sql index d45ff3dc2d..7649742ffc 100644 --- a/backend/framework/domain/src/main/resources/migration/3.4.0/ddl/V3.4.0_2__ga_ddl.sql +++ b/backend/framework/domain/src/main/resources/migration/3.4.0/ddl/V3.4.0_2__ga_ddl.sql @@ -70,5 +70,11 @@ CREATE INDEX idx_start_time ON exec_task_item(start_time desc); CREATE INDEX idx_end_time ON exec_task_item(end_time desc); CREATE INDEX idx_executor ON exec_task_item(executor); + +ALTER TABLE project + ADD all_resource_pool BIT DEFAULT b'0' NOT NULL COMMENT '全部资源池'; + +CREATE INDEX idx_all_resource_pool ON project(all_resource_pool); + -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchEditRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchEditRequest.java index c2bee4bbea..769dc2eaa6 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchEditRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchEditRequest.java @@ -18,10 +18,7 @@ public class ApiCaseBatchEditRequest extends ApiTestCaseBatchRequest implements private static final long serialVersionUID = 1L; @Schema(description = "标签") - private LinkedHashSet< - @NotBlank - @Size(min = 1, max = 64, message = "{api_test_case.tag.length_range}") - String> tags; + private LinkedHashSet tags; @Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment") @NotBlank private String type; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiMockBatchEditRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiMockBatchEditRequest.java index 5c8170fa03..afdca4bda0 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiMockBatchEditRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiMockBatchEditRequest.java @@ -2,7 +2,6 @@ package io.metersphere.api.dto.definition; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,10 +17,7 @@ public class ApiMockBatchEditRequest extends ApiTestCaseBatchRequest implements private static final long serialVersionUID = 1L; @Schema(description = "标签") - private LinkedHashSet< - @NotBlank - @Size(min = 1, max = 64, message = "{api_test_case.tag.length_range}") - String> tags; + private LinkedHashSet tags; @Schema(description = "批量编辑的类型 状态 :Status,标签: Tags") @NotBlank private String type; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchEditRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchEditRequest.java index 4f9067998c..7ccdd59253 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchEditRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioBatchEditRequest.java @@ -18,10 +18,7 @@ public class ApiScenarioBatchEditRequest extends ApiScenarioBatchRequest impleme private static final long serialVersionUID = 1L; @Schema(description = "标签") - private LinkedHashSet< - @NotBlank - @Size(min = 1, max = 64, message = "{api_test_case.tag.length_range}") - String> tags; + private LinkedHashSet tags; @Schema(description = "批量编辑的类型 用例等级: Priority,状态 :Status,标签: Tags,用例环境: Environment") @NotBlank private String type; diff --git a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java index 6d82df6073..5b0ec8c952 100644 --- a/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java +++ b/backend/services/case-management/src/main/java/io/metersphere/functional/service/FunctionalCaseService.java @@ -1033,8 +1033,16 @@ public class FunctionalCaseService { functionalCase.setUpdateUser(userId); extFunctionalCaseMapper.batchUpdate(functionalCase, ids); } + } else if (request.isClear()){ + FunctionalCase functionalCase = new FunctionalCase(); + functionalCase.setTags(new ArrayList<>()); + functionalCase.setProjectId(request.getProjectId()); + functionalCase.setUpdateTime(System.currentTimeMillis()); + functionalCase.setUpdateUser(userId); + extFunctionalCaseMapper.batchUpdate(functionalCase, ids); } + } public Map moduleCount(FunctionalCasePageRequest request, boolean delete) { diff --git a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java index 37466a91ee..9b99cd94c0 100644 --- a/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java +++ b/backend/services/case-management/src/test/java/io/metersphere/functional/controller/FunctionalCaseControllerTests.java @@ -691,6 +691,34 @@ public class FunctionalCaseControllerTests extends BaseTest { this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request); functionalCase = functionalCaseMapper.selectByPrimaryKey("TEST_FUNCTIONAL_CASE_ID_1"); Assertions.assertTrue(CollectionUtils.isEmpty(functionalCase.getTags())); + request.setAppend(false); + request.setClear(false); + request.setTags(Arrays.asList("覆盖标签1", "覆盖标签2")); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request); + functionalCase = functionalCaseMapper.selectByPrimaryKey("TEST_FUNCTIONAL_CASE_ID_1"); + Assertions.assertTrue(CollectionUtils.isNotEmpty(functionalCase.getTags())); + request.setAppend(false); + request.setClear(false); + request.setTags(new ArrayList<>()); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request); + functionalCase = functionalCaseMapper.selectByPrimaryKey("TEST_FUNCTIONAL_CASE_ID_1"); + Assertions.assertTrue(CollectionUtils.isNotEmpty(functionalCase.getTags())); + request.setAppend(false); + request.setClear(true); + request.setTags(new ArrayList<>()); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request); + functionalCase = functionalCaseMapper.selectByPrimaryKey("TEST_FUNCTIONAL_CASE_ID_1"); + Assertions.assertTrue(CollectionUtils.isEmpty(functionalCase.getTags())); + request.setAppend(false); + request.setClear(false); + request.setTags(new ArrayList<>()); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_BATCH_EDIT_URL, request); + functionalCase = functionalCaseMapper.selectByPrimaryKey("TEST_FUNCTIONAL_CASE_ID_1"); + Assertions.assertTrue(CollectionUtils.isEmpty(functionalCase.getTags())); } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ProjectBaseRequest.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ProjectBaseRequest.java index 1b1a45113b..d372c8b10f 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ProjectBaseRequest.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ProjectBaseRequest.java @@ -32,6 +32,9 @@ public class ProjectBaseRequest { @Schema(description = "是否启用") private Boolean enable; + @Schema(description = "全部资源池") + private boolean allResourcePool = false; + @Schema(description = "模块设置", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private List moduleIds; diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/CommonProjectService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/CommonProjectService.java index e5a28970a5..ac1d0a2b4d 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/CommonProjectService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/CommonProjectService.java @@ -123,6 +123,7 @@ public class CommonProjectService { project.setUpdateUser(createUser); project.setCreateUser(createUser); project.setEnable(addProjectDTO.getEnable()); + project.setAllResourcePool(addProjectDTO.isAllResourcePool()); project.setDescription(addProjectDTO.getDescription()); addProjectDTO.setId(project.getId()); BeanUtils.copyBean(projectDTO, project); 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 b1f1d971b5..a9e758bb56 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 @@ -800,6 +800,14 @@ public class TestPlanService extends TestPlanBaseUtilsService { testPlan.setUpdateUser(userId); extTestPlanMapper.batchUpdate(testPlan, ids); } + } else if (request.isClear()){ + //替换标签 + TestPlan testPlan = new TestPlan(); + testPlan.setTags(new ArrayList<>()); + testPlan.setProjectId(request.getProjectId()); + testPlan.setUpdateTime(System.currentTimeMillis()); + testPlan.setUpdateUser(userId); + extTestPlanMapper.batchUpdate(testPlan, ids); } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java index 0bd031ebbb..b070a233b2 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java @@ -2425,6 +2425,28 @@ public class TestPlanTests extends BaseTest { this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_EDIT, request); testPlan = testPlanMapper.selectByPrimaryKey("wx_test_plan_id_1"); Assertions.assertTrue(CollectionUtils.isEmpty(testPlan.getTags())); + request.setTags(List.of("tag1")); + request.setAppend(false); + request.setClear(false); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_EDIT, request); + testPlan = testPlanMapper.selectByPrimaryKey("wx_test_plan_id_1"); + Assertions.assertTrue(CollectionUtils.isNotEmpty(testPlan.getTags())); + request.setTags(new ArrayList<>()); + request.setAppend(false); + request.setClear(false); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_EDIT, request); + testPlan = testPlanMapper.selectByPrimaryKey("wx_test_plan_id_1"); + Assertions.assertTrue(CollectionUtils.isNotEmpty(testPlan.getTags())); + request.setTags(new ArrayList<>()); + request.setAppend(false); + request.setClear(true); + request.setSelectAll(true); + this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_EDIT, request); + testPlan = testPlanMapper.selectByPrimaryKey("wx_test_plan_id_1"); + Assertions.assertTrue(CollectionUtils.isEmpty(testPlan.getTags())); + } @Test