diff --git a/backend/src/main/java/io/metersphere/base/domain/Issues.java b/backend/src/main/java/io/metersphere/base/domain/Issues.java index fafaa92c08..bc9814bfcd 100644 --- a/backend/src/main/java/io/metersphere/base/domain/Issues.java +++ b/backend/src/main/java/io/metersphere/base/domain/Issues.java @@ -28,5 +28,7 @@ public class Issues implements Serializable { private String projectName; + private String currentOwner; + private static final long serialVersionUID = 1L; -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/notice/service/MailService.java b/backend/src/main/java/io/metersphere/notice/service/MailService.java index c423e8e83b..4390e52190 100644 --- a/backend/src/main/java/io/metersphere/notice/service/MailService.java +++ b/backend/src/main/java/io/metersphere/notice/service/MailService.java @@ -76,7 +76,7 @@ public class MailService { "\n" + "
\n" + "

" + type + "定时任务结果通知

\n" + - "

尊敬的用户:您好,您所执行的" + testName + "运行失败,请点击报告链接查看

\n" + + "

尊敬的用户:您好,您所执行的" + testName + "运行失败

\n" + "
\n" + "\n" + ""; @@ -89,7 +89,7 @@ public class MailService { "\n" + "
\n" + "

" + type + "定时任务结果通知

\n" + - "

尊敬的用户:您好," + testName + "运行成功,请点击报告链接查看

\n" + + "

尊敬的用户:您好," + testName + "运行成功

\n" + "
\n" + "\n" + ""; diff --git a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java index 2c580d4b17..9c7e07647c 100644 --- a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java +++ b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java @@ -238,8 +238,17 @@ public class PerformanceTestService { startEngine(loadTest, engine, request.getTriggerMode()); if (request.getTriggerMode().equals("SCHEDULE")) { - List notice = noticeService.queryNotice(request.getId()); - mailService.sendHtml(engine.getReportId(), notice, "status", "performance"); + List notice = null; + try { + notice = noticeService.queryNotice(request.getId()); + } catch (Exception e) { + e.printStackTrace(); + } + try { + mailService.sendHtml(engine.getReportId(), notice, "status", "performance"); + } catch (Exception e) { + e.printStackTrace(); + } } return engine.getReportId(); } diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java index 664612f156..dd0921a569 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java @@ -67,7 +67,7 @@ public class TestCaseReviewController { @PostMapping("/edit") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) - public void editCaseReview(@RequestBody TestCaseReview testCaseReview) { + public void editCaseReview(@RequestBody SaveTestCaseReviewRequest testCaseReview) { testCaseReviewService.editCaseReview(testCaseReview); } diff --git a/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java b/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java index 7a4079c695..2587823c4b 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestCaseReviewService.java @@ -26,6 +26,8 @@ import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; @@ -54,6 +56,10 @@ public class TestCaseReviewService { ExtProjectMapper extProjectMapper; @Resource UserService userService; + @Resource + TestCaseMapper testCaseMapper; + @Resource + TestCaseReviewTestCaseMapper testCaseReviewTestCaseMapper; public void saveTestCaseReview(SaveTestCaseReviewRequest reviewRequest) { checkCaseReviewExist(reviewRequest); @@ -119,20 +125,87 @@ public class TestCaseReviewService { .collect(Collectors.toList()); UserExample userExample = new UserExample(); - userExample.createCriteria().andIdIn(userIds); - return userMapper.selectByExample(userExample); + UserExample.Criteria criteria = userExample.createCriteria(); + if (!CollectionUtils.isEmpty(userIds)) { + criteria.andIdIn(userIds); + return userMapper.selectByExample(userExample); + } + return new ArrayList<>(); } public List recent(String currentWorkspaceId) { return extTestCaseReviewMapper.listByWorkspaceId(currentWorkspaceId); } - public void editCaseReview(TestCaseReview testCaseReview) { + public void editCaseReview(SaveTestCaseReviewRequest testCaseReview) { + editCaseReviewer(testCaseReview); + editCaseReviewProject(testCaseReview); testCaseReview.setUpdateTime(System.currentTimeMillis()); checkCaseReviewExist(testCaseReview); testCaseReviewMapper.updateByPrimaryKeySelective(testCaseReview); } + private void editCaseReviewer(SaveTestCaseReviewRequest testCaseReview) { + // 要更新的reviewerIds + List reviewerIds = testCaseReview.getUserIds(); + + String id = testCaseReview.getId(); + TestCaseReviewUsersExample testCaseReviewUsersExample = new TestCaseReviewUsersExample(); + testCaseReviewUsersExample.createCriteria().andReviewIdEqualTo(id); + List testCaseReviewUsers = testCaseReviewUsersMapper.selectByExample(testCaseReviewUsersExample); + List dbReviewIds = testCaseReviewUsers.stream().map(TestCaseReviewUsers::getUserId).collect(Collectors.toList()); + + reviewerIds.forEach(reviewerId -> { + if (!dbReviewIds.contains(reviewerId)) { + TestCaseReviewUsers caseReviewUser = new TestCaseReviewUsers(); + caseReviewUser.setUserId(reviewerId); + caseReviewUser.setReviewId(id); + testCaseReviewUsersMapper.insertSelective(caseReviewUser); + } + }); + + TestCaseReviewUsersExample example = new TestCaseReviewUsersExample(); + example.createCriteria().andReviewIdEqualTo(id).andUserIdNotIn(reviewerIds); + testCaseReviewUsersMapper.deleteByExample(example); + } + + private void editCaseReviewProject(SaveTestCaseReviewRequest testCaseReview) { + List projectIds = testCaseReview.getProjectIds(); + String id = testCaseReview.getId(); + if (!CollectionUtils.isEmpty(projectIds)) { + TestCaseReviewProjectExample testCaseReviewProjectExample = new TestCaseReviewProjectExample(); + testCaseReviewProjectExample.createCriteria().andReviewIdEqualTo(id); + List testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(testCaseReviewProjectExample); + List dbProjectIds = testCaseReviewProjects.stream().map(TestCaseReviewProject::getProjectId).collect(Collectors.toList()); + projectIds.forEach(projectId -> { + if (!dbProjectIds.contains(projectId)) { + TestCaseReviewProject testCaseReviewProject = new TestCaseReviewProject(); + testCaseReviewProject.setReviewId(id); + testCaseReviewProject.setProjectId(projectId); + testCaseReviewProjectMapper.insert(testCaseReviewProject); + } + }); + + TestCaseReviewProjectExample example = new TestCaseReviewProjectExample(); + example.createCriteria().andReviewIdEqualTo(id).andProjectIdNotIn(projectIds); + testCaseReviewProjectMapper.deleteByExample(example); + + + // 关联的项目下的用例idList + TestCaseExample testCaseExample = new TestCaseExample(); + testCaseExample.createCriteria().andProjectIdIn(projectIds); + List caseList = testCaseMapper.selectByExample(testCaseExample); + List caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList()); + + TestCaseReviewTestCaseExample testCaseReviewTestCaseExample = new TestCaseReviewTestCaseExample(); + TestCaseReviewTestCaseExample.Criteria criteria = testCaseReviewTestCaseExample.createCriteria().andReviewIdEqualTo(id); + if (!CollectionUtils.isEmpty(caseIds)) { + criteria.andCaseIdNotIn(caseIds); + } + testCaseReviewTestCaseMapper.deleteByExample(testCaseReviewTestCaseExample); + } + } + private void checkCaseReviewExist(TestCaseReview testCaseReview) { if (testCaseReview.getName() != null) { TestCaseReviewExample example = new TestCaseReviewExample(); diff --git a/frontend/src/business/components/common/components/MsScheduleEdit.vue b/frontend/src/business/components/common/components/MsScheduleEdit.vue index cb6d6bd411..50e866fb49 100644 --- a/frontend/src/business/components/common/components/MsScheduleEdit.vue +++ b/frontend/src/business/components/common/components/MsScheduleEdit.vue @@ -187,6 +187,7 @@ this.form.cronValue = this.schedule.value; listenGoBack(this.close); this.handleClick() + this.activeName = 'first' }, crontabFill(value, resultList) { //确定后回传的值 diff --git a/frontend/src/business/components/track/home/components/ReviewList.vue b/frontend/src/business/components/track/home/components/ReviewList.vue index 7ebda37fdc..876d19cd13 100644 --- a/frontend/src/business/components/track/home/components/ReviewList.vue +++ b/frontend/src/business/components/track/home/components/ReviewList.vue @@ -5,7 +5,7 @@ + content="待我评审" @click="searchMyCreator"/> diff --git a/frontend/src/business/components/track/plan/view/comonents/TestCaseRelevance.vue b/frontend/src/business/components/track/plan/view/comonents/TestCaseRelevance.vue index 41568160f6..3401ffacf7 100644 --- a/frontend/src/business/components/track/plan/view/comonents/TestCaseRelevance.vue +++ b/frontend/src/business/components/track/plan/view/comonents/TestCaseRelevance.vue @@ -154,6 +154,7 @@ }, methods: { openTestCaseRelevanceDialog() { + this.getProject(); this.initData(); this.dialogFormVisible = true; }, @@ -219,7 +220,6 @@ initData() { this.getCaseNames(); this.getAllNodeTreeByPlanId(); - this.getProject(); }, refresh() { this.close(); diff --git a/frontend/src/business/components/track/plan/view/comonents/report/TemplateComponent/DefectListComponent.vue b/frontend/src/business/components/track/plan/view/comonents/report/TemplateComponent/DefectListComponent.vue index 3a141ed057..9e19cb6c0c 100644 --- a/frontend/src/business/components/track/plan/view/comonents/report/TemplateComponent/DefectListComponent.vue +++ b/frontend/src/business/components/track/plan/view/comonents/report/TemplateComponent/DefectListComponent.vue @@ -48,7 +48,7 @@ show-overflow-tooltip> diff --git a/frontend/src/business/components/track/review/components/TestCaseReviewEdit.vue b/frontend/src/business/components/track/review/components/TestCaseReviewEdit.vue index 3ea4a3dfbd..ecb6fa1811 100644 --- a/frontend/src/business/components/track/review/components/TestCaseReviewEdit.vue +++ b/frontend/src/business/components/track/review/components/TestCaseReviewEdit.vue @@ -25,7 +25,6 @@ - + { - this.$success(this.$t('commons.save_success')); - this.dialogFormVisible = false; - this.$emit("refresh"); - }); + + if (this.operationType === 'edit') { + const nowIds = param.projectIds; + let sign = true; + this.dbProjectIds.forEach(dbId => { + if (nowIds.indexOf(dbId) === -1 && sign) { + sign = false; + this.$confirm('取消项目关联会同时取消该项目下已关联的测试用例', '提示', { + confirmButtonText: this.$t('commons.confirm'), + cancelButtonText: this.$t('commons.cancel'), + type: 'warning' + }).then(() => { + this.editTestReview(param); + }).catch(() => { + this.$info(this.$t('commons.cancel')) + }); + } + }); + if (sign) { + this.editTestReview(param); + } + } else { + this.editTestReview(param); + } + + } else { return false; } }); }, + editTestReview(param) { + this.$post('/test/case/review/' + this.operationType, param, () => { + this.$success(this.$t('commons.save_success')); + this.dialogFormVisible = false; + this.$emit("refresh"); + }); + }, getProjects() { this.result = this.$get("/project/listAll", (response) => { if (response.success) { @@ -204,7 +232,8 @@ export default { }); }, statusChange(status) { - + this.form.status = status; + this.$forceUpdate(); }, close() { removeGoBackListener(this.close); diff --git a/frontend/src/business/components/track/review/components/TestCaseReviewList.vue b/frontend/src/business/components/track/review/components/TestCaseReviewList.vue index b708fa6886..6ac142939a 100644 --- a/frontend/src/business/components/track/review/components/TestCaseReviewList.vue +++ b/frontend/src/business/components/track/review/components/TestCaseReviewList.vue @@ -37,42 +37,14 @@ - - - - - - - - - - - + + + + @@ -105,7 +77,7 @@ - + @@ -217,9 +189,6 @@ export default { _sort(column, this.condition); this.initTableData(); }, - reCreate() { - - } } } diff --git a/frontend/src/business/components/track/review/view/components/TestReviewRelevance.vue b/frontend/src/business/components/track/review/view/components/TestReviewRelevance.vue index 2ddf8c0157..0500c7d16d 100644 --- a/frontend/src/business/components/track/review/view/components/TestReviewRelevance.vue +++ b/frontend/src/business/components/track/review/view/components/TestReviewRelevance.vue @@ -154,6 +154,7 @@ export default { }, methods: { openTestReviewRelevanceDialog() { + this.getProject(); this.initData(); this.dialogFormVisible = true; }, @@ -217,7 +218,6 @@ export default { initData() { this.getReviews(); this.getAllNodeTreeByPlanId(); - this.getProject(); }, refresh() { this.close(); @@ -225,7 +225,7 @@ export default { getAllNodeTreeByPlanId() { if (this.reviewId) { let param = { - testPlanId: this.reviewId, + reviewId: this.reviewId, projectId: this.projectId }; this.result = this.$post("/case/node/list/all/review", param , response => { diff --git a/frontend/src/business/components/track/review/view/components/TestReviewTestCaseList.vue b/frontend/src/business/components/track/review/view/components/TestReviewTestCaseList.vue index 3f17ab8c4c..6b30ffc5fc 100644 --- a/frontend/src/business/components/track/review/view/components/TestReviewTestCaseList.vue +++ b/frontend/src/business/components/track/review/view/components/TestReviewTestCaseList.vue @@ -95,37 +95,6 @@ show-overflow-tooltip> - - - - - @@ -320,18 +277,6 @@ export default { let data = response.data; this.total = data.itemCount; this.tableData = data.listObject; - for (let i = 0; i < this.tableData.length; i++) { - if (this.tableData[i]) { - this.$set(this.tableData[i], "issuesSize", 0); - this.$get("/issues/get/" + this.tableData[i].caseId, response => { - let issues = response.data; - if (this.tableData[i]) { - this.$set(this.tableData[i], "issuesSize", issues.length); - this.$set(this.tableData[i], "issuesContent", issues); - } - }) - } - } this.selectRows.clear(); }); } @@ -502,6 +447,7 @@ export default { }, startReview() { if (this.tableData.length !== 0) { + this.isReadOnly = false; this.$refs.testReviewTestCaseEdit.openTestCaseEdit(this.tableData[0]); } else { this.$warning("没有关联的评审!"); diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 12766b7e45..b2af4dc7df 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -936,7 +936,7 @@ export default { performance: "Number of performance tests", resource_pool: "Available test resource pool", max_threads: "Maximum Concurrency", - duration: "Stress test duration", + duration: "Stress test duration(minutes)", use_default: "Use default quota", yes: "Yes", no: "No", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index e0d3cf4bc4..0d70e08efd 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -938,7 +938,7 @@ export default { performance: "性能测试数量", resource_pool: "可用测试资源池", max_threads: "最大并发数", - duration: "压测时长", + duration: "压测时长(分钟)", use_default: "使用默认配额", yes: "是", no: "否", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 495b9cb10b..446bf3b624 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -938,7 +938,7 @@ export default { performance: "性能測試數量", resource_pool: "可用測試資源池", max_threads: "最大並發數", - duration: "壓測時長", + duration: "壓測時長(分鐘)", use_default: "使用默認配額", yes: "是", no: "否",