Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5221ec796d
|
@ -263,13 +263,20 @@
|
|||
<artifactId>spring-boot-starter-data-ldap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger 解析 -->
|
||||
<!-- swagger2 解析 -->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-parser</artifactId>
|
||||
<version>1.0.51</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger3 解析 -->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>io.swagger.parser.v3</groupId>-->
|
||||
<!--<artifactId>swagger-parser</artifactId>-->
|
||||
<!--<version>2.0.24</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!-- 执行 js 代码依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.sdk</groupId>
|
||||
|
|
|
@ -81,5 +81,10 @@ public class ApiAutomationController {
|
|||
apiAutomationService.run(request);
|
||||
}
|
||||
|
||||
@PostMapping("/getReference")
|
||||
public List<ApiScenario> getReference(@RequestBody ApiScenarioRequest request) {
|
||||
return apiAutomationService.getReference(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> scenarioIds;
|
||||
|
||||
private String content;
|
||||
}
|
||||
|
|
|
@ -15,5 +15,7 @@ public class RunScenarioRequest {
|
|||
|
||||
private String environmentId;
|
||||
|
||||
private String triggerMode;
|
||||
|
||||
private List<String> scenarioIds;
|
||||
}
|
||||
|
|
|
@ -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<KeyValue> variables;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<MsTestElement> hashTree;
|
||||
|
||||
// 公共环境逐层传递,如果自身有环境 以自身引用环境为准否则以公共环境作为请求环境
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree testPlanTree = tree.add(getPlan());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree groupTree = tree.add(getThreadGroup());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
|
|
|
@ -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<KeyValue> variables;
|
||||
}
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
addAssertions(tree);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> 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);
|
||||
|
|
|
@ -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<KeyValue> headers;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
HeaderManager headerManager = new HeaderManager();
|
||||
headerManager.setEnabled(true);
|
||||
headerManager.setName(this.getName() + "Headers");
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree groupTree = tree.add(ifController());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
for (MsTestElement el : hashTree) {
|
||||
el.toHashTree(tree, el.getHashTree(), config);
|
||||
}
|
||||
|
|
|
@ -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<MsExtractXPath> xpath;
|
||||
private String type = "Extract";
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
addRequestExtractors(tree);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
JSR223Sampler processor = new JSR223Sampler();
|
||||
processor.setEnabled(true);
|
||||
processor.setName(this.getName() + "JSR223Processor");
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
JSR223PostProcessor processor = new JSR223PostProcessor();
|
||||
processor.setEnabled(true);
|
||||
processor.setName(this.getName() + "JSR223PostProcessor");
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
JSR223PreProcessor processor = new JSR223PreProcessor();
|
||||
processor.setEnabled(true);
|
||||
processor.setName(this.getName() + "JSR223PreProcessor");
|
||||
|
|
|
@ -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<KeyValue> attachmentArgs;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree testPlanTree = new ListedHashTree();
|
||||
testPlanTree.add(dubboConfig());
|
||||
tree.set(dubboSample(), testPlanTree);
|
||||
|
|
|
@ -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<KeyValue> arguments;
|
||||
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> 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<KeyValue> 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<String, String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree samplerHashTree = tree.add(jdbcSampler());
|
||||
tree.add(jdbcDataSource());
|
||||
tree.add(arguments(this.getName() + " Variables", this.getVariables()));
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree samplerHashTree = new ListedHashTree();
|
||||
samplerHashTree.add(tcpConfig());
|
||||
tree.set(tcpSampler(), samplerHashTree);
|
||||
|
|
|
@ -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<MsTestElement> hashTree, EnvironmentConfig config) {
|
||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||
final HashTree groupTree = tree.add(constantTimer());
|
||||
if (CollectionUtils.isNotEmpty(hashTree)) {
|
||||
hashTree.forEach(el -> {
|
||||
|
|
|
@ -229,7 +229,11 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
|||
if (StringUtils.equals("Error", report.getStatus())) {
|
||||
event = NoticeConstants.Event.EXECUTE_FAILED;
|
||||
}
|
||||
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
|
|
|
@ -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<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
|
||||
});
|
||||
group.setHashTree(elements);
|
||||
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
|
||||
// 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取
|
||||
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
|
||||
new TypeReference<LinkedList<MsTestElement>>() {
|
||||
});
|
||||
LinkedList<KeyValue> variables = mapper.readValue(element.getString("variables"),
|
||||
new TypeReference<LinkedList<KeyValue>>() {
|
||||
});
|
||||
scenario.setHashTree(elements);
|
||||
scenario.setVariables(variables);
|
||||
LinkedList<MsTestElement> 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<MultipartFile> bodyFiles) {
|
||||
List<String> 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<ApiScenario> getReference(ApiScenarioRequest request) {
|
||||
return extApiScenarioMapper.selectReference(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ApiScenario> 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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<String> values) {
|
||||
addCriterion("pass_rate in", values, "passRate");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPassRateNotIn(List<String> 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<String> values) {
|
||||
addCriterion("last_result in", values, "lastResult");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLastResultNotIn(List<String> 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<String> values) {
|
||||
addCriterion("report_id in", values, "reportId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andReportIdNotIn(List<String> 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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -29,5 +29,7 @@ public class User implements Serializable {
|
|||
|
||||
private String source;
|
||||
|
||||
private String lastProjectId;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -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<String> values) {
|
||||
addCriterion("last_project_id in", values, "lastProjectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLastProjectIdNotIn(List<String> 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 {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</delete>
|
||||
|
||||
<select id="selectAll" resultType="io.metersphere.api.dto.ApiMonitorSearch">
|
||||
select distinct url from api_data_view;
|
||||
select distinct url from api_data_view order by url;
|
||||
</select>
|
||||
|
||||
<select id="selectResponseTimeByUrl" parameterType="java.lang.String"
|
||||
|
@ -56,7 +56,7 @@
|
|||
</select>
|
||||
|
||||
<select id="selectReportIdByUrlAndStartTime" resultType="java.lang.String">
|
||||
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};
|
||||
</select>
|
||||
|
||||
<insert id="insertListApiData" parameterType="java.util.List">
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
<result column="pass_rate" jdbcType="VARCHAR" property="passRate" />
|
||||
<result column="last_result" jdbcType="VARCHAR" property="lastResult" />
|
||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenario">
|
||||
<result column="scenario_definition" jdbcType="LONGVARCHAR" property="scenarioDefinition" />
|
||||
|
@ -83,7 +86,7 @@
|
|||
<sql id="Base_Column_List">
|
||||
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
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
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>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenario">
|
||||
insert into api_scenario
|
||||
|
@ -201,6 +206,15 @@
|
|||
<if test="updateTime != null">
|
||||
update_time,
|
||||
</if>
|
||||
<if test="passRate != null">
|
||||
pass_rate,
|
||||
</if>
|
||||
<if test="lastResult != null">
|
||||
last_result,
|
||||
</if>
|
||||
<if test="reportId != null">
|
||||
report_id,
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition,
|
||||
</if>
|
||||
|
@ -254,6 +268,15 @@
|
|||
<if test="updateTime != null">
|
||||
#{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="passRate != null">
|
||||
#{passRate,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="lastResult != null">
|
||||
#{lastResult,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="reportId != null">
|
||||
#{reportId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
#{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -316,6 +339,15 @@
|
|||
<if test="record.updateTime != null">
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.passRate != null">
|
||||
pass_rate = #{record.passRate,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.lastResult != null">
|
||||
last_result = #{record.lastResult,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.reportId != null">
|
||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.scenarioDefinition != null">
|
||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -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}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -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}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -417,6 +455,15 @@
|
|||
<if test="updateTime != null">
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="passRate != null">
|
||||
pass_rate = #{passRate,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="lastResult != null">
|
||||
last_result = #{lastResult,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="reportId != null">
|
||||
report_id = #{reportId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
|
@ -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}
|
||||
</update>
|
||||
|
@ -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}
|
||||
</update>
|
||||
</mapper>
|
|
@ -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<MessageTask> selectByExampleWithBLOBs(MessageTaskExample example);
|
||||
|
||||
List<MessageTask> 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);
|
||||
}
|
|
@ -2,17 +2,20 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.base.mapper.MessageTaskMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.MessageTask">
|
||||
<id column="id" jdbcType="VARCHAR" property="id"/>
|
||||
<result column="type" jdbcType="VARCHAR" property="type"/>
|
||||
<result column="event" jdbcType="VARCHAR" property="event"/>
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId"/>
|
||||
<result column="task_type" jdbcType="VARCHAR" property="taskType"/>
|
||||
<result column="webhook" jdbcType="VARCHAR" property="webhook"/>
|
||||
<result column="identification" jdbcType="VARCHAR" property="identification"/>
|
||||
<result column="is_set" jdbcType="BIT" property="isSet"/>
|
||||
<result column="organization_id" jdbcType="VARCHAR" property="organizationId"/>
|
||||
<result column="test_id" jdbcType="VARCHAR" property="testId"/>
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime"/>
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||
<result column="event" jdbcType="VARCHAR" property="event" />
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId" />
|
||||
<result column="task_type" jdbcType="VARCHAR" property="taskType" />
|
||||
<result column="webhook" jdbcType="VARCHAR" property="webhook" />
|
||||
<result column="identification" jdbcType="VARCHAR" property="identification" />
|
||||
<result column="is_set" jdbcType="BIT" property="isSet" />
|
||||
<result column="organization_id" jdbcType="VARCHAR" property="organizationId" />
|
||||
<result column="test_id" jdbcType="VARCHAR" property="testId" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.MessageTask">
|
||||
<result column="template" jdbcType="LONGVARCHAR" property="template" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -25,13 +28,13 @@
|
|||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
AND ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
AND ${criterion.condition} #{criterion.value} AND #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
AND ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
|
@ -76,6 +79,25 @@
|
|||
id, `type`, event, user_id, task_type, webhook, identification, is_set, organization_id,
|
||||
test_id, create_time
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
`template`
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.MessageTaskExample" resultMap="ResultMapWithBLOBs">
|
||||
SELECT
|
||||
<if test="distinct">
|
||||
DISTINCT
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
FROM message_task
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
ORDER BY ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
|
@ -90,9 +112,11 @@
|
|||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from message_task
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
@ -107,14 +131,16 @@
|
|||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
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>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
insert into message_task
|
||||
|
@ -152,6 +178,9 @@
|
|||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="template != null">
|
||||
`template`,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -187,6 +216,9 @@
|
|||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="template != null">
|
||||
#{template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.MessageTaskExample" resultType="java.lang.Long">
|
||||
|
@ -231,24 +263,45 @@
|
|||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.template != null">
|
||||
`template` = #{record.template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||
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}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
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}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -286,21 +339,39 @@
|
|||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="template != null">
|
||||
`template` = #{template,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
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>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.MessageTask">
|
||||
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}
|
||||
</update>
|
||||
</mapper>
|
|
@ -14,6 +14,7 @@
|
|||
<result column="last_organization_id" jdbcType="VARCHAR" property="lastOrganizationId" />
|
||||
<result column="phone" jdbcType="VARCHAR" property="phone" />
|
||||
<result column="source" jdbcType="VARCHAR" property="source" />
|
||||
<result column="last_project_id" jdbcType="VARCHAR" property="lastProjectId" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -75,7 +76,7 @@
|
|||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
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
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.base.domain.UserExample" resultMap="BaseResultMap">
|
||||
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>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.User">
|
||||
insert into user
|
||||
|
@ -158,6 +159,9 @@
|
|||
<if test="source != null">
|
||||
`source`,
|
||||
</if>
|
||||
<if test="lastProjectId != null">
|
||||
last_project_id,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -196,6 +200,9 @@
|
|||
<if test="source != null">
|
||||
#{source,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="lastProjectId != null">
|
||||
#{lastProjectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.UserExample" resultType="java.lang.Long">
|
||||
|
@ -243,6 +250,9 @@
|
|||
<if test="record.source != null">
|
||||
`source` = #{record.source,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.lastProjectId != null">
|
||||
last_project_id = #{record.lastProjectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -261,7 +271,8 @@
|
|||
last_workspace_id = #{record.lastWorkspaceId,jdbcType=VARCHAR},
|
||||
last_organization_id = #{record.lastOrganizationId,jdbcType=VARCHAR},
|
||||
phone = #{record.phone,jdbcType=VARCHAR},
|
||||
`source` = #{record.source,jdbcType=VARCHAR}
|
||||
`source` = #{record.source,jdbcType=VARCHAR},
|
||||
last_project_id = #{record.lastProjectId,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -302,6 +313,9 @@
|
|||
<if test="source != null">
|
||||
`source` = #{source,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="lastProjectId != null">
|
||||
last_project_id = #{lastProjectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -317,7 +331,8 @@
|
|||
last_workspace_id = #{lastWorkspaceId,jdbcType=VARCHAR},
|
||||
last_organization_id = #{lastOrganizationId,jdbcType=VARCHAR},
|
||||
phone = #{phone,jdbcType=VARCHAR},
|
||||
`source` = #{source,jdbcType=VARCHAR}
|
||||
`source` = #{source,jdbcType=VARCHAR},
|
||||
last_project_id = #{lastProjectId,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
</mapper>
|
|
@ -14,4 +14,6 @@ public interface ExtApiScenarioMapper {
|
|||
|
||||
List<ApiScenario> selectIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<ApiScenario> selectReference(@Param("request") ApiScenarioRequest request);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
select api_scenario.id, api_scenario.project_id, api_scenario.tag_id, api_scenario.user_id,
|
||||
api_scenario.api_scenario_module_id,api_scenario.module_path, api_scenario.name, api_scenario.level,
|
||||
api_scenario.status, api_scenario.principal, api_scenario.step_total, api_scenario.follow_people,
|
||||
api_scenario.last_result,api_scenario.pass_rate,api_scenario.report_id,
|
||||
api_scenario.schedule, api_scenario.description, api_scenario.create_time, api_scenario.update_time,
|
||||
project.name as project_name, user.name as user_name
|
||||
from api_scenario
|
||||
|
@ -70,4 +71,23 @@
|
|||
#{v}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="selectReference" resultType="io.metersphere.base.domain.ApiScenario">
|
||||
select * from api_scenario
|
||||
<where>
|
||||
id != #{request.id}
|
||||
<if test="request.workspaceId != null">
|
||||
AND project.workspace_id = #{request.workspaceId}
|
||||
</if>
|
||||
<if test="request.projectId != null">
|
||||
AND project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.moduleId != null">
|
||||
AND api_scenario_module_id = #{request.moduleId}
|
||||
</if>
|
||||
and scenario_definition like CONCAT('%', #{request.id},'%')
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
|
@ -17,4 +17,5 @@ public class MessageDetail {
|
|||
private Boolean isSet;
|
||||
private String testId;
|
||||
private Long createTime;
|
||||
private String template;
|
||||
}
|
||||
|
|
|
@ -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<String> 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<String> 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<String, Object> 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<String> getUserPhones(List<String> userIds) {
|
||||
|
|
|
@ -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<String> 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<String, Object> 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);
|
||||
|
|
|
@ -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<MessageDetail> messageDetails;
|
||||
switch (taskType) {
|
||||
case NoticeConstants.Mode.API:
|
||||
|
|
|
@ -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<MessageDetail> searchMessageByTestId(String testId) {
|
||||
MessageTaskExample example = new MessageTaskExample();
|
||||
example.createCriteria().andTestIdEqualTo(testId);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||
List<MessageDetail> scheduleMessageTask = new ArrayList<>();
|
||||
Map<String, List<MessageTask>> 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<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExampleWithBLOBs(example);
|
||||
|
||||
Map<String, List<MessageTask>> 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));
|
||||
|
|
|
@ -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<String, Object> 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);
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -0,0 +1 @@
|
|||
alter table user add last_project_id varchar(50) null;
|
|
@ -64,8 +64,8 @@
|
|||
|
||||
<!--要生成的数据库表 -->
|
||||
|
||||
<table tableName="api_scenario"/>
|
||||
<table tableName="api_scenario_report"/>
|
||||
<table tableName="api_scenario_report_detail"/>
|
||||
|
||||
</context>
|
||||
</generatorConfiguration>
|
|
@ -4,7 +4,7 @@
|
|||
<el-card>
|
||||
<section class="report-container" v-if="this.report.testId">
|
||||
|
||||
<ms-api-report-view-header :report="report" @reportExport="handleExport" @reportSave="handleSave"/>
|
||||
<ms-api-report-view-header :debug="debug" :report="report" @reportExport="handleExport" @reportSave="handleSave"/>
|
||||
|
||||
<main v-if="this.isNotRunning">
|
||||
<ms-metric-chart :content="content" :totalTime="totalTime"/>
|
||||
|
@ -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() {
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<header class="report-header">
|
||||
<el-row>
|
||||
<el-col>
|
||||
<span><el-input size="mini" style="width: 200px" v-model="report.name"/> </span>
|
||||
<span v-if="!debug"><el-input size="mini" style="width: 200px" v-model="report.name"/> </span>
|
||||
<span class="time"> {{ report.createTime | timestampFormatDate }}</span>
|
||||
|
||||
<el-button :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleExport(report.name)" style="margin-right: 10px">
|
||||
{{$t('test_track.plan_view.export_report')}}
|
||||
</el-button>
|
||||
|
||||
<el-button :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleSave(report.name)" style="margin-right: 10px">
|
||||
<el-button v-if="!debug" :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleSave(report.name)" style="margin-right: 10px">
|
||||
{{$t('commons.save')}}
|
||||
</el-button>
|
||||
|
||||
|
@ -23,7 +23,10 @@
|
|||
|
||||
export default {
|
||||
name: "MsApiReportViewHeader",
|
||||
props: ['report'],
|
||||
props: {
|
||||
report: {},
|
||||
debug: Boolean,
|
||||
},
|
||||
computed: {
|
||||
path() {
|
||||
return "/api/test/edit?id=" + this.report.testId;
|
||||
|
|
|
@ -1,34 +1,18 @@
|
|||
<template>
|
||||
<div class="metric-container">
|
||||
<el-row type="flex">
|
||||
<div class="metric">
|
||||
<div class="value">{{request.responseResult.responseTime}} ms</div>
|
||||
<div class="name">{{$t('api_report.response_time')}}</div>
|
||||
<br>
|
||||
<div class="value">{{request.responseResult.latency}} ms</div>
|
||||
<div class="name">{{$t('api_report.latency')}}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="value">{{request.requestSize}} bytes</div>
|
||||
<div class="name">{{$t('api_report.request_size')}}</div>
|
||||
<br>
|
||||
<div class="value">{{request.responseResult.responseSize}} bytes</div>
|
||||
<div class="name">{{$t('api_report.response_size')}}</div>
|
||||
</div>
|
||||
|
||||
<div class="metric horizontal">
|
||||
<el-row type="flex">
|
||||
<div class="code">
|
||||
<div class="value" :class="{'error': error}">{{request.responseResult.responseCode}}</div>
|
||||
<div class="name">{{$t('api_report.response_code')}}</div>
|
||||
</div>
|
||||
<div class="split"></div>
|
||||
<div class="message">
|
||||
<div class="value">{{request.responseResult.responseMessage}}</div>
|
||||
<div class="name">{{$t('api_report.response_message')}}</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_code')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseCode ? request.responseResult.responseCode :'0'}}</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_time')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseTime?request.responseResult.responseTime:0}} ms</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_size')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550; margin-top:2px;margin-left:10px;float: left">{{request.responseResult.responseSize?request.responseResult.responseSize:0}} bytes</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<p class="el-divider--horizontal"></p>
|
||||
<div @click="active">
|
||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
||||
<el-col :span="10" v-if="indexNumber!=undefined">
|
||||
<el-col :span="14" v-if="indexNumber!=undefined">
|
||||
<div class="method">
|
||||
<div class="el-step__icon is-text ms-api-col" v-if="indexNumber%2 ==0">
|
||||
<div class="el-step__icon-inner"> {{ indexNumber+1 }}</div>
|
||||
|
@ -14,14 +14,10 @@
|
|||
{{ request.name }}
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="method">
|
||||
{{ request.method }}
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="5">
|
||||
<el-tooltip effect="dark" :content="request.responseResult.responseCode" placement="bottom" :open-delay="800">
|
||||
<div class="url">{{ request.responseResult.responseCode }}</div>
|
||||
<div class="url" style="color: #5daf34">{{ request.responseResult.responseCode }}</div>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,6 @@
|
|||
<template>
|
||||
<div class="request-result">
|
||||
<div @click="active">
|
||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
||||
<el-col :span="12">
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': isActive}"/>
|
||||
{{scenarioName}}
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
{{$t('api_report.start_time')}}
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
{{$t('api_report.response_time')}}
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
{{$t('api_report.error')}}
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
{{$t('api_report.assertions')}}
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
{{$t('api_report.result')}}
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div>
|
||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
||||
<el-col :span="2">
|
||||
<div class="method">
|
||||
|
@ -35,7 +14,7 @@
|
|||
</el-tooltip>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
{{request.startTime | timestampFormatDate(true) }}
|
||||
{{request.startTime | timestampFormatDate(true) }}
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<div class="time">
|
||||
|
@ -67,7 +46,7 @@
|
|||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
||||
<ms-request-metric :request="request"/>
|
||||
<ms-request-text :request="request"/>
|
||||
<ms-request-text :request="request"/>
|
||||
<br>
|
||||
<ms-response-text :request-type="requestType" :response="request.responseResult"/>
|
||||
</el-tab-pane>
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
<!-- 请求参数-->
|
||||
<el-collapse-transition>
|
||||
<div v-if="request.active">
|
||||
<div v-if="request.protocol === 'HTTP'">
|
||||
<el-input :placeholder="$t('api_test.definition.request.path_all_info')" v-model="request.url" style="width: 85%;margin-top: 10px" size="small">
|
||||
<el-select v-model="request.method" slot="prepend" style="width: 100px" size="small">
|
||||
<el-option v-for="item in reqOptions" :key="item.id" :label="item.label" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-input>
|
||||
</div>
|
||||
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
|
||||
<ms-api-request-form :headers="request.headers " :request="request" v-if="request.protocol==='HTTP'"/>
|
||||
<ms-tcp-basis-parameters :request="request" :currentProject="currentProject" v-if="request.protocol==='TCP'"/>
|
||||
|
@ -41,6 +48,7 @@
|
|||
import MsTcpBasisParameters from "../../definition/components/request/tcp/BasisParameters";
|
||||
import MsDubboBasisParameters from "../../definition/components/request/dubbo/BasisParameters";
|
||||
import MsApiRequestForm from "../../definition/components/request/http/ApiRequestForm";
|
||||
import {REQ_METHOD} from "../../definition/model/JsonData";
|
||||
|
||||
export default {
|
||||
name: "MsApiComponent",
|
||||
|
@ -51,7 +59,22 @@
|
|||
},
|
||||
components: {MsSqlBasisParameters, MsTcpBasisParameters, MsDubboBasisParameters, MsApiRequestForm},
|
||||
data() {
|
||||
return {loading: false,}
|
||||
return {loading: false, reqOptions: REQ_METHOD,}
|
||||
},
|
||||
created() {
|
||||
if (this.request.protocol === 'HTTP') {
|
||||
try {
|
||||
let urlObject = new URL(this.request.url);
|
||||
let url = urlObject.protocol + "//" + urlObject.host + "/";
|
||||
let path = this.request.url.substr(url.length);
|
||||
if (!path.startsWith('/')) {
|
||||
path = "/" + path;
|
||||
}
|
||||
this.request.path = path;
|
||||
} catch (e) {
|
||||
this.request.path = this.request.url;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
remove() {
|
||||
|
@ -94,4 +117,12 @@
|
|||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -58,6 +58,10 @@
|
|||
let name = this.request.name;
|
||||
Object.assign(this.request, row.request);
|
||||
this.request.name = name;
|
||||
if (this.request.protocol === 'HTTP') {
|
||||
this.request.url = row.url;
|
||||
this.request.method = row.method;
|
||||
}
|
||||
this.request.resourceId = getUUID();
|
||||
this.$emit('addCustomizeApi', this.request);
|
||||
},
|
||||
|
@ -72,5 +76,12 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card class="table-card" v-loading="result.loading">
|
||||
<el-card class="table-card" v-loading="loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :condition.sync="condition" @search="search" title=""
|
||||
:show-create="false"/>
|
||||
|
@ -37,31 +37,30 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stepTotal" :label="$t('api_test.automation.step')" show-overflow-tooltip/>
|
||||
<el-table-column prop="status" :label="$t('api_test.automation.last_result')">
|
||||
<el-table-column prop="lastResult" :label="$t('api_test.automation.last_result')">
|
||||
<template v-slot:default="{row}">
|
||||
<el-link type="success" v-if="row.status === 'Success'">{{ $t('api_test.automation.success') }}</el-link>
|
||||
<el-link type="danger" v-if="row.status === 'Fail'">{{ $t('api_test.automation.fail') }}</el-link>
|
||||
<el-link type="warning" v-if="row.status === 'Trash'">{{ $t('api_test.automation.trash') }}</el-link>
|
||||
<el-link type="success" @click="showReport(row)" v-if="row.lastResult === 'Success'">{{ $t('api_test.automation.success') }}</el-link>
|
||||
<el-link type="danger" @click="showReport(row)" v-if="row.lastResult === 'Fail'">{{ $t('api_test.automation.fail') }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="passingRate" :label="$t('api_test.automation.passing_rate')"
|
||||
<el-table-column prop="passRate" :label="$t('api_test.automation.passing_rate')"
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column :label="$t('commons.operating')" width="180">
|
||||
<el-table-column :label="$t('commons.operating')" width="200px" v-if="!referenced">
|
||||
<template v-slot:default="{row}">
|
||||
<el-button type="text" @click="edit(row)">{{ $t('api_test.automation.edit') }}</el-button>
|
||||
<el-button type="text" @click="execute(row)">{{ $t('api_test.automation.execute') }}</el-button>
|
||||
<el-button type="text" @click="copy(row)">{{ $t('api_test.automation.copy') }}</el-button>
|
||||
<el-button type="text" @click="remove(row)">{{ $t('api_test.automation.remove') }}</el-button>
|
||||
<ms-scenario-extend-buttons :row="row"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
|
||||
<div>
|
||||
<!-- 调试结果 -->
|
||||
<!-- 执行结果 -->
|
||||
<el-drawer :visible.sync="runVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject!=undefined ? currentProject.id:''"/>
|
||||
<ms-api-report-detail @refresh="search" :infoDb="infoDb" :report-id="reportId" :currentProjectId="currentProject!=undefined ? currentProject.id:''"/>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</el-card>
|
||||
|
@ -76,18 +75,27 @@
|
|||
import MsTag from "../../../common/components/MsTag";
|
||||
import {getUUID} from "@/common/js/utils";
|
||||
import MsApiReportDetail from "../report/ApiReportDetail";
|
||||
import MsTableMoreBtn from "./TableMoreBtn";
|
||||
import MsScenarioExtendButtons from "@/business/components/api/automation/scenario/ScenarioExtendBtns";
|
||||
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioList",
|
||||
components: {ShowMoreBtn, MsTablePagination, MsTableHeader, MsTag, MsApiReportDetail},
|
||||
components: {MsTablePagination, MsTableMoreBtn, ShowMoreBtn, MsTableHeader, MsTag, MsApiReportDetail, MsScenarioExtendButtons},
|
||||
props: {
|
||||
currentProject: Object,
|
||||
currentModule: Object,
|
||||
referenced: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
loading: false,
|
||||
condition: {},
|
||||
currentScenario: {},
|
||||
schedule: {},
|
||||
selectAll: false,
|
||||
selection: [],
|
||||
tableData: [],
|
||||
|
@ -95,6 +103,7 @@
|
|||
pageSize: 10,
|
||||
total: 0,
|
||||
reportId: "",
|
||||
infoDb: false,
|
||||
runVisible: false,
|
||||
runData: [],
|
||||
buttons: [
|
||||
|
@ -116,6 +125,7 @@
|
|||
},
|
||||
methods: {
|
||||
search() {
|
||||
this.loading = true;
|
||||
this.condition.filters = ["Prepare", "Underway", "Completed"];
|
||||
if (this.currentModule != null) {
|
||||
if (this.currentModule.id === "root") {
|
||||
|
@ -132,10 +142,11 @@
|
|||
}
|
||||
|
||||
let url = "/api/automation/list/" + this.currentPage + "/" + this.pageSize;
|
||||
this.result = this.$post(url, this.condition, response => {
|
||||
this.$post(url, this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleCommand(cmd) {
|
||||
|
@ -154,12 +165,13 @@
|
|||
|
||||
},
|
||||
handleBatchExecute() {
|
||||
this.infoDb = false;
|
||||
let url = "/api/automation/run";
|
||||
let run = {};
|
||||
let scenarioIds = this.selection;
|
||||
run.id = getUUID();
|
||||
run.scenarioIds = scenarioIds;
|
||||
this.result = this.$post(url, run, response => {
|
||||
this.$post(url, run, response => {
|
||||
let data = response.data;
|
||||
this.runVisible = true;
|
||||
this.reportId = run.id;
|
||||
|
@ -179,13 +191,14 @@
|
|||
this.$emit('edit', row);
|
||||
},
|
||||
execute(row) {
|
||||
this.infoDb = false;
|
||||
let url = "/api/automation/run";
|
||||
let run = {};
|
||||
let scenarioIds = [];
|
||||
scenarioIds.push(row.id);
|
||||
run.id = getUUID();
|
||||
run.scenarioIds = scenarioIds;
|
||||
this.result = this.$post(url, run, response => {
|
||||
this.$post(url, run, response => {
|
||||
let data = response.data;
|
||||
this.runVisible = true;
|
||||
this.reportId = run.id;
|
||||
|
@ -195,6 +208,47 @@
|
|||
row.id = getUUID();
|
||||
this.$emit('edit', row);
|
||||
},
|
||||
showReport(row) {
|
||||
this.runVisible = true;
|
||||
this.infoDb = true;
|
||||
this.reportId = row.reportId;
|
||||
},
|
||||
handleQuote() {
|
||||
|
||||
},
|
||||
handleSchedule(row) {
|
||||
this.currentScenario = row;
|
||||
if (row.schedule) {
|
||||
if (Object.prototype.toString.call(row.schedule).match(/\[object (\w+)\]/)[1].toLowerCase() === 'object') {
|
||||
this.schedule = row.schedule;
|
||||
} else {
|
||||
this.schedule = JSON.parse(row.schedule);
|
||||
}
|
||||
}
|
||||
this.$refs.scheduleEdit.open();
|
||||
},
|
||||
saveCronExpression(cronExpression) {
|
||||
this.schedule.enable = true;
|
||||
this.schedule.value = cronExpression;
|
||||
this.saveSchedule();
|
||||
},
|
||||
saveSchedule() {
|
||||
this.checkScheduleEdit();
|
||||
let param = {};
|
||||
param = this.schedule;
|
||||
param.resourceId = this.currentScenario.id;
|
||||
let url = '/api/automation/schedule/create';
|
||||
if (param.id) {
|
||||
url = '/api/automation/schedule/update';
|
||||
}
|
||||
this.$post(url, param, () => {
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.search();
|
||||
});
|
||||
},
|
||||
checkScheduleEdit() {
|
||||
return true;
|
||||
},
|
||||
remove(row) {
|
||||
if (this.currentModule !== undefined && this.currentModule != null && this.currentModule.id === "gc") {
|
||||
this.$get('/api/automation/delete/' + row.id, () => {
|
||||
|
|
|
@ -201,9 +201,9 @@
|
|||
<div v-if="operatingElements.indexOf('HTTPSamplerProxy')>0 || operatingElements.indexOf('DubboSampler')>0 || operatingElements.indexOf('JDBCSampler')>0 || operatingElements.indexOf('TCPSampler')>0 ">
|
||||
<el-button class="ms-right-buttion" size="small" style="color: #F56C6C;background-color: #FCF1F1" @click="apiListImport">+{{$t('api_test.automation.api_list_import')}}</el-button>
|
||||
</div>
|
||||
<div v-if="operatingElements.indexOf('OT_IMPORT')>0">
|
||||
<!--<div v-if="operatingElements.indexOf('OT_IMPORT')>0">
|
||||
<el-button class="ms-right-buttion" size="small" style="color: #409EFF;background-color: #EEF5FE" @click="addComponent('OT_IMPORT')">+{{$t('api_test.automation.external_import')}}</el-button>
|
||||
</div>
|
||||
</div>-->
|
||||
<div v-if="operatingElements.indexOf('ConstantTimer')>0">
|
||||
<el-button class="ms-right-buttion" size="small" style="color: #67C23A;background-color: #F2F9EE" @click="addComponent('ConstantTimer')">+{{$t('api_test.automation.wait_controller')}}</el-button>
|
||||
</div>
|
||||
|
@ -263,7 +263,7 @@
|
|||
@runRefresh="runRefresh" ref="runTest"/>
|
||||
<!-- 调试结果 -->
|
||||
<el-drawer :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
|
||||
<ms-api-report-detail :report-id="reportId" :currentProjectId="currentProject.id"/>
|
||||
<ms-api-report-detail :report-id="reportId" :debug="true" :currentProjectId="currentProject.id"/>
|
||||
</el-drawer>
|
||||
|
||||
<!--场景公共参数-->
|
||||
|
@ -342,7 +342,7 @@
|
|||
debugVisible: false,
|
||||
customizeRequest: {protocol: "HTTP", type: "API", hashTree: [], referenced: 'Created', active: false},
|
||||
operatingElements: [],
|
||||
currentRow: {cases: [], apis: []},
|
||||
currentRow: {cases: [], apis: [], referenced: true},
|
||||
selectedTreeNode: undefined,
|
||||
expandedNode: [],
|
||||
scenarioDefinition: [],
|
||||
|
@ -553,7 +553,11 @@
|
|||
this.$error(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
this.debugData = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
||||
this.debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, referenced: 'Created',
|
||||
environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||
};
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
},
|
||||
getEnvironments() {
|
||||
|
@ -681,6 +685,7 @@
|
|||
if (response.data.scenarioDefinition != null) {
|
||||
let obj = JSON.parse(response.data.scenarioDefinition);
|
||||
this.currentEnvironmentId = obj.environmentId;
|
||||
this.currentScenario.variables = obj.variables;
|
||||
this.scenarioDefinition = obj.hashTree;
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +700,10 @@
|
|||
this.currentScenario.stepTotal = this.scenarioDefinition.length;
|
||||
this.currentScenario.modulePath = this.getPath(this.currentScenario.apiScenarioModuleId);
|
||||
// 构建一个场景对象 方便引用处理
|
||||
let scenario = {id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition};
|
||||
let scenario = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, variables: this.currentScenario.variables,
|
||||
type: "scenario", referenced: 'Created', environmentId: this.currentEnvironmentId, hashTree: this.scenarioDefinition
|
||||
};
|
||||
this.currentScenario.scenarioDefinition = scenario;
|
||||
this.currentScenario.tagId = JSON.stringify(this.currentScenario.tagId);
|
||||
if (this.currentModule != null) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
:current-module="currentModule"
|
||||
@edit="editScenario"
|
||||
@selection="setData"
|
||||
:referenced="true"
|
||||
ref="apiScenarioList"/>
|
||||
|
||||
<el-button style="float: right;margin: 10px" @click="importApiScenario" type="primary">{{ $t('api_test.scenario.reference') }}</el-button>
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
<el-card>
|
||||
<el-row>
|
||||
<div>
|
||||
<div class="el-step__icon is-text" :style="styleType" style="margin-right: 10px">
|
||||
<div class="el-step__icon-inner">{{jsr223ProcessorData.index}}</div>
|
||||
</div>
|
||||
<el-button class="ms-left-buttion" size="small" :style="styleType" style="color: #B8741A;background-color: #F9F1EA">{{title}}</el-button>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': this.jsr223ProcessorData.active}" @click="changeActive" style="margin-left: 20px"/>
|
||||
<el-input size="small" v-model="jsr223ProcessorData.name" class="ms-api-header-select" style="width: 380px"/>
|
||||
<el-button size="small" style="float: right" @click="remove">移除</el-button>
|
||||
<el-button size="small" style="float: right" @click="remove">{{$t('commons.remove')}}</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-collapse-transition>
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.automation.case_ref')" :visible.sync="visible"
|
||||
width="45%" :destroy-on-close="true">
|
||||
<span>{{ $t('api_test.automation.scenario_ref') }}:</span>
|
||||
<div class="refs" v-loading="scenarioLoading">
|
||||
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">{{ item.name }}</div>
|
||||
</div>
|
||||
|
||||
<span>{{ $t('api_test.automation.plan_ref') }}:</span>
|
||||
<div class="refs">
|
||||
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">{{ item.name }}</div>
|
||||
</div>
|
||||
|
||||
<template v-slot:footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="visible = false" @keydown.enter.native.prevent>
|
||||
{{ $t('commons.confirm') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "MsReferenceView",
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
scenarioLoading: false,
|
||||
scenarioRefs: [],
|
||||
planRefs: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getReferenceData(row) {
|
||||
this.scenarioLoading = true;
|
||||
this.scenarioRefs = [];
|
||||
this.$post("/api/automation/getReference/", row, response => {
|
||||
this.scenarioRefs = response.data;
|
||||
this.scenarioLoading = false;
|
||||
})
|
||||
},
|
||||
open(row) {
|
||||
this.getReferenceData(row);
|
||||
this.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.refs {
|
||||
min-height: 50px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
font-size: 12px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<el-dropdown @command="handleCommand" class="scenario-ext-btn">
|
||||
<el-link type="primary" :underline="false">
|
||||
<el-icon class="el-icon-more"></el-icon>
|
||||
</el-link>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
<ms-reference-view ref="viewRef"/>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsReferenceView from "@/business/components/api/automation/scenario/ReferenceView";
|
||||
|
||||
export default {
|
||||
name: "MsScenarioExtendButtons",
|
||||
components: {MsReferenceView},
|
||||
props: {
|
||||
row: Object
|
||||
},
|
||||
methods: {
|
||||
handleCommand(cmd) {
|
||||
switch (cmd) {
|
||||
case "ref":
|
||||
this.$refs.viewRef.open(this.row);
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scenario-ext-btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,60 @@
|
|||
<template>
|
||||
<div v-if="isShow" style="float: right">
|
||||
<el-dropdown placement="bottom" trigger="click" size="medium">
|
||||
<div @click.stop class="show-more-btn">
|
||||
<i class="el-icon-more ms-icon-more"/>
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown" class="dropdown-menu-class">
|
||||
<el-dropdown-item v-for="(btn,index) in buttons" :key="index" @click.native.stop="click(btn)">
|
||||
{{btn.name}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ShowMoreBtn",
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
buttons: Array,
|
||||
row: Object,
|
||||
size: Number
|
||||
},
|
||||
methods: {
|
||||
click(btn) {
|
||||
if (btn.handleClick instanceof Function) {
|
||||
btn.handleClick(this.row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ms-icon-more {
|
||||
margin-top: 15px;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.show-more-btn {
|
||||
width: 20px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.show-more-btn-title {
|
||||
color: #696969;
|
||||
background-color: #e2e2e2;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.dropdown-menu-class {
|
||||
padding: 1px 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
|
@ -193,7 +193,7 @@
|
|||
},
|
||||
editApi(row) {
|
||||
this.currentApi = row;
|
||||
this.handleTabsEdit(row.name, "add");
|
||||
this.handleTabsEdit(this.$t('api_test.definition.request.edit_api') + "-" + row.name, "add");
|
||||
},
|
||||
handleCase(testCase) {
|
||||
this.currentApi = testCase;
|
||||
|
@ -219,7 +219,7 @@
|
|||
for (let index in this.apiTabs) {
|
||||
let tab = this.apiTabs[index];
|
||||
if (tab.name === this.apiDefaultTab) {
|
||||
tab.title = data.name;
|
||||
tab.title = this.$t('api_test.definition.request.edit_api') + "-" + data.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
@ -400,6 +402,9 @@
|
|||
test.request = JSON.parse(test.request);
|
||||
}
|
||||
this.apiCaseList = response.data;
|
||||
if (this.apiCaseList.length == 0) {
|
||||
this.addCase();
|
||||
}
|
||||
});
|
||||
},
|
||||
validate(row) {
|
||||
|
|
|
@ -73,9 +73,14 @@
|
|||
|
||||
<el-table-column :label="$t('commons.operating')" min-width="130" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<el-button type="text" @click="editApi(scope.row)">编辑</el-button>
|
||||
<el-button type="text" @click="handleTestCase(scope.row)">用例</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">删除</el-button>
|
||||
<div v-if="currentRow!=undefined && currentRow.referenced">
|
||||
<el-button type="text" @click="handleTestCase(scope.row)">用例</el-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-button type="text" @click="editApi(scope.row)">编辑</el-button>
|
||||
<el-button type="text" @click="handleTestCase(scope.row)">用例</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
<div :style="customizeStyle" v-loading="loading">
|
||||
<el-card>
|
||||
<div>
|
||||
<div class="el-step__icon is-text" style="color: #A30014;background-color: #F7E6E9;margin-right: 10px" v-if="assertions.index">
|
||||
<div class="el-step__icon-inner">{{assertions.index}}</div>
|
||||
</div>
|
||||
<el-button class="ms-left-buttion" size="small" style="color: #A30014;background-color: #F7E6E9">{{$t('api_test.definition.request.assertions_rule')}}</el-button>
|
||||
<el-button size="small" style="float: right;margin-top: 0px" @click="remove">移除</el-button>
|
||||
<el-button size="small" style="float: right;margin-top: 0px" @click="remove">{{$t('commons.remove')}}</el-button>
|
||||
</div>
|
||||
<div class="assertion-add">
|
||||
<el-row :gutter="10">
|
||||
|
@ -11,9 +14,6 @@
|
|||
<el-select :disabled="isReadOnly" class="assertion-item" v-model="type"
|
||||
:placeholder="$t('api_test.request.assertions.select_type')"
|
||||
size="small">
|
||||
<!--
|
||||
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
|
||||
-->
|
||||
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
|
||||
<el-option :label="'JSONPath'" :value="options.JSON_PATH"/>
|
||||
<el-option :label="'XPath'" :value="options.XPATH2"/>
|
||||
|
@ -22,10 +22,6 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<!--
|
||||
<ms-api-assertion-text :is-read-only="isReadOnly" :list="assertions.regex" v-if="type === options.TEXT"
|
||||
:callback="after"/>
|
||||
-->
|
||||
<ms-api-assertion-regex :is-read-only="isReadOnly" :list="assertions.regex" v-if="type === options.REGEX"
|
||||
:callback="after"/>
|
||||
<ms-api-assertion-json-path :is-read-only="isReadOnly" :list="assertions.jsonPath"
|
||||
|
@ -41,24 +37,8 @@
|
|||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<!--<div v-if="!scenario">-->
|
||||
<!--<el-row :gutter="10" class="json-path-suggest-button">-->
|
||||
<!--<el-link size="small" type="primary" @click="suggestJsonOpen" style="margin-right: 20px">-->
|
||||
<!--{{ $t('api_test.request.assertions.json_path_suggest') }}-->
|
||||
<!--</el-link>-->
|
||||
<!--<el-link size="small" type="danger" @click="clearJson">-->
|
||||
<!--{{ $t('api_test.request.assertions.json_path_clear') }}-->
|
||||
<!--</el-link>-->
|
||||
<!--</el-row>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
|
||||
|
||||
<!--<ms-api-jsonpath-suggest-list @addJsonpathSuggest="addJsonpathSuggest" :request="request"-->
|
||||
<!--ref="jsonpathSuggestList"/>-->
|
||||
|
||||
<ms-api-assertions-edit :is-read-only="isReadOnly" :assertions="assertions" :reloadData="reloadData" style="margin-bottom: 20px"/>
|
||||
</el-card>
|
||||
</div>
|
||||
|
|
|
@ -102,5 +102,7 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
/deep/ .el-tabs__nav-wrap::after {
|
||||
height: 0px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -50,8 +50,7 @@
|
|||
import {getUUID, getCurrentUser} from "@/common/js/utils";
|
||||
import MsResponseText from "../response/ResponseText";
|
||||
import MsRun from "../Run";
|
||||
import {createComponent, Request} from "../jmeter/components";
|
||||
import HeaderManager from "../jmeter/components/configurations/header-manager";
|
||||
import {createComponent} from "../jmeter/components";
|
||||
import {REQ_METHOD} from "../../model/JsonData";
|
||||
import MsRequestResultTail from "../response/RequestResultTail";
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div :style="customizeStyle">
|
||||
<el-card>
|
||||
<div class="el-step__icon is-text" style="color: #015478;background-color: #E6EEF2;margin-right: 10px" v-if="extract.index">
|
||||
<div class="el-step__icon-inner">{{extract.index}}</div>
|
||||
</div>
|
||||
<el-button class="ms-left-buttion" size="small" style="color: #015478;background-color: #E6EEF2">{{$t('api_test.definition.request.extract_param')}}</el-button>
|
||||
<el-button size="small" style="float: right;margin-top: 0px" @click="remove">移除</el-button>
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ export default class HTTPSamplerProxy extends Sampler {
|
|||
this.rest = [];
|
||||
this.files = [];
|
||||
this.headers = [];
|
||||
this.hashTree = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -226,5 +226,4 @@
|
|||
height: 18px;
|
||||
border-radius: 42%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,34 +1,18 @@
|
|||
<template>
|
||||
<div class="metric-container">
|
||||
<el-row type="flex">
|
||||
<div class="metric">
|
||||
<div class="value">{{response.responseResult.responseTime}} ms</div>
|
||||
<div class="name">{{$t('api_report.response_time')}}</div>
|
||||
<br>
|
||||
<div class="value">{{response.responseResult.latency}} ms</div>
|
||||
<div class="name">{{$t('api_report.latency')}}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="value">{{response.requestSize}} bytes</div>
|
||||
<div class="name">{{$t('api_report.request_size')}}</div>
|
||||
<br>
|
||||
<div class="value">{{response.responseResult.responseSize}} bytes</div>
|
||||
<div class="name">{{$t('api_report.response_size')}}</div>
|
||||
</div>
|
||||
|
||||
<div class="metric horizontal">
|
||||
<el-row type="flex">
|
||||
<div class="code">
|
||||
<div class="value" :class="{'error': error}">{{response.responseResult.responseCode}}</div>
|
||||
<div class="name">{{$t('api_report.response_code')}}</div>
|
||||
</div>
|
||||
<div class="split"></div>
|
||||
<div class="message">
|
||||
<div class="value">{{response.responseResult.responseMessage}}</div>
|
||||
<div class="name">{{$t('api_report.response_message')}}</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_code')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{response.responseResult.responseCode ? response.responseResult.responseCode :'0'}}</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_time')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{response.responseResult.responseTime?response.responseResult.responseTime:0}} ms</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_size')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550; margin-top:2px;margin-left:10px;float: left">{{response.responseResult.responseSize?response.responseResult.responseSize:0}} bytes</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -51,56 +35,6 @@
|
|||
|
||||
<style scoped>
|
||||
.metric-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
padding: 10px;
|
||||
border: 1px solid #EBEEF5;
|
||||
min-width: 120px;
|
||||
height: 114px;
|
||||
}
|
||||
|
||||
.metric + .metric {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.metric .value {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.metric .name {
|
||||
color: #404040;
|
||||
opacity: 0.5;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.metric.horizontal {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.metric .code {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.metric .code .value {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.metric .code .value.error {
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.metric .split {
|
||||
height: 114px;
|
||||
border-left: 1px solid #EBEEF5;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.metric .message {
|
||||
max-height: 114px;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
},
|
||||
computed: {
|
||||
isSqlType() {
|
||||
return (this.currentProtocol === "SQL" && this.response.responseResult.responseCode === '200' && this.mode ==='table');
|
||||
return (this.currentProtocol === "SQL" && this.response.responseResult.responseCode === '200' && this.mode === 'table');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +120,10 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
/deep/ .el-tabs__nav-wrap::after {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<el-divider class="menu-divider"/>
|
||||
<el-menu-item :index="'/performance/project/create'">
|
||||
<el-menu-item :index="'/setting/project/create'">
|
||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/api/home'">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<common-monitor-chart>
|
||||
<template>
|
||||
<div id="response-time-chart" :style="{ width:'100%',height:'100%' }">
|
||||
<chart :options="getOptions()" :style="{ width:'100%' }"></chart>
|
||||
<chart :options="getOptions()" :style="{ width:'100%' }" v-on:click="click"></chart>
|
||||
</div>
|
||||
</template>
|
||||
</common-monitor-chart>
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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'),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -213,10 +213,4 @@ export default {
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/deep/ .el-select__tags {
|
||||
flex-wrap: unset;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/performance/project/create'">
|
||||
<el-menu-item :index="'/setting/project/create'">
|
||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/performance/home'">
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</el-menu-item>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item v-for="menu in project" :key="menu.index" :index="menu.index" class="setting-item"
|
||||
<el-menu-item v-for="menu in project" :key="menu.index" :index="'/setting/project/all'" class="setting-item"
|
||||
v-permission="menu.roles">
|
||||
<template v-slot:title>
|
||||
<font-awesome-icon class="icon" :icon="['fa', 'bars']" size="lg"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass"
|
||||
>
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||
prop="event" :disabled="!scope.row.isSet">
|
||||
|
@ -64,8 +64,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
||||
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||
<template v-slot:default="scope">
|
||||
<el-button
|
||||
type="success"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
v-xpack
|
||||
@click="handleTemplate(scope.$index,scope.row)"
|
||||
>{{ $t('organization.message.template') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -98,14 +106,22 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
const TASK_TYPE = 'DEFECT_TASK';
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "DefectTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
defectReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -211,6 +227,11 @@ export default {
|
|||
},
|
||||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,22 +11,22 @@
|
|||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-table
|
||||
:data="jenkinsTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
:data="jenkinsTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event"
|
||||
:placeholder="$t('organization.message.select_events')"
|
||||
size="mini"
|
||||
prop="events" :disabled="!scope.row.isSet">
|
||||
<el-option
|
||||
v-for="item in jenkinsEventOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
v-for="item in jenkinsEventOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -36,10 +36,10 @@
|
|||
<el-select v-model="row.userIds" filterable multiple size="mini"
|
||||
:placeholder="$t('commons.please_select')" style="width: 100%;" :disabled="!row.isSet">
|
||||
<el-option
|
||||
v-for="item in jenkinsReceiverOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
v-for="item in jenkinsReceiverOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -51,10 +51,10 @@
|
|||
:disabled="!scope.row.isSet" @change="handleEdit(scope.$index, scope.row)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in receiveTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
v-for="item in receiveTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -66,48 +66,65 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
||||
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||
<template v-slot:default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-show="scope.row.isSet"
|
||||
@click="handleAddTask(scope.$index,scope.row)"
|
||||
type="success"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
v-xpack
|
||||
@click="handleTemplate(scope.$index,scope.row)"
|
||||
>{{ $t('organization.message.template') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
@click="handleAddTask(scope.$index,scope.row)"
|
||||
>{{ $t('commons.add') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
v-show="scope.row.isSet"
|
||||
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
@click.native.prevent="removeRowTask(scope.$index,jenkinsTask)"
|
||||
>{{ $t('commons.cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click="handleEditTask(scope.$index,scope.row)"
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="!scope.row.isSet"
|
||||
@click="handleEditTask(scope.$index,scope.row)"
|
||||
>{{ $t('commons.edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click.native.prevent="deleteRowTask(scope.$index,scope.row)"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
v-show="!scope.row.isSet"
|
||||
@click.native.prevent="deleteRowTask(scope.$index,scope.row)"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
const TASK_TYPE = 'JENKINS_TASK';
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "JenkinsNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
jenkinsReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -187,7 +204,6 @@ export default {
|
|||
} else {
|
||||
data.isReadOnly = true;
|
||||
}
|
||||
|
||||
},
|
||||
addTask(data) {
|
||||
this.result = this.$post("/notice/save/message/task", data, () => {
|
||||
|
@ -215,6 +231,11 @@ export default {
|
|||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
:data="scheduleTask"
|
||||
class="tb-edit"
|
||||
border
|
||||
size="mini"
|
||||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
<el-table-column :label="$t('schedule.event')" prop="events" min-width="15%">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event"
|
||||
<el-select v-model="scope.row.event" size="mini"
|
||||
:placeholder="$t('organization.message.select_events')"
|
||||
prop="events" :disabled="!scope.row.isSet">
|
||||
<el-option
|
||||
|
@ -33,7 +32,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column :label="$t('schedule.receiver')" prop="userIds" min-width="20%">
|
||||
<template v-slot:default="{row}">
|
||||
<el-select v-model="row.userIds" filterable multiple
|
||||
<el-select v-model="row.userIds" filterable multiple size="mini"
|
||||
:placeholder="$t('commons.please_select')" style="width: 100%;" :disabled="!row.isSet">
|
||||
<el-option
|
||||
v-for="item in scheduleReceiverOptions"
|
||||
|
@ -44,9 +43,10 @@
|
|||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('schedule.receiving_mode')" min-width="20%" prop="type">
|
||||
<el-table-column :label="$t('schedule.receiving_mode')" prop="type" min-width="15%">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.type" :placeholder="$t('organization.message.select_receiving_method')"
|
||||
size="mini"
|
||||
:disabled="!scope.row.isSet" @change="handleEdit(scope.$index, scope.row)"
|
||||
>
|
||||
<el-option
|
||||
|
@ -60,12 +60,20 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="webhook" min-width="20%" prop="webhook">
|
||||
<template v-slot:default="scope">
|
||||
<el-input v-model="scope.row.webhook" placeholder="webhook地址"
|
||||
<el-input v-model="scope.row.webhook" placeholder="webhook地址" size="mini"
|
||||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
||||
<el-table-column :label="$t('commons.operating')" prop="result" min-width="20%">
|
||||
<template v-slot:default="scope">
|
||||
<el-button
|
||||
type="success"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
v-xpack
|
||||
@click="handleTemplate(scope.$index,scope.row)"
|
||||
>{{ $t('organization.message.template') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -102,13 +110,21 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "ScheduleTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
testId: String,
|
||||
scheduleReceiverOptions: Array,
|
||||
|
@ -226,6 +242,11 @@ export default {
|
|||
headClass() {
|
||||
return "text-align:center;background:'#ededed'"
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass"
|
||||
>
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')"
|
||||
@change="handleTestPlanReceivers(scope.row)" size="mini"
|
||||
|
@ -64,8 +64,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
||||
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||
<template v-slot:default="scope">
|
||||
<el-button
|
||||
type="success"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
v-xpack
|
||||
@click="handleTemplate(scope.$index,scope.row)"
|
||||
>{{ $t('organization.message.template') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -98,15 +106,23 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
const TASK_TYPE = 'TEST_PLAN_TASK';
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "TestPlanTaskNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
testPlanReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -231,6 +247,11 @@ export default {
|
|||
}
|
||||
row.testPlanReceiverOptions = testPlanReceivers;
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
testPlanReceiverOptions(value) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:cell-style="rowClass"
|
||||
:header-cell-style="headClass"
|
||||
>
|
||||
<el-table-column :label="$t('schedule.event')" min-width="20%" prop="events">
|
||||
<el-table-column :label="$t('schedule.event')" min-width="15%" prop="events">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.event" :placeholder="$t('organization.message.select_events')" size="mini"
|
||||
@change="handleReviewReceivers(scope.row)"
|
||||
|
@ -65,8 +65,16 @@
|
|||
:disabled="!scope.row.isSet||!scope.row.isReadOnly"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')" min-width="20%" prop="result">
|
||||
<el-table-column :label="$t('commons.operating')" min-width="25%" prop="result">
|
||||
<template v-slot:default="scope">
|
||||
<el-button
|
||||
type="success"
|
||||
size="mini"
|
||||
v-if="scope.row.isSet"
|
||||
v-xpack
|
||||
@click="handleTemplate(scope.$index,scope.row)"
|
||||
>{{ $t('organization.message.template') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
@ -99,14 +107,22 @@
|
|||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<notice-template v-xpack ref="noticeTemplate"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {hasLicense} from "@/common/js/utils";
|
||||
|
||||
const TASK_TYPE = 'REVIEW_TASK';
|
||||
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
|
||||
const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./notice/NoticeTemplate.vue") : {};
|
||||
|
||||
export default {
|
||||
name: "TestReviewNotification",
|
||||
components: {
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
props: {
|
||||
reviewReceiverOptions: {
|
||||
type: Array
|
||||
|
@ -236,6 +252,11 @@ export default {
|
|||
break;
|
||||
}
|
||||
row.reviewReceiverOptions = reviewReceiverOptions;
|
||||
},
|
||||
handleTemplate(index, row) {
|
||||
if (hasLicense()) {
|
||||
this.$refs.noticeTemplate.open(row);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -1,53 +1,51 @@
|
|||
<template>
|
||||
<ms-container>
|
||||
<ms-main-container>
|
||||
<el-card class="table-card" v-loading="result.loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||
:create-tip="btnTips" title=""/>
|
||||
</template>
|
||||
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
||||
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
||||
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<pre>{{ scope.row.description }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
||||
@deleteClick="handleDelete(scope.row)">
|
||||
<template v-slot:behind>
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||
</template>
|
||||
</ms-table-operator>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</el-card>
|
||||
</ms-main-container>
|
||||
<div v-loading="result.loading">
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||
:create-tip="btnTips" :title="$t('commons.project')"/>
|
||||
</template>
|
||||
<el-table border class="adjust-table" @row-click="link" :data="items" style="width: 100%" @sort-change="sort">
|
||||
<el-table-column prop="name" :label="$t('commons.name')" width="250" show-overflow-tooltip/>
|
||||
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<pre>{{ scope.row.description }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator :is-tester-permission="true" @editClick="edit(scope.row)"
|
||||
@deleteClick="handleDelete(scope.row)">
|
||||
<template v-slot:behind>
|
||||
<ms-table-operator-button :is-tester-permission="true" :tip="$t('api_test.environment.environment_config')" icon="el-icon-setting"
|
||||
type="info" @exec="openEnvironmentConfig(scope.row)"/>
|
||||
</template>
|
||||
</ms-table-operator>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ms-table-pagination :change="list" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||
:total="total"/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog :close-on-click-modal="false" :title="title" :visible.sync="createVisible" destroy-on-close @close="handleClose">
|
||||
<el-form :model="form" :rules="rules" ref="form" label-position="right" label-width="100px" size="small">
|
||||
|
@ -80,23 +78,23 @@
|
|||
|
||||
<api-environment-config ref="environmentConfig"/>
|
||||
|
||||
</ms-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsCreateBox from "../settings/CreateBox";
|
||||
import MsCreateBox from "../CreateBox";
|
||||
import {Message} from "element-ui";
|
||||
import MsTablePagination from "../common/pagination/TablePagination";
|
||||
import MsTableHeader from "../common/components/MsTableHeader";
|
||||
import MsTableOperator from "../common/components/MsTableOperator";
|
||||
import MsDialogFooter from "../common/components/MsDialogFooter";
|
||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||
import MsDialogFooter from "../../common/components/MsDialogFooter";
|
||||
import {_sort, getCurrentUser, listenGoBack, removeGoBackListener} from "@/common/js/utils";
|
||||
import MsContainer from "../common/components/MsContainer";
|
||||
import MsMainContainer from "../common/components/MsMainContainer";
|
||||
import MsDeleteConfirm from "../common/components/MsDeleteConfirm";
|
||||
import MsTableOperatorButton from "../common/components/MsTableOperatorButton";
|
||||
import ApiEnvironmentConfig from "../api/test/components/ApiEnvironmentConfig";
|
||||
import TemplateComponent from "../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsDeleteConfirm from "../../common/components/MsDeleteConfirm";
|
||||
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
|
||||
import ApiEnvironmentConfig from "../../api/test/components/ApiEnvironmentConfig";
|
||||
import TemplateComponent from "../../track/plan/view/comonents/report/TemplateComponent/TemplateComponent";
|
||||
import {ApiEvent, LIST_CHANGE, PerformanceEvent, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||
|
||||
export default {
|
||||
|
@ -144,25 +142,13 @@ export default {
|
|||
if (this.$route.path.split('/')[2] === 'project' &&
|
||||
this.$route.path.split('/')[3] === 'create') {
|
||||
this.create();
|
||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
||||
this.$router.replace('/setting/project/all');
|
||||
}
|
||||
this.list();
|
||||
},
|
||||
activated() {
|
||||
this.list();
|
||||
},
|
||||
watch: {
|
||||
'$route'(to) {
|
||||
if (this.$route.path.split('/')[2] === 'project' &&
|
||||
to.path.split('/')[3] === 'create') {
|
||||
this.create();
|
||||
this.$router.push('/' + this.baseUrl + '/project/all');
|
||||
} else if (this.$route.path.split('/')[2] === 'project' &&
|
||||
to.path.split('/')[3] === 'all') {
|
||||
this.list();
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentUser: () => {
|
||||
return getCurrentUser();
|
||||
|
@ -179,7 +165,7 @@ export default {
|
|||
return false;
|
||||
}
|
||||
this.title = this.$t('project.create');
|
||||
listenGoBack(this.handleClose);
|
||||
// listenGoBack(this.handleClose);
|
||||
this.createVisible = true;
|
||||
this.form = {};
|
||||
},
|
||||
|
@ -247,6 +233,9 @@ export default {
|
|||
handleClose() {
|
||||
removeGoBackListener(this.handleClose);
|
||||
this.createVisible = false;
|
||||
this.tapd = false;
|
||||
this.jira = false;
|
||||
this.zentao = false;
|
||||
},
|
||||
search() {
|
||||
this.list();
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsProject from "@/business/components/project/MsProject";
|
||||
import MsProject from "@/business/components/settings/project/MsProject";
|
||||
export default {
|
||||
name: "Project",
|
||||
components: {MsProject},
|
||||
|
|
|
@ -80,9 +80,9 @@ export default {
|
|||
}
|
||||
},
|
||||
{
|
||||
path: 'project',
|
||||
component: () => import('@/business/components/settings/project/Project'),
|
||||
meta: {project: true, title: '项目管理'}
|
||||
path: 'project/:type',
|
||||
component: () => import('@/business/components/settings/project/MsProject'),
|
||||
meta: {project: true, title: 'project.manager'}
|
||||
},
|
||||
|
||||
]
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
|
||||
<script>
|
||||
import NodeEdit from "./NodeEdit";
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER} from "../../../../common/js/constants";
|
||||
import {checkoutTestManagerOrTestUser, hasRoles} from "../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<span class="menu-title">{{'[' + title + ']'}}</span>
|
||||
<el-select filterable slot="prepend" v-model="value" @change="changeData" class="project_menu"
|
||||
<el-select filterable slot="prepend" v-model="value" @change="changeData" :style="{width: width}"
|
||||
size="small">
|
||||
<el-option v-for="(item,index) in data" :key="index" :label="item.name" :value="index"/>
|
||||
</el-select>
|
||||
|
@ -20,6 +20,12 @@
|
|||
},
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default() {
|
||||
return "214px";
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -43,9 +49,6 @@
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.project_menu {
|
||||
width: 214px;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
color: darkgrey;
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
<template v-slot:title>{{ $t('commons.project') }}</template>
|
||||
<search-list ref="projectRecent" :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<el-menu-item :index="'/performance/project/create'">
|
||||
<el-menu-item :index="'/setting/project/create'">
|
||||
<font-awesome-icon :icon="['fa', 'plus']"/>
|
||||
<span style="padding-left: 7px;">创建项目</span>
|
||||
<span style="padding-left: 7px;">{{ $t("project.create") }}</span>
|
||||
</el-menu-item>
|
||||
<ms-show-all :index="'/setting/project'"/>
|
||||
<ms-show-all :index="'/setting/project/all'"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-menu-item :index="'/track/home'">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<related-test-plan-list ref="relatedTestPlanList"/>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<review-list :title="$t('review.my_review')" ref="caseReviewList"/>
|
||||
<review-list :title="$t('test_track.review.my_review')" ref="caseReviewList"/>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="9">
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
<script>
|
||||
|
||||
import NodeTree from "../../common/NodeTree";
|
||||
import TestPlanTestCaseList from "./comonents/TestPlanTestCaseList";
|
||||
import TestCaseRelevance from "./comonents/TestCaseRelevance";
|
||||
import TestPlanTestCaseList from "./comonents/functional/FunctionalTestCaseList";
|
||||
import TestCaseRelevance from "./comonents/functional/TestCaseFunctionalRelevance";
|
||||
import SelectMenu from "../../common/SelectMenu";
|
||||
import MsContainer from "../../../common/components/MsContainer";
|
||||
import MsAsideContainer from "../../../common/components/MsAsideContainer";
|
||||
|
|
|
@ -1,105 +1,169 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"
|
||||
:visible.sync="dialogFormVisible"
|
||||
@close="close"
|
||||
width="60%" v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
top="50px">
|
||||
|
||||
<el-container class="main-content">
|
||||
<el-aside class="tree-aside" width="250px">
|
||||
<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName :
|
||||
$t('test_track.switch_project') }}
|
||||
</el-link>
|
||||
<node-tree class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refresh="refresh"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</el-aside>
|
||||
<test-case-relevance-base ref="baseRelevance">
|
||||
|
||||
<el-container>
|
||||
<el-main class="case-content">
|
||||
<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>
|
||||
<el-table
|
||||
:data="testCases"
|
||||
@filter-change="filter"
|
||||
row-key="id"
|
||||
@mouseleave.passive="leave"
|
||||
v-el-table-infinite-scroll="scrollLoading"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
<template v-slot:aside>
|
||||
<node-tree class="node-tree"
|
||||
@nodeSelectEvent="nodeChange"
|
||||
@refresh="refresh"
|
||||
:tree-nodes="treeNodes"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<el-table-column
|
||||
type="selection"></el-table-column>
|
||||
<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>
|
||||
<el-table
|
||||
:data="testCases"
|
||||
@filter-change="filter"
|
||||
row-key="id"
|
||||
@mouseleave.passive="leave"
|
||||
v-el-table-infinite-scroll="scrollLoading"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelectionChange"
|
||||
height="50vh"
|
||||
ref="table">
|
||||
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('test_track.case.name')"
|
||||
style="width: 100%">
|
||||
<template v-slot:default="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table-column
|
||||
type="selection"></el-table-column>
|
||||
|
||||
<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>
|
||||
<div style="text-align: center">共 {{total}} 条</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('test_track.case.name')"
|
||||
style="width: 100%">
|
||||
<template v-slot:default="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
:filters="priorityFilters"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:filters="typeFilters"
|
||||
column-key="type"
|
||||
:label="$t('test_track.case.type')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<type-table-item :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="dialogFormVisible = false" @confirm="saveCaseRelevance"/>
|
||||
</template>
|
||||
<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>
|
||||
<div style="text-align: center">共 {{total}} 条</div>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>
|
||||
</div>
|
||||
</test-case-relevance-base>
|
||||
|
||||
<!--<div>-->
|
||||
<!--<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"-->
|
||||
<!--:visible.sync="dialogFormVisible"-->
|
||||
<!--@close="close"-->
|
||||
<!--width="60%" v-loading="result.loading"-->
|
||||
<!--:close-on-click-modal="false"-->
|
||||
<!--top="50px">-->
|
||||
|
||||
<!--<el-container class="main-content">-->
|
||||
<!--<el-aside class="tree-aside" width="250px">-->
|
||||
<!--<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName :-->
|
||||
<!--$t('test_track.switch_project') }}-->
|
||||
<!--</el-link>-->
|
||||
<!--<node-tree class="node-tree"-->
|
||||
<!--@nodeSelectEvent="nodeChange"-->
|
||||
<!--@refresh="refresh"-->
|
||||
<!--:tree-nodes="treeNodes"-->
|
||||
<!--ref="nodeTree"/>-->
|
||||
<!--</el-aside>-->
|
||||
|
||||
<!--<el-container>-->
|
||||
<!--<el-main class="case-content">-->
|
||||
<!--<ms-table-header :condition.sync="condition" @search="search" title="" :show-create="false"/>-->
|
||||
<!--<el-table-->
|
||||
<!--:data="testCases"-->
|
||||
<!--@filter-change="filter"-->
|
||||
<!--row-key="id"-->
|
||||
<!--@mouseleave.passive="leave"-->
|
||||
<!--v-el-table-infinite-scroll="scrollLoading"-->
|
||||
<!--@select-all="handleSelectAll"-->
|
||||
<!--@select="handleSelectionChange"-->
|
||||
<!--height="50vh"-->
|
||||
<!--ref="table">-->
|
||||
|
||||
<!--<el-table-column-->
|
||||
<!--type="selection"></el-table-column>-->
|
||||
|
||||
<!--<el-table-column-->
|
||||
<!--prop="name"-->
|
||||
<!--:label="$t('test_track.case.name')"-->
|
||||
<!--style="width: 100%">-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--{{scope.row.name}}-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--<el-table-column-->
|
||||
<!--prop="priority"-->
|
||||
<!--:filters="priorityFilters"-->
|
||||
<!--column-key="priority"-->
|
||||
<!--:label="$t('test_track.case.priority')"-->
|
||||
<!--show-overflow-tooltip>-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--<priority-table-item :value="scope.row.priority"/>-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--<el-table-column-->
|
||||
<!--prop="type"-->
|
||||
<!--:filters="typeFilters"-->
|
||||
<!--column-key="type"-->
|
||||
<!--:label="$t('test_track.case.type')"-->
|
||||
<!--show-overflow-tooltip>-->
|
||||
<!--<template v-slot:default="scope">-->
|
||||
<!--<type-table-item :value="scope.row.type"/>-->
|
||||
<!--</template>-->
|
||||
<!--</el-table-column>-->
|
||||
<!--</el-table>-->
|
||||
|
||||
<!--<div v-if="!lineStatus" style="text-align: center">{{$t('test_track.review_view.last_page')}}</div>-->
|
||||
<!--<div style="text-align: center">共 {{total}} 条</div>-->
|
||||
<!--</el-main>-->
|
||||
<!--</el-container>-->
|
||||
<!--</el-container>-->
|
||||
|
||||
<!--<template v-slot:footer>-->
|
||||
<!--<ms-dialog-footer @cancel="dialogFormVisible = false" @confirm="saveCaseRelevance"/>-->
|
||||
<!--</template>-->
|
||||
|
||||
<!--</el-dialog>-->
|
||||
|
||||
<!--<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>-->
|
||||
<!--</div>-->
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import NodeTree from '../../../common/NodeTree';
|
||||
import MsDialogFooter from '../../../../common/components/MsDialogFooter'
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import {_filter} from "../../../../../../common/js/utils";
|
||||
import MsTableSearchBar from "../../../../common/components/MsTableSearchBar";
|
||||
import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar";
|
||||
import MsTableHeader from "../../../../common/components/MsTableHeader";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import SwitchProject from "../../../case/components/SwitchProject";
|
||||
import NodeTree from '../../../../common/NodeTree';
|
||||
import MsDialogFooter from '../../../../../common/components/MsDialogFooter'
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MsTableSearchBar from "../../../../../common/components/MsTableSearchBar";
|
||||
import MsTableAdvSearchBar from "../../../../../common/components/search/MsTableAdvSearchBar";
|
||||
import MsTableHeader from "../../../../../common/components/MsTableHeader";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import SwitchProject from "../../../../case/components/SwitchProject";
|
||||
import elTableInfiniteScroll from 'el-table-infinite-scroll';
|
||||
import TestCaseRelevanceBase from "../base/TestCaseRelevanceBase";
|
||||
import {_filter} from "../../../../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "TestCaseRelevance",
|
||||
name: "TestCaseApiRelevance",
|
||||
components: {
|
||||
TestCaseRelevanceBase,
|
||||
NodeTree,
|
||||
MsDialogFooter,
|
||||
PriorityTableItem,
|
||||
|
@ -168,10 +232,13 @@
|
|||
this.toggleSelection(this.testCases);
|
||||
},
|
||||
methods: {
|
||||
openTestCaseRelevanceDialog() {
|
||||
this.getProject();
|
||||
this.dialogFormVisible = true;
|
||||
|
||||
open() {
|
||||
this.$refs.baseRelevance.open();
|
||||
|
||||
//
|
||||
},
|
||||
|
||||
saveCaseRelevance() {
|
||||
let param = {};
|
||||
param.planId = this.planId;
|
|
@ -10,8 +10,9 @@
|
|||
:draggable="false"
|
||||
ref="nodeTree"/>
|
||||
</template>
|
||||
|
||||
<template v-slot:main>
|
||||
<test-plan-test-case-list
|
||||
<test-plan-api-case-list
|
||||
class="table-list"
|
||||
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
|
||||
@refresh="refresh"
|
||||
|
@ -21,23 +22,28 @@
|
|||
ref="testPlanTestCaseList"/>
|
||||
</template>
|
||||
|
||||
<test-case-relevance
|
||||
<test-case-api-relevance
|
||||
@refresh="refresh"
|
||||
:plan-id="planId"
|
||||
ref="testCaseRelevance"/>
|
||||
|
||||
</ms-test-plan-common-component>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeTree from "../../../../common/NodeTree";
|
||||
import TestPlanTestCaseList from "../TestPlanTestCaseList";
|
||||
import TestCaseRelevance from "../TestCaseRelevance";
|
||||
import MsTestPlanCommonComponent from "../TestPlanCommonComponent";
|
||||
import TestPlanTestCaseList from "../functional/FunctionalTestCaseList";
|
||||
import TestCaseRelevance from "../functional/TestCaseFunctionalRelevance";
|
||||
import MsTestPlanCommonComponent from "../base/TestPlanCommonComponent";
|
||||
import TestPlanApiCaseList from "./TestPlanApiCaseList";
|
||||
import TestCaseApiRelevance from "./TestCaseApiRelevance";
|
||||
|
||||
export default {
|
||||
name: "TestPlanApi",
|
||||
components: {
|
||||
TestCaseApiRelevance,
|
||||
TestPlanApiCaseList,
|
||||
MsTestPlanCommonComponent,
|
||||
TestCaseRelevance,
|
||||
TestPlanTestCaseList,
|
||||
|
@ -77,7 +83,7 @@
|
|||
this.getNodeTreeByPlanId();
|
||||
},
|
||||
openTestCaseRelevanceDialog() {
|
||||
this.$refs.testCaseRelevance.openTestCaseRelevanceDialog();
|
||||
this.$refs.testCaseRelevance.open();
|
||||
},
|
||||
nodeChange(nodeIds, pNodes) {
|
||||
this.selectNodeIds = nodeIds;
|
||||
|
|
|
@ -213,33 +213,33 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ExecutorEdit from './ExecutorEdit';
|
||||
import StatusEdit from './StatusEdit';
|
||||
import TestPlanTestCaseEdit from "./TestPlanTestCaseEdit";
|
||||
import MsTipButton from '../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../common/NodeBreadcrumb';
|
||||
import ExecutorEdit from '../ExecutorEdit';
|
||||
import StatusEdit from '../StatusEdit';
|
||||
import TestPlanTestCaseEdit from "../functional/FunctionalTestCaseEdit";
|
||||
import MsTipButton from '../../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../../common/NodeBreadcrumb';
|
||||
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, TokenKey, WORKSPACE_ID} from "@/common/js/constants";
|
||||
import {_filter, _sort, checkoutTestManagerOrTestUser, hasRoles} from "@/common/js/utils";
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "./TestReportTemplateList";
|
||||
import TestCaseReportView from "./report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../case/components/BatchEdit";
|
||||
import PriorityTableItem from "../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "../TestReportTemplateList";
|
||||
import TestCaseReportView from "../report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../../case/components/BatchEdit";
|
||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||
import {hub} from "@/business/components/track/plan/event-bus";
|
||||
|
||||
export default {
|
||||
name: "TestPlanTestCaseList",
|
||||
name: "TestPlanApiCaseList",
|
||||
components: {
|
||||
TestCaseReportView,
|
||||
TestReportTemplateList,
|
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog :title="$t('test_track.plan_view.relevance_test_case')"
|
||||
:visible.sync="dialogVisible"
|
||||
@close="close"
|
||||
width="60%" v-loading="result.loading"
|
||||
:close-on-click-modal="false"
|
||||
top="50px">
|
||||
|
||||
<el-container class="main-content">
|
||||
<el-aside class="tree-aside" width="250px">
|
||||
<select-menu
|
||||
:data="projects"
|
||||
width="185px"
|
||||
:current-data="currentProject"
|
||||
:title="$t('test_track.plan_view.plan')"
|
||||
@dataChange="changeProject"/>
|
||||
<slot name="aside"></slot>
|
||||
</el-aside>
|
||||
|
||||
<el-container>
|
||||
<el-main class="case-content">
|
||||
<slot></slot>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ms-dialog-footer @cancel="dialogVisible = false" @confirm="save"/>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsDialogFooter from '../../../../../common/components/MsDialogFooter'
|
||||
import SelectMenu from "../../../../common/SelectMenu";
|
||||
|
||||
export default {
|
||||
name: "TestCaseRelevanceBase",
|
||||
components: {
|
||||
SelectMenu,
|
||||
MsDialogFooter,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
dialogVisible: false,
|
||||
currentProject: {},
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
projects: [],
|
||||
|
||||
};
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.getProject();
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
|
||||
refreshNode() {
|
||||
this.$emit('refresh');
|
||||
},
|
||||
|
||||
save() {
|
||||
this.$emit('save');
|
||||
},
|
||||
|
||||
refresh() {
|
||||
// this.close();
|
||||
|
||||
},
|
||||
|
||||
close() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
|
||||
getProject() {
|
||||
if (this.planId) {
|
||||
this.result = this.$post("/test/plan/project/", {planId: this.planId}, res => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.projects = data;
|
||||
this.projectId = data[0].id;
|
||||
this.projectName = data[0].name;
|
||||
this.changeProject(data[0]);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
changeProject(project) {
|
||||
this.currentProject = project;
|
||||
this.$emit('setProject', project.id);
|
||||
// 获取项目时刷新该项目模块
|
||||
this.$emit('refreshNode');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.tb-edit .el-input {
|
||||
display: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tb-edit .current-row .el-input {
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.tb-edit .current-row .el-input + span {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
.node-tree {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.el-header {
|
||||
background-color: darkgrey;
|
||||
color: #333;
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
.case-content {
|
||||
padding: 0px 20px;
|
||||
height: 100%;
|
||||
/*border: 1px solid #EBEEF5;*/
|
||||
}
|
||||
|
||||
.tree-aside {
|
||||
min-height: 300px;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
min-height: 300px;
|
||||
height: 100%;
|
||||
/*border: 1px solid #EBEEF5;*/
|
||||
}
|
||||
|
||||
.project-link {
|
||||
float: right;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue