diff --git a/backend/pom.xml b/backend/pom.xml index c123bf47ee..07439ad68f 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -263,13 +263,20 @@ spring-boot-starter-data-ldap - + io.swagger swagger-parser 1.0.51 + + + + + + + org.graalvm.sdk diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index 6c2a0298b1..78b9d27964 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; + import java.util.List; @RestController @@ -92,5 +93,10 @@ public class ApiAutomationController { apiAutomationService.run(request); } + @PostMapping("/getReference") + public List getReference(@RequestBody ApiScenarioRequest request) { + return apiAutomationService.getReference(request); + } + } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index ca3c58506c..e8bb28bd11 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -35,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; + import java.io.*; import java.util.ArrayList; import java.util.LinkedList; @@ -329,4 +330,8 @@ public class ApiAutomationService { createAPIReportResult(request.getId(), ReportTriggerMode.MANUAL.name()); return request.getId(); } + + public List getReference(ApiScenarioRequest request) { + return extApiScenarioMapper.selectReference(request); + } } diff --git a/backend/src/main/java/io/metersphere/base/domain/MessageTask.java b/backend/src/main/java/io/metersphere/base/domain/MessageTask.java index 56a1d14d7a..03866ff546 100644 --- a/backend/src/main/java/io/metersphere/base/domain/MessageTask.java +++ b/backend/src/main/java/io/metersphere/base/domain/MessageTask.java @@ -1,8 +1,9 @@ package io.metersphere.base.domain; -import java.io.Serializable; import lombok.Data; +import java.io.Serializable; + @Data public class MessageTask implements Serializable { private String id; @@ -27,5 +28,7 @@ public class MessageTask implements Serializable { private Long createTime; + private String template; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml index 671a97fdb5..fe6d86d421 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml @@ -15,7 +15,7 @@ - select distinct url from api_data_view; + select distinct url from api_data_view order by url; - select report_id from api_data_view where response_code != 200 and url=#{apiUrl} and start_time=#{startTime}; + select report_id from api_data_view where url=#{apiUrl} and start_time=#{startTime}; diff --git a/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.java b/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.java index a65b6a46f3..1220f9d2da 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.java @@ -2,9 +2,10 @@ package io.metersphere.base.mapper; import io.metersphere.base.domain.MessageTask; import io.metersphere.base.domain.MessageTaskExample; -import java.util.List; import org.apache.ibatis.annotations.Param; +import java.util.List; + public interface MessageTaskMapper { long countByExample(MessageTaskExample example); @@ -16,15 +17,21 @@ public interface MessageTaskMapper { int insertSelective(MessageTask record); + List selectByExampleWithBLOBs(MessageTaskExample example); + List selectByExample(MessageTaskExample example); MessageTask selectByPrimaryKey(String id); int updateByExampleSelective(@Param("record") MessageTask record, @Param("example") MessageTaskExample example); + int updateByExampleWithBLOBs(@Param("record") MessageTask record, @Param("example") MessageTaskExample example); + int updateByExample(@Param("record") MessageTask record, @Param("example") MessageTaskExample example); int updateByPrimaryKeySelective(MessageTask record); + int updateByPrimaryKeyWithBLOBs(MessageTask record); + int updateByPrimaryKey(MessageTask record); } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.xml index c3d7a6ae5e..64d5f3312e 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/MessageTaskMapper.xml @@ -2,17 +2,20 @@ - - - - - - - - - - - + + + + + + + + + + + + + + @@ -25,13 +28,13 @@ and ${criterion.condition} - and ${criterion.condition} #{criterion.value} + AND ${criterion.condition} #{criterion.value} - and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue} - and ${criterion.condition} + AND ${criterion.condition} #{listItem} @@ -76,6 +79,25 @@ id, `type`, event, user_id, task_type, webhook, identification, is_set, organization_id, test_id, create_time + + `template` + + + SELECT + + DISTINCT + + + , + + FROM message_task + + + + + ORDER BY ${orderByClause} + + select @@ -90,9 +112,11 @@ order by ${orderByClause} - + select + , + from message_task where id = #{id,jdbcType=VARCHAR} @@ -107,14 +131,16 @@ - insert into message_task (id, `type`, event, - user_id, task_type, webhook, - identification, is_set, organization_id, - test_id, create_time) - values (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR}, - #{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR}, - #{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR}, - #{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}) + INSERT INTO message_task (id, `type`, event, + user_id, task_type, webhook, + identification, is_set, organization_id, + test_id, create_time, `template` + ) + VALUES (#{id,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{event,jdbcType=VARCHAR}, + #{userId,jdbcType=VARCHAR}, #{taskType,jdbcType=VARCHAR}, #{webhook,jdbcType=VARCHAR}, + #{identification,jdbcType=VARCHAR}, #{isSet,jdbcType=BIT}, #{organizationId,jdbcType=VARCHAR}, + #{testId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{template,jdbcType=LONGVARCHAR} + ) insert into message_task @@ -152,6 +178,9 @@ create_time, + + `template`, + @@ -187,6 +216,9 @@ #{createTime,jdbcType=BIGINT}, + + #{template,jdbcType=LONGVARCHAR}, + @@ -231,24 +263,45 @@ create_time = #{record.createTime,jdbcType=BIGINT}, + + `template` = #{record.template,jdbcType=LONGVARCHAR}, + + + UPDATE message_task + SET id = #{record.id,jdbcType=VARCHAR}, + `type` = #{record.type,jdbcType=VARCHAR}, + event = #{record.event,jdbcType=VARCHAR}, + user_id = #{record.userId,jdbcType=VARCHAR}, + task_type = #{record.taskType,jdbcType=VARCHAR}, + webhook = #{record.webhook,jdbcType=VARCHAR}, + identification = #{record.identification,jdbcType=VARCHAR}, + is_set = #{record.isSet,jdbcType=BIT}, + organization_id = #{record.organizationId,jdbcType=VARCHAR}, + test_id = #{record.testId,jdbcType=VARCHAR}, + create_time = #{record.createTime,jdbcType=BIGINT}, + `template` = #{record.template,jdbcType=LONGVARCHAR} + + + + update message_task set id = #{record.id,jdbcType=VARCHAR}, - `type` = #{record.type,jdbcType=VARCHAR}, - event = #{record.event,jdbcType=VARCHAR}, - user_id = #{record.userId,jdbcType=VARCHAR}, - task_type = #{record.taskType,jdbcType=VARCHAR}, - webhook = #{record.webhook,jdbcType=VARCHAR}, - identification = #{record.identification,jdbcType=VARCHAR}, - is_set = #{record.isSet,jdbcType=BIT}, - organization_id = #{record.organizationId,jdbcType=VARCHAR}, - test_id = #{record.testId,jdbcType=VARCHAR}, - create_time = #{record.createTime,jdbcType=BIGINT} + `type` = #{record.type,jdbcType=VARCHAR}, + event = #{record.event,jdbcType=VARCHAR}, + user_id = #{record.userId,jdbcType=VARCHAR}, + task_type = #{record.taskType,jdbcType=VARCHAR}, + webhook = #{record.webhook,jdbcType=VARCHAR}, + identification = #{record.identification,jdbcType=VARCHAR}, + is_set = #{record.isSet,jdbcType=BIT}, + organization_id = #{record.organizationId,jdbcType=VARCHAR}, + test_id = #{record.testId,jdbcType=VARCHAR}, + create_time = #{record.createTime,jdbcType=BIGINT} @@ -286,21 +339,39 @@ create_time = #{createTime,jdbcType=BIGINT}, + + `template` = #{template,jdbcType=LONGVARCHAR}, + where id = #{id,jdbcType=VARCHAR} + + UPDATE message_task + SET `type` = #{type,jdbcType=VARCHAR}, + event = #{event,jdbcType=VARCHAR}, + user_id = #{userId,jdbcType=VARCHAR}, + task_type = #{taskType,jdbcType=VARCHAR}, + webhook = #{webhook,jdbcType=VARCHAR}, + identification = #{identification,jdbcType=VARCHAR}, + is_set = #{isSet,jdbcType=BIT}, + organization_id = #{organizationId,jdbcType=VARCHAR}, + test_id = #{testId,jdbcType=VARCHAR}, + create_time = #{createTime,jdbcType=BIGINT}, + `template` = #{template,jdbcType=LONGVARCHAR} + WHERE id = #{id,jdbcType=VARCHAR} + - update message_task - set `type` = #{type,jdbcType=VARCHAR}, - event = #{event,jdbcType=VARCHAR}, - user_id = #{userId,jdbcType=VARCHAR}, - task_type = #{taskType,jdbcType=VARCHAR}, - webhook = #{webhook,jdbcType=VARCHAR}, - identification = #{identification,jdbcType=VARCHAR}, - is_set = #{isSet,jdbcType=BIT}, - organization_id = #{organizationId,jdbcType=VARCHAR}, - test_id = #{testId,jdbcType=VARCHAR}, - create_time = #{createTime,jdbcType=BIGINT} - where id = #{id,jdbcType=VARCHAR} + UPDATE message_task + SET `type` = #{type,jdbcType=VARCHAR}, + event = #{event,jdbcType=VARCHAR}, + user_id = #{userId,jdbcType=VARCHAR}, + task_type = #{taskType,jdbcType=VARCHAR}, + webhook = #{webhook,jdbcType=VARCHAR}, + identification = #{identification,jdbcType=VARCHAR}, + is_set = #{isSet,jdbcType=BIT}, + organization_id = #{organizationId,jdbcType=VARCHAR}, + test_id = #{testId,jdbcType=VARCHAR}, + create_time = #{createTime,jdbcType=BIGINT} + WHERE id = #{id,jdbcType=VARCHAR} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java index cbe5877cb4..bec0fbde89 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java @@ -14,4 +14,6 @@ public interface ExtApiScenarioMapper { List selectIds(@Param("ids") List ids); + List selectReference(@Param("request") ApiScenarioRequest request); + } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml index b7a744ccb7..b4f05a7bba 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml @@ -71,4 +71,23 @@ #{v} + + + select * from api_scenario + + id != #{request.id} + + AND project.workspace_id = #{request.workspaceId} + + + AND project_id = #{request.projectId} + + + AND api_scenario_module_id = #{request.moduleId} + + and scenario_definition like CONCAT('%', #{request.id},'%') + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/notice/domain/MessageDetail.java b/backend/src/main/java/io/metersphere/notice/domain/MessageDetail.java index 9f4c94ca5f..431a7b67f0 100644 --- a/backend/src/main/java/io/metersphere/notice/domain/MessageDetail.java +++ b/backend/src/main/java/io/metersphere/notice/domain/MessageDetail.java @@ -17,4 +17,5 @@ public class MessageDetail { private Boolean isSet; private String testId; private Long createTime; + private String template; } diff --git a/backend/src/main/java/io/metersphere/notice/sender/AbstractNoticeSender.java b/backend/src/main/java/io/metersphere/notice/sender/AbstractNoticeSender.java index 27da4a75dc..fdde00c1fb 100644 --- a/backend/src/main/java/io/metersphere/notice/sender/AbstractNoticeSender.java +++ b/backend/src/main/java/io/metersphere/notice/sender/AbstractNoticeSender.java @@ -5,7 +5,9 @@ import io.metersphere.commons.utils.LogUtil; import io.metersphere.notice.domain.MessageDetail; import io.metersphere.notice.domain.UserDetail; import io.metersphere.service.UserService; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.StringUtils; import javax.annotation.Resource; @@ -14,6 +16,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public abstract class AbstractNoticeSender implements NoticeSender { @@ -21,13 +24,16 @@ public abstract class AbstractNoticeSender implements NoticeSender { private UserService userService; protected String getContext(MessageDetail messageDetail, NoticeModel noticeModel) { + // 如果配置了模版就直接使用模版 + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + return getContent(messageDetail.getTemplate(), noticeModel.getParamMap()); + } // 处理 userIds 中包含的特殊值 List realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent()); messageDetail.setUserIds(realUserIds); // 处理 WeCom Ding context String context = ""; - String status = noticeModel.getStatus(); switch (messageDetail.getEvent()) { case NoticeConstants.Event.CREATE: case NoticeConstants.Event.UPDATE: @@ -48,6 +54,10 @@ public abstract class AbstractNoticeSender implements NoticeSender { } protected String getHtmlContext(MessageDetail messageDetail, NoticeModel noticeModel) { + // 如果配置了模版就直接使用模版 + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + return getContent(messageDetail.getTemplate(), noticeModel.getParamMap()); + } // 处理 userIds 中包含的特殊值 List realUserIds = getRealUserIds(messageDetail.getUserIds(), noticeModel.getRelatedUsers(), messageDetail.getEvent()); messageDetail.setUserIds(realUserIds); @@ -77,7 +87,20 @@ public abstract class AbstractNoticeSender implements NoticeSender { } catch (IOException e) { LogUtil.error(e); } - return context; + return getContent(context, noticeModel.getParamMap()); + } + + protected String getContent(String template, Map context) { + if (MapUtils.isNotEmpty(context)) { + for (String k : context.keySet()) { + if (context.get(k) != null) { + template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", context.get(k).toString()); + } else { + template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置"); + } + } + } + return template; } protected List getUserPhones(List userIds) { diff --git a/backend/src/main/java/io/metersphere/notice/sender/impl/MailNoticeSender.java b/backend/src/main/java/io/metersphere/notice/sender/impl/MailNoticeSender.java index 5e1c0f3edd..dc61109f9b 100644 --- a/backend/src/main/java/io/metersphere/notice/sender/impl/MailNoticeSender.java +++ b/backend/src/main/java/io/metersphere/notice/sender/impl/MailNoticeSender.java @@ -5,8 +5,6 @@ import io.metersphere.notice.domain.MessageDetail; import io.metersphere.notice.sender.AbstractNoticeSender; import io.metersphere.notice.sender.NoticeModel; import io.metersphere.notice.service.MailService; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.RegExUtils; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; @@ -15,14 +13,13 @@ import javax.annotation.Resource; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.List; -import java.util.Map; @Component public class MailNoticeSender extends AbstractNoticeSender { @Resource private MailService mailService; - private void sendMail(MessageDetail messageDetail, String template, NoticeModel noticeModel) throws MessagingException { + private void sendMail(MessageDetail messageDetail, String context, NoticeModel noticeModel) throws MessagingException { JavaMailSenderImpl javaMailSender = mailService.getMailSender(); MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); @@ -31,25 +28,11 @@ public class MailNoticeSender extends AbstractNoticeSender { List emails = super.getUserEmails(messageDetail.getUserIds()); String[] users = emails.toArray(new String[0]); LogUtil.info("收件人地址: " + emails); - helper.setText(this.getContent(template, noticeModel.getParamMap()), true); + helper.setText(context, true); helper.setTo(users); javaMailSender.send(mimeMessage); } - - public String getContent(String template, Map context) { - if (MapUtils.isNotEmpty(context)) { - for (String k : context.keySet()) { - if (context.get(k) != null) { - template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", context.get(k).toString()); - } else { - template = RegExUtils.replaceAll(template, "\\$\\{" + k + "}", "未设置"); - } - } - } - return template; - } - @Override public void send(MessageDetail messageDetail, NoticeModel noticeModel) { String context = super.getHtmlContext(messageDetail, noticeModel); diff --git a/backend/src/main/java/io/metersphere/notice/service/NoticeSendService.java b/backend/src/main/java/io/metersphere/notice/service/NoticeSendService.java index 1adc46a06b..3aea7a17cc 100644 --- a/backend/src/main/java/io/metersphere/notice/service/NoticeSendService.java +++ b/backend/src/main/java/io/metersphere/notice/service/NoticeSendService.java @@ -2,7 +2,6 @@ package io.metersphere.notice.service; import com.alibaba.nacos.client.utils.StringUtils; import io.metersphere.commons.constants.NoticeConstants; -import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.notice.domain.MessageDetail; import io.metersphere.notice.sender.NoticeModel; import io.metersphere.notice.sender.NoticeSender; @@ -22,10 +21,8 @@ public class NoticeSendService { private WeComNoticeSender weComNoticeSender; @Resource private DingNoticeSender dingNoticeSender; - - private void event(String event) { - - } + @Resource + private NoticeService noticeService; private NoticeSender getNoticeSender(MessageDetail messageDetail) { NoticeSender noticeSender = null; @@ -47,8 +44,6 @@ public class NoticeSendService { } public void send(String taskType, NoticeModel noticeModel) { - NoticeService noticeService = CommonBeanFactory.getBean(NoticeService.class); - assert noticeService != null; List messageDetails; switch (taskType) { case NoticeConstants.Mode.API: diff --git a/backend/src/main/java/io/metersphere/notice/service/NoticeService.java b/backend/src/main/java/io/metersphere/notice/service/NoticeService.java index d4abf85876..0ab7b30d26 100644 --- a/backend/src/main/java/io/metersphere/notice/service/NoticeService.java +++ b/backend/src/main/java/io/metersphere/notice/service/NoticeService.java @@ -33,14 +33,17 @@ public class NoticeService { SessionUser user = SessionUtils.getUser(); String orgId = user.getLastOrganizationId(); long time = System.currentTimeMillis(); - String identification = UUID.randomUUID().toString(); - messageDetail.getUserIds().forEach(m -> { - checkUserIdExist(m, messageDetail, orgId); + String identification = messageDetail.getIdentification(); + if (StringUtils.isBlank(identification)) { + identification = UUID.randomUUID().toString(); + } + for (String userId : messageDetail.getUserIds()) { + checkUserIdExist(userId, messageDetail, orgId); MessageTask messageTask = new MessageTask(); messageTask.setId(UUID.randomUUID().toString()); messageTask.setEvent(messageDetail.getEvent()); messageTask.setTaskType(messageDetail.getTaskType()); - messageTask.setUserId(m); + messageTask.setUserId(userId); messageTask.setType(messageDetail.getType()); messageTask.setWebhook(messageDetail.getWebhook()); messageTask.setIdentification(identification); @@ -48,8 +51,15 @@ public class NoticeService { messageTask.setOrganizationId(orgId); messageTask.setTestId(messageDetail.getTestId()); messageTask.setCreateTime(time); + setTemplate(messageDetail, messageTask); messageTaskMapper.insert(messageTask); - }); + } + } + + private void setTemplate(MessageDetail messageDetail, MessageTask messageTask) { + if (StringUtils.isNotBlank(messageDetail.getTemplate())) { + messageTask.setTemplate(messageDetail.getTemplate()); + } } private void checkUserIdExist(String userId, MessageDetail list, String orgId) { @@ -80,7 +90,7 @@ public class NoticeService { public List searchMessageByTestId(String testId) { MessageTaskExample example = new MessageTaskExample(); example.createCriteria().andTestIdEqualTo(testId); - List messageTaskLists = messageTaskMapper.selectByExample(example); + List messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example); List scheduleMessageTask = new ArrayList<>(); Map> MessageTaskMap = messageTaskLists.stream().collect(Collectors.groupingBy(MessageTask::getIdentification)); MessageTaskMap.forEach((k, v) -> { @@ -100,7 +110,7 @@ public class NoticeService { example.createCriteria() .andTaskTypeEqualTo(type) .andOrganizationIdEqualTo(orgId); - List messageTaskLists = messageTaskMapper.selectByExample(example); + List messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example); Map> messageTaskMap = messageTaskLists.stream() .collect(Collectors.groupingBy(NoticeService::fetchGroupKey)); @@ -130,6 +140,7 @@ public class NoticeService { messageDetail.setType(m.getType()); messageDetail.setIsSet(m.getIsSet()); messageDetail.setCreateTime(m.getCreateTime()); + messageDetail.setTemplate(m.getTemplate()); } if (CollectionUtils.isNotEmpty(userIds)) { messageDetail.setUserIds(new ArrayList<>(userIds)); diff --git a/backend/src/main/resources/db/migration/V48__notice_template.sql b/backend/src/main/resources/db/migration/V48__notice_template.sql new file mode 100644 index 0000000000..9e0ee80fc5 --- /dev/null +++ b/backend/src/main/resources/db/migration/V48__notice_template.sql @@ -0,0 +1,13 @@ +ALTER TABLE message_task + MODIFY identification varchar(50) NOT NULL; + +ALTER TABLE message_task + MODIFY organization_id varchar(50) NULL; + +ALTER TABLE message_task + MODIFY test_id varchar(50) NULL; + +ALTER TABLE message_task + ADD template TEXT NULL; + +DROP TABLE IF EXISTS notice; \ No newline at end of file diff --git a/frontend/src/business/components/api/automation/scenario/ReferenceView.vue b/frontend/src/business/components/api/automation/scenario/ReferenceView.vue new file mode 100644 index 0000000000..a57c532467 --- /dev/null +++ b/frontend/src/business/components/api/automation/scenario/ReferenceView.vue @@ -0,0 +1,62 @@ + + + {{ $t('api_test.automation.scenario_ref') }}: + + {{ item.name }} + + + {{ $t('api_test.automation.plan_ref') }}: + + {{ item.name }} + + + + + + + + + + + diff --git a/frontend/src/business/components/api/automation/scenario/ScenarioExtendBtns.vue b/frontend/src/business/components/api/automation/scenario/ScenarioExtendBtns.vue new file mode 100644 index 0000000000..fa42193b8b --- /dev/null +++ b/frontend/src/business/components/api/automation/scenario/ScenarioExtendBtns.vue @@ -0,0 +1,38 @@ + + + + + + + {{ $t('api_test.automation.view_ref') }} + + + + + + + + diff --git a/frontend/src/business/components/api/definition/components/ApiCaseList.vue b/frontend/src/business/components/api/definition/components/ApiCaseList.vue index 6dc9aa3c5f..3833153408 100644 --- a/frontend/src/business/components/api/definition/components/ApiCaseList.vue +++ b/frontend/src/business/components/api/definition/components/ApiCaseList.vue @@ -358,7 +358,7 @@ let bodyUploadFiles = []; row.bodyUploadIds = []; let request = row.request; - if (request.body) { + if (request.body && request.body.kvs) { request.body.kvs.forEach(param => { if (param.files) { param.files.forEach(item => { @@ -372,19 +372,21 @@ }); } }); - request.body.binary.forEach(param => { - if (param.files) { - param.files.forEach(item => { - if (item.file) { - let fileId = getUUID().substring(0, 8); - item.name = item.file.name; - item.id = fileId; - row.bodyUploadIds.push(fileId); - bodyUploadFiles.push(item.file); - } - }); - } - }); + if (request.body.binary) { + request.body.binary.forEach(param => { + if (param.files) { + param.files.forEach(item => { + if (item.file) { + let fileId = getUUID().substring(0, 8); + item.name = item.file.name; + item.id = fileId; + row.bodyUploadIds.push(fileId); + bodyUploadFiles.push(item.file); + } + }); + } + }); + } } return bodyUploadFiles; }, diff --git a/frontend/src/business/components/api/definition/components/Run.vue b/frontend/src/business/components/api/definition/components/Run.vue index 3d9e370d69..73c2c4c263 100644 --- a/frontend/src/business/components/api/definition/components/Run.vue +++ b/frontend/src/business/components/api/definition/components/Run.vue @@ -58,25 +58,10 @@ getBodyUploadFiles(obj) { let bodyUploadFiles = []; obj.bodyUploadIds = []; - this.runData.forEach(request => { - if (request.body) { - request.body.kvs.forEach(param => { - if (param.files) { - param.files.forEach(item => { - if (item.file) { - if (!item.id) { - let fileId = getUUID().substring(0, 12); - item.name = item.file.name; - item.id = fileId; - } - obj.bodyUploadIds.push(item.id); - bodyUploadFiles.push(item.file); - } - }); - } - }); - if (request.body.binary) { - request.body.binary.forEach(param => { + if (this.runData) { + this.runData.forEach(request => { + if (request.body) { + request.body.kvs.forEach(param => { if (param.files) { param.files.forEach(item => { if (item.file) { @@ -91,9 +76,26 @@ }); } }); + if (request.body.binary) { + request.body.binary.forEach(param => { + if (param.files) { + param.files.forEach(item => { + if (item.file) { + if (!item.id) { + let fileId = getUUID().substring(0, 12); + item.name = item.file.name; + item.id = fileId; + } + obj.bodyUploadIds.push(item.id); + bodyUploadFiles.push(item.file); + } + }); + } + }); + } } - } - }); + }); + } return bodyUploadFiles; }, run() { diff --git a/frontend/src/business/components/api/head/ApiHeaderMenus.vue b/frontend/src/business/components/api/head/ApiHeaderMenus.vue index 65420495e0..497ad39762 100644 --- a/frontend/src/business/components/api/head/ApiHeaderMenus.vue +++ b/frontend/src/business/components/api/head/ApiHeaderMenus.vue @@ -8,11 +8,11 @@ {{ $t('commons.project') }} - + - 创建项目 + {{ $t("project.create") }} - + diff --git a/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue b/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue index ca7903e471..f5847b5f71 100644 --- a/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue +++ b/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue @@ -2,7 +2,7 @@ - + @@ -27,20 +27,15 @@ export default { }, methods: { click(params) { - //如果状态不是以2开头 - if (params.value.substr(0, 1) !== '2') { - let startTime = params.name; - this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, { - 'apiUrl': this.apiUrl - }, response => { - this.reportId = response.data; - let reportId = this.reportId - let url = '#/api/report/view/' + reportId; - let target = '_blank'; - window.open(url, target); - }); - } - + let startTime = params.name; + this.result = this.$$get('/api/monitor/getReportId', {'startTime': startTime}, { + 'apiUrl': this.apiUrl + }, response => { + this.reportId = response.data; + let reportId = this.reportId + let url = '#/api/report/view/' + reportId; + window.open(url, '_blank'); + }); }, getOptions() { return { diff --git a/frontend/src/business/components/api/router.js b/frontend/src/business/components/api/router.js index 6df34af109..0a297fcdb5 100644 --- a/frontend/src/business/components/api/router.js +++ b/frontend/src/business/components/api/router.js @@ -1,4 +1,4 @@ -import MsProject from "@/business/components/project/MsProject"; +import MsProject from "@/business/components/settings/project/MsProject"; export default { path: "/api", @@ -24,11 +24,11 @@ export default { name: "ApiTestList", component: () => import('@/business/components/api/test/ApiTestList'), }, - { - path: "project/:type", - name: "fucProject", - component: MsProject, - }, + // { + // path: "project/:type", + // name: "fucProject", + // component: MsProject, + // }, { path: "report/list/:testId", name: "ApiReportList", @@ -53,6 +53,11 @@ export default { path: "automation/report", name: "ApiReportList", component: () => import('@/business/components/api/automation/report/ApiReportList'), - } + }, + { + path: 'monitor/view', + name: 'ApiMonitor', + component: () => import('@/business/components/api/monitor/ApiMonitor'), + }, ] } diff --git a/frontend/src/business/components/common/components/MsScheduleEdit.vue b/frontend/src/business/components/common/components/MsScheduleEdit.vue index 75e854aba6..d3fa5b57d4 100644 --- a/frontend/src/business/components/common/components/MsScheduleEdit.vue +++ b/frontend/src/business/components/common/components/MsScheduleEdit.vue @@ -213,10 +213,4 @@ export default { margin-bottom: 10px; } -/deep/ .el-select__tags { - flex-wrap: unset; - overflow: auto; -} - - diff --git a/frontend/src/business/components/common/head/SearchList.vue b/frontend/src/business/components/common/head/SearchList.vue index 39744e3de6..d399064435 100644 --- a/frontend/src/business/components/common/head/SearchList.vue +++ b/frontend/src/business/components/common/head/SearchList.vue @@ -32,7 +32,7 @@ export default { options: Object }, mounted() { - this.recent(); + this.init(); }, data() { return { @@ -44,7 +44,7 @@ export default { watch: { search_text(val) { if (!val) { - this.recent(); + this.init(); } else { this.search(); } @@ -66,7 +66,7 @@ export default { }, methods: { - recent: function () { + init: function () { if (hasRoles(ROLE_TEST_VIEWER, ROLE_TEST_USER, ROLE_TEST_MANAGER)) { this.result = this.$get(this.options.url, (response) => { this.items = response.data; diff --git a/frontend/src/business/components/performance/head/PerformanceHeaderMenus.vue b/frontend/src/business/components/performance/head/PerformanceHeaderMenus.vue index 37b60f9943..79324356fb 100644 --- a/frontend/src/business/components/performance/head/PerformanceHeaderMenus.vue +++ b/frontend/src/business/components/performance/head/PerformanceHeaderMenus.vue @@ -9,11 +9,11 @@ {{ $t('commons.project') }} - + - 创建项目 + {{ $t("project.create") }} - + diff --git a/frontend/src/business/components/performance/report/PerformanceTestReport.vue b/frontend/src/business/components/performance/report/PerformanceTestReport.vue index a48975eb31..281c85daca 100644 --- a/frontend/src/business/components/performance/report/PerformanceTestReport.vue +++ b/frontend/src/business/components/performance/report/PerformanceTestReport.vue @@ -241,14 +241,9 @@ export default { confirmButtonText: this.$t('commons.confirm'), callback: (action) => { if (action === 'confirm') { - let ids = Array.from(this.selectRows).map(row => row.id); - this.result = this.$post('/performance/report/batch/delete', {ids: ids}, () => { - this.selectRows.clear(); - this.$success(this.$t('commons.delete_success')); - this.search(); - // 发送广播,刷新 head 上的最新列表 - PerformanceEvent.$emit(LIST_CHANGE); - }); + this.selectRows.forEach(row => { + this._handleDelete(row); + }) } } }); diff --git a/frontend/src/business/components/performance/router.js b/frontend/src/business/components/performance/router.js index 8c4197e01d..6f3e24799e 100644 --- a/frontend/src/business/components/performance/router.js +++ b/frontend/src/business/components/performance/router.js @@ -1,4 +1,4 @@ -import MsProject from "@/business/components/project/MsProject"; +import MsProject from "@/business/components/settings/project/MsProject"; const PerformanceTest = () => import('@/business/components/performance/PerformanceTest') const PerformanceTestHome = () => import('@/business/components/performance/home/PerformanceTestHome') @@ -43,11 +43,11 @@ export default { name: "perPlan", component: PerformanceTestList }, - { - path: "project/:type", - name: "perProject", - component: MsProject - }, + // { + // path: "project/:type", + // name: "perProject", + // component: MsProject + // }, { path: "report/:type", name: "perReport", diff --git a/frontend/src/business/components/settings/SettingMenu.vue b/frontend/src/business/components/settings/SettingMenu.vue index a3d69c9650..0488333240 100644 --- a/frontend/src/business/components/settings/SettingMenu.vue +++ b/frontend/src/business/components/settings/SettingMenu.vue @@ -41,7 +41,7 @@ - diff --git a/frontend/src/business/components/settings/organization/components/DefectTaskNotification.vue b/frontend/src/business/components/settings/organization/components/DefectTaskNotification.vue index 2699ccac3f..9443c71359 100644 --- a/frontend/src/business/components/settings/organization/components/DefectTaskNotification.vue +++ b/frontend/src/business/components/settings/organization/components/DefectTaskNotification.vue @@ -17,7 +17,7 @@ :cell-style="rowClass" :header-cell-style="headClass" > - + @@ -64,8 +64,16 @@ :disabled="!scope.row.isSet||!scope.row.isReadOnly"> - + + {{ $t('organization.message.template') }} + + diff --git a/frontend/src/business/components/settings/organization/components/ScheduleTaskNotification.vue b/frontend/src/business/components/settings/organization/components/ScheduleTaskNotification.vue index 0d7b8600aa..7eb6ed443c 100644 --- a/frontend/src/business/components/settings/organization/components/ScheduleTaskNotification.vue +++ b/frontend/src/business/components/settings/organization/components/ScheduleTaskNotification.vue @@ -14,12 +14,11 @@ :data="scheduleTask" class="tb-edit" border - size="mini" :cell-style="rowClass" :header-cell-style="headClass"> - + - - - + - - + + {{ $t('organization.message.template') }} + + diff --git a/frontend/src/business/components/settings/organization/components/TestPlanTaskNotification.vue b/frontend/src/business/components/settings/organization/components/TestPlanTaskNotification.vue index dc89d40597..07da85f9a4 100644 --- a/frontend/src/business/components/settings/organization/components/TestPlanTaskNotification.vue +++ b/frontend/src/business/components/settings/organization/components/TestPlanTaskNotification.vue @@ -17,7 +17,7 @@ :cell-style="rowClass" :header-cell-style="headClass" > - + - + + {{ $t('organization.message.template') }} + + diff --git a/frontend/src/business/components/track/plan/view/comonents/TestPlanCommonComponent.vue b/frontend/src/business/components/track/plan/view/comonents/base/TestPlanCommonComponent.vue similarity index 63% rename from frontend/src/business/components/track/plan/view/comonents/TestPlanCommonComponent.vue rename to frontend/src/business/components/track/plan/view/comonents/base/TestPlanCommonComponent.vue index 4ca9b25873..c0dbcb6ff2 100644 --- a/frontend/src/business/components/track/plan/view/comonents/TestPlanCommonComponent.vue +++ b/frontend/src/business/components/track/plan/view/comonents/base/TestPlanCommonComponent.vue @@ -15,9 +15,9 @@ + + diff --git a/frontend/src/business/components/track/plan/view/comonents/functional/TestCaseFunctionalRelevance.vue b/frontend/src/business/components/track/plan/view/comonents/functional/TestCaseFunctionalRelevance.vue new file mode 100644 index 0000000000..6db1d91e41 --- /dev/null +++ b/frontend/src/business/components/track/plan/view/comonents/functional/TestCaseFunctionalRelevance.vue @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + {{scope.row.name}} + + + + + + + + + + + + + + + {{$t('test_track.review_view.last_page')}} + 共 {{total}} 条 + + + + + + + + diff --git a/frontend/src/business/components/track/plan/view/comonents/functional/TestPlanFunctional.vue b/frontend/src/business/components/track/plan/view/comonents/functional/TestPlanFunctional.vue index ad3244fff9..8a1161d781 100644 --- a/frontend/src/business/components/track/plan/view/comonents/functional/TestPlanFunctional.vue +++ b/frontend/src/business/components/track/plan/view/comonents/functional/TestPlanFunctional.vue @@ -11,7 +11,7 @@ ref="nodeTree"/> - - @@ -31,16 +31,18 @@