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 d7500fdc88..6d46f0e708 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -81,5 +81,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/dto/APIReportResult.java b/backend/src/main/java/io/metersphere/api/dto/APIReportResult.java index 24ce8bff11..a46fa22a0c 100644 --- a/backend/src/main/java/io/metersphere/api/dto/APIReportResult.java +++ b/backend/src/main/java/io/metersphere/api/dto/APIReportResult.java @@ -4,6 +4,8 @@ import io.metersphere.base.domain.ApiTestReport; import lombok.Getter; import lombok.Setter; +import java.util.List; + @Setter @Getter public class APIReportResult extends ApiTestReport { @@ -14,5 +16,7 @@ public class APIReportResult extends ApiTestReport { private String userName; + private List scenarioIds; + private String content; } diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java index f3d7ddc2f4..623f1bd371 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java @@ -15,5 +15,7 @@ public class RunScenarioRequest { private String environmentId; + private String triggerMode; + private List scenarioIds; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java index b49d589d42..5d3dd08502 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java @@ -17,7 +17,10 @@ import io.metersphere.commons.utils.CommonBeanFactory; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; import org.apache.jorphan.collections.HashTree; +import org.apache.jmeter.config.Arguments; import java.util.LinkedList; import java.util.List; @@ -40,11 +43,14 @@ public class MsScenario extends MsTestElement { @JSONField(ordinal = 13) private List variables; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { if (environmentId != null) { ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId); - config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + config.setConfig(JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class)); + } + if (CollectionUtils.isNotEmpty(this.getVariables())) { + config.setVariables(this.variables); } if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) { return; @@ -66,10 +72,29 @@ public class MsScenario extends MsTestElement { ex.printStackTrace(); } } + // 场景变量 + if (CollectionUtils.isNotEmpty(this.getVariables())) { + tree.add(arguments()); + } + if (CollectionUtils.isNotEmpty(hashTree)) { for (MsTestElement el : hashTree) { el.toHashTree(tree, el.getHashTree(), config); } } + } + + private Arguments arguments() { + Arguments arguments = new Arguments(); + arguments.setEnabled(true); + arguments.setName(name + "Variables"); + arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); + arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); + variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> + arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") + ); + return arguments; + } + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java index ad11c71b03..71bcb99f86 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java @@ -16,7 +16,6 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler; import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; import io.metersphere.api.dto.definition.request.timer.MsConstantTimer; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.commons.utils.LogUtil; import lombok.Data; import org.apache.jmeter.protocol.http.control.AuthManager; @@ -71,7 +70,7 @@ public class MsTestElement { private LinkedList hashTree; // 公共环境逐层传递,如果自身有环境 以自身引用环境为准否则以公共环境作为请求环境 - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { for (MsTestElement el : hashTree) { el.toHashTree(tree, el.hashTree, config); } @@ -95,7 +94,7 @@ public class MsTestElement { return null; } - public HashTree generateHashTree(EnvironmentConfig config) { + public HashTree generateHashTree(ParameterConfig config) { HashTree jmeterTestPlanHashTree = new ListedHashTree(); this.toHashTree(jmeterTestPlanHashTree, this.hashTree, config); return jmeterTestPlanHashTree; @@ -103,7 +102,7 @@ public class MsTestElement { public HashTree generateHashTree() { HashTree jmeterTestPlanHashTree = new ListedHashTree(); - this.toHashTree(jmeterTestPlanHashTree, this.hashTree, null); + this.toHashTree(jmeterTestPlanHashTree, this.hashTree, new ParameterConfig()); return jmeterTestPlanHashTree; } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestPlan.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestPlan.java index 4af1e721e8..b45f3c2bd0 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestPlan.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestPlan.java @@ -1,7 +1,6 @@ package io.metersphere.api.dto.definition.request; import com.alibaba.fastjson.annotation.JSONType; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -19,7 +18,7 @@ import java.util.List; public class MsTestPlan extends MsTestElement { private String type = "TestPlan"; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree testPlanTree = tree.add(getPlan()); if (CollectionUtils.isNotEmpty(hashTree)) { hashTree.forEach(el -> { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java index 3e366cd4a7..0a27bb1abb 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java @@ -1,7 +1,6 @@ package io.metersphere.api.dto.definition.request; import com.alibaba.fastjson.annotation.JSONType; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -19,7 +18,7 @@ import java.util.List; public class MsThreadGroup extends MsTestElement { private String type = "ThreadGroup"; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree groupTree = tree.add(getThreadGroup()); if (CollectionUtils.isNotEmpty(hashTree)) { hashTree.forEach(el -> { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java new file mode 100644 index 0000000000..ccd068cf60 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/ParameterConfig.java @@ -0,0 +1,15 @@ +package io.metersphere.api.dto.definition.request; + +import io.metersphere.api.dto.scenario.KeyValue; +import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import lombok.Data; + +import java.util.List; + +@Data +public class ParameterConfig { + // 环境配置 + private EnvironmentConfig config; + // 公共场景参数 + private List variables; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/MsAssertions.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/MsAssertions.java index 2deb0a4091..59cc74c491 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/MsAssertions.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/assertions/MsAssertions.java @@ -2,7 +2,7 @@ package io.metersphere.api.dto.definition.request.assertions; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -24,7 +24,7 @@ public class MsAssertions extends MsTestElement { private MsAssertionDuration duration; private String type = "Assertions"; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { addAssertions(tree); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/auth/MsAuthManager.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/auth/MsAuthManager.java index 48652c4bcd..8ef3a3ae2a 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/auth/MsAuthManager.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/auth/MsAuthManager.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; @@ -50,7 +51,7 @@ public class MsAuthManager extends MsTestElement { @JSONField(ordinal = 18) private String environment; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { AuthManager authManager = new AuthManager(); authManager.setEnabled(true); authManager.setName(this.getUsername() + "AuthManager"); @@ -63,8 +64,8 @@ public class MsAuthManager extends MsTestElement { if (environment != null) { ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); ApiTestEnvironmentWithBLOBs environmentWithBLOBs = environmentService.get(environment); - config = JSONObject.parseObject(environmentWithBLOBs.getConfig(), EnvironmentConfig.class); - this.url = config.getHttpConfig().getProtocol() + "://" + config.getHttpConfig().getSocket(); + EnvironmentConfig envConfig = JSONObject.parseObject(environmentWithBLOBs.getConfig(), EnvironmentConfig.class); + this.url = envConfig.getHttpConfig().getProtocol() + "://" + envConfig.getHttpConfig().getSocket(); } } auth.setDomain(this.domain); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/configurations/MsHeaderManager.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/configurations/MsHeaderManager.java index 82ec171102..ee33dba7b8 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/configurations/MsHeaderManager.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/configurations/MsHeaderManager.java @@ -3,8 +3,8 @@ package io.metersphere.api.dto.definition.request.configurations; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.scenario.KeyValue; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -25,7 +25,7 @@ public class MsHeaderManager extends MsTestElement { @JSONField(ordinal = 10) private List headers; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { HeaderManager headerManager = new HeaderManager(); headerManager.setEnabled(true); headerManager.setName(this.getName() + "Headers"); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java index 59e69fbe7d..4560c0da05 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/controller/MsIfController.java @@ -2,7 +2,7 @@ package io.metersphere.api.dto.definition.request.controller; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -25,7 +25,7 @@ public class MsIfController extends MsTestElement { private String operator; private String value; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree groupTree = tree.add(ifController()); if (CollectionUtils.isNotEmpty(hashTree)) { hashTree.forEach(el -> { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/dns/MsDNSCacheManager.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/dns/MsDNSCacheManager.java index f5d88f6aff..ef505a4959 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/dns/MsDNSCacheManager.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/dns/MsDNSCacheManager.java @@ -2,6 +2,7 @@ package io.metersphere.api.dto.definition.request.dns; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.Host; @@ -23,7 +24,7 @@ import java.util.List; @JSONType(typeName = "DNSCacheManager") public class MsDNSCacheManager extends MsTestElement { - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { for (MsTestElement el : hashTree) { el.toHashTree(tree, el.getHashTree(), config); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/extract/MsExtract.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/extract/MsExtract.java index 06e3cc00fa..a06d72673a 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/extract/MsExtract.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/extract/MsExtract.java @@ -2,7 +2,7 @@ package io.metersphere.api.dto.definition.request.extract; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -24,7 +24,7 @@ public class MsExtract extends MsTestElement { private List xpath; private String type = "Extract"; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { addRequestExtractors(tree); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java index 83d0a2205a..d729b7ccff 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/MsJSR223Processor.java @@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition.request.processors; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -26,7 +26,7 @@ public class MsJSR223Processor extends MsTestElement { @JSONField(ordinal = 11) private String scriptLanguage; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { JSR223Sampler processor = new JSR223Sampler(); processor.setEnabled(true); processor.setName(this.getName() + "JSR223Processor"); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJSR223PostProcessor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJSR223PostProcessor.java index 0776127b7a..75253ceaaa 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJSR223PostProcessor.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/post/MsJSR223PostProcessor.java @@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition.request.processors.post; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -27,7 +27,7 @@ public class MsJSR223PostProcessor extends MsTestElement { private String scriptLanguage; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { JSR223PostProcessor processor = new JSR223PostProcessor(); processor.setEnabled(true); processor.setName(this.getName() + "JSR223PostProcessor"); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJSR223PreProcessor.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJSR223PreProcessor.java index 631188bbe3..8ebcea1129 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJSR223PreProcessor.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/processors/pre/MsJSR223PreProcessor.java @@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition.request.processors.pre; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -26,7 +26,7 @@ public class MsJSR223PreProcessor extends MsTestElement { @JSONField(ordinal = 11) private String scriptLanguage; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { JSR223PreProcessor processor = new JSR223PreProcessor(); processor.setEnabled(true); processor.setName(this.getName() + "JSR223PreProcessor"); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java index 7f3a6c8d50..7cafdada30 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java @@ -7,11 +7,11 @@ import io.github.ningyu.jmeter.plugin.dubbo.sample.DubboSample; import io.github.ningyu.jmeter.plugin.dubbo.sample.MethodArgument; import io.github.ningyu.jmeter.plugin.util.Constants; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.sampler.dubbo.MsConfigCenter; import io.metersphere.api.dto.definition.request.sampler.dubbo.MsConsumerAndService; import io.metersphere.api.dto.definition.request.sampler.dubbo.MsRegistryCenter; import io.metersphere.api.dto.scenario.KeyValue; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -51,7 +51,7 @@ public class MsDubboSampler extends MsTestElement { @JSONField(ordinal = 59) private List attachmentArgs; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree testPlanTree = new ListedHashTree(); testPlanTree.add(dubboConfig()); tree.set(dubboSample(), testPlanTree); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 4b31329eb7..5106f1209d 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; @@ -27,7 +28,11 @@ import org.apache.jorphan.collections.HashTree; import java.net.URL; import java.net.URLDecoder; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Data @EqualsAndHashCode(callSuper = true) @@ -80,7 +85,7 @@ public class MsHTTPSamplerProxy extends MsTestElement { @JSONField(ordinal = 24) private List arguments; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { HTTPSamplerProxy sampler = new HTTPSamplerProxy(); sampler.setEnabled(true); sampler.setName(this.getName()); @@ -96,23 +101,25 @@ public class MsHTTPSamplerProxy extends MsTestElement { if (useEnvironment != null) { ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class); ApiTestEnvironmentWithBLOBs environment = environmentService.get(useEnvironment); - config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + config.setConfig(JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class)); } try { - if (config != null) { + if (config != null && config.getConfig() != null) { String url = ""; - sampler.setDomain(config.getHttpConfig().getDomain()); - sampler.setPort(config.getHttpConfig().getPort()); - sampler.setProtocol(config.getHttpConfig().getProtocol()); - url = config.getHttpConfig().getProtocol() + "://" + config.getHttpConfig().getSocket(); + sampler.setDomain(config.getConfig().getHttpConfig().getDomain()); + sampler.setPort(config.getConfig().getHttpConfig().getPort()); + sampler.setProtocol(config.getConfig().getHttpConfig().getProtocol()); + url = config.getConfig().getHttpConfig().getProtocol() + "://" + config.getConfig().getHttpConfig().getSocket(); URL urlObject = new URL(url); String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath(); if (StringUtils.isNotBlank(this.getPath())) { envPath += this.getPath(); } if (CollectionUtils.isNotEmpty(this.getRest()) && this.isRest()) { - sampler.setPath(getRestParameters(URLDecoder.decode(envPath, "UTF-8"))); - } else { + envPath = getRestParameters(URLDecoder.decode(envPath, "UTF-8")); + sampler.setPath(envPath); + } + if (CollectionUtils.isNotEmpty(this.getArguments())) { sampler.setPath(getPostQueryParameters(URLDecoder.decode(envPath, "UTF-8"))); } } else { @@ -125,18 +132,24 @@ public class MsHTTPSamplerProxy extends MsTestElement { sampler.setPort(urlObject.getPort()); sampler.setProtocol(urlObject.getProtocol()); - sampler.setPath(getRestParameters(URLDecoder.decode(urlObject.getPath(), "UTF-8"))); - sampler.setPath(getPostQueryParameters(URLDecoder.decode(urlObject.getPath(), "UTF-8"))); + if (CollectionUtils.isNotEmpty(this.getRest()) && this.isRest()) { + sampler.setPath(getRestParameters(URLDecoder.decode(urlObject.getPath(), "UTF-8"))); + } + if (CollectionUtils.isNotEmpty(this.getArguments())) { + sampler.setPath(getPostQueryParameters(URLDecoder.decode(urlObject.getPath(), "UTF-8"))); + } } } catch (Exception e) { LogUtil.error(e); } - + // REST参数 + if (CollectionUtils.isNotEmpty(this.getArguments())) { + sampler.setArguments(httpArguments(this.getRest())); + } // 请求参数 if (CollectionUtils.isNotEmpty(this.getArguments())) { sampler.setArguments(httpArguments(this.getArguments())); } - // 请求体 if (!StringUtils.equals(this.getMethod(), "GET")) { List bodyParams = this.body.getBodyParams(sampler, this.getId()); @@ -148,9 +161,10 @@ public class MsHTTPSamplerProxy extends MsTestElement { setHeader(httpSamplerTree); } //判断是否要开启DNS - if (config != null && config.getCommonConfig() != null && config.getCommonConfig().isEnableHost()) { - MsDNSCacheManager.addEnvironmentVariables(httpSamplerTree, this.getName(), config); - MsDNSCacheManager.addEnvironmentDNS(httpSamplerTree, this.getName(), config); + if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null + && config.getConfig().getCommonConfig().isEnableHost()) { + MsDNSCacheManager.addEnvironmentVariables(httpSamplerTree, this.getName(), config.getConfig()); + MsDNSCacheManager.addEnvironmentDNS(httpSamplerTree, this.getName(), config.getConfig()); } if (CollectionUtils.isNotEmpty(hashTree)) { for (MsTestElement el : hashTree) { @@ -163,10 +177,22 @@ public class MsHTTPSamplerProxy extends MsTestElement { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(path); stringBuffer.append("/"); + Map keyValueMap = new HashMap<>(); this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue -> - stringBuffer.append(keyValue.getValue()).append("/") + keyValueMap.put(keyValue.getName(), keyValue.getValue()) ); - return stringBuffer.substring(0, stringBuffer.length() - 1); + + Pattern p = Pattern.compile("(\\{)([\\w]+)(\\})"); + Matcher m = p.matcher(path); + StringBuffer sb = new StringBuffer(); + while (m.find()) { + String group = m.group(2); + //替换并且把替换好的值放到sb中 + m.appendReplacement(sb, keyValueMap.get(group)); + } + //把符合的数据追加到sb尾 + m.appendTail(sb); + return sb.toString(); } private String getPostQueryParameters(String path) { @@ -209,4 +235,5 @@ public class MsHTTPSamplerProxy extends MsTestElement { private boolean isRest() { return this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).toArray().length > 0; } + } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java index 2b4330fc64..3c0ca2c866 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java @@ -3,9 +3,9 @@ package io.metersphere.api.dto.definition.request.sampler; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.scenario.DatabaseConfig; import io.metersphere.api.dto.scenario.KeyValue; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -39,7 +39,7 @@ public class MsJDBCSampler extends MsTestElement { @JSONField(ordinal = 16) private String environmentId; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree samplerHashTree = tree.add(jdbcSampler()); tree.add(jdbcDataSource()); tree.add(arguments(this.getName() + " Variables", this.getVariables())); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java index fee1ea7efb..def4cda1b6 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsTCPSampler.java @@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition.request.sampler; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -49,7 +49,7 @@ public class MsTCPSampler extends MsTestElement { @JSONField(ordinal = 23) private String request; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree samplerHashTree = new ListedHashTree(); samplerHashTree.add(tcpConfig()); tree.set(tcpSampler(), samplerHashTree); diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/timer/MsConstantTimer.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/timer/MsConstantTimer.java index a1057b6647..bdba212760 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/timer/MsConstantTimer.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/timer/MsConstantTimer.java @@ -3,7 +3,7 @@ package io.metersphere.api.dto.definition.request.timer; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; +import io.metersphere.api.dto.definition.request.ParameterConfig; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.collections.CollectionUtils; @@ -26,7 +26,7 @@ public class MsConstantTimer extends MsTestElement { @JSONField(ordinal = 12) private String delay; - public void toHashTree(HashTree tree, List hashTree, EnvironmentConfig config) { + public void toHashTree(HashTree tree, List hashTree, ParameterConfig config) { final HashTree groupTree = tree.add(constantTimer()); if (CollectionUtils.isNotEmpty(hashTree)) { hashTree.forEach(el -> { diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java index bccf9dccb6..d9e14fe60e 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java @@ -229,7 +229,11 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl if (StringUtils.equals("Error", report.getStatus())) { event = NoticeConstants.Event.EXECUTE_FAILED; } - + Map paramMap = new HashMap<>(); + paramMap.put("testName", report.getName()); + paramMap.put("id", report.getId()); + paramMap.put("type", "performance"); + paramMap.put("url", baseSystemConfigDTO.getUrl()); NoticeModel noticeModel = NoticeModel.builder() .successContext(successContext) .successMailTemplate("ApiSuccessfulNotification") @@ -239,6 +243,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl .status(report.getStatus()) .event(event) .subject(subject) + .paramMap(paramMap) .build(); noticeSendService.send(report.getTriggerMode(), noticeModel); } 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 0a8993c4d3..d52b7cdebd 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -9,9 +9,8 @@ import com.google.gson.Gson; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.definition.RunDefinitionRequest; -import io.metersphere.api.dto.definition.request.MsTestElement; -import io.metersphere.api.dto.definition.request.MsTestPlan; -import io.metersphere.api.dto.definition.request.MsThreadGroup; +import io.metersphere.api.dto.definition.request.*; +import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.base.domain.*; @@ -20,6 +19,7 @@ import io.metersphere.base.mapper.ApiTagMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ApiRunMode; +import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; @@ -219,7 +219,7 @@ public class ApiAutomationService { } } - private void createAPIReportResult(String id) { + private void createAPIReportResult(String id, String triggerMode) { APIReportResult report = new APIReportResult(); report.setId(id); report.setTestId(id); @@ -229,6 +229,7 @@ public class ApiAutomationService { report.setUpdateTime(System.currentTimeMillis()); report.setStatus(APITestStatus.Running.name()); report.setUserId(SessionUtils.getUserId()); + report.setTriggerMode(triggerMode); apiReportService.addResult(report); } @@ -244,7 +245,6 @@ public class ApiAutomationService { MsTestPlan testPlan = new MsTestPlan(); testPlan.setHashTree(new LinkedList<>()); HashTree jmeterTestPlanHashTree = new ListedHashTree(); - EnvironmentConfig config = null; for (ApiScenario item : apiScenarios) { MsThreadGroup group = new MsThreadGroup(); group.setLabel(item.getName()); @@ -253,25 +253,29 @@ public class ApiAutomationService { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); JSONObject element = JSON.parseObject(item.getScenarioDefinition()); - String environmentId = element.getString("environmentId"); - if (environmentId != null) { - ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId); - config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); - } - - LinkedList elements = mapper.readValue(element.getString("hashTree"), new TypeReference>() { - }); - group.setHashTree(elements); + MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class); + // 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取 + LinkedList elements = mapper.readValue(element.getString("hashTree"), + new TypeReference>() { + }); + LinkedList variables = mapper.readValue(element.getString("variables"), + new TypeReference>() { + }); + scenario.setHashTree(elements); + scenario.setVariables(variables); + LinkedList scenarios = new LinkedList<>(); + scenarios.add(scenario); + group.setHashTree(scenarios); testPlan.getHashTree().add(group); } catch (Exception ex) { ex.printStackTrace(); } } - testPlan.toHashTree(jmeterTestPlanHashTree, testPlan.getHashTree(), config); - + testPlan.toHashTree(jmeterTestPlanHashTree, testPlan.getHashTree(), new ParameterConfig()); // 调用执行方法 jMeterService.runDefinition(request.getId(), jmeterTestPlanHashTree, request.getReportId(), ApiRunMode.SCENARIO.name()); - createAPIReportResult(request.getId()); + + createAPIReportResult(request.getId(), request.getTriggerMode() == null ? ReportTriggerMode.API.name() : request.getTriggerMode()); return request.getId(); } @@ -286,17 +290,23 @@ public class ApiAutomationService { public String run(RunDefinitionRequest request, List bodyFiles) { List bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); createBodyFiles(bodyUploadIds, bodyFiles); - EnvironmentConfig config = null; + EnvironmentConfig envConfig = null; if (request.getEnvironmentId() != null) { ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId()); - config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + envConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); } + ParameterConfig config = new ParameterConfig(); + config.setConfig(envConfig); HashTree hashTree = request.getTestElement().generateHashTree(config); request.getTestElement().getJmx(hashTree); // 调用执行方法 jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name()); - createAPIReportResult(request.getId()); + 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/api/service/ApiScenarioReportService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java index 54401c9125..ee3fc6b221 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java @@ -1,5 +1,6 @@ package io.metersphere.api.service; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.DeleteAPIReportRequest; @@ -7,6 +8,7 @@ import io.metersphere.api.dto.QueryAPIReportRequest; import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.api.jmeter.TestResult; import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiScenarioMapper; import io.metersphere.base.mapper.ApiScenarioReportDetailMapper; import io.metersphere.base.mapper.ApiScenarioReportMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper; @@ -21,6 +23,7 @@ import sun.security.util.Cache; import javax.annotation.Resource; import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; import java.util.List; import java.util.UUID; @@ -35,6 +38,8 @@ public class ApiScenarioReportService { private ApiScenarioReportMapper apiScenarioReportMapper; @Resource private ApiScenarioReportDetailMapper apiScenarioReportDetailMapper; + @Resource + private ApiScenarioMapper apiScenarioMapper; public void complete(TestResult result) { Object obj = cache.get(result.getTestId()); @@ -139,6 +144,27 @@ public class ApiScenarioReportService { public String add(APIScenarioReportResult test) { ApiScenarioReport report = createReport(test); ApiScenarioReportDetail detail = new ApiScenarioReportDetail(); + TestResult result = JSON.parseObject(test.getContent(), TestResult.class); + // 更新场景 + if (result != null) { + result.getScenarios().forEach(item -> { + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andNameEqualTo(item.getName()).andProjectIdEqualTo(test.getProjectId()); + List list = apiScenarioMapper.selectByExample(example); + if (list.size() > 0) { + ApiScenario scenario = list.get(0); + if (item.getError() > 0) { + scenario.setLastResult("Fail"); + } else { + scenario.setLastResult("Success"); + } + String passRate = new DecimalFormat("0%").format((float) item.getSuccess() / (item.getSuccess() + item.getError())); + scenario.setPassRate(passRate); + scenario.setReportId(report.getId()); + apiScenarioMapper.updateByPrimaryKey(scenario); + } + }); + } detail.setContent(test.getContent().getBytes(StandardCharsets.UTF_8)); detail.setReportId(report.getId()); detail.setProjectId(test.getProjectId()); diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiScenario.java b/backend/src/main/java/io/metersphere/base/domain/ApiScenario.java index ceba28c3dc..0ed46c37e2 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ApiScenario.java +++ b/backend/src/main/java/io/metersphere/base/domain/ApiScenario.java @@ -37,6 +37,12 @@ public class ApiScenario implements Serializable { private Long updateTime; + private String passRate; + + private String lastResult; + + private String reportId; + private String scenarioDefinition; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiScenarioExample.java b/backend/src/main/java/io/metersphere/base/domain/ApiScenarioExample.java index 45c28b2630..b1a2df8872 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ApiScenarioExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/ApiScenarioExample.java @@ -1193,6 +1193,216 @@ public class ApiScenarioExample { addCriterion("update_time not between", value1, value2, "updateTime"); return (Criteria) this; } + + public Criteria andPassRateIsNull() { + addCriterion("pass_rate is null"); + return (Criteria) this; + } + + public Criteria andPassRateIsNotNull() { + addCriterion("pass_rate is not null"); + return (Criteria) this; + } + + public Criteria andPassRateEqualTo(String value) { + addCriterion("pass_rate =", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateNotEqualTo(String value) { + addCriterion("pass_rate <>", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateGreaterThan(String value) { + addCriterion("pass_rate >", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateGreaterThanOrEqualTo(String value) { + addCriterion("pass_rate >=", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateLessThan(String value) { + addCriterion("pass_rate <", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateLessThanOrEqualTo(String value) { + addCriterion("pass_rate <=", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateLike(String value) { + addCriterion("pass_rate like", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateNotLike(String value) { + addCriterion("pass_rate not like", value, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateIn(List values) { + addCriterion("pass_rate in", values, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateNotIn(List values) { + addCriterion("pass_rate not in", values, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateBetween(String value1, String value2) { + addCriterion("pass_rate between", value1, value2, "passRate"); + return (Criteria) this; + } + + public Criteria andPassRateNotBetween(String value1, String value2) { + addCriterion("pass_rate not between", value1, value2, "passRate"); + return (Criteria) this; + } + + public Criteria andLastResultIsNull() { + addCriterion("last_result is null"); + return (Criteria) this; + } + + public Criteria andLastResultIsNotNull() { + addCriterion("last_result is not null"); + return (Criteria) this; + } + + public Criteria andLastResultEqualTo(String value) { + addCriterion("last_result =", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultNotEqualTo(String value) { + addCriterion("last_result <>", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultGreaterThan(String value) { + addCriterion("last_result >", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultGreaterThanOrEqualTo(String value) { + addCriterion("last_result >=", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultLessThan(String value) { + addCriterion("last_result <", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultLessThanOrEqualTo(String value) { + addCriterion("last_result <=", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultLike(String value) { + addCriterion("last_result like", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultNotLike(String value) { + addCriterion("last_result not like", value, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultIn(List values) { + addCriterion("last_result in", values, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultNotIn(List values) { + addCriterion("last_result not in", values, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultBetween(String value1, String value2) { + addCriterion("last_result between", value1, value2, "lastResult"); + return (Criteria) this; + } + + public Criteria andLastResultNotBetween(String value1, String value2) { + addCriterion("last_result not between", value1, value2, "lastResult"); + return (Criteria) this; + } + + public Criteria andReportIdIsNull() { + addCriterion("report_id is null"); + return (Criteria) this; + } + + public Criteria andReportIdIsNotNull() { + addCriterion("report_id is not null"); + return (Criteria) this; + } + + public Criteria andReportIdEqualTo(String value) { + addCriterion("report_id =", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotEqualTo(String value) { + addCriterion("report_id <>", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdGreaterThan(String value) { + addCriterion("report_id >", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdGreaterThanOrEqualTo(String value) { + addCriterion("report_id >=", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLessThan(String value) { + addCriterion("report_id <", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLessThanOrEqualTo(String value) { + addCriterion("report_id <=", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLike(String value) { + addCriterion("report_id like", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotLike(String value) { + addCriterion("report_id not like", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdIn(List values) { + addCriterion("report_id in", values, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotIn(List values) { + addCriterion("report_id not in", values, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdBetween(String value1, String value2) { + addCriterion("report_id between", value1, value2, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotBetween(String value1, String value2) { + addCriterion("report_id not between", value1, value2, "reportId"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java b/backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java index b6c632c40c..5c7a12abd6 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java +++ b/backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java @@ -1,8 +1,7 @@ package io.metersphere.base.domain; -import lombok.Data; - import java.io.Serializable; +import lombok.Data; @Data public class ApiScenarioReport implements Serializable { 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/domain/User.java b/backend/src/main/java/io/metersphere/base/domain/User.java index e5e79131a3..2eb1fb1785 100644 --- a/backend/src/main/java/io/metersphere/base/domain/User.java +++ b/backend/src/main/java/io/metersphere/base/domain/User.java @@ -29,5 +29,7 @@ public class User implements Serializable { private String source; + private String lastProjectId; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/UserExample.java b/backend/src/main/java/io/metersphere/base/domain/UserExample.java index 986bec6d9d..d4d5db7577 100644 --- a/backend/src/main/java/io/metersphere/base/domain/UserExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/UserExample.java @@ -923,6 +923,76 @@ public class UserExample { addCriterion("`source` not between", value1, value2, "source"); return (Criteria) this; } + + public Criteria andLastProjectIdIsNull() { + addCriterion("last_project_id is null"); + return (Criteria) this; + } + + public Criteria andLastProjectIdIsNotNull() { + addCriterion("last_project_id is not null"); + return (Criteria) this; + } + + public Criteria andLastProjectIdEqualTo(String value) { + addCriterion("last_project_id =", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdNotEqualTo(String value) { + addCriterion("last_project_id <>", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdGreaterThan(String value) { + addCriterion("last_project_id >", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdGreaterThanOrEqualTo(String value) { + addCriterion("last_project_id >=", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdLessThan(String value) { + addCriterion("last_project_id <", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdLessThanOrEqualTo(String value) { + addCriterion("last_project_id <=", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdLike(String value) { + addCriterion("last_project_id like", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdNotLike(String value) { + addCriterion("last_project_id not like", value, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdIn(List values) { + addCriterion("last_project_id in", values, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdNotIn(List values) { + addCriterion("last_project_id not in", values, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdBetween(String value1, String value2) { + addCriterion("last_project_id between", value1, value2, "lastProjectId"); + return (Criteria) this; + } + + public Criteria andLastProjectIdNotBetween(String value1, String value2) { + addCriterion("last_project_id not between", value1, value2, "lastProjectId"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { 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 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/ApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiScenarioMapper.xml index bca2504e6d..ec7a2add91 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiScenarioMapper.xml @@ -18,6 +18,9 @@ + + + @@ -83,7 +86,7 @@ id, project_id, tag_id, user_id, api_scenario_module_id, module_path, `name`, `level`, `status`, principal, step_total, follow_people, schedule, description, create_time, - update_time + update_time, pass_rate, last_result, report_id scenario_definition @@ -142,13 +145,15 @@ `name`, `level`, `status`, principal, step_total, follow_people, schedule, description, create_time, - update_time, scenario_definition) + update_time, pass_rate, last_result, + report_id, scenario_definition) values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{tagId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{apiScenarioModuleId,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER}, #{followPeople,jdbcType=VARCHAR}, #{schedule,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, - #{updateTime,jdbcType=BIGINT}, #{scenarioDefinition,jdbcType=LONGVARCHAR}) + #{updateTime,jdbcType=BIGINT}, #{passRate,jdbcType=VARCHAR}, #{lastResult,jdbcType=VARCHAR}, + #{reportId,jdbcType=VARCHAR}, #{scenarioDefinition,jdbcType=LONGVARCHAR}) insert into api_scenario @@ -201,6 +206,15 @@ update_time, + + pass_rate, + + + last_result, + + + report_id, + scenario_definition, @@ -254,6 +268,15 @@ #{updateTime,jdbcType=BIGINT}, + + #{passRate,jdbcType=VARCHAR}, + + + #{lastResult,jdbcType=VARCHAR}, + + + #{reportId,jdbcType=VARCHAR}, + #{scenarioDefinition,jdbcType=LONGVARCHAR}, @@ -316,6 +339,15 @@ update_time = #{record.updateTime,jdbcType=BIGINT}, + + pass_rate = #{record.passRate,jdbcType=VARCHAR}, + + + last_result = #{record.lastResult,jdbcType=VARCHAR}, + + + report_id = #{record.reportId,jdbcType=VARCHAR}, + scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR}, @@ -342,6 +374,9 @@ description = #{record.description,jdbcType=VARCHAR}, create_time = #{record.createTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT}, + pass_rate = #{record.passRate,jdbcType=VARCHAR}, + last_result = #{record.lastResult,jdbcType=VARCHAR}, + report_id = #{record.reportId,jdbcType=VARCHAR}, scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR} @@ -364,7 +399,10 @@ schedule = #{record.schedule,jdbcType=VARCHAR}, description = #{record.description,jdbcType=VARCHAR}, create_time = #{record.createTime,jdbcType=BIGINT}, - update_time = #{record.updateTime,jdbcType=BIGINT} + update_time = #{record.updateTime,jdbcType=BIGINT}, + pass_rate = #{record.passRate,jdbcType=VARCHAR}, + last_result = #{record.lastResult,jdbcType=VARCHAR}, + report_id = #{record.reportId,jdbcType=VARCHAR} @@ -417,6 +455,15 @@ update_time = #{updateTime,jdbcType=BIGINT}, + + pass_rate = #{passRate,jdbcType=VARCHAR}, + + + last_result = #{lastResult,jdbcType=VARCHAR}, + + + report_id = #{reportId,jdbcType=VARCHAR}, + scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR}, @@ -440,6 +487,9 @@ description = #{description,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT}, + pass_rate = #{passRate,jdbcType=VARCHAR}, + last_result = #{lastResult,jdbcType=VARCHAR}, + report_id = #{reportId,jdbcType=VARCHAR}, scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR} where id = #{id,jdbcType=VARCHAR} @@ -459,7 +509,10 @@ schedule = #{schedule,jdbcType=VARCHAR}, description = #{description,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=BIGINT}, - update_time = #{updateTime,jdbcType=BIGINT} + update_time = #{updateTime,jdbcType=BIGINT}, + pass_rate = #{passRate,jdbcType=VARCHAR}, + last_result = #{lastResult,jdbcType=VARCHAR}, + report_id = #{reportId,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR} \ No newline at end of file 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 + , + 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}, + select @@ -111,13 +112,13 @@ insert into user (id, `name`, email, `password`, `status`, create_time, update_time, `language`, last_workspace_id, - last_organization_id, phone, `source` - ) + last_organization_id, phone, `source`, + last_project_id) values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{language,jdbcType=VARCHAR}, #{lastWorkspaceId,jdbcType=VARCHAR}, - #{lastOrganizationId,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{source,jdbcType=VARCHAR} - ) + #{lastOrganizationId,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{source,jdbcType=VARCHAR}, + #{lastProjectId,jdbcType=VARCHAR}) insert into user @@ -158,6 +159,9 @@ `source`, + + last_project_id, + @@ -196,6 +200,9 @@ #{source,jdbcType=VARCHAR}, + + #{lastProjectId,jdbcType=VARCHAR}, + + + + + \ 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/java/io/metersphere/performance/notice/PerformanceNoticeTask.java b/backend/src/main/java/io/metersphere/performance/notice/PerformanceNoticeTask.java index 6b9ea8226f..76782f6839 100644 --- a/backend/src/main/java/io/metersphere/performance/notice/PerformanceNoticeTask.java +++ b/backend/src/main/java/io/metersphere/performance/notice/PerformanceNoticeTask.java @@ -15,6 +15,8 @@ import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -49,7 +51,7 @@ public class PerformanceNoticeTask { } try { //查询定时任务是否关闭 - Thread.sleep(1000 * 30);// 每分钟检查 loadtest 的状态 + Thread.sleep(1000 * 10);// 检查 loadtest 的状态 } catch (InterruptedException e) { LogUtil.error(e.getMessage(), e); } @@ -81,7 +83,11 @@ public class PerformanceNoticeTask { if (PerformanceTestStatus.Error.name().equals(loadTestReport.getStatus())) { event = NoticeConstants.Event.EXECUTE_FAILED; } - + Map paramMap = new HashMap<>(); + paramMap.put("testName", loadTestReport.getName()); + paramMap.put("id", loadTestReport.getId()); + paramMap.put("type", "performance"); + paramMap.put("url", baseSystemConfigDTO.getUrl()); NoticeModel noticeModel = NoticeModel.builder() .successContext(successContext) .successMailTemplate("PerformanceApiSuccessNotification") @@ -91,6 +97,7 @@ public class PerformanceNoticeTask { .status(loadTestReport.getStatus()) .subject(subject) .event(event) + .paramMap(paramMap) .build(); noticeSendService.send(loadTestReport.getTriggerMode(), noticeModel); } 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/backend/src/main/resources/db/migration/V49__user_add_project_id.sql b/backend/src/main/resources/db/migration/V49__user_add_project_id.sql new file mode 100644 index 0000000000..c282253624 --- /dev/null +++ b/backend/src/main/resources/db/migration/V49__user_add_project_id.sql @@ -0,0 +1 @@ +alter table user add last_project_id varchar(50) null; \ No newline at end of file diff --git a/backend/src/main/resources/generatorConfig.xml b/backend/src/main/resources/generatorConfig.xml index 2bbafcfd42..60e77f17f1 100644 --- a/backend/src/main/resources/generatorConfig.xml +++ b/backend/src/main/resources/generatorConfig.xml @@ -64,8 +64,8 @@ +
-
\ No newline at end of file diff --git a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue index fd57c5587b..2606122ccf 100644 --- a/frontend/src/business/components/api/automation/report/ApiReportDetail.vue +++ b/frontend/src/business/components/api/automation/report/ApiReportDetail.vue @@ -4,7 +4,7 @@
- +
@@ -71,6 +71,7 @@ reportId: String, currentProjectId: String, infoDb: Boolean, + debug: Boolean, }, watch: { reportId() { @@ -178,6 +179,8 @@ this.$success(this.$t('commons.save_success')); this.loading = false; this.$emit('refresh'); + }, error => { + this.loading = false; }); }, exportReportReset() { diff --git a/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue b/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue index 6fa1940fa1..fc2fad06e5 100644 --- a/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue +++ b/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue @@ -2,14 +2,14 @@
- + {{ report.createTime | timestampFormatDate }} {{$t('test_track.plan_view.export_report')}} - + {{$t('commons.save')}} @@ -23,7 +23,10 @@ export default { name: "MsApiReportViewHeader", - props: ['report'], + props: { + report: {}, + debug: Boolean, + }, computed: { path() { return "/api/test/edit?id=" + this.report.testId; diff --git a/frontend/src/business/components/api/automation/report/components/RequestMetric.vue b/frontend/src/business/components/api/automation/report/components/RequestMetric.vue index cdffc5d23d..b52a45bf62 100644 --- a/frontend/src/business/components/api/automation/report/components/RequestMetric.vue +++ b/frontend/src/business/components/api/automation/report/components/RequestMetric.vue @@ -1,34 +1,18 @@ diff --git a/frontend/src/business/components/api/automation/report/components/RequestResult.vue b/frontend/src/business/components/api/automation/report/components/RequestResult.vue index 7a05c45919..3bd2e6a620 100644 --- a/frontend/src/business/components/api/automation/report/components/RequestResult.vue +++ b/frontend/src/business/components/api/automation/report/components/RequestResult.vue @@ -3,7 +3,7 @@

- +
{{ indexNumber+1 }}
@@ -14,14 +14,10 @@ {{ request.name }}
- -
- {{ request.method }} -
-
+ -
{{ request.responseResult.responseCode }}
+
{{ request.responseResult.responseCode }}
@@ -122,16 +118,18 @@ } .ms-api-col { - background-color: #FCF1F1; - border-color: #67C23A; + background-color: #EFF0F0; + border-color: #EFF0F0; margin-right: 10px; - color: #67C23A; + font-size: 12px; + color: #64666A; } .ms-api-col-create { background-color: #EBF2F2; border-color: #008080; margin-right: 10px; + font-size: 12px; color: #008080; } diff --git a/frontend/src/business/components/api/automation/report/components/RequestResultTail.vue b/frontend/src/business/components/api/automation/report/components/RequestResultTail.vue index 049a419b3f..97ed21bb7b 100644 --- a/frontend/src/business/components/api/automation/report/components/RequestResultTail.vue +++ b/frontend/src/business/components/api/automation/report/components/RequestResultTail.vue @@ -1,27 +1,6 @@