Merge branch 'dev' of https://github.com/fit2cloudrd/metersphere-server into dev
This commit is contained in:
commit
e5e7737f29
|
@ -42,7 +42,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -53,7 +52,9 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
@ -66,7 +67,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -119,10 +119,6 @@
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
|
@ -188,6 +184,16 @@
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<addResources>true</addResources>
|
<addResources>true</addResources>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package io.metersphere.api.controller;
|
||||||
|
|
||||||
|
import com.github.pagehelper.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.api.dto.DeleteAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
|
import io.metersphere.api.service.APIReportService;
|
||||||
|
import io.metersphere.base.domain.ApiTestReport;
|
||||||
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
|
import io.metersphere.commons.utils.Pager;
|
||||||
|
import io.metersphere.user.SessionUtils;
|
||||||
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/api/report")
|
||||||
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
||||||
|
public class APIReportController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private APIReportService apiReportService;
|
||||||
|
|
||||||
|
@GetMapping("recent/{count}")
|
||||||
|
public List<APIReportResult> recentTest(@PathVariable int count) {
|
||||||
|
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
QueryAPIReportRequest request = new QueryAPIReportRequest();
|
||||||
|
request.setWorkspaceId(currentWorkspaceId);
|
||||||
|
PageHelper.startPage(1, count, true);
|
||||||
|
return apiReportService.recentTest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
|
public Pager<List<APIReportResult>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryAPIReportRequest request) {
|
||||||
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
|
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
return PageUtils.setPageInfo(page, apiReportService.list(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get/{testId}")
|
||||||
|
public ApiTestReport get(@PathVariable String testId) {
|
||||||
|
return apiReportService.get(testId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestBody DeleteAPIReportRequest request) {
|
||||||
|
apiReportService.delete(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,13 +6,11 @@ import io.metersphere.api.dto.APITestResult;
|
||||||
import io.metersphere.api.dto.DeleteAPITestRequest;
|
import io.metersphere.api.dto.DeleteAPITestRequest;
|
||||||
import io.metersphere.api.dto.QueryAPITestRequest;
|
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||||
import io.metersphere.api.service.ApiTestService;
|
import io.metersphere.api.service.APITestService;
|
||||||
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.controller.request.testplan.SaveTestPlanRequest;
|
|
||||||
import io.metersphere.service.FileService;
|
|
||||||
import io.metersphere.user.SessionUtils;
|
import io.metersphere.user.SessionUtils;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
@ -28,9 +26,7 @@ import javax.annotation.Resource;
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
||||||
public class APITestController {
|
public class APITestController {
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestService apiTestService;
|
private APITestService apiTestService;
|
||||||
@Resource
|
|
||||||
private FileService fileService;
|
|
||||||
|
|
||||||
@GetMapping("recent/{count}")
|
@GetMapping("recent/{count}")
|
||||||
public List<APITestResult> recentTest(@PathVariable int count) {
|
public List<APITestResult> recentTest(@PathVariable int count) {
|
||||||
|
@ -48,9 +44,14 @@ public class APITestController {
|
||||||
return PageUtils.setPageInfo(page, apiTestService.list(request));
|
return PageUtils.setPageInfo(page, apiTestService.list(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/save", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
|
||||||
public String save(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
|
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
|
||||||
return apiTestService.save(request, files);
|
apiTestService.create(request, files);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
|
||||||
|
public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
|
||||||
|
apiTestService.update(request, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get/{testId}")
|
@GetMapping("/get/{testId}")
|
||||||
|
@ -63,8 +64,8 @@ public class APITestController {
|
||||||
apiTestService.delete(request);
|
apiTestService.delete(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/run", consumes = {"multipart/form-data"})
|
@PostMapping(value = "/run")
|
||||||
public String run(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
|
public void run(@RequestBody SaveAPITestRequest request) {
|
||||||
return apiTestService.run(request, files);
|
apiTestService.run(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.ApiTestReport;
|
||||||
|
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class APIReportResult extends ApiTestReport {
|
||||||
|
|
||||||
|
private String projectName;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class DeleteAPIReportRequest {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package io.metersphere.api.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class QueryAPIReportRequest {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String projectId;
|
||||||
|
private String name;
|
||||||
|
private String workspaceId;
|
||||||
|
private boolean recent = false;
|
||||||
|
|
||||||
|
}
|
|
@ -1,45 +1,149 @@
|
||||||
package io.metersphere.api.jmeter;
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import io.metersphere.api.service.APIReportService;
|
||||||
|
import io.metersphere.api.service.APITestService;
|
||||||
|
import io.metersphere.commons.constants.APITestStatus;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.assertions.AssertionResult;
|
import org.apache.jmeter.assertions.AssertionResult;
|
||||||
import org.apache.jmeter.samplers.SampleResult;
|
import org.apache.jmeter.samplers.SampleResult;
|
||||||
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
|
||||||
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JMeter BackendListener扩展, jmx脚本中使用
|
||||||
|
*/
|
||||||
public class APIBackendListenerClient extends AbstractBackendListenerClient implements Serializable {
|
public class APIBackendListenerClient extends AbstractBackendListenerClient implements Serializable {
|
||||||
|
|
||||||
private final AtomicInteger count = new AtomicInteger();
|
// 与前端JMXGenerator的SPLIT对应,用于获取 测试名称 和 测试ID
|
||||||
|
private final static String SPLIT = "@@:";
|
||||||
|
// 测试ID作为key
|
||||||
|
private final Map<String, List<SampleResult>> queue = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
|
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
|
||||||
System.out.println(context.getParameter("id"));
|
|
||||||
sampleResults.forEach(result -> {
|
sampleResults.forEach(result -> {
|
||||||
for (AssertionResult assertionResult : result.getAssertionResults()) {
|
// 将不同的测试脚本按测试ID分开
|
||||||
System.out.println(assertionResult.getName() + ": " + assertionResult.isError());
|
String label = result.getSampleLabel();
|
||||||
System.out.println(assertionResult.getName() + ": " + assertionResult.isFailure());
|
if (!label.contains(SPLIT)) {
|
||||||
System.out.println(assertionResult.getName() + ": " + assertionResult.getFailureMessage());
|
LogUtil.error("request name format is invalid, name: " + label);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
String name = label.split(SPLIT)[0];
|
||||||
println("getSampleLabel", result.getSampleLabel());
|
String testId = label.split(SPLIT)[1];
|
||||||
println("getErrorCount", result.getErrorCount());
|
if (!queue.containsKey(testId)) {
|
||||||
println("getRequestHeaders", result.getRequestHeaders());
|
List<SampleResult> testResults = new ArrayList<>();
|
||||||
println("getResponseHeaders", result.getResponseHeaders());
|
queue.put(testId, testResults);
|
||||||
println("getSampleLabel", result.getSampleLabel());
|
}
|
||||||
println("getSampleLabel", result.getSampleLabel());
|
result.setSampleLabel(name);
|
||||||
println("getResponseCode", result.getResponseCode());
|
queue.get(testId).add(result);
|
||||||
println("getResponseCode size", result.getResponseData().length);
|
|
||||||
println("getLatency", result.getLatency());
|
|
||||||
println("end - start", result.getEndTime() - result.getStartTime());
|
|
||||||
println("getTimeStamp", result.getTimeStamp());
|
|
||||||
println("getTime", result.getTime());
|
|
||||||
});
|
});
|
||||||
System.err.println(count.addAndGet(sampleResults.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void println(String name, Object value) {
|
@Override
|
||||||
System.out.println(name + ": " + value);
|
public void teardownTest(BackendListenerContext context) throws Exception {
|
||||||
|
APITestService apiTestService = CommonBeanFactory.getBean(APITestService.class);
|
||||||
|
if (apiTestService == null) {
|
||||||
|
LogUtil.error("apiTestService is required");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APIReportService apiReportService = CommonBeanFactory.getBean(APIReportService.class);
|
||||||
|
if (apiReportService == null) {
|
||||||
|
LogUtil.error("apiReportService is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.forEach((id, sampleResults) -> {
|
||||||
|
TestResult testResult = new TestResult();
|
||||||
|
testResult.setId(id);
|
||||||
|
testResult.setTotal(sampleResults.size());
|
||||||
|
|
||||||
|
// key: 场景Id
|
||||||
|
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
sampleResults.forEach(result -> {
|
||||||
|
String thread = StringUtils.substringBeforeLast(result.getThreadName(), " ");
|
||||||
|
String scenarioName = StringUtils.substringBefore(thread, SPLIT);
|
||||||
|
String scenarioId = StringUtils.substringAfter(thread, SPLIT);
|
||||||
|
ScenarioResult scenarioResult;
|
||||||
|
if (!scenarios.containsKey(scenarioId)) {
|
||||||
|
scenarioResult = new ScenarioResult();
|
||||||
|
scenarioResult.setId(scenarioId);
|
||||||
|
scenarioResult.setName(scenarioName);
|
||||||
|
scenarios.put(scenarioId, scenarioResult);
|
||||||
|
} else {
|
||||||
|
scenarioResult = scenarios.get(scenarioId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isSuccessful()) {
|
||||||
|
scenarioResult.addSuccess();
|
||||||
|
testResult.addSuccess();
|
||||||
|
} else {
|
||||||
|
scenarioResult.addError();
|
||||||
|
testResult.addError();
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestResult requestResult = getRequestResult(result);
|
||||||
|
scenarioResult.getRequestResult().add(requestResult);
|
||||||
|
|
||||||
|
testResult.addPassAssertions(requestResult.getPassAssertions());
|
||||||
|
testResult.addTotalAssertions(requestResult.getTotalAssertions());
|
||||||
|
|
||||||
|
scenarioResult.addPassAssertions(requestResult.getPassAssertions());
|
||||||
|
scenarioResult.addTotalAssertions(requestResult.getTotalAssertions());
|
||||||
|
});
|
||||||
|
testResult.getScenarios().addAll(scenarios.values());
|
||||||
|
apiTestService.changeStatus(id, APITestStatus.Completed);
|
||||||
|
apiReportService.save(testResult);
|
||||||
|
});
|
||||||
|
queue.clear();
|
||||||
|
super.teardownTest(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestResult getRequestResult(SampleResult result) {
|
||||||
|
RequestResult requestResult = new RequestResult();
|
||||||
|
requestResult.setName(result.getSampleLabel());
|
||||||
|
requestResult.setUrl(result.getUrlAsString());
|
||||||
|
requestResult.setSuccess(result.isSuccessful());
|
||||||
|
requestResult.setBody(result.getSamplerData());
|
||||||
|
requestResult.setHeaders(result.getRequestHeaders());
|
||||||
|
requestResult.setRequestSize(result.getSentBytes());
|
||||||
|
requestResult.setTotalAssertions(result.getAssertionResults().length);
|
||||||
|
|
||||||
|
ResponseResult responseResult = requestResult.getResponseResult();
|
||||||
|
responseResult.setBody(result.getResponseDataAsString());
|
||||||
|
responseResult.setHeaders(result.getResponseHeaders());
|
||||||
|
responseResult.setLatency(result.getLatency());
|
||||||
|
responseResult.setResponseCode(result.getResponseCode());
|
||||||
|
responseResult.setResponseSize(result.getResponseData().length);
|
||||||
|
responseResult.setResponseTime(result.getTime());
|
||||||
|
responseResult.setResponseMessage(result.getResponseMessage());
|
||||||
|
|
||||||
|
for (AssertionResult assertionResult : result.getAssertionResults()) {
|
||||||
|
ResponseAssertionResult responseAssertionResult = getResponseAssertionResult(assertionResult);
|
||||||
|
if (responseAssertionResult.isPass()) {
|
||||||
|
requestResult.addPassAssertions();
|
||||||
|
}
|
||||||
|
responseResult.getAssertions().add(responseAssertionResult);
|
||||||
|
}
|
||||||
|
return requestResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseAssertionResult getResponseAssertionResult(AssertionResult assertionResult) {
|
||||||
|
ResponseAssertionResult responseAssertionResult = new ResponseAssertionResult();
|
||||||
|
responseAssertionResult.setMessage(assertionResult.getFailureMessage());
|
||||||
|
responseAssertionResult.setName(assertionResult.getName());
|
||||||
|
responseAssertionResult.setPass(!assertionResult.isFailure());
|
||||||
|
return responseAssertionResult;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RequestResult {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
private long requestSize;
|
||||||
|
|
||||||
|
private boolean success;
|
||||||
|
|
||||||
|
private String headers;
|
||||||
|
|
||||||
|
private String cookies;
|
||||||
|
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
private int totalAssertions = 0;
|
||||||
|
|
||||||
|
private int passAssertions = 0;
|
||||||
|
|
||||||
|
private final ResponseResult responseResult = new ResponseResult();
|
||||||
|
|
||||||
|
public void addPassAssertions() {
|
||||||
|
this.passAssertions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ResponseAssertionResult {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
private boolean pass;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ResponseResult {
|
||||||
|
|
||||||
|
private String responseCode;
|
||||||
|
|
||||||
|
private String responseMessage;
|
||||||
|
|
||||||
|
private long responseTime;
|
||||||
|
|
||||||
|
private long latency;
|
||||||
|
|
||||||
|
private long responseSize;
|
||||||
|
|
||||||
|
private String headers;
|
||||||
|
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
private final List<ResponseAssertionResult> assertions = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ScenarioResult {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private long responseTime;
|
||||||
|
|
||||||
|
private int error = 0;
|
||||||
|
|
||||||
|
private int success = 0;
|
||||||
|
|
||||||
|
private int totalAssertions = 0;
|
||||||
|
|
||||||
|
private int passAssertions = 0;
|
||||||
|
|
||||||
|
private final List<RequestResult> requestResult = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addError() {
|
||||||
|
this.error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSuccess() {
|
||||||
|
this.success++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTotalAssertions(int count) {
|
||||||
|
this.totalAssertions += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPassAssertions(int count) {
|
||||||
|
this.passAssertions += count;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package io.metersphere.api.jmeter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TestResult {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private int success = 0;
|
||||||
|
|
||||||
|
private int error = 0;
|
||||||
|
|
||||||
|
private int total = 0;
|
||||||
|
|
||||||
|
private int totalAssertions = 0;
|
||||||
|
|
||||||
|
private int passAssertions = 0;
|
||||||
|
|
||||||
|
private final List<ScenarioResult> scenarios = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addError() {
|
||||||
|
this.error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSuccess() {
|
||||||
|
this.success++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTotalAssertions(int count) {
|
||||||
|
this.totalAssertions += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPassAssertions(int count) {
|
||||||
|
this.passAssertions += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.metersphere.api.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.api.dto.DeleteAPIReportRequest;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
|
import io.metersphere.api.jmeter.TestResult;
|
||||||
|
import io.metersphere.base.domain.ApiTestReport;
|
||||||
|
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
||||||
|
import io.metersphere.base.mapper.ApiTestReportMapper;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtApiTestReportMapper;
|
||||||
|
import io.metersphere.commons.constants.APITestStatus;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class APIReportService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private APITestService apiTestService;
|
||||||
|
@Resource
|
||||||
|
private ApiTestReportMapper apiTestReportMapper;
|
||||||
|
@Resource
|
||||||
|
private ExtApiTestReportMapper extApiTestReportMapper;
|
||||||
|
|
||||||
|
public List<APIReportResult> list(QueryAPIReportRequest request) {
|
||||||
|
return extApiTestReportMapper.list(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<APIReportResult> recentTest(QueryAPIReportRequest request) {
|
||||||
|
request.setRecent(true);
|
||||||
|
return extApiTestReportMapper.list(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiTestReport get(String id) {
|
||||||
|
return apiTestReportMapper.selectByPrimaryKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<APIReportResult> listByTestId(String testId) {
|
||||||
|
return extApiTestReportMapper.listByTestId(testId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(DeleteAPIReportRequest request) {
|
||||||
|
apiTestReportMapper.deleteByPrimaryKey(request.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(TestResult result) {
|
||||||
|
ApiTestWithBLOBs test = apiTestService.get(result.getId());
|
||||||
|
ApiTestReport report = new ApiTestReport();
|
||||||
|
report.setId(UUID.randomUUID().toString());
|
||||||
|
report.setTestId(result.getId());
|
||||||
|
report.setName(test.getName());
|
||||||
|
report.setDescription(test.getDescription());
|
||||||
|
report.setContent(JSONObject.toJSONString(result));
|
||||||
|
report.setCreateTime(System.currentTimeMillis());
|
||||||
|
report.setUpdateTime(System.currentTimeMillis());
|
||||||
|
report.setStatus(APITestStatus.Completed.name());
|
||||||
|
apiTestReportMapper.insert(report);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,22 +13,21 @@ import io.metersphere.commons.constants.APITestStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.service.FileService;
|
import io.metersphere.service.FileService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class ApiTestService {
|
public class APITestService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiTestMapper apiTestMapper;
|
private ApiTestMapper apiTestMapper;
|
||||||
|
@ -50,28 +49,21 @@ public class ApiTestService {
|
||||||
return extApiTestMapper.list(request);
|
return extApiTestMapper.list(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String save(SaveAPITestRequest request, List<MultipartFile> files) {
|
public void create(SaveAPITestRequest request, List<MultipartFile> files) {
|
||||||
if (files == null || files.isEmpty()) {
|
if (files == null || files.isEmpty()) {
|
||||||
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
||||||
}
|
}
|
||||||
|
ApiTestWithBLOBs test = createTest(request);
|
||||||
final ApiTestWithBLOBs test;
|
saveFile(test.getId(), files);
|
||||||
if (StringUtils.isNotBlank(request.getId())) {
|
|
||||||
// 删除原来的文件
|
|
||||||
deleteFileByTestId(request.getId());
|
|
||||||
test = updateTest(request);
|
|
||||||
} else {
|
|
||||||
test = createTest(request);
|
|
||||||
}
|
}
|
||||||
// 保存新文件
|
|
||||||
files.forEach(file -> {
|
public void update(SaveAPITestRequest request, List<MultipartFile> files) {
|
||||||
final FileMetadata fileMetadata = fileService.saveFile(file);
|
if (files == null || files.isEmpty()) {
|
||||||
ApiTestFile apiTestFile = new ApiTestFile();
|
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
||||||
apiTestFile.setTestId(test.getId());
|
}
|
||||||
apiTestFile.setFileId(fileMetadata.getId());
|
deleteFileByTestId(request.getId());
|
||||||
apiTestFileMapper.insert(apiTestFile);
|
ApiTestWithBLOBs test = updateTest(request);
|
||||||
});
|
saveFile(test.getId(), files);
|
||||||
return test.getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiTestWithBLOBs get(String id) {
|
public ApiTestWithBLOBs get(String id) {
|
||||||
|
@ -83,15 +75,15 @@ public class ApiTestService {
|
||||||
apiTestMapper.deleteByPrimaryKey(request.getId());
|
apiTestMapper.deleteByPrimaryKey(request.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String run(SaveAPITestRequest request, List<MultipartFile> files) {
|
public void run(SaveAPITestRequest request) {
|
||||||
String id = save(request, files);
|
ApiTestFile file = getFileByTestId(request.getId());
|
||||||
try {
|
if (file == null) {
|
||||||
changeStatus(request.getId(), APITestStatus.Running);
|
MSException.throwException(Translator.get("file_cannot_be_null"));
|
||||||
jMeterService.run(files.get(0).getInputStream());
|
|
||||||
} catch (IOException e) {
|
|
||||||
MSException.throwException(Translator.get("api_load_script_error"));
|
|
||||||
}
|
}
|
||||||
return id;
|
byte[] bytes = fileService.loadFileAsBytes(file.getFileId());
|
||||||
|
InputStream is = new ByteArrayInputStream(bytes);
|
||||||
|
changeStatus(request.getId(), APITestStatus.Running);
|
||||||
|
jMeterService.run(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeStatus(String id, APITestStatus status) {
|
public void changeStatus(String id, APITestStatus status) {
|
||||||
|
@ -121,7 +113,7 @@ public class ApiTestService {
|
||||||
}
|
}
|
||||||
|
|
||||||
final ApiTestWithBLOBs test = new ApiTestWithBLOBs();
|
final ApiTestWithBLOBs test = new ApiTestWithBLOBs();
|
||||||
test.setId(UUID.randomUUID().toString());
|
test.setId(request.getId());
|
||||||
test.setName(request.getName());
|
test.setName(request.getName());
|
||||||
test.setProjectId(request.getProjectId());
|
test.setProjectId(request.getProjectId());
|
||||||
test.setScenarioDefinition(request.getScenarioDefinition());
|
test.setScenarioDefinition(request.getScenarioDefinition());
|
||||||
|
@ -132,6 +124,16 @@ public class ApiTestService {
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveFile(String testId, List<MultipartFile> files) {
|
||||||
|
files.forEach(file -> {
|
||||||
|
final FileMetadata fileMetadata = fileService.saveFile(file);
|
||||||
|
ApiTestFile apiTestFile = new ApiTestFile();
|
||||||
|
apiTestFile.setTestId(testId);
|
||||||
|
apiTestFile.setFileId(fileMetadata.getId());
|
||||||
|
apiTestFileMapper.insert(apiTestFile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void deleteFileByTestId(String testId) {
|
private void deleteFileByTestId(String testId) {
|
||||||
ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
|
ApiTestFileExample ApiTestFileExample = new ApiTestFileExample();
|
||||||
ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
|
ApiTestFileExample.createCriteria().andTestIdEqualTo(testId);
|
|
@ -6,7 +6,7 @@ import java.io.Serializable;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class LoadTestReportLog implements Serializable {
|
public class LoadTestReportLog implements Serializable {
|
||||||
private Long id;
|
private String id;
|
||||||
|
|
||||||
private String reportId;
|
private String reportId;
|
||||||
|
|
||||||
|
|
|
@ -114,52 +114,62 @@ public class LoadTestReportLogExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdEqualTo(Long value) {
|
public Criteria andIdEqualTo(String value) {
|
||||||
addCriterion("id =", value, "id");
|
addCriterion("id =", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotEqualTo(Long value) {
|
public Criteria andIdNotEqualTo(String value) {
|
||||||
addCriterion("id <>", value, "id");
|
addCriterion("id <>", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdGreaterThan(Long value) {
|
public Criteria andIdGreaterThan(String value) {
|
||||||
addCriterion("id >", value, "id");
|
addCriterion("id >", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdGreaterThanOrEqualTo(Long value) {
|
public Criteria andIdGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("id >=", value, "id");
|
addCriterion("id >=", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdLessThan(Long value) {
|
public Criteria andIdLessThan(String value) {
|
||||||
addCriterion("id <", value, "id");
|
addCriterion("id <", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdLessThanOrEqualTo(Long value) {
|
public Criteria andIdLessThanOrEqualTo(String value) {
|
||||||
addCriterion("id <=", value, "id");
|
addCriterion("id <=", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdIn(List<Long> values) {
|
public Criteria andIdLike(String value) {
|
||||||
|
addCriterion("id like", value, "id");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andIdNotLike(String value) {
|
||||||
|
addCriterion("id not like", value, "id");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andIdIn(List<String> values) {
|
||||||
addCriterion("id in", values, "id");
|
addCriterion("id in", values, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotIn(List<Long> values) {
|
public Criteria andIdNotIn(List<String> values) {
|
||||||
addCriterion("id not in", values, "id");
|
addCriterion("id not in", values, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdBetween(Long value1, Long value2) {
|
public Criteria andIdBetween(String value1, String value2) {
|
||||||
addCriterion("id between", value1, value2, "id");
|
addCriterion("id between", value1, value2, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotBetween(Long value1, Long value2) {
|
public Criteria andIdNotBetween(String value1, String value2) {
|
||||||
addCriterion("id not between", value1, value2, "id");
|
addCriterion("id not between", value1, value2, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import java.io.Serializable;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class LoadTestReportResult implements Serializable {
|
public class LoadTestReportResult implements Serializable {
|
||||||
private Long id;
|
private String id;
|
||||||
|
|
||||||
private String reportId;
|
private String reportId;
|
||||||
|
|
||||||
|
|
|
@ -114,52 +114,62 @@ public class LoadTestReportResultExample {
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdEqualTo(Long value) {
|
public Criteria andIdEqualTo(String value) {
|
||||||
addCriterion("id =", value, "id");
|
addCriterion("id =", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotEqualTo(Long value) {
|
public Criteria andIdNotEqualTo(String value) {
|
||||||
addCriterion("id <>", value, "id");
|
addCriterion("id <>", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdGreaterThan(Long value) {
|
public Criteria andIdGreaterThan(String value) {
|
||||||
addCriterion("id >", value, "id");
|
addCriterion("id >", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdGreaterThanOrEqualTo(Long value) {
|
public Criteria andIdGreaterThanOrEqualTo(String value) {
|
||||||
addCriterion("id >=", value, "id");
|
addCriterion("id >=", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdLessThan(Long value) {
|
public Criteria andIdLessThan(String value) {
|
||||||
addCriterion("id <", value, "id");
|
addCriterion("id <", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdLessThanOrEqualTo(Long value) {
|
public Criteria andIdLessThanOrEqualTo(String value) {
|
||||||
addCriterion("id <=", value, "id");
|
addCriterion("id <=", value, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdIn(List<Long> values) {
|
public Criteria andIdLike(String value) {
|
||||||
|
addCriterion("id like", value, "id");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andIdNotLike(String value) {
|
||||||
|
addCriterion("id not like", value, "id");
|
||||||
|
return (Criteria) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria andIdIn(List<String> values) {
|
||||||
addCriterion("id in", values, "id");
|
addCriterion("id in", values, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotIn(List<Long> values) {
|
public Criteria andIdNotIn(List<String> values) {
|
||||||
addCriterion("id not in", values, "id");
|
addCriterion("id not in", values, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdBetween(Long value1, Long value2) {
|
public Criteria andIdBetween(String value1, String value2) {
|
||||||
addCriterion("id between", value1, value2, "id");
|
addCriterion("id between", value1, value2, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria andIdNotBetween(Long value1, Long value2) {
|
public Criteria andIdNotBetween(String value1, String value2) {
|
||||||
addCriterion("id not between", value1, value2, "id");
|
addCriterion("id not between", value1, value2, "id");
|
||||||
return (Criteria) this;
|
return (Criteria) this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public interface LoadTestReportLogMapper {
|
||||||
|
|
||||||
int deleteByExample(LoadTestReportLogExample example);
|
int deleteByExample(LoadTestReportLogExample example);
|
||||||
|
|
||||||
int deleteByPrimaryKey(Long id);
|
int deleteByPrimaryKey(String id);
|
||||||
|
|
||||||
int insert(LoadTestReportLog record);
|
int insert(LoadTestReportLog record);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public interface LoadTestReportLogMapper {
|
||||||
|
|
||||||
List<LoadTestReportLog> selectByExample(LoadTestReportLogExample example);
|
List<LoadTestReportLog> selectByExample(LoadTestReportLogExample example);
|
||||||
|
|
||||||
LoadTestReportLog selectByPrimaryKey(Long id);
|
LoadTestReportLog selectByPrimaryKey(String id);
|
||||||
|
|
||||||
int updateByExampleSelective(@Param("record") LoadTestReportLog record, @Param("example") LoadTestReportLogExample example);
|
int updateByExampleSelective(@Param("record") LoadTestReportLog record, @Param("example") LoadTestReportLogExample example);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="io.metersphere.base.mapper.LoadTestReportLogMapper">
|
<mapper namespace="io.metersphere.base.mapper.LoadTestReportLogMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportLog">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportLog">
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||||
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
|
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
@ -103,17 +103,17 @@
|
||||||
order by ${orderByClause}
|
order by ${orderByClause}
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
|
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||||
select
|
select
|
||||||
<include refid="Base_Column_List" />
|
<include refid="Base_Column_List" />
|
||||||
,
|
,
|
||||||
<include refid="Blob_Column_List" />
|
<include refid="Blob_Column_List" />
|
||||||
from load_test_report_log
|
from load_test_report_log
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</select>
|
</select>
|
||||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
|
||||||
delete from load_test_report_log
|
delete from load_test_report_log
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</delete>
|
</delete>
|
||||||
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportLogExample">
|
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportLogExample">
|
||||||
delete from load_test_report_log
|
delete from load_test_report_log
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
||||||
insert into load_test_report_log (id, report_id, resource_id,
|
insert into load_test_report_log (id, report_id, resource_id,
|
||||||
content)
|
content)
|
||||||
values (#{id,jdbcType=BIGINT}, #{reportId,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
|
||||||
#{content,jdbcType=LONGVARCHAR})
|
#{content,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
#{id,jdbcType=BIGINT},
|
#{id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="reportId != null">
|
<if test="reportId != null">
|
||||||
#{reportId,jdbcType=VARCHAR},
|
#{reportId,jdbcType=VARCHAR},
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
update load_test_report_log
|
update load_test_report_log
|
||||||
<set>
|
<set>
|
||||||
<if test="record.id != null">
|
<if test="record.id != null">
|
||||||
id = #{record.id,jdbcType=BIGINT},
|
id = #{record.id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.reportId != null">
|
<if test="record.reportId != null">
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||||
update load_test_report_log
|
update load_test_report_log
|
||||||
set id = #{record.id,jdbcType=BIGINT},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
resource_id = #{record.resourceId,jdbcType=VARCHAR},
|
resource_id = #{record.resourceId,jdbcType=VARCHAR},
|
||||||
content = #{record.content,jdbcType=LONGVARCHAR}
|
content = #{record.content,jdbcType=LONGVARCHAR}
|
||||||
|
@ -196,7 +196,7 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update load_test_report_log
|
update load_test_report_log
|
||||||
set id = #{record.id,jdbcType=BIGINT},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
resource_id = #{record.resourceId,jdbcType=VARCHAR}
|
resource_id = #{record.resourceId,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
|
@ -216,19 +216,19 @@
|
||||||
content = #{content,jdbcType=LONGVARCHAR},
|
content = #{content,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
</set>
|
</set>
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
||||||
update load_test_report_log
|
update load_test_report_log
|
||||||
set report_id = #{reportId,jdbcType=VARCHAR},
|
set report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
resource_id = #{resourceId,jdbcType=VARCHAR},
|
resource_id = #{resourceId,jdbcType=VARCHAR},
|
||||||
content = #{content,jdbcType=LONGVARCHAR}
|
content = #{content,jdbcType=LONGVARCHAR}
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTestReportLog">
|
||||||
update load_test_report_log
|
update load_test_report_log
|
||||||
set report_id = #{reportId,jdbcType=VARCHAR},
|
set report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
resource_id = #{resourceId,jdbcType=VARCHAR}
|
resource_id = #{resourceId,jdbcType=VARCHAR}
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -11,7 +11,7 @@ public interface LoadTestReportResultMapper {
|
||||||
|
|
||||||
int deleteByExample(LoadTestReportResultExample example);
|
int deleteByExample(LoadTestReportResultExample example);
|
||||||
|
|
||||||
int deleteByPrimaryKey(Long id);
|
int deleteByPrimaryKey(String id);
|
||||||
|
|
||||||
int insert(LoadTestReportResult record);
|
int insert(LoadTestReportResult record);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public interface LoadTestReportResultMapper {
|
||||||
|
|
||||||
List<LoadTestReportResult> selectByExample(LoadTestReportResultExample example);
|
List<LoadTestReportResult> selectByExample(LoadTestReportResultExample example);
|
||||||
|
|
||||||
LoadTestReportResult selectByPrimaryKey(Long id);
|
LoadTestReportResult selectByPrimaryKey(String id);
|
||||||
|
|
||||||
int updateByExampleSelective(@Param("record") LoadTestReportResult record, @Param("example") LoadTestReportResultExample example);
|
int updateByExampleSelective(@Param("record") LoadTestReportResult record, @Param("example") LoadTestReportResultExample example);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="io.metersphere.base.mapper.LoadTestReportResultMapper">
|
<mapper namespace="io.metersphere.base.mapper.LoadTestReportResultMapper">
|
||||||
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportResult">
|
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.LoadTestReportResult">
|
||||||
<id column="id" jdbcType="BIGINT" property="id" />
|
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||||
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
|
||||||
<result column="report_key" jdbcType="VARCHAR" property="reportKey" />
|
<result column="report_key" jdbcType="VARCHAR" property="reportKey" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
@ -103,17 +103,17 @@
|
||||||
order by ${orderByClause}
|
order by ${orderByClause}
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
|
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
|
||||||
select
|
select
|
||||||
<include refid="Base_Column_List" />
|
<include refid="Base_Column_List" />
|
||||||
,
|
,
|
||||||
<include refid="Blob_Column_List" />
|
<include refid="Blob_Column_List" />
|
||||||
from load_test_report_result
|
from load_test_report_result
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</select>
|
</select>
|
||||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
|
||||||
delete from load_test_report_result
|
delete from load_test_report_result
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</delete>
|
</delete>
|
||||||
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportResultExample">
|
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.LoadTestReportResultExample">
|
||||||
delete from load_test_report_result
|
delete from load_test_report_result
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
<insert id="insert" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
||||||
insert into load_test_report_result (id, report_id, report_key,
|
insert into load_test_report_result (id, report_id, report_key,
|
||||||
report_value)
|
report_value)
|
||||||
values (#{id,jdbcType=BIGINT}, #{reportId,jdbcType=VARCHAR}, #{reportKey,jdbcType=VARCHAR},
|
values (#{id,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, #{reportKey,jdbcType=VARCHAR},
|
||||||
#{reportValue,jdbcType=LONGVARCHAR})
|
#{reportValue,jdbcType=LONGVARCHAR})
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
#{id,jdbcType=BIGINT},
|
#{id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="reportId != null">
|
<if test="reportId != null">
|
||||||
#{reportId,jdbcType=VARCHAR},
|
#{reportId,jdbcType=VARCHAR},
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
update load_test_report_result
|
update load_test_report_result
|
||||||
<set>
|
<set>
|
||||||
<if test="record.id != null">
|
<if test="record.id != null">
|
||||||
id = #{record.id,jdbcType=BIGINT},
|
id = #{record.id,jdbcType=VARCHAR},
|
||||||
</if>
|
</if>
|
||||||
<if test="record.reportId != null">
|
<if test="record.reportId != null">
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||||
update load_test_report_result
|
update load_test_report_result
|
||||||
set id = #{record.id,jdbcType=BIGINT},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
report_key = #{record.reportKey,jdbcType=VARCHAR},
|
report_key = #{record.reportKey,jdbcType=VARCHAR},
|
||||||
report_value = #{record.reportValue,jdbcType=LONGVARCHAR}
|
report_value = #{record.reportValue,jdbcType=LONGVARCHAR}
|
||||||
|
@ -196,7 +196,7 @@
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByExample" parameterType="map">
|
<update id="updateByExample" parameterType="map">
|
||||||
update load_test_report_result
|
update load_test_report_result
|
||||||
set id = #{record.id,jdbcType=BIGINT},
|
set id = #{record.id,jdbcType=VARCHAR},
|
||||||
report_id = #{record.reportId,jdbcType=VARCHAR},
|
report_id = #{record.reportId,jdbcType=VARCHAR},
|
||||||
report_key = #{record.reportKey,jdbcType=VARCHAR}
|
report_key = #{record.reportKey,jdbcType=VARCHAR}
|
||||||
<if test="_parameter != null">
|
<if test="_parameter != null">
|
||||||
|
@ -216,19 +216,19 @@
|
||||||
report_value = #{reportValue,jdbcType=LONGVARCHAR},
|
report_value = #{reportValue,jdbcType=LONGVARCHAR},
|
||||||
</if>
|
</if>
|
||||||
</set>
|
</set>
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
||||||
update load_test_report_result
|
update load_test_report_result
|
||||||
set report_id = #{reportId,jdbcType=VARCHAR},
|
set report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
report_key = #{reportKey,jdbcType=VARCHAR},
|
report_key = #{reportKey,jdbcType=VARCHAR},
|
||||||
report_value = #{reportValue,jdbcType=LONGVARCHAR}
|
report_value = #{reportValue,jdbcType=LONGVARCHAR}
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTestReportResult">
|
||||||
update load_test_report_result
|
update load_test_report_result
|
||||||
set report_id = #{reportId,jdbcType=VARCHAR},
|
set report_id = #{reportId,jdbcType=VARCHAR},
|
||||||
report_key = #{reportKey,jdbcType=VARCHAR}
|
report_key = #{reportKey,jdbcType=VARCHAR}
|
||||||
where id = #{id,jdbcType=BIGINT}
|
where id = #{id,jdbcType=VARCHAR}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.base.mapper.ext;
|
package io.metersphere.base.mapper.ext;
|
||||||
|
|
||||||
import io.metersphere.controller.request.ReportRequest;
|
import io.metersphere.api.dto.APIReportResult;
|
||||||
|
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||||
import io.metersphere.dto.ApiReportDTO;
|
import io.metersphere.dto.ApiReportDTO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
@ -8,7 +9,8 @@ import java.util.List;
|
||||||
|
|
||||||
public interface ExtApiTestReportMapper {
|
public interface ExtApiTestReportMapper {
|
||||||
|
|
||||||
List<ApiReportDTO> getReportList(@Param("reportRequest") ReportRequest request);
|
List<APIReportResult> list(@Param("request") QueryAPIReportRequest request);
|
||||||
|
|
||||||
|
List<APIReportResult> listByTestId(@Param("testId") String testId);
|
||||||
|
|
||||||
ApiReportDTO getReportTestAndProInfo(@Param("id") String id);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,43 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiTestReportMapper">
|
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiTestReportMapper">
|
||||||
|
|
||||||
<select id="getReportList" resultType="io.metersphere.dto.ApiReportDTO">
|
<resultMap id="BaseResultMap" type="io.metersphere.api.dto.APIReportResult"
|
||||||
select ltr.id, ltr.name, ltr.test_id as testId, ltr.description,
|
extends="io.metersphere.base.mapper.ApiTestReportMapper.BaseResultMap">
|
||||||
ltr.create_time as createTime, ltr.update_time as updateTime, ltr.status as status, lt.name as testName
|
<result column="project_name" property="projectName"/>
|
||||||
from api_test_report ltr left join api_test lt on ltr.test_id = lt.id
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="list" resultMap="BaseResultMap">
|
||||||
|
SELECT t.name, t.description,
|
||||||
|
r.id, r.test_id, r.create_time, r.update_time, r.status,
|
||||||
|
project.name AS project_name
|
||||||
|
FROM api_test_report r JOIN api_test t ON r.test_id = t.id
|
||||||
|
JOIN project ON project.id = t.project_id
|
||||||
<where>
|
<where>
|
||||||
<if test="reportRequest.name != null">
|
<if test="request.name != null">
|
||||||
AND ltr.name like CONCAT('%', #{reportRequest.name},'%')
|
AND r.name like CONCAT('%', #{request.name},'%')
|
||||||
|
</if>
|
||||||
|
<if test="request.projectId != null">
|
||||||
|
AND project.id = #{request.projectId}
|
||||||
|
</if>
|
||||||
|
<if test="request.workspaceId != null">
|
||||||
|
AND project.workspace_id = #{request.workspaceId,jdbcType=VARCHAR}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
|
<if test="request.recent">
|
||||||
|
ORDER BY r.update_time DESC
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getReportTestAndProInfo" resultType="io.metersphere.dto.ApiReportDTO">
|
<select id="listByTestId" resultMap="BaseResultMap">
|
||||||
select ltr.id, ltr.name, ltr.test_id as testId, ltr.description,
|
SELECT t.name, t.description,
|
||||||
ltr.create_time as createTime, ltr.update_time as updateTime, ltr.status as status, ltr.content as content,
|
r.id, r.test_id, r.create_time, r.update_time, r.status,
|
||||||
lt.name as testName,
|
project.name AS project_name
|
||||||
p.id as projectId, p.name as projectName
|
FROM api_test_report r JOIN api_test t ON r.test_id = t.id
|
||||||
from api_test_report ltr left join api_test lt on ltr.test_id = lt.id left join project p on lt.project_id = p.id
|
JOIN project ON project.id = t.project_id
|
||||||
where ltr.id = #{id}
|
<where>
|
||||||
|
r.test_id = #{testId}
|
||||||
|
</where>
|
||||||
|
ORDER BY r.update_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -1,53 +0,0 @@
|
||||||
package io.metersphere.controller;
|
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
|
||||||
import com.github.pagehelper.PageHelper;
|
|
||||||
import io.metersphere.base.domain.ApiTestReport;
|
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
|
||||||
import io.metersphere.commons.utils.Pager;
|
|
||||||
import io.metersphere.controller.request.ReportRequest;
|
|
||||||
import io.metersphere.dto.ApiReportDTO;
|
|
||||||
import io.metersphere.service.ApiReportService;
|
|
||||||
import io.metersphere.user.SessionUtils;
|
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(value = "/api/report")
|
|
||||||
public class ApiReportController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ApiReportService apiReportService;
|
|
||||||
|
|
||||||
@GetMapping("/recent/{count}")
|
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
|
||||||
public List<ApiTestReport> recentProjects(@PathVariable int count) {
|
|
||||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
|
||||||
ReportRequest request = new ReportRequest();
|
|
||||||
request.setWorkspaceId(currentWorkspaceId);
|
|
||||||
PageHelper.startPage(1, count);
|
|
||||||
return apiReportService.getRecentReportList(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/list/all/{goPage}/{pageSize}")
|
|
||||||
public Pager<List<ApiReportDTO>> getReportList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ReportRequest request) {
|
|
||||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
|
||||||
return PageUtils.setPageInfo(page, apiReportService.getReportList(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/delete/{reportId}")
|
|
||||||
public void deleteReport(@PathVariable String reportId) {
|
|
||||||
apiReportService.deleteReport(reportId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/test/pro/info/{reportId}")
|
|
||||||
public ApiReportDTO getReportTestAndProInfo(@PathVariable String reportId) {
|
|
||||||
return apiReportService.getReportTestAndProInfo(reportId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,11 +3,14 @@ package io.metersphere.controller;
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.base.domain.TestResourcePool;
|
import io.metersphere.base.domain.TestResourcePool;
|
||||||
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
|
import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
|
||||||
import io.metersphere.dto.TestResourcePoolDTO;
|
import io.metersphere.dto.TestResourcePoolDTO;
|
||||||
import io.metersphere.service.TestResourcePoolService;
|
import io.metersphere.service.TestResourcePoolService;
|
||||||
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -15,6 +18,7 @@ import java.util.List;
|
||||||
|
|
||||||
@RequestMapping("testresourcepool")
|
@RequestMapping("testresourcepool")
|
||||||
@RestController
|
@RestController
|
||||||
|
@RequiresRoles(RoleConstants.ADMIN)
|
||||||
public class TestResourcePoolController {
|
public class TestResourcePoolController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -35,6 +39,11 @@ public class TestResourcePoolController {
|
||||||
testResourcePoolService.updateTestResourcePool(testResourcePoolDTO);
|
testResourcePoolService.updateTestResourcePool(testResourcePoolDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/update/{poolId}/{status}")
|
||||||
|
public void updateTestResourcePoolStatus(@PathVariable String poolId, @PathVariable String status) {
|
||||||
|
testResourcePoolService.updateTestResourcePoolStatus(poolId, status);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("list/{goPage}/{pageSize}")
|
@PostMapping("list/{goPage}/{pageSize}")
|
||||||
public Pager<List<TestResourcePoolDTO>> listResourcePools(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryResourcePoolRequest request) {
|
public Pager<List<TestResourcePoolDTO>> listResourcePools(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryResourcePoolRequest request) {
|
||||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
|
@ -42,6 +51,7 @@ public class TestResourcePoolController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("list/all/valid")
|
@GetMapping("list/all/valid")
|
||||||
|
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
||||||
public List<TestResourcePool> listValidResourcePools() {
|
public List<TestResourcePool> listValidResourcePools() {
|
||||||
return testResourcePoolService.listValidResourcePools();
|
return testResourcePoolService.listValidResourcePools();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class UserRoleController {
|
||||||
|
|
||||||
@GetMapping("/list/ws/{workspaceId}/{userId}")
|
@GetMapping("/list/ws/{workspaceId}/{userId}")
|
||||||
@RequiresRoles(value = {RoleConstants.ADMIN,RoleConstants.ORG_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.ADMIN,RoleConstants.ORG_ADMIN}, logical = Logical.OR)
|
||||||
public List<Role> getWorkspaceMemberRole(@PathVariable String workspaceId, @PathVariable String userId) {
|
public List<Role> getWorkspaceMemberRoles(@PathVariable String workspaceId, @PathVariable String userId) {
|
||||||
return userRoleService.getWorkspaceMemberRoles(workspaceId, userId);
|
return userRoleService.getWorkspaceMemberRoles(workspaceId, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class KubernetesTestEngine extends AbstractEngine {
|
||||||
kubernetesProvider.confirmNamespace(context.getNamespace());
|
kubernetesProvider.confirmNamespace(context.getNamespace());
|
||||||
// create cm
|
// create cm
|
||||||
try (KubernetesClient client = kubernetesProvider.getKubernetesClient()) {
|
try (KubernetesClient client = kubernetesProvider.getKubernetesClient()) {
|
||||||
String configMapName = context.getTestId() + "-files";
|
String configMapName = "jmeter-" + context.getTestId() + "-files";
|
||||||
ConfigMap configMap = client.configMaps().inNamespace(context.getNamespace()).withName(configMapName).get();
|
ConfigMap configMap = client.configMaps().inNamespace(context.getNamespace()).withName(configMapName).get();
|
||||||
if (configMap == null) {
|
if (configMap == null) {
|
||||||
ConfigMap item = new ConfigMap();
|
ConfigMap item = new ConfigMap();
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package io.metersphere.service;
|
|
||||||
|
|
||||||
import io.metersphere.base.domain.ApiTestReport;
|
|
||||||
import io.metersphere.base.domain.ApiTestReportExample;
|
|
||||||
import io.metersphere.base.mapper.ApiTestReportMapper;
|
|
||||||
import io.metersphere.base.mapper.ext.ExtApiTestReportMapper;
|
|
||||||
import io.metersphere.controller.request.ReportRequest;
|
|
||||||
import io.metersphere.dto.ApiReportDTO;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public class ApiReportService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ApiTestReportMapper ApiTestReportMapper;
|
|
||||||
@Resource
|
|
||||||
private ExtApiTestReportMapper extApiTestReportMapper;
|
|
||||||
|
|
||||||
public List<ApiTestReport> getRecentReportList(ReportRequest request) {
|
|
||||||
ApiTestReportExample example = new ApiTestReportExample();
|
|
||||||
example.setOrderByClause("update_time desc");
|
|
||||||
return ApiTestReportMapper.selectByExample(example);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ApiReportDTO> getReportList(ReportRequest request) {
|
|
||||||
return extApiTestReportMapper.getReportList(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteReport(String reportId) {
|
|
||||||
ApiTestReportMapper.deleteByPrimaryKey(reportId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ApiReportDTO getReportTestAndProInfo(String reportId) {
|
|
||||||
return extApiTestReportMapper.getReportTestAndProInfo(reportId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -228,6 +228,7 @@ public class PerformanceTestService {
|
||||||
List<TestResource> testResourceList = testResourceService.getResourcesByPoolId(resourcePoolId);
|
List<TestResource> testResourceList = testResourceService.getResourcesByPoolId(resourcePoolId);
|
||||||
testResourceList.forEach(r -> {
|
testResourceList.forEach(r -> {
|
||||||
LoadTestReportLog record = new LoadTestReportLog();
|
LoadTestReportLog record = new LoadTestReportLog();
|
||||||
|
record.setId(UUID.randomUUID().toString());
|
||||||
record.setReportId(testReport.getId());
|
record.setReportId(testReport.getId());
|
||||||
record.setResourceId(r.getId());
|
record.setResourceId(r.getId());
|
||||||
record.setContent(StringUtils.EMPTY);
|
record.setContent(StringUtils.EMPTY);
|
||||||
|
|
|
@ -72,6 +72,36 @@ public class TestResourcePoolService {
|
||||||
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateTestResourcePoolStatus(String poolId, String status) {
|
||||||
|
TestResourcePool testResourcePool = testResourcePoolMapper.selectByPrimaryKey(poolId);
|
||||||
|
if (testResourcePool == null) {
|
||||||
|
MSException.throwException("Resource Pool not found.");
|
||||||
|
}
|
||||||
|
testResourcePool.setUpdateTime(System.currentTimeMillis());
|
||||||
|
testResourcePool.setStatus(status);
|
||||||
|
// 禁用资源池
|
||||||
|
if (INVALID.name().equals(status)) {
|
||||||
|
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TestResourcePoolDTO testResourcePoolDTO = new TestResourcePoolDTO();
|
||||||
|
try {
|
||||||
|
BeanUtils.copyProperties(testResourcePoolDTO, testResourcePool);
|
||||||
|
TestResourceExample example2 = new TestResourceExample();
|
||||||
|
example2.createCriteria().andTestResourcePoolIdEqualTo(poolId);
|
||||||
|
List<TestResource> testResources = testResourceMapper.selectByExampleWithBLOBs(example2);
|
||||||
|
testResourcePoolDTO.setResources(testResources);
|
||||||
|
if (validateTestResourcePool(testResourcePoolDTO)) {
|
||||||
|
testResourcePoolMapper.updateByPrimaryKeySelective(testResourcePool);
|
||||||
|
} else {
|
||||||
|
MSException.throwException("Resource Pool is invalid.");
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<TestResourcePoolDTO> listResourcePools(QueryResourcePoolRequest request) {
|
public List<TestResourcePoolDTO> listResourcePools(QueryResourcePoolRequest request) {
|
||||||
TestResourcePoolExample example = new TestResourcePoolExample();
|
TestResourcePoolExample example = new TestResourcePoolExample();
|
||||||
TestResourcePoolExample.Criteria criteria = example.createCriteria();
|
TestResourcePoolExample.Criteria criteria = example.createCriteria();
|
||||||
|
@ -96,15 +126,14 @@ public class TestResourcePoolService {
|
||||||
return testResourcePoolDTOS;
|
return testResourcePoolDTOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTestResourcePool(TestResourcePoolDTO testResourcePool) {
|
private boolean validateTestResourcePool(TestResourcePoolDTO testResourcePool) {
|
||||||
if (StringUtils.equalsIgnoreCase(testResourcePool.getType(), ResourcePoolTypeEnum.K8S.name())) {
|
if (StringUtils.equalsIgnoreCase(testResourcePool.getType(), ResourcePoolTypeEnum.K8S.name())) {
|
||||||
validateK8s(testResourcePool);
|
return validateK8s(testResourcePool);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
validateNodes(testResourcePool);
|
return validateNodes(testResourcePool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateNodes(TestResourcePoolDTO testResourcePool) {
|
private boolean validateNodes(TestResourcePoolDTO testResourcePool) {
|
||||||
if (CollectionUtils.isEmpty(testResourcePool.getResources())) {
|
if (CollectionUtils.isEmpty(testResourcePool.getResources())) {
|
||||||
MSException.throwException(Translator.get("no_nodes_message"));
|
MSException.throwException(Translator.get("no_nodes_message"));
|
||||||
}
|
}
|
||||||
|
@ -121,19 +150,21 @@ public class TestResourcePoolService {
|
||||||
MSException.throwException(Translator.get("duplicate_node_ip"));
|
MSException.throwException(Translator.get("duplicate_node_ip"));
|
||||||
}
|
}
|
||||||
testResourcePool.setStatus(VALID.name());
|
testResourcePool.setStatus(VALID.name());
|
||||||
|
boolean isValid = true;
|
||||||
for (TestResource resource : testResourcePool.getResources()) {
|
for (TestResource resource : testResourcePool.getResources()) {
|
||||||
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
||||||
boolean isValidate = validateNode(nodeDTO);
|
boolean isValidate = validateNode(nodeDTO);
|
||||||
if (!isValidate) {
|
if (!isValidate) {
|
||||||
testResourcePool.setStatus(ResourceStatusEnum.INVALID.name());
|
testResourcePool.setStatus(ResourceStatusEnum.INVALID.name());
|
||||||
resource.setStatus(ResourceStatusEnum.INVALID.name());
|
resource.setStatus(ResourceStatusEnum.INVALID.name());
|
||||||
|
isValid = false;
|
||||||
} else {
|
} else {
|
||||||
resource.setStatus(VALID.name());
|
resource.setStatus(VALID.name());
|
||||||
}
|
}
|
||||||
resource.setTestResourcePoolId(testResourcePool.getId());
|
resource.setTestResourcePoolId(testResourcePool.getId());
|
||||||
updateTestResource(resource);
|
updateTestResource(resource);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateNode(NodeDTO node) {
|
private boolean validateNode(NodeDTO node) {
|
||||||
|
@ -145,7 +176,7 @@ public class TestResourcePoolService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateK8s(TestResourcePoolDTO testResourcePool) {
|
private boolean validateK8s(TestResourcePoolDTO testResourcePool) {
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(testResourcePool.getResources()) || testResourcePool.getResources().size() != 1) {
|
if (CollectionUtils.isEmpty(testResourcePool.getResources()) || testResourcePool.getResources().size() != 1) {
|
||||||
throw new RuntimeException(Translator.get("only_one_k8s"));
|
throw new RuntimeException(Translator.get("only_one_k8s"));
|
||||||
|
@ -153,18 +184,21 @@ public class TestResourcePoolService {
|
||||||
|
|
||||||
TestResource testResource = testResourcePool.getResources().get(0);
|
TestResource testResource = testResourcePool.getResources().get(0);
|
||||||
testResource.setTestResourcePoolId(testResourcePool.getId());
|
testResource.setTestResourcePoolId(testResourcePool.getId());
|
||||||
|
boolean isValid;
|
||||||
try {
|
try {
|
||||||
KubernetesProvider provider = new KubernetesProvider(testResource.getConfiguration());
|
KubernetesProvider provider = new KubernetesProvider(testResource.getConfiguration());
|
||||||
provider.validateCredential();
|
provider.validateCredential();
|
||||||
testResource.setStatus(VALID.name());
|
testResource.setStatus(VALID.name());
|
||||||
testResourcePool.setStatus(VALID.name());
|
testResourcePool.setStatus(VALID.name());
|
||||||
|
isValid = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
testResource.setStatus(ResourceStatusEnum.INVALID.name());
|
testResource.setStatus(ResourceStatusEnum.INVALID.name());
|
||||||
testResourcePool.setStatus(ResourceStatusEnum.INVALID.name());
|
testResourcePool.setStatus(ResourceStatusEnum.INVALID.name());
|
||||||
|
isValid = false;
|
||||||
}
|
}
|
||||||
deleteTestResource(testResourcePool.getId());
|
deleteTestResource(testResourcePool.getId());
|
||||||
updateTestResource(testResource);
|
updateTestResource(testResource);
|
||||||
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTestResource(TestResource testResource) {
|
private void updateTestResource(TestResource testResource) {
|
||||||
|
@ -189,6 +223,10 @@ public class TestResourcePoolService {
|
||||||
List<TestResourcePoolDTO> testResourcePools = listResourcePools(request);
|
List<TestResourcePoolDTO> testResourcePools = listResourcePools(request);
|
||||||
// 重新校验 pool
|
// 重新校验 pool
|
||||||
for (TestResourcePoolDTO pool : testResourcePools) {
|
for (TestResourcePoolDTO pool : testResourcePools) {
|
||||||
|
// 手动设置成无效的, 排除
|
||||||
|
if (INVALID.name().equals(pool.getStatus())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
updateTestResourcePool(pool);
|
updateTestResourcePool(pool);
|
||||||
} catch (MSException e) {
|
} catch (MSException e) {
|
||||||
|
@ -201,4 +239,5 @@ public class TestResourcePoolService {
|
||||||
example.createCriteria().andStatusEqualTo(ResourceStatusEnum.VALID.name());
|
example.createCriteria().andStatusEqualTo(ResourceStatusEnum.VALID.name());
|
||||||
return testResourcePoolMapper.selectByExample(example);
|
return testResourcePoolMapper.selectByExample(example);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
CREATE TABLE IF NOT EXISTS `file_content` (
|
CREATE TABLE IF NOT EXISTS `file_content` (
|
||||||
`file_id` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT 'File ID',
|
`file_id` varchar(64) NOT NULL COMMENT 'File ID',
|
||||||
`file` longblob COMMENT 'File content',
|
`file` longblob COMMENT 'File content',
|
||||||
PRIMARY KEY (`file_id`)
|
PRIMARY KEY (`file_id`)
|
||||||
)
|
)
|
||||||
|
@ -70,29 +70,24 @@ CREATE TABLE IF NOT EXISTS `load_test_report_detail` (
|
||||||
DEFAULT CHARSET=utf8mb4
|
DEFAULT CHARSET=utf8mb4
|
||||||
COLLATE=utf8mb4_bin;
|
COLLATE=utf8mb4_bin;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `load_test_report_result` (
|
|
||||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
|
||||||
`report_id` varchar(50) NOT NULL,
|
|
||||||
`report_key` varchar(64) DEFAULT NULL,
|
|
||||||
`report_value` text,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `load_test_report_result_report_id_report_key_index` (`report_id`,`report_key`)
|
|
||||||
)
|
|
||||||
ENGINE=InnoDB
|
|
||||||
DEFAULT CHARSET=utf8mb4
|
|
||||||
COLLATE=utf8mb4_bin;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `load_test_report_log` (
|
CREATE TABLE IF NOT EXISTS `load_test_report_log` (
|
||||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
`id` varchar(50) NOT NULL,
|
||||||
`report_id` varchar(50) NOT NULL,
|
`report_id` varchar(50) NOT NULL,
|
||||||
`resource_id` varchar(50) DEFAULT NULL,
|
`resource_id` varchar(50) DEFAULT NULL,
|
||||||
`content` longtext,
|
`content` longtext ,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `load_test_report_log_report_id_resource_name_index` (`report_id`,`resource_id`)
|
KEY `load_test_report_log_report_id_resource_name_index` (`report_id`,`resource_id`)
|
||||||
)
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||||
ENGINE=InnoDB
|
|
||||||
DEFAULT CHARSET=utf8mb4
|
CREATE TABLE IF NOT EXISTS `load_test_report_result` (
|
||||||
COLLATE=utf8mb4_bin;
|
`id` varchar(50) NOT NULL,
|
||||||
|
`report_id` varchar(50) NOT NULL,
|
||||||
|
`report_key` varchar(64) DEFAULT NULL,
|
||||||
|
`report_value` text ,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `load_test_report_result_report_id_report_key_index` (`report_id`,`report_key`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `organization` (
|
CREATE TABLE IF NOT EXISTS `organization` (
|
||||||
`id` varchar(50) NOT NULL COMMENT 'Organization ID',
|
`id` varchar(50) NOT NULL COMMENT 'Organization ID',
|
||||||
|
@ -145,7 +140,7 @@ CREATE TABLE IF NOT EXISTS `system_parameter` (
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `test_resource` (
|
CREATE TABLE IF NOT EXISTS `test_resource` (
|
||||||
`id` varchar(50) NOT NULL COMMENT 'Test resource ID',
|
`id` varchar(50) NOT NULL COMMENT 'Test resource ID',
|
||||||
`test_resource_pool_id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test resource pool ID this test resource belongs to',
|
`test_resource_pool_id` varchar(50) NOT NULL COMMENT 'Test resource pool ID this test resource belongs to',
|
||||||
`configuration` longtext COMMENT 'Test resource configuration',
|
`configuration` longtext COMMENT 'Test resource configuration',
|
||||||
`status` varchar(64) NOT NULL COMMENT 'Test resource status',
|
`status` varchar(64) NOT NULL COMMENT 'Test resource status',
|
||||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||||
|
@ -217,13 +212,13 @@ CREATE TABLE IF NOT EXISTS `workspace` (
|
||||||
-- api start
|
-- api start
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `api_test` (
|
CREATE TABLE IF NOT EXISTS `api_test` (
|
||||||
`id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test ID',
|
`id` varchar(50) NOT NULL COMMENT 'Test ID',
|
||||||
`project_id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Project ID this test belongs to',
|
`project_id` varchar(50) NOT NULL COMMENT 'Project ID this test belongs to',
|
||||||
`name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test name',
|
`name` varchar(64) NOT NULL COMMENT 'Test name',
|
||||||
`description` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'Test description',
|
`description` varchar(255) DEFAULT NULL COMMENT 'Test description',
|
||||||
`scenario_definition` longtext COLLATE utf8mb4_bin COMMENT 'Scenario definition (JSON format)',
|
`scenario_definition` longtext COMMENT 'Scenario definition (JSON format)',
|
||||||
`schedule` longtext COLLATE utf8mb4_bin COMMENT 'Test schedule (cron list)',
|
`schedule` longtext COMMENT 'Test schedule (cron list)',
|
||||||
`status` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
|
`status` varchar(64) DEFAULT NULL,
|
||||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<template v-slot:title>{{$t('commons.report')}}</template>
|
<template v-slot:title>{{$t('commons.report')}}</template>
|
||||||
<ms-recent-list :options="reportRecent"/>
|
<ms-recent-list :options="reportRecent"/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<ms-show-all :index="'/api/report/all'"/>
|
<ms-show-all :index="'/api/report/list/all'"/>
|
||||||
<!-- <el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>-->
|
<!-- <el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>-->
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
title: this.$t('report.recent'),
|
title: this.$t('report.recent'),
|
||||||
url: "/api/report/recent/5",
|
url: "/api/report/recent/5",
|
||||||
index: function (item) {
|
index: function (item) {
|
||||||
return '/api/report/view/' + item.id;
|
return '/api/report/view?id=' + item.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
<template>
|
||||||
|
<div class="container" v-loading="result.loading">
|
||||||
|
<div class="main-content">
|
||||||
|
<el-card>
|
||||||
|
<template v-slot:header>
|
||||||
|
<ms-table-header :condition.sync="condition" @search="search" :title="$t('commons.test')"
|
||||||
|
:show-create="false"/>
|
||||||
|
</template>
|
||||||
|
<el-table :data="tableData" class="table-content">
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
:label="$t('commons.name')"
|
||||||
|
width="150"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="description"
|
||||||
|
:label="$t('commons.description')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
width="250"
|
||||||
|
:label="$t('commons.create_time')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
width="250"
|
||||||
|
:label="$t('commons.update_time')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
width="150"
|
||||||
|
:label="$t('commons.operating')">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<el-button @click="handleView(scope.row)" type="primary" icon="el-icon-s-data" size="mini" circle/>
|
||||||
|
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="search" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {MsTableHeader, MsTablePagination},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {},
|
||||||
|
condition: {name: ""},
|
||||||
|
projectId: null,
|
||||||
|
tableData: [],
|
||||||
|
multipleSelection: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
loading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeRouteEnter(to, from, next) {
|
||||||
|
next(self => {
|
||||||
|
self.testId = to.params.testId;
|
||||||
|
self.search();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
search() {
|
||||||
|
let param = {
|
||||||
|
name: this.condition.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.testId !== 'all') {
|
||||||
|
param.testId = this.testId;
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = "/api/report/list/" + this.currentPage + "/" + this.pageSize
|
||||||
|
this.result = this.$post(url, param, response => {
|
||||||
|
let data = response.data;
|
||||||
|
this.total = data.itemCount;
|
||||||
|
this.tableData = data.listObject;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.multipleSelection = val;
|
||||||
|
},
|
||||||
|
handleView(report) {
|
||||||
|
this.$router.push({
|
||||||
|
path: '/api/report/view/' + report.id,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleDelete(report) {
|
||||||
|
this.$alert(this.$t('load_test.delete_confirm') + report.name + "?", '', {
|
||||||
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
|
callback: (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
this.result = this.$post("/api/report/delete", {id: report.id}, () => {
|
||||||
|
this.$success(this.$t('commons.delete_success'));
|
||||||
|
this.search();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.table-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,169 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="container" v-loading="result.loading">
|
|
||||||
<div class="main-content">
|
|
||||||
<el-card>
|
|
||||||
<template v-slot:header>
|
|
||||||
<el-row type="flex" justify="space-between" align="middle">
|
|
||||||
<span class="title">{{$t('commons.report')}}</span>
|
|
||||||
<span class="search">
|
|
||||||
<el-input type="text" size="small" :placeholder="$t('report.search_by_name')"
|
|
||||||
prefix-icon="el-icon-search"
|
|
||||||
maxlength="60"
|
|
||||||
v-model="condition" @change="search" clearable/>
|
|
||||||
</span>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<el-table :data="tableData" class="test-content">
|
|
||||||
<el-table-column
|
|
||||||
prop="name"
|
|
||||||
:label="$t('commons.name')"
|
|
||||||
width="150"
|
|
||||||
show-overflow-tooltip>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="description"
|
|
||||||
:label="$t('commons.description')"
|
|
||||||
show-overflow-tooltip>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="testName"
|
|
||||||
:label="$t('report.test_name')"
|
|
||||||
width="150"
|
|
||||||
show-overflow-tooltip>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
width="250"
|
|
||||||
:label="$t('commons.create_time')">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
width="250"
|
|
||||||
:label="$t('commons.update_time')">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
width="150"
|
|
||||||
:label="$t('commons.operating')">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-button @click="handleEdit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
|
|
||||||
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="22" :offset="1">
|
|
||||||
<div class="table-page">
|
|
||||||
<el-pagination
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page.sync="currentPage"
|
|
||||||
:page-sizes="[5, 10, 20, 50, 100]"
|
|
||||||
:page-size="pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "ApiTestReport",
|
|
||||||
created: function () {
|
|
||||||
this.initTableData();
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
result: {},
|
|
||||||
queryPath: "/api/report/list/all",
|
|
||||||
deletePath: "/api/report/delete/",
|
|
||||||
condition: "",
|
|
||||||
projectId: null,
|
|
||||||
tableData: [],
|
|
||||||
multipleSelection: [],
|
|
||||||
currentPage: 1,
|
|
||||||
pageSize: 5,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
|
||||||
testId: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initTableData() {
|
|
||||||
let param = {
|
|
||||||
name: this.condition,
|
|
||||||
};
|
|
||||||
this.result = this.$post(this.buildPagePath(this.queryPath), param, response => {
|
|
||||||
let data = response.data;
|
|
||||||
this.total = data.itemCount;
|
|
||||||
this.tableData = data.listObject;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
search() {
|
|
||||||
this.initTableData();
|
|
||||||
},
|
|
||||||
buildPagePath(path) {
|
|
||||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
|
||||||
},
|
|
||||||
handleSizeChange(size) {
|
|
||||||
this.pageSize = size;
|
|
||||||
this.initTableData();
|
|
||||||
},
|
|
||||||
handleCurrentChange(current) {
|
|
||||||
this.currentPage = current;
|
|
||||||
this.initTableData();
|
|
||||||
},
|
|
||||||
handleSelectionChange(val) {
|
|
||||||
this.multipleSelection = val;
|
|
||||||
},
|
|
||||||
handleEdit(report) {
|
|
||||||
this.$router.push({
|
|
||||||
path: '/api/report/view/' + report.id
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleDelete(report) {
|
|
||||||
this.$alert(this.$t('load_test.delete_confirm') + report.name + "?", '', {
|
|
||||||
confirmButtonText: this.$t('commons.confirm'),
|
|
||||||
callback: (action) => {
|
|
||||||
if (action === 'confirm') {
|
|
||||||
this._handleDelete(report);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_handleDelete(report) {
|
|
||||||
this.result = this.$post(this.deletePath + report.id, {}, () => {
|
|
||||||
this.$message({
|
|
||||||
message: this.$t('commons.delete_success'),
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
this.initTableData();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.test-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-page {
|
|
||||||
padding-top: 20px;
|
|
||||||
margin-right: -9px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -16,7 +16,7 @@
|
||||||
{{$t('commons.save')}}
|
{{$t('commons.save')}}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button type="primary" plain :disabled="isDisabled" @click="runTest">
|
<el-button type="primary" plain @click="runTest">
|
||||||
{{$t('load_test.save_and_run')}}
|
{{$t('load_test.save_and_run')}}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="warning" plain @click="cancel">{{$t('commons.cancel')}}</el-button>
|
<el-button type="warning" plain @click="cancel">{{$t('commons.cancel')}}</el-button>
|
||||||
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
create: false,
|
||||||
result: {},
|
result: {},
|
||||||
projects: [],
|
projects: [],
|
||||||
change: false,
|
change: false,
|
||||||
|
@ -65,8 +66,10 @@
|
||||||
this.projects = response.data;
|
this.projects = response.data;
|
||||||
})
|
})
|
||||||
if (this.id) {
|
if (this.id) {
|
||||||
|
this.create = false;
|
||||||
this.getTest(this.id);
|
this.getTest(this.id);
|
||||||
} else {
|
} else {
|
||||||
|
this.create = true;
|
||||||
this.test = new Test();
|
this.test = new Test();
|
||||||
if (this.$refs.config) {
|
if (this.$refs.config) {
|
||||||
this.$refs.config.reset();
|
this.$refs.config.reset();
|
||||||
|
@ -89,20 +92,28 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
saveTest: function () {
|
saveTest: function () {
|
||||||
this.change = false;
|
this.save(() => {
|
||||||
|
|
||||||
this.result = this.$request(this.getOptions("/api/save"), response => {
|
|
||||||
this.test.id = response.data;
|
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save: function (callback) {
|
||||||
|
this.change = false;
|
||||||
|
let url = this.create ? "/api/create" : "/api/update";
|
||||||
|
this.result = this.$request(this.getOptions(url), response => {
|
||||||
|
this.create = false;
|
||||||
|
if (callback) callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
runTest: function () {
|
runTest: function () {
|
||||||
this.change = false;
|
this.change = false;
|
||||||
|
|
||||||
this.result = this.$request(this.getOptions("/api/run"), response => {
|
this.save(() => {
|
||||||
this.test.id = response.data;
|
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
|
this.result = this.$post("/api/run", {id: this.test.id}, response => {
|
||||||
|
this.$success(this.$t('api_test.running'));
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
cancel: function () {
|
cancel: function () {
|
||||||
this.$router.push('/api/test/list/all');
|
this.$router.push('/api/test/list/all');
|
||||||
|
@ -123,7 +134,6 @@
|
||||||
let jmx = this.test.toJMX();
|
let jmx = this.test.toJMX();
|
||||||
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
let blob = new Blob([jmx.xml], {type: "application/octet-stream"});
|
||||||
formData.append("files", new File([blob], jmx.name));
|
formData.append("files", new File([blob], jmx.name));
|
||||||
console.log(jmx.xml)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<ms-table-header :condition.sync="condition" @search="search" :title="$t('commons.test')"
|
<ms-table-header :condition.sync="condition" @search="search" :title="$t('commons.test')"
|
||||||
@create="create" :createTip="$t('load_test.create')"/>
|
@create="create" :createTip="$t('load_test.create')"/>
|
||||||
</template>
|
</template>
|
||||||
<el-table :data="tableData" class="test-content">
|
<el-table :data="tableData" class="table-content">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
:label="$t('commons.name')"
|
:label="$t('commons.name')"
|
||||||
|
@ -70,8 +70,7 @@
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false
|
||||||
testId: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -128,7 +127,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.test-content {
|
.table-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -204,6 +204,39 @@ export class ThreadGroup extends DefaultTestElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class PostThreadGroup extends DefaultTestElement {
|
||||||
|
constructor(testName) {
|
||||||
|
super('PostThreadGroup', 'PostThreadGroupGui', 'PostThreadGroup', testName || 'tearDown Thread Group');
|
||||||
|
|
||||||
|
this.intProp("ThreadGroup.num_threads", 1);
|
||||||
|
this.intProp("ThreadGroup.ramp_time", 1);
|
||||||
|
this.boolProp("ThreadGroup.scheduler", false);
|
||||||
|
this.stringProp("ThreadGroup.on_sample_error", "continue");
|
||||||
|
|
||||||
|
let loopAttrs = {
|
||||||
|
name: "ThreadGroup.main_controller",
|
||||||
|
elementType: "LoopController",
|
||||||
|
guiclass: "LoopControlPanel",
|
||||||
|
testclass: "LoopController",
|
||||||
|
testname: "Loop Controller",
|
||||||
|
enabled: "true"
|
||||||
|
};
|
||||||
|
let loopController = this.add(new Element('elementProp', loopAttrs));
|
||||||
|
loopController.boolProp('LoopController.continue_forever', false);
|
||||||
|
loopController.stringProp('LoopController.loops', 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DebugSampler extends DefaultTestElement {
|
||||||
|
constructor(testName) {
|
||||||
|
super('DebugSampler', 'TestBeanGUI', 'DebugSampler', testName || 'Debug Sampler');
|
||||||
|
|
||||||
|
this.boolProp("displayJMeterProperties", false);
|
||||||
|
this.boolProp("displayJMeterVariables", true);
|
||||||
|
this.boolProp("displaySystemProperties", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class HTTPSamplerProxy extends DefaultTestElement {
|
export class HTTPSamplerProxy extends DefaultTestElement {
|
||||||
constructor(testName, request) {
|
constructor(testName, request) {
|
||||||
super('HTTPSamplerProxy', 'HttpTestSampleGui', 'HTTPSamplerProxy', testName || 'HTTP Request');
|
super('HTTPSamplerProxy', 'HttpTestSampleGui', 'HTTPSamplerProxy', testName || 'HTTP Request');
|
||||||
|
@ -219,37 +252,6 @@ export class HTTPSamplerProxy extends DefaultTestElement {
|
||||||
this.stringProp("HTTPSampler.port", this.request.port);
|
this.stringProp("HTTPSampler.port", this.request.port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addRequestArguments(arg) {
|
|
||||||
if (arg instanceof HTTPSamplerArguments) {
|
|
||||||
this.add(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addRequestBody(body) {
|
|
||||||
if (body instanceof HTTPSamplerArguments) {
|
|
||||||
this.boolProp('HTTPSampler.postBodyRaw', true);
|
|
||||||
this.add(body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
putRequestHeader(header) {
|
|
||||||
if (header instanceof HeaderManager) {
|
|
||||||
this.put(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
putResponseAssertion(assertion) {
|
|
||||||
if (assertion instanceof ResponseAssertion) {
|
|
||||||
this.put(assertion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
putDurationAssertion(assertion) {
|
|
||||||
if (assertion instanceof DurationAssertion) {
|
|
||||||
this.put(assertion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这是一个Element
|
// 这是一个Element
|
||||||
|
@ -373,8 +375,10 @@ export class BackendListener extends DefaultTestElement {
|
||||||
constructor(testName, className, args) {
|
constructor(testName, className, args) {
|
||||||
super('BackendListener', 'BackendListenerGui', 'BackendListener', testName || 'Backend Listener');
|
super('BackendListener', 'BackendListenerGui', 'BackendListener', testName || 'Backend Listener');
|
||||||
this.stringProp('classname', className);
|
this.stringProp('classname', className);
|
||||||
|
if (args && args.length > 0) {
|
||||||
this.add(new ElementArguments(args));
|
this.add(new ElementArguments(args));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElementArguments extends Element {
|
export class ElementArguments extends Element {
|
||||||
|
@ -397,3 +401,6 @@ export class ElementArguments extends Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Class {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import {
|
||||||
TestElement,
|
TestElement,
|
||||||
TestPlan,
|
TestPlan,
|
||||||
ThreadGroup,
|
ThreadGroup,
|
||||||
|
PostThreadGroup,
|
||||||
|
DebugSampler,
|
||||||
HeaderManager,
|
HeaderManager,
|
||||||
HTTPSamplerArguments,
|
HTTPSamplerArguments,
|
||||||
ResponseCodeAssertion,
|
ResponseCodeAssertion,
|
||||||
|
@ -13,9 +15,21 @@ import {
|
||||||
BackendListener
|
BackendListener
|
||||||
} from "./JMX";
|
} from "./JMX";
|
||||||
|
|
||||||
export const generateId = function () {
|
export const uuid = function () {
|
||||||
return Math.floor(Math.random() * 10000);
|
let d = new Date().getTime()
|
||||||
};
|
let d2 = (performance && performance.now && (performance.now() * 1000)) || 0;
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
let r = Math.random() * 16;
|
||||||
|
if (d > 0) {
|
||||||
|
r = (d + r) % 16 | 0;
|
||||||
|
d = Math.floor(d / 16);
|
||||||
|
} else {
|
||||||
|
r = (d2 + r) % 16 | 0;
|
||||||
|
d2 = Math.floor(d2 / 16);
|
||||||
|
}
|
||||||
|
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const BODY_TYPE = {
|
export const BODY_TYPE = {
|
||||||
KV: "KeyValue",
|
KV: "KeyValue",
|
||||||
|
@ -75,7 +89,7 @@ export class Test extends BaseConfig {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
this.version = '1.0.0';
|
this.version = '1.0.0';
|
||||||
this.id = null;
|
this.id = uuid();
|
||||||
this.name = null;
|
this.name = null;
|
||||||
this.projectId = null;
|
this.projectId = null;
|
||||||
this.scenarioDefinition = [];
|
this.scenarioDefinition = [];
|
||||||
|
@ -101,7 +115,7 @@ export class Test extends BaseConfig {
|
||||||
export class Scenario extends BaseConfig {
|
export class Scenario extends BaseConfig {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
this.id = generateId();
|
this.id = uuid();
|
||||||
this.name = null;
|
this.name = null;
|
||||||
this.url = null;
|
this.url = null;
|
||||||
this.parameters = [];
|
this.parameters = [];
|
||||||
|
@ -122,7 +136,7 @@ export class Scenario extends BaseConfig {
|
||||||
export class Request extends BaseConfig {
|
export class Request extends BaseConfig {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
this.id = generateId();
|
this.id = uuid();
|
||||||
this.name = null;
|
this.name = null;
|
||||||
this.url = null;
|
this.url = null;
|
||||||
this.method = null;
|
this.method = null;
|
||||||
|
@ -144,6 +158,10 @@ export class Request extends BaseConfig {
|
||||||
options.assertions = new Assertions(options.assertions);
|
options.assertions = new Assertions(options.assertions);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return !!this.url && !!this.method
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Body extends BaseConfig {
|
export class Body extends BaseConfig {
|
||||||
|
@ -304,14 +322,23 @@ class JMeterTestPlan extends Element {
|
||||||
|
|
||||||
class JMXGenerator {
|
class JMXGenerator {
|
||||||
constructor(test) {
|
constructor(test) {
|
||||||
if (!test || !test.id || !(test instanceof Test)) return;
|
if (!test || !(test instanceof Test)) return null;
|
||||||
|
|
||||||
|
if (!test.id) {
|
||||||
|
test.id = "#NULL_TEST_ID#";
|
||||||
|
}
|
||||||
|
const SPLIT = "@@:";
|
||||||
|
|
||||||
let testPlan = new TestPlan(test.name);
|
let testPlan = new TestPlan(test.name);
|
||||||
test.scenarioDefinition.forEach(scenario => {
|
test.scenarioDefinition.forEach(scenario => {
|
||||||
let threadGroup = new ThreadGroup(scenario.name);
|
let threadGroup = new ThreadGroup(scenario.name + SPLIT + scenario.id);
|
||||||
|
|
||||||
scenario.requests.forEach(request => {
|
scenario.requests.forEach(request => {
|
||||||
let httpSamplerProxy = new HTTPSamplerProxy(request.name, new JMXRequest(request));
|
if (!request.isValid()) return;
|
||||||
|
|
||||||
|
// test.id用于处理结果时区分属于哪个测试
|
||||||
|
let name = request.name + SPLIT + test.id;
|
||||||
|
let httpSamplerProxy = new HTTPSamplerProxy(name, new JMXRequest(request));
|
||||||
|
|
||||||
this.addRequestHeader(httpSamplerProxy, request);
|
this.addRequestHeader(httpSamplerProxy, request);
|
||||||
|
|
||||||
|
@ -326,8 +353,15 @@ class JMXGenerator {
|
||||||
threadGroup.put(httpSamplerProxy);
|
threadGroup.put(httpSamplerProxy);
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addBackendListener(threadGroup, test.id);
|
this.addBackendListener(threadGroup);
|
||||||
testPlan.put(threadGroup);
|
testPlan.put(threadGroup);
|
||||||
|
|
||||||
|
// 暂时不加
|
||||||
|
// let tearDownThreadGroup = new PostThreadGroup();
|
||||||
|
// tearDownThreadGroup.put(new DebugSampler(test.id));
|
||||||
|
// this.addBackendListener(tearDownThreadGroup);
|
||||||
|
//
|
||||||
|
// testPlan.put(tearDownThreadGroup);
|
||||||
})
|
})
|
||||||
|
|
||||||
this.jmeterTestPlan = new JMeterTestPlan();
|
this.jmeterTestPlan = new JMeterTestPlan();
|
||||||
|
@ -338,14 +372,14 @@ class JMXGenerator {
|
||||||
let name = request.name + " Headers";
|
let name = request.name + " Headers";
|
||||||
let headers = request.headers.filter(this.filter);
|
let headers = request.headers.filter(this.filter);
|
||||||
if (headers.length > 0) {
|
if (headers.length > 0) {
|
||||||
httpSamplerProxy.putRequestHeader(new HeaderManager(name, headers));
|
httpSamplerProxy.put(new HeaderManager(name, headers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addRequestArguments(httpSamplerProxy, request) {
|
addRequestArguments(httpSamplerProxy, request) {
|
||||||
let args = request.parameters.filter(this.filter)
|
let args = request.parameters.filter(this.filter)
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
httpSamplerProxy.addRequestArguments(new HTTPSamplerArguments(args));
|
httpSamplerProxy.add(new HTTPSamplerArguments(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,19 +391,20 @@ class JMXGenerator {
|
||||||
body.push({name: '', value: request.body.raw});
|
body.push({name: '', value: request.body.raw});
|
||||||
}
|
}
|
||||||
|
|
||||||
httpSamplerProxy.addRequestBody(new HTTPSamplerArguments(body));
|
httpSamplerProxy.boolProp('HTTPSampler.postBodyRaw', true);
|
||||||
|
httpSamplerProxy.add(new HTTPSamplerArguments(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
addRequestAssertion(httpSamplerProxy, request) {
|
addRequestAssertion(httpSamplerProxy, request) {
|
||||||
let assertions = request.assertions;
|
let assertions = request.assertions;
|
||||||
if (assertions.regex.length > 0) {
|
if (assertions.regex.length > 0) {
|
||||||
assertions.regex.filter(this.filter).forEach(regex => {
|
assertions.regex.filter(this.filter).forEach(regex => {
|
||||||
httpSamplerProxy.putResponseAssertion(this.getAssertion(regex));
|
httpSamplerProxy.put(this.getAssertion(regex));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assertions.duration.isValid()) {
|
if (assertions.duration.isValid()) {
|
||||||
httpSamplerProxy.putDurationAssertion(assertions.duration.type, assertions.duration.value);
|
httpSamplerProxy.put(assertions.duration.type, assertions.duration.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,11 +422,10 @@ class JMXGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addBackendListener(threadGroup, testId) {
|
addBackendListener(threadGroup) {
|
||||||
let testName = 'API Backend Listener';
|
let testName = 'API Backend Listener';
|
||||||
let className = 'io.metersphere.api.jmeter.APIBackendListenerClient';
|
let className = 'io.metersphere.api.jmeter.APIBackendListenerClient';
|
||||||
let args = [{name: 'id', value: testId}];
|
threadGroup.put(new BackendListener(testName, className));
|
||||||
threadGroup.put(new BackendListener(testName, className, args));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filter(config) {
|
filter(config) {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ms-tag v-for="(role, index) in roles"
|
||||||
|
:key="index"
|
||||||
|
:effect="effect"
|
||||||
|
:type="type"
|
||||||
|
:content="role.name"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsTag from "./MsTag";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsRolesTag",
|
||||||
|
components: {MsTag},
|
||||||
|
props: {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'primary',
|
||||||
|
},
|
||||||
|
roles: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
effect: {
|
||||||
|
type: String,
|
||||||
|
default: 'dark',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -6,6 +6,7 @@
|
||||||
:effect="effect">
|
:effect="effect">
|
||||||
<el-button @click="exec()"
|
<el-button @click="exec()"
|
||||||
@click.stop="clickStop"
|
@click.stop="clickStop"
|
||||||
|
@keydown.enter.native.prevent
|
||||||
circle
|
circle
|
||||||
:type="type"
|
:type="type"
|
||||||
:icon="icon"
|
:icon="icon"
|
||||||
|
|
|
@ -16,7 +16,6 @@ import PersonSetting from "../../settings/personal/PersonSetting";
|
||||||
import SystemWorkspace from "../../settings/system/SystemWorkspace";
|
import SystemWorkspace from "../../settings/system/SystemWorkspace";
|
||||||
import PerformanceChart from "../../performance/report/components/PerformanceChart";
|
import PerformanceChart from "../../performance/report/components/PerformanceChart";
|
||||||
import PerformanceTestReport from "../../performance/report/PerformanceTestReport";
|
import PerformanceTestReport from "../../performance/report/PerformanceTestReport";
|
||||||
import ApiTestReport from "../../api/report/ApiTestReport";
|
|
||||||
import ApiTest from "../../api/ApiTest";
|
import ApiTest from "../../api/ApiTest";
|
||||||
import PerformanceTest from "../../performance/PerformanceTest";
|
import PerformanceTest from "../../performance/PerformanceTest";
|
||||||
import ApiTestConfig from "../../api/test/ApiTestConfig";
|
import ApiTestConfig from "../../api/test/ApiTestConfig";
|
||||||
|
@ -30,6 +29,7 @@ import TestPlan from "../../track/plan/TestPlan";
|
||||||
import TestPlanView from "../../track/plan/view/TestPlanView";
|
import TestPlanView from "../../track/plan/view/TestPlanView";
|
||||||
import TestCase from "../../track/case/TestCase";
|
import TestCase from "../../track/case/TestCase";
|
||||||
import TestTrack from "../../track/TestTrack";
|
import TestTrack from "../../track/TestTrack";
|
||||||
|
import ApiReportList from "../../api/report/ApiReportList";
|
||||||
|
|
||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
|
|
||||||
|
@ -117,13 +117,13 @@ const router = new VueRouter({
|
||||||
component: MsProject
|
component: MsProject
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "report/:type",
|
path: "report/list/:testId",
|
||||||
name: "fucReport",
|
name: "ApiReportList",
|
||||||
component: ApiTestReport
|
component: ApiReportList
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "report/view/:reportId",
|
path: "report/view/:reportId",
|
||||||
name: "fucReportView",
|
name: "ApiReportView",
|
||||||
component: ApiReportView
|
component: ApiReportView
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -136,10 +136,10 @@
|
||||||
},
|
},
|
||||||
handleEdit(report) {
|
handleEdit(report) {
|
||||||
if (report.status === "Error") {
|
if (report.status === "Error") {
|
||||||
this.$warning("报告生成错误,无法查看!");
|
this.$warning(this.$t('report.generation_error'));
|
||||||
return false
|
return false
|
||||||
} else if (report.status === "Starting") {
|
} else if (report.status === "Starting") {
|
||||||
this.$info("报告生成中...")
|
this.$info(this.$t('being_generated'))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
|
@ -172,10 +172,4 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-page {
|
|
||||||
padding-top: 20px;
|
|
||||||
margin-right: -9px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;" @click="submit('form')" size="medium">
|
<el-button type="primary" @keydown.enter.native.prevent @click="submit('form')" size="medium">
|
||||||
{{$t('commons.save')}}
|
{{$t('commons.save')}}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="menus">
|
<div class="menus">
|
||||||
<ms-current-user/>
|
<ms-current-user/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<h1>设置</h1>
|
<h1>{{$t('commons.setting')}}</h1>
|
||||||
<ms-setting-menu/>
|
<ms-setting-menu/>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
|
@ -11,17 +11,12 @@
|
||||||
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
||||||
<el-table-column prop="roles" :label="$t('commons.role')" width="140">
|
<el-table-column prop="roles" :label="$t('commons.role')" width="140">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag v-for="(role, index) in scope.row.roles" :key="index" size="mini" effect="dark">
|
<ms-roles-tag :roles="scope.row.roles"/>
|
||||||
{{ role.name }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit" size="mini"
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
circle/>
|
|
||||||
<el-button @click="del(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete" size="mini"
|
|
||||||
circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -58,8 +53,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="submitForm('form')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="submitForm('form')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -92,8 +88,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateOrgMember('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateOrgMember('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -105,10 +102,12 @@
|
||||||
import {TokenKey} from "../../../../common/js/constants";
|
import {TokenKey} from "../../../../common/js/constants";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsOrganizationMember",
|
name: "MsOrganizationMember",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsRolesTag, MsTableOperator},
|
||||||
created() {
|
created() {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,10 +16,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit" size="mini"
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
circle/>
|
|
||||||
<el-button @click="del(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete" size="mini"
|
|
||||||
circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -38,8 +35,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="submit('form')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="submit('form')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -55,26 +53,23 @@
|
||||||
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
||||||
<el-table-column :label="$t('commons.role')" width="120">
|
<el-table-column :label="$t('commons.role')" width="120">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag v-for="(role, index) in scope.row.roles" :key="index" size="mini" effect="dark" type="success">
|
<ms-roles-tag :roles="scope.row.roles" type="success"/>
|
||||||
{{ role.name }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')">
|
<el-table-column :label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="editMember(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit"
|
<ms-table-operator @editClick="editMember(scope.row)" @deleteClick="delMember(scope.row)"/>
|
||||||
size="mini" circle/>
|
|
||||||
<el-button @click="delMember(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete"
|
|
||||||
size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<ms-table-pagination :change="dialogSearch" :current-page.sync="dialogCurrentPage" :page-size.sync="dialogPageSize"
|
<ms-table-pagination :change="dialogSearch" :current-page.sync="dialogCurrentPage"
|
||||||
|
:page-size.sync="dialogPageSize"
|
||||||
:total="dialogTotal"/>
|
:total="dialogTotal"/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- add workspace member dialog -->
|
<!-- add workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%" :destroy-on-close="true"
|
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%"
|
||||||
|
:destroy-on-close="true"
|
||||||
@close="closeFunc">
|
@close="closeFunc">
|
||||||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
||||||
size="small">
|
size="small">
|
||||||
|
@ -105,14 +100,16 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="submitForm('form')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="submitForm('form')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- update workspace member dialog -->
|
<!-- update workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%" :destroy-on-close="true"
|
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%"
|
||||||
|
:destroy-on-close="true"
|
||||||
@close="closeFunc">
|
@close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
|
@ -141,8 +138,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateOrgMember('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateOrgMember('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -156,10 +154,12 @@
|
||||||
import {TokenKey} from "../../../../common/js/constants";
|
import {TokenKey} from "../../../../common/js/constants";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsOrganizationWorkspace",
|
name: "MsOrganizationWorkspace",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsRolesTag, MsTableOperator},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.list();
|
this.list();
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,8 +27,10 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-dialog :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%"
|
||||||
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" ref="updateUserForm">
|
:destroy-on-close="true" @close="closeFunc">
|
||||||
|
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
|
||||||
|
ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -44,8 +46,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateUser('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateUser('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -68,7 +71,7 @@
|
||||||
rule: {
|
rule: {
|
||||||
name: [
|
name: [
|
||||||
{required: true, message: this.$t('member.input_name'), trigger: 'blur'},
|
{required: true, message: this.$t('member.input_name'), trigger: 'blur'},
|
||||||
{ min: 2, max: 10, message: this.$t('commons.input_limit', [2, 10]), trigger: 'blur' },
|
{min: 2, max: 10, message: this.$t('commons.input_limit', [2, 10]), trigger: 'blur'},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9.·-]+$/,
|
pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9.·-]+$/,
|
||||||
|
@ -85,7 +88,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
email: [
|
email: [
|
||||||
{ required: true, message: this.$t('member.input_email'), trigger: 'blur' },
|
{required: true, message: this.$t('member.input_email'), trigger: 'blur'},
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
pattern: /^([A-Za-z0-9_\-.])+@([A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/,
|
pattern: /^([A-Za-z0-9_\-.])+@([A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/,
|
||||||
|
@ -112,7 +115,7 @@
|
||||||
updateUser(updateUserForm) {
|
updateUser(updateUserForm) {
|
||||||
this.$refs[updateUserForm].validate(valide => {
|
this.$refs[updateUserForm].validate(valide => {
|
||||||
if (valide) {
|
if (valide) {
|
||||||
this.result = this.$post(this.updatePath, this.form,response => {
|
this.result = this.$post(this.updatePath, this.form, response => {
|
||||||
this.$success(this.$t('commons.modify_success'));
|
this.$success(this.$t('commons.modify_success'));
|
||||||
localStorage.setItem(TokenKey, JSON.stringify(response.data));
|
localStorage.setItem(TokenKey, JSON.stringify(response.data));
|
||||||
this.updateVisible = false;
|
this.updateVisible = false;
|
||||||
|
|
|
@ -19,10 +19,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')">
|
<el-table-column :label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit" size="mini"
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
circle/>
|
|
||||||
<el-button @click="del(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete" size="mini"
|
|
||||||
circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -41,17 +38,12 @@
|
||||||
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
||||||
<el-table-column :label="$t('commons.role')" width="140">
|
<el-table-column :label="$t('commons.role')" width="140">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag v-for="(role, index) in scope.row.roles" :key="index" size="mini" effect="dark">
|
<ms-roles-tag :roles="scope.row.roles"/>
|
||||||
{{ role.name }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')">
|
<el-table-column :label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="editMember(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit"
|
<ms-table-operator @editClick="editMember(scope.row)" @deleteClick="delMember(scope.row)"/>
|
||||||
size="mini" circle/>
|
|
||||||
<el-button @click="delMember(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete"
|
|
||||||
size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -74,8 +66,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="createOrganization('createOrganization')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="createOrganization('createOrganization')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -95,9 +88,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateOrganization('updateOrganizationForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateOrganization('updateOrganizationForm')"
|
size="medium">{{$t('organization.modify')}}
|
||||||
size="medium">{{$t('organization.modify')}}</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -135,8 +128,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="submitForm('form')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="submitForm('form')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -172,8 +166,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateOrgMember('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateOrgMember('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -185,10 +180,12 @@
|
||||||
import MsCreateBox from "../CreateBox";
|
import MsCreateBox from "../CreateBox";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsOrganization",
|
name: "MsOrganization",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsRolesTag, MsTableOperator},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
queryPath: '/organization/list',
|
queryPath: '/organization/list',
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
<el-button @click="del(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -50,7 +49,7 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;" @click="submit('form')" size="medium">{{$t('commons.save')}}</el-button>
|
<el-button type="primary" @keydown.enter.native.prevent @click="submit('form')" size="medium">{{$t('commons.save')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -78,7 +77,7 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" @click="updateWorkspace('updateForm')" onkeydown="return false;"
|
<el-button type="primary" @click="updateWorkspace('updateForm')" @keydown.enter.native.prevent
|
||||||
size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -96,17 +95,12 @@
|
||||||
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
||||||
<el-table-column :label="$t('commons.role')" width="120">
|
<el-table-column :label="$t('commons.role')" width="120">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag v-for="(role, index) in scope.row.roles" :key="index" size="mini" effect="dark" type="success">
|
<ms-roles-tag :roles="scope.row.roles" type="success"/>
|
||||||
{{ role.name }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')">
|
<el-table-column :label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="editMember(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit"
|
<ms-table-operator @editClick="editMember(scope.row)" @deleteClick="delMember(scope.row)"/>
|
||||||
size="mini" circle/>
|
|
||||||
<el-button @click="delMember(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete"
|
|
||||||
size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -116,7 +110,8 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- add workspace member dialog -->
|
<!-- add workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%" :destroy-on-close="true"
|
<el-dialog :title="$t('member.create')" :visible.sync="dialogWsMemberAddVisible" width="30%"
|
||||||
|
:destroy-on-close="true"
|
||||||
@close="closeFunc">
|
@close="closeFunc">
|
||||||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
||||||
size="small">
|
size="small">
|
||||||
|
@ -147,13 +142,16 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;" @click="submitForm('form')" size="medium">{{$t('commons.save')}}</el-button>
|
<el-button type="primary" @keydown.enter.native.prevent @click="submitForm('form')" size="medium">
|
||||||
|
{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- update workspace member dialog -->
|
<!-- update workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%" :destroy-on-close="true"
|
<el-dialog :title="$t('member.modify')" :visible.sync="dialogWsMemberUpdateVisible" width="30%"
|
||||||
|
:destroy-on-close="true"
|
||||||
@close="closeFunc">
|
@close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
|
@ -182,8 +180,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" @click="updateOrgMember('updateUserForm')" onkeydown="return false;"
|
<el-button type="primary" @click="updateOrgMember('updateUserForm')" @keydown.enter.native.prevent
|
||||||
size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -197,10 +196,12 @@
|
||||||
import {Message} from "element-ui";
|
import {Message} from "element-ui";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsSystemWorkspace",
|
name: "MsSystemWorkspace",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsRolesTag, MsTableOperator},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.list();
|
this.list();
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,8 +38,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
<el-button @click="del(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -122,9 +121,10 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="createTestResourcePool('createTestResourcePoolForm')" @keydown.enter.native.prevent
|
||||||
@click="createTestResourcePool('createTestResourcePoolForm')"
|
type="primary"
|
||||||
size="medium">{{$t('commons.create')}}</el-button>
|
size="medium">{{$t('commons.create')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -202,9 +202,10 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateTestResourcePool('updateTestResourcePoolForm')" @keydown.enter.native.prevent
|
||||||
@click="updateTestResourcePool('updateTestResourcePoolForm')"
|
type="primary"
|
||||||
size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -216,10 +217,11 @@
|
||||||
import MsCreateBox from "../CreateBox";
|
import MsCreateBox from "../CreateBox";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsTestResourcePool",
|
name: "MsTestResourcePool",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsTableOperator},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
|
@ -413,8 +415,12 @@
|
||||||
this.form = {};
|
this.form = {};
|
||||||
},
|
},
|
||||||
changeSwitch(row) {
|
changeSwitch(row) {
|
||||||
this.result = this.$post('/testresourcepool/update', row).then(() => {
|
this.result = this.$get('/testresourcepool/update/' + row.id + '/' + row.status)
|
||||||
|
.then(() => {
|
||||||
this.$success(this.$t('test_resource_pool.status_change_success'));
|
this.$success(this.$t('test_resource_pool.status_change_success'));
|
||||||
|
}).catch(() => {
|
||||||
|
this.$error(this.$t('test_resource_pool.status_change_failed'));
|
||||||
|
row.status = 'INVALID';
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.operating')">
|
<el-table-column :label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)"/>
|
||||||
<el-button @click="del(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -59,8 +58,8 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="createUser('createUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="createUser('createUserForm')" size="medium">创建</el-button>
|
size="medium">{{$t('commons.save')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -83,8 +82,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateUser('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateUser('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -96,10 +96,11 @@
|
||||||
import MsCreateBox from "../CreateBox";
|
import MsCreateBox from "../CreateBox";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsUser",
|
name: "MsUser",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsTableOperator},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
queryPath: '/user/special/list',
|
queryPath: '/user/special/list',
|
||||||
|
|
|
@ -9,19 +9,14 @@
|
||||||
<el-table-column prop="name" :label="$t('commons.username')"/>
|
<el-table-column prop="name" :label="$t('commons.username')"/>
|
||||||
<el-table-column prop="email" :label="$t('commons.email')"/>
|
<el-table-column prop="email" :label="$t('commons.email')"/>
|
||||||
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
<el-table-column prop="phone" :label="$t('commons.phone')"/>
|
||||||
<el-table-column prop="roles" label="角色" width="120">
|
<el-table-column prop="roles" :label="$t('commons.role')" width="120">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag v-for="(role, index) in scope.row.roles" :key="index" size="mini" effect="dark" type="success">
|
<ms-roles-tag :roles="scope.row.roles" type="success"/>
|
||||||
{{ role.name }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="edit(scope.row)" onkeydown="return false;" type="primary" icon="el-icon-edit" size="mini"
|
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)" v-permission="['test_manager']"/>
|
||||||
circle v-permission="['test_manager']"/>
|
|
||||||
<el-button @click="del(scope.row)" onkeydown="return false;" type="danger" icon="el-icon-delete" size="mini"
|
|
||||||
circle v-permission="['test_manager']"/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -29,9 +24,10 @@
|
||||||
:total="total"/>
|
:total="total"/>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-dialog title="添加成员" :visible.sync="createVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="createVisible" width="30%" :destroy-on-close="true"
|
||||||
|
@close="closeFunc">
|
||||||
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
|
<el-form :model="form" ref="form" :rules="rules" label-position="right" label-width="100px" size="small">
|
||||||
<el-form-item label="成员" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
<el-select v-model="form.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||||
class="select-width">
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
|
@ -44,7 +40,7 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色" prop="roleIds">
|
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||||
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in form.roles"
|
v-for="item in form.roles"
|
||||||
|
@ -57,13 +53,15 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="submitForm('form')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="submitForm('form')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog title="修改成员" :visible.sync="updateVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateVisible" width="30%" :destroy-on-close="true"
|
||||||
|
@close="closeFunc">
|
||||||
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="form" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
|
||||||
|
@ -77,7 +75,7 @@
|
||||||
<el-form-item :label="$t('commons.phone')" prop="phone">
|
<el-form-item :label="$t('commons.phone')" prop="phone">
|
||||||
<el-input v-model="form.phone" autocomplete="off"/>
|
<el-input v-model="form.phone" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色" prop="roleIds">
|
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||||
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in form.allroles"
|
v-for="item in form.allroles"
|
||||||
|
@ -90,8 +88,9 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" onkeydown="return false;"
|
<el-button @click="updateWorkspaceMember('updateUserForm')" @keydown.enter.native.prevent type="primary"
|
||||||
@click="updateWorkspaceMember('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
size="medium">{{$t('commons.save')}}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -104,10 +103,12 @@
|
||||||
import {TokenKey} from "../../../../common/js/constants";
|
import {TokenKey} from "../../../../common/js/constants";
|
||||||
import MsTablePagination from "../../common/pagination/TablePagination";
|
import MsTablePagination from "../../common/pagination/TablePagination";
|
||||||
import MsTableHeader from "../../common/components/MsTableHeader";
|
import MsTableHeader from "../../common/components/MsTableHeader";
|
||||||
|
import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
|
import MsTableOperator from "../../common/components/MsTableOperator";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsMember",
|
name: "MsMember",
|
||||||
components: {MsCreateBox, MsTablePagination, MsTableHeader},
|
components: {MsCreateBox, MsTablePagination, MsTableHeader, MsRolesTag, MsTableOperator},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
result: {},
|
result: {},
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<el-dialog :title="$t('test_track.plan_view.change_executor')"
|
<el-dialog :title="$t('test_track.case.move')"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
:before-close="close"
|
:before-close="close"
|
||||||
width="20%">
|
width="20%">
|
||||||
|
|
||||||
<el-select v-model.trim="module"
|
<el-select v-model.trim="module"
|
||||||
:placeholder="$t('test_track.plan_view.select_executor')"
|
:placeholder="$t('test_track.case.move')"
|
||||||
filterable>
|
filterable>
|
||||||
<el-option v-for="item in moduleOptions" :key="item.id"
|
<el-option v-for="item in moduleOptions" :key="item.id"
|
||||||
:label="item.path" :value="item.id"></el-option>
|
:label="item.path" :value="item.id"></el-option>
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default {
|
||||||
commons: {
|
commons: {
|
||||||
'workspace': 'Workspace',
|
'workspace': 'Workspace',
|
||||||
'organization': 'Organization',
|
'organization': 'Organization',
|
||||||
|
'setting': 'Setting',
|
||||||
'project': 'Project',
|
'project': 'Project',
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'description': 'Description',
|
'description': 'Description',
|
||||||
|
@ -314,6 +315,7 @@ export default {
|
||||||
'fill_the_data': 'Please complete the data',
|
'fill_the_data': 'Please complete the data',
|
||||||
'delete_prompt': 'This operation will permanently delete the resource pool, continue?',
|
'delete_prompt': 'This operation will permanently delete the resource pool, continue?',
|
||||||
'status_change_success': 'Successfully changed the status!',
|
'status_change_success': 'Successfully changed the status!',
|
||||||
|
'status_change_failed': 'Failed to change the status!',
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
'home': 'Home'
|
'home': 'Home'
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default {
|
||||||
commons: {
|
commons: {
|
||||||
'workspace': '工作空间',
|
'workspace': '工作空间',
|
||||||
'organization': '组织',
|
'organization': '组织',
|
||||||
|
'setting': '设置',
|
||||||
'project': '项目',
|
'project': '项目',
|
||||||
'name': '名称',
|
'name': '名称',
|
||||||
'description': '描述',
|
'description': '描述',
|
||||||
|
@ -186,6 +187,7 @@ export default {
|
||||||
},
|
},
|
||||||
api_test: {
|
api_test: {
|
||||||
save_and_run: "保存并执行",
|
save_and_run: "保存并执行",
|
||||||
|
running: "正在执行",
|
||||||
reset: "重置",
|
reset: "重置",
|
||||||
input_name: "请输入测试名称",
|
input_name: "请输入测试名称",
|
||||||
select_project: "请选择项目",
|
select_project: "请选择项目",
|
||||||
|
@ -359,6 +361,7 @@ export default {
|
||||||
'fill_the_data': '请完善数据',
|
'fill_the_data': '请完善数据',
|
||||||
'delete_prompt': '此操作将永久删除该资源池, 是否继续?',
|
'delete_prompt': '此操作将永久删除该资源池, 是否继续?',
|
||||||
'status_change_success': '状态修改成功!',
|
'status_change_success': '状态修改成功!',
|
||||||
|
'status_change_failed': '状态修改失败!',
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
'home': '首页'
|
'home': '首页'
|
||||||
|
|
Loading…
Reference in New Issue