From 3a1992cfb0591cf79d23f15212113872cb39a2d0 Mon Sep 17 00:00:00 2001 From: shiziyuan9527 Date: Mon, 7 Nov 2022 18:48:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA):=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E5=A2=9E=E5=8A=A0=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=88=A0=E9=99=A4=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --story=1010195 --user=李玉号 【测试计划】测试计划新增批量删除功能 https://www.tapd.cn/55049933/s/1291099 --- .../listener/TestPlanDeletedListener.java | 22 ++++- .../service/plan/TestPlanApiCaseService.java | 9 ++ .../plan/TestPlanScenarioCaseService.java | 13 +++ .../constants/PermissionConstants.java | 1 + .../service/BaseScheduleService.java | 9 ++ .../listener/TestPlanDeletedListener.java | 19 ++++- .../plan/service/TestPlanLoadCaseService.java | 9 ++ .../controller/TestPlanController.java | 8 ++ .../plan/request/BatchOperateRequest.java | 16 ++++ .../plan/service/TestPlanFollowService.java | 11 +++ .../service/TestPlanPrincipalService.java | 11 +++ .../plan/service/TestPlanReportService.java | 8 ++ .../plan/service/TestPlanService.java | 82 +++++++++++++++++-- .../frontend/src/api/remote/plan/test-plan.js | 4 + .../business/plan/components/TestPlanList.vue | 33 +++++++- test-track/frontend/src/i18n/lang/en-US.js | 3 + test-track/frontend/src/i18n/lang/zh-CN.js | 3 + test-track/frontend/src/i18n/lang/zh-TW.js | 3 + 18 files changed, 247 insertions(+), 17 deletions(-) create mode 100644 test-track/backend/src/main/java/io/metersphere/plan/request/BatchOperateRequest.java diff --git a/api-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java b/api-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java index 21e3e50ebc..137b4c19fa 100644 --- a/api-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java +++ b/api-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java @@ -1,14 +1,18 @@ package io.metersphere.listener; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import io.metersphere.commons.constants.KafkaTopicConstants; import io.metersphere.commons.utils.LogUtil; import io.metersphere.service.plan.TestPlanApiCaseService; import io.metersphere.service.plan.TestPlanScenarioCaseService; +import org.apache.commons.collections.CollectionUtils; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.List; @Component public class TestPlanDeletedListener { @@ -18,12 +22,22 @@ public class TestPlanDeletedListener { private TestPlanApiCaseService testPlanApiCaseService; @Resource private TestPlanScenarioCaseService testPlanScenarioCaseService; + @Resource + private ObjectMapper objectMapper; @KafkaListener(id = CONSUME_ID, topics = KafkaTopicConstants.TEST_PLAN_DELETED_TOPIC, groupId = "${spring.application.name}") public void consume(ConsumerRecord record) { - String planId = record.value(); - LogUtil.info("api service consume TEST_PLAN_DELETED_TOPIC message, plan id: " + planId); - testPlanApiCaseService.deleteByPlanId(planId); - testPlanScenarioCaseService.deleteByPlanId(planId); + try { + List planIds = objectMapper.readValue(record.value(), new TypeReference<>() {}); + if (CollectionUtils.isEmpty(planIds)) { + return; + } + LogUtil.info("api service consume TEST_PLAN_DELETED_TOPIC message, planIds: ", planIds); + testPlanApiCaseService.deleteByPlanIds(planIds); + testPlanScenarioCaseService.deleteByPlanIds(planIds); + } catch (Exception e) { + LogUtil.error("api service consume TEST_PLAN_DELETED_TOPIC message error, planIds: " + record.value(), e); + } + } } diff --git a/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanApiCaseService.java b/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanApiCaseService.java index 25b92a5f4c..e15b05702e 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanApiCaseService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanApiCaseService.java @@ -186,6 +186,15 @@ public class TestPlanApiCaseService { return testPlanApiCaseMapper.deleteByExample(example); } + public void deleteByPlanIds(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return; + } + TestPlanApiCaseExample example = new TestPlanApiCaseExample(); + example.createCriteria().andTestPlanIdIn(planIds); + testPlanApiCaseMapper.deleteByExample(example); + } + public void deleteApiCaseBath(TestPlanApiCaseBatchRequest request) { List deleteIds = request.getIds(); if (request.getCondition() != null && request.getCondition().isSelectAll()) { diff --git a/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanScenarioCaseService.java b/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanScenarioCaseService.java index 18140bd40b..c59214afeb 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanScenarioCaseService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/plan/TestPlanScenarioCaseService.java @@ -385,6 +385,19 @@ public class TestPlanScenarioCaseService { deleteApiCaseBath(request); } + public void deleteByPlanIds(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return; + } + TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); + example.createCriteria().andTestPlanIdIn(planIds); + List testPlanApiScenarios = testPlanApiScenarioMapper.selectByExample(example); + List ids = testPlanApiScenarios.stream().map(TestPlanApiScenario::getId).collect(Collectors.toList()); + TestPlanScenarioCaseBatchRequest request = new TestPlanScenarioCaseBatchRequest(); + request.setIds(ids); + deleteApiCaseBath(request); + } + public void deleteByRelevanceProjectIds(String planId, List relevanceProjectIds) { TestPlanScenarioCaseBatchRequest request = new TestPlanScenarioCaseBatchRequest(); request.setIds(extTestPlanScenarioCaseMapper.getNotRelevanceCaseIds(planId, relevanceProjectIds)); diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/constants/PermissionConstants.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/constants/PermissionConstants.java index 48f06a681b..8e693fe7e5 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/constants/PermissionConstants.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/commons/constants/PermissionConstants.java @@ -108,6 +108,7 @@ public class PermissionConstants { public static final String PROJECT_TRACK_PLAN_READ_CREATE = "PROJECT_TRACK_PLAN:READ+CREATE"; public static final String PROJECT_TRACK_PLAN_READ_EDIT = "PROJECT_TRACK_PLAN:READ+EDIT"; public static final String PROJECT_TRACK_PLAN_READ_DELETE = "PROJECT_TRACK_PLAN:READ+DELETE"; + public static final String PROJECT_TRACK_PLAN_READ_BATCH_DELETE = "PROJECT_TRACK_PLAN:READ+BATCH_DELETE"; public static final String PROJECT_TRACK_PLAN_READ_SCHEDULE = "PROJECT_TRACK_PLAN:READ+SCHEDULE"; public static final String PROJECT_TRACK_PLAN_READ_RELEVANCE_OR_CANCEL = "PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL"; public static final String PROJECT_TRACK_PLAN_READ_RUN = "PROJECT_TRACK_PLAN:READ+RUN"; diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/BaseScheduleService.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/BaseScheduleService.java index beddcbcee8..6de9db203f 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/BaseScheduleService.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/service/BaseScheduleService.java @@ -92,6 +92,15 @@ public class BaseScheduleService { return scheduleMapper.deleteByExample(scheduleExample); } + public int deleteByResourceIds(List resourceIds, String group) { + ScheduleExample scheduleExample = new ScheduleExample(); + scheduleExample.createCriteria().andResourceIdIn(resourceIds); + for (String resourceId : resourceIds) { + removeJob(resourceId, group); + } + return scheduleMapper.deleteByExample(scheduleExample); + } + public int deleteByWorkspaceId(String workspaceId) { ScheduleExample scheduleExample = new ScheduleExample(); diff --git a/performance-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java b/performance-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java index bd6661e23c..255be2d2a1 100644 --- a/performance-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java +++ b/performance-test/backend/src/main/java/io/metersphere/listener/TestPlanDeletedListener.java @@ -1,13 +1,17 @@ package io.metersphere.listener; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import io.metersphere.commons.constants.KafkaTopicConstants; import io.metersphere.commons.utils.LogUtil; import io.metersphere.plan.service.TestPlanLoadCaseService; +import org.apache.commons.collections.CollectionUtils; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.util.List; @Component public class TestPlanDeletedListener { @@ -15,11 +19,20 @@ public class TestPlanDeletedListener { @Resource private TestPlanLoadCaseService testPlanLoadCaseService; + @Resource + private ObjectMapper objectMapper; @KafkaListener(id = CONSUME_ID, topics = KafkaTopicConstants.TEST_PLAN_DELETED_TOPIC, groupId = "${spring.application.name}") public void consume(ConsumerRecord record) { - String planId = record.value(); - LogUtil.info("performance service consume TEST_PLAN_DELETED_TOPIC message, plan id: " + planId); - testPlanLoadCaseService.deleteByPlanId(planId); + try { + List planIds = objectMapper.readValue(record.value(), new TypeReference<>() {}); + if (CollectionUtils.isEmpty(planIds)) { + return; + } + LogUtil.info("performance service consume TEST_PLAN_DELETED_TOPIC message, plans: " + planIds); + testPlanLoadCaseService.deleteByPlanIds(planIds); + } catch (Exception e) { + LogUtil.error("performance service consume TEST_PLAN_DELETED_TOPIC message error, plans: " + record.value(), e); + } } } diff --git a/performance-test/backend/src/main/java/io/metersphere/plan/service/TestPlanLoadCaseService.java b/performance-test/backend/src/main/java/io/metersphere/plan/service/TestPlanLoadCaseService.java index 5d17e408ee..29047e6aaa 100644 --- a/performance-test/backend/src/main/java/io/metersphere/plan/service/TestPlanLoadCaseService.java +++ b/performance-test/backend/src/main/java/io/metersphere/plan/service/TestPlanLoadCaseService.java @@ -352,6 +352,15 @@ public class TestPlanLoadCaseService { testPlanLoadCaseMapper.deleteByExample(example); } + public void deleteByPlanIds(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return; + } + TestPlanLoadCaseExample example = new TestPlanLoadCaseExample(); + example.createCriteria().andTestPlanIdIn(planIds); + testPlanLoadCaseMapper.deleteByExample(example); + } + public List getAllCases(String planId) { List cases = extTestPlanLoadCaseMapper.getCases(planId, null); diff --git a/test-track/backend/src/main/java/io/metersphere/controller/TestPlanController.java b/test-track/backend/src/main/java/io/metersphere/controller/TestPlanController.java index 32484bcde1..d4bb1ca2d1 100644 --- a/test-track/backend/src/main/java/io/metersphere/controller/TestPlanController.java +++ b/test-track/backend/src/main/java/io/metersphere/controller/TestPlanController.java @@ -15,6 +15,7 @@ import io.metersphere.plan.dto.TestCaseReportStatusResultDTO; import io.metersphere.plan.dto.TestPlanDTO; import io.metersphere.plan.dto.TestPlanSimpleReportDTO; import io.metersphere.plan.request.AddTestPlanRequest; +import io.metersphere.plan.request.BatchOperateRequest; import io.metersphere.plan.request.QueryTestPlanRequest; import io.metersphere.plan.request.ScheduleInfoRequest; import io.metersphere.plan.request.api.TestPlanRunRequest; @@ -169,6 +170,13 @@ public class TestPlanController { return testPlanService.deleteTestPlan(testPlanId); } + @PostMapping("/delete/batch") + @RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_BATCH_DELETE) + @MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.BATCH_DEL, project = "#request.projectId", beforeEvent = "#msClass.getDeleteBatchLogDetails(#request)", msClass = TestPlanService.class) + public void deleteTestPlanBatch(@RequestBody BatchOperateRequest request) { + testPlanService.deleteTestPlanBatch(request); + } + @PostMapping("/relevance") @MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.ASSOCIATE_CASE, content = "#msClass.getLogDetails(#request)", msClass = TestPlanService.class) public void testPlanRelevance(@RequestBody PlanCaseRelevanceRequest request) { diff --git a/test-track/backend/src/main/java/io/metersphere/plan/request/BatchOperateRequest.java b/test-track/backend/src/main/java/io/metersphere/plan/request/BatchOperateRequest.java new file mode 100644 index 0000000000..2d2733af28 --- /dev/null +++ b/test-track/backend/src/main/java/io/metersphere/plan/request/BatchOperateRequest.java @@ -0,0 +1,16 @@ +package io.metersphere.plan.request; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class BatchOperateRequest { + private List ids; + boolean selectAll; + private List unSelectIds; + private QueryTestPlanRequest queryTestPlanRequest; + private String projectId; +} diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanFollowService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanFollowService.java index 48efd85c60..35a121c245 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanFollowService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanFollowService.java @@ -3,11 +3,13 @@ package io.metersphere.plan.service; import io.metersphere.base.domain.TestPlanFollow; import io.metersphere.base.domain.TestPlanFollowExample; import io.metersphere.base.mapper.TestPlanFollowMapper; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.util.List; @Service @Transactional(rollbackFor = Exception.class) @@ -26,6 +28,15 @@ public class TestPlanFollowService { testPlanFollowMapper.deleteByExample(example); } + public void deletePlanFollowByPlanIds(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return; + } + TestPlanFollowExample example = new TestPlanFollowExample(); + example.createCriteria().andTestPlanIdIn(planIds); + testPlanFollowMapper.deleteByExample(example); + } + public TestPlanFollow insert(TestPlanFollow testPlanFollow) { testPlanFollowMapper.insert(testPlanFollow); return testPlanFollow; diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java index 6d4d0fc1e1..3b6eddcf75 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanPrincipalService.java @@ -3,11 +3,13 @@ package io.metersphere.plan.service; import io.metersphere.base.domain.TestPlanPrincipal; import io.metersphere.base.domain.TestPlanPrincipalExample; import io.metersphere.base.mapper.TestPlanPrincipalMapper; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.util.List; @Service @Transactional(rollbackFor = Exception.class) @@ -26,6 +28,15 @@ public class TestPlanPrincipalService { testPlanPrincipalMapper.deleteByExample(example); } + public void deletePlanPrincipalByPlanIds(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return; + } + TestPlanPrincipalExample example = new TestPlanPrincipalExample(); + example.createCriteria().andTestPlanIdIn(planIds); + testPlanPrincipalMapper.deleteByExample(example); + } + public TestPlanPrincipal insert(TestPlanPrincipal testPlanPrincipal) { testPlanPrincipalMapper.insert(testPlanPrincipal); return testPlanPrincipal; diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java index 5f4f64e300..849a5f8765 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanReportService.java @@ -962,6 +962,14 @@ public class TestPlanReportService { this.delete(testPlanReportIdList); } + public void deleteByPlanIds(List planIds) { + TestPlanReportExample example = new TestPlanReportExample(); + example.createCriteria().andTestPlanIdIn(planIds); + List reportList = testPlanReportMapper.selectByExample(example); + List ids = reportList.stream().map(TestPlanReport::getId).collect(Collectors.toList()); + this.delete(ids); + } + public TestPlanSimpleReportDTO getShareDbReport(ShareInfo shareInfo, String reportId) { HttpHeaderUtils.runAsUser(shareInfo.getCreateUserId()); try { diff --git a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanService.java b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanService.java index 8ab24cf8bd..9c40f6dee0 100644 --- a/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanService.java +++ b/test-track/backend/src/main/java/io/metersphere/plan/service/TestPlanService.java @@ -1,5 +1,7 @@ package io.metersphere.plan.service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; @@ -22,6 +24,7 @@ import io.metersphere.log.vo.track.TestPlanReference; import io.metersphere.plan.dto.*; import io.metersphere.plan.job.TestPlanTestJob; import io.metersphere.plan.request.AddTestPlanRequest; +import io.metersphere.plan.request.BatchOperateRequest; import io.metersphere.plan.request.QueryTestPlanRequest; import io.metersphere.plan.request.ScheduleInfoRequest; import io.metersphere.plan.request.api.ApiPlanReportRequest; @@ -142,7 +145,8 @@ public class TestPlanService { private TestPlanExecutionQueueService testPlanExecutionQueueService; @Resource private KafkaTemplate kafkaTemplate; - + @Resource + private ObjectMapper objectMapper; public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) { if (getTestPlanByName(testPlan.getName()).size() > 0) { MSException.throwException(Translator.get("plan_name_already_exists")); @@ -302,7 +306,11 @@ public class TestPlanService { public int deleteTestPlan(String planId) { // 发送删除通知 - kafkaTemplate.send(KafkaTopicConstants.TEST_PLAN_DELETED_TOPIC, planId); + try { + kafkaTemplate.send(KafkaTopicConstants.TEST_PLAN_DELETED_TOPIC, objectMapper.writeValueAsString(List.of(planId))); + } catch (JsonProcessingException e) { + LogUtil.error("send msg to TEST_PLAN_DELETED_TOPIC error", e); + } testPlanPrincipalService.deleteTestPlanPrincipalByPlanId(planId); testPlanFollowService.deleteTestPlanFollowByPlanId(planId); @@ -316,6 +324,35 @@ public class TestPlanService { return testPlanMapper.deleteByPrimaryKey(planId); } + public int deleteTestPlans(List planIds) { + if (CollectionUtils.isEmpty(planIds)) { + return 0; + } + + TestPlanExample testPlanExample = new TestPlanExample(); + testPlanExample.createCriteria().andIdIn(planIds); + int deletedSize = testPlanMapper.deleteByExample(testPlanExample); + + testPlanPrincipalService.deletePlanPrincipalByPlanIds(planIds); + testPlanFollowService.deletePlanFollowByPlanIds(planIds); + + TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample(); + testPlanTestCaseExample.createCriteria().andPlanIdIn(planIds); + testPlanTestCaseMapper.deleteByExample(testPlanTestCaseExample); + + + testPlanReportService.deleteByPlanIds(planIds); + //删除定时任务 + baseScheduleService.deleteByResourceIds(planIds, ScheduleGroup.TEST_PLAN_TEST.name()); + + try { + kafkaTemplate.send(KafkaTopicConstants.TEST_PLAN_DELETED_TOPIC, objectMapper.writeValueAsString(planIds)); + } catch (Exception e) { + LogUtil.error("send msg to TEST_PLAN_DELETED_TOPIC error", e); + } + return deletedSize; + } + public void deleteTestCaseByPlanId(String testPlanId) { TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample(); testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(testPlanId); @@ -971,18 +1008,28 @@ public class TestPlanService { testPlanExample.createCriteria().andIdIn(ids); List planList = testPlanMapper.selectByExample(testPlanExample); if (CollectionUtils.isNotEmpty(planList)) { - List detailsList = new ArrayList<>(); - for (TestPlan plan : planList) { - List columns = ReflexObjectUtil.getColumns(planList.get(0), TestPlanReference.testPlanColumns); - OperatingLogDetails details = new OperatingLogDetails(JSON.toJSONString(plan.getId()), plan.getProjectId(), plan.getName(), plan.getCreator(), columns); - detailsList.add(details); - } - return JSON.toJSONString(detailsList); + List names = planList.stream().map(TestPlan::getName).collect(Collectors.toList()); + OperatingLogDetails details = new OperatingLogDetails(JSON.toJSONString(ids), planList.get(0).getProjectId(), String.join(",", names), planList.get(0).getCreator(), new LinkedList<>()); + return JSON.toJSONString(details); } } return null; } + public String getDeleteBatchLogDetails(BatchOperateRequest request) { + List ids = request.getIds(); + if (request.isSelectAll()) { + QueryTestPlanRequest queryTestPlanRequest = request.getQueryTestPlanRequest(); + request.getQueryTestPlanRequest().setOrders(ServiceUtils.getDefaultOrder(queryTestPlanRequest.getOrders())); + if (StringUtils.isNotBlank(queryTestPlanRequest.getProjectId())) { + request.getQueryTestPlanRequest().setProjectId(queryTestPlanRequest.getProjectId()); + } + List testPlans = extTestPlanMapper.list(queryTestPlanRequest); + ids = testPlans.stream().map(TestPlan::getId).collect(Collectors.toList()); + } + return getLogDetails(ids); + } + public String getLogDetails(String id) { TestPlan plan = testPlanMapper.selectByPrimaryKey(id); if (plan != null) { @@ -1893,4 +1940,21 @@ public class TestPlanService { testPlanMapper.updateByPrimaryKey(testPlan); } } + + public void deleteTestPlanBatch(BatchOperateRequest request) { + List ids = request.getIds(); + if (request.isSelectAll()) { + QueryTestPlanRequest queryTestPlanRequest = request.getQueryTestPlanRequest(); + request.getQueryTestPlanRequest().setOrders(ServiceUtils.getDefaultOrder(queryTestPlanRequest.getOrders())); + if (StringUtils.isNotBlank(queryTestPlanRequest.getProjectId())) { + request.getQueryTestPlanRequest().setProjectId(queryTestPlanRequest.getProjectId()); + } + List testPlans = extTestPlanMapper.list(queryTestPlanRequest); + ids = testPlans.stream().map(TestPlan::getId).collect(Collectors.toList()); + if (request.getUnSelectIds() != null) { + ids.removeAll(request.getUnSelectIds()); + } + } + this.deleteTestPlans(ids); + } } diff --git a/test-track/frontend/src/api/remote/plan/test-plan.js b/test-track/frontend/src/api/remote/plan/test-plan.js index 59523544b3..de894a9a79 100644 --- a/test-track/frontend/src/api/remote/plan/test-plan.js +++ b/test-track/frontend/src/api/remote/plan/test-plan.js @@ -277,6 +277,10 @@ export function updateBatchScheduleEnable(param) { return post(BASE_URL + 'schedule/Batch/updateEnable', param); } +export function batchDeletePlan(param) { + return post(BASE_URL + 'delete/batch', param); +} + export function createSchedule(param){ return post(BASE_URL + 'schedule/create',param); } diff --git a/test-track/frontend/src/business/plan/components/TestPlanList.vue b/test-track/frontend/src/business/plan/components/TestPlanList.vue index 085f1351be..ce199fcf9e 100644 --- a/test-track/frontend/src/business/plan/components/TestPlanList.vue +++ b/test-track/frontend/src/business/plan/components/TestPlanList.vue @@ -373,7 +373,7 @@ import { testPlanEditFollows, testPlanEditRunConfig, testPlanGetEnableScheduleCount, testPlanGetFollow, testPlanGetPrincipal, testPlanHaveExecCase, testPlanHaveUiCase, testPlanList, testPlanRun, testPlanRunBatch, - testPlanRunSave, testPlanUpdateScheduleEnable + testPlanRunSave, testPlanUpdateScheduleEnable, batchDeletePlan } from "@/api/remote/plan/test-plan"; import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn"; import MsTable from "metersphere-frontend/src/components/table/MsTable"; @@ -455,6 +455,11 @@ export default { name: this.$t('api_test.automation.batch_execute'), handleClick: this.handleBatchExecute, permissions: ['PROJECT_TRACK_PLAN:READ+SCHEDULE'] + }, + { + name: this.$t('commons.delete_batch'), + handleClick: this.handleBatchDelete, + permissions: ['PROJECT_TRACK_PLAN:READ+BATCH_DELETE'] } ], simpleOperators: [ @@ -620,6 +625,32 @@ export default { this.$refs.testPlanLitTable.isSelectDataAll(false); this.initTableData(); }, + handleBatchDelete() { + this.$confirm(this.$t('plan.batch_delete_tip').toString(), this.$t('commons.delete_batch').toString(), { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + type: 'warning', + }).then(() => { + let ids = [], param = {}; + param.projectId = getCurrentProjectID(); + if (this.condition.selectAll) { + param.unSelectIds = this.condition.unSelectIds; + param.selectAll = true; + param.queryTestPlanRequest = this.condition; + } else { + this.$refs.testPlanLitTable.selectRows.forEach((item) => { + ids.push(item.id) + }); + } + param.ids = ids; + this.cardLoading = batchDeletePlan(param).then(() => { + this.refresh(); + this.$success(this.$t('commons.delete_success')); + }); + }).catch(() => { + this.$info(this.$t('commons.delete_cancel')); + }); + }, handleBatchSwitch() { let param = []; let size = 0; diff --git a/test-track/frontend/src/i18n/lang/en-US.js b/test-track/frontend/src/i18n/lang/en-US.js index 93271564ab..9669b2b8f0 100644 --- a/test-track/frontend/src/i18n/lang/en-US.js +++ b/test-track/frontend/src/i18n/lang/en-US.js @@ -20,6 +20,9 @@ const message = { test_plan: "Test Plan", failure_times: "Failure times", } + }, + plan: { + batch_delete_tip: "Do you want to continue deleting the test plan?", } } export default { diff --git a/test-track/frontend/src/i18n/lang/zh-CN.js b/test-track/frontend/src/i18n/lang/zh-CN.js index 0c0085f50e..209c957af8 100644 --- a/test-track/frontend/src/i18n/lang/zh-CN.js +++ b/test-track/frontend/src/i18n/lang/zh-CN.js @@ -20,6 +20,9 @@ const message = { test_plan: "所属测试计划", failure_times: "失败次数", } + }, + plan: { + batch_delete_tip: "批量删除测试计划,是否继续?", } } diff --git a/test-track/frontend/src/i18n/lang/zh-TW.js b/test-track/frontend/src/i18n/lang/zh-TW.js index 3e0df8cc4b..eb63135d21 100644 --- a/test-track/frontend/src/i18n/lang/zh-TW.js +++ b/test-track/frontend/src/i18n/lang/zh-TW.js @@ -20,6 +20,9 @@ const message = { test_plan: "所屬測試計劃", failure_times: "失敗次數", } + }, + plan: { + batch_delete_tip: "批量刪除測試計劃,是否繼續?", } }