Merge branch 'dev' of github.com:metersphere/metersphere into dev
This commit is contained in:
commit
5f1ed2611b
|
@ -1,8 +1,12 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QueryAPIReportRequest {
|
||||
|
@ -12,5 +16,6 @@ public class QueryAPIReportRequest {
|
|||
private String name;
|
||||
private String workspaceId;
|
||||
private boolean recent = false;
|
||||
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QueryAPITestRequest {
|
||||
|
@ -12,5 +16,7 @@ public class QueryAPITestRequest {
|
|||
private String name;
|
||||
private String workspaceId;
|
||||
private boolean recent = false;
|
||||
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ import io.metersphere.base.mapper.ApiTestReportMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtApiTestReportMapper;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.dto.DashboardTestDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
@ -24,8 +26,6 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class APIReportService {
|
||||
|
@ -38,6 +38,7 @@ public class APIReportService {
|
|||
private ExtApiTestReportMapper extApiTestReportMapper;
|
||||
|
||||
public List<APIReportResult> list(QueryAPIReportRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extApiTestReportMapper.list(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.dto.APITestResult;
|
||||
import io.metersphere.api.dto.DeleteAPITestRequest;
|
||||
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
|
@ -11,6 +10,7 @@ import io.metersphere.base.mapper.ApiTestMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtApiTestMapper;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.service.FileService;
|
||||
|
@ -19,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
@ -26,8 +27,6 @@ import java.util.Objects;
|
|||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class APITestService {
|
||||
|
@ -46,6 +45,7 @@ public class APITestService {
|
|||
private APIReportService apiReportService;
|
||||
|
||||
public List<APITestResult> list(QueryAPITestRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extApiTestMapper.list(request);
|
||||
}
|
||||
|
||||
|
@ -130,10 +130,22 @@ public class APITestService {
|
|||
test.setScenarioDefinition(request.getScenarioDefinition());
|
||||
test.setUpdateTime(System.currentTimeMillis());
|
||||
test.setStatus(APITestStatus.Saved.name());
|
||||
checkApiTestExist(test);
|
||||
apiTestMapper.updateByPrimaryKeySelective(test);
|
||||
return test;
|
||||
}
|
||||
|
||||
private void checkApiTestExist(ApiTest apiTest) {
|
||||
if (apiTest.getName() != null) {
|
||||
ApiTestExample example = new ApiTestExample();
|
||||
example.createCriteria()
|
||||
.andNameEqualTo(apiTest.getName());
|
||||
if (apiTestMapper.selectByExample(example).size() > 0) {
|
||||
MSException.throwException(Translator.get("api_test_name_already_exists"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ApiTestWithBLOBs createTest(SaveAPITestRequest request) {
|
||||
ApiTestExample example = new ApiTestExample();
|
||||
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId());
|
||||
|
@ -150,10 +162,22 @@ public class APITestService {
|
|||
test.setUpdateTime(System.currentTimeMillis());
|
||||
test.setStatus(APITestStatus.Saved.name());
|
||||
test.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
||||
checkApiTestPlanExist(test);
|
||||
apiTestMapper.insert(test);
|
||||
return test;
|
||||
}
|
||||
|
||||
private void checkApiTestPlanExist(ApiTest apiTest) {
|
||||
if (apiTest.getName() != null) {
|
||||
ApiTestExample example = new ApiTestExample();
|
||||
example.createCriteria()
|
||||
.andNameEqualTo(apiTest.getName());
|
||||
if (apiTestMapper.selectByExample(example).size() > 0) {
|
||||
MSException.throwException(Translator.get("api_test_name_already_exists"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveFile(String testId, List<MultipartFile> files) {
|
||||
files.forEach(file -> {
|
||||
final FileMetadata fileMetadata = fileService.saveFile(file);
|
||||
|
|
|
@ -26,8 +26,23 @@
|
|||
<if test="request.id != null">
|
||||
AND api_test.id = #{request.id}
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
and api_test.${key} in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
order by api_test.update_time desc
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
api_test.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
<select id="countByProjectId" resultType="java.lang.Long">
|
||||
select count(id) from api_test
|
||||
|
|
|
@ -26,8 +26,23 @@
|
|||
<if test="request.workspaceId != null">
|
||||
AND project.workspace_id = #{request.workspaceId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
and r.${key} in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY r.update_time DESC
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
r.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="listByTestId" resultMap="BaseResultMap">
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
<if test="request.id != null">
|
||||
AND load_test.id = #{request.id}
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
and load_test.${key} in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
|
|
|
@ -17,4 +17,6 @@ public interface ExtLoadTestReportMapper {
|
|||
LoadTestReport selectByPrimaryKey(String id);
|
||||
|
||||
List<DashboardTestDTO> selectDashboardTests(@Param("workspaceId") String workspaceId, @Param("startTimestamp") long startTimestamp);
|
||||
|
||||
List<String> selectResourceId(@Param("reportId") String reportId);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,23 @@
|
|||
<if test="reportRequest.workspaceId != null">
|
||||
AND workspace_id = #{reportRequest.workspaceId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="reportRequest.filters != null and reportRequest.filters.size() > 0">
|
||||
<foreach collection="reportRequest.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
and ltr.${key} in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY ltr.update_time DESC
|
||||
<if test="reportRequest.orders != null and reportRequest.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="reportRequest.orders" separator="," item="order">
|
||||
ltr.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getReportTestAndProInfo" resultType="io.metersphere.dto.ReportDTO">
|
||||
|
@ -62,4 +77,11 @@
|
|||
GROUP BY x
|
||||
</select>
|
||||
|
||||
<select id="selectResourceId" resultType="string">
|
||||
SELECT resource_id
|
||||
FROM load_test_report_log
|
||||
WHERE report_id = #{reportId}
|
||||
GROUP BY resource_id
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -15,7 +15,12 @@
|
|||
and w.id = #{proRequest.workspaceId}
|
||||
</if>
|
||||
</where>
|
||||
order by p.update_time desc
|
||||
<if test="proRequest.orders != null and proRequest.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="proRequest.orders" separator="," item="order">
|
||||
p.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
<select id="getProjectIdByWorkspaceId" resultType="java.lang.String">
|
||||
select id
|
||||
|
|
|
@ -3,9 +3,12 @@ package io.metersphere.controller.request;
|
|||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ProjectRequest {
|
||||
private String workspaceId;
|
||||
private String name;
|
||||
private List<OrderRequest> orders;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.metersphere.performance.controller;
|
|||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.LoadTestReport;
|
||||
import io.metersphere.base.domain.LoadTestReportLog;
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
|
@ -19,9 +20,10 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "performance/report")
|
||||
public class PerformanceReportController {
|
||||
|
@ -99,9 +101,15 @@ public class PerformanceReportController {
|
|||
return reportService.getLoadTestReport(reportId);
|
||||
}
|
||||
|
||||
@GetMapping("log/{reportId}")
|
||||
public List<LogDetailDTO> logs(@PathVariable String reportId) {
|
||||
return reportService.logs(reportId);
|
||||
@GetMapping("log/resource/{reportId}")
|
||||
public List<LogDetailDTO> getResourceIds(@PathVariable String reportId) {
|
||||
return reportService.getReportLogResource(reportId);
|
||||
}
|
||||
|
||||
@GetMapping("log/{reportId}/{resourceId}/{goPage}")
|
||||
public Pager<List<LoadTestReportLog>> logs(@PathVariable String reportId, @PathVariable String resourceId, @PathVariable int goPage) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, 10, true);
|
||||
return PageUtils.setPageInfo(page, reportService.getReportLogs(reportId, resourceId));
|
||||
}
|
||||
|
||||
@GetMapping("log/download/{reportId}/{resourceId}")
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package io.metersphere.performance.controller.request;
|
||||
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ReportRequest {
|
||||
private String name;
|
||||
private String workspaceId;
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ public class EngineFactory {
|
|||
public static Engine createEngine(LoadTestWithBLOBs loadTest) {
|
||||
String resourcePoolId = loadTest.getTestResourcePoolId();
|
||||
if (StringUtils.isBlank(resourcePoolId)) {
|
||||
MSException.throwException("Resource Pool ID is empty.");
|
||||
MSException.throwException(Translator.get("test_resource_pool_id_is_null"));
|
||||
}
|
||||
|
||||
TestResourcePool resourcePool = testResourcePoolService.getResourcePool(resourcePoolId);
|
||||
if (resourcePool == null) {
|
||||
MSException.throwException("Resource Pool is empty.");
|
||||
MSException.throwException(Translator.get("test_resource_pool_id_is_null"));
|
||||
}
|
||||
|
||||
final ResourcePoolTypeEnum type = ResourcePoolTypeEnum.valueOf(resourcePool.getType());
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.performance.service;
|
||||
|
||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
||||
|
@ -10,7 +9,9 @@ import io.metersphere.commons.constants.APITestStatus;
|
|||
import io.metersphere.commons.constants.PerformanceTestStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.dto.DashboardTestDTO;
|
||||
import io.metersphere.dto.LoadTestDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
|
@ -29,10 +30,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
import javax.annotation.Resource;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -66,6 +64,7 @@ public class PerformanceTestService {
|
|||
private ReportService reportService;
|
||||
|
||||
public List<LoadTestDTO> list(QueryTestPlanRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extLoadTestMapper.list(request);
|
||||
}
|
||||
|
||||
|
@ -250,6 +249,12 @@ public class PerformanceTestService {
|
|||
|
||||
public List<LoadTestDTO> recentTestPlans(QueryTestPlanRequest request) {
|
||||
// 查询最近的测试计划
|
||||
List<OrderRequest> orders = new ArrayList<>();
|
||||
OrderRequest orderRequest = new OrderRequest();
|
||||
orderRequest.setName("update_time");
|
||||
orderRequest.setType("desc");
|
||||
orders.add(orderRequest);
|
||||
request.setOrders(orders);
|
||||
return extLoadTestMapper.list(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import io.metersphere.commons.constants.PerformanceTestStatus;
|
|||
import io.metersphere.commons.constants.ReportKeys;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.dto.LogDetailDTO;
|
||||
import io.metersphere.dto.ReportDTO;
|
||||
import io.metersphere.performance.base.*;
|
||||
|
@ -23,11 +25,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -47,10 +48,17 @@ public class ReportService {
|
|||
private TestResourceService testResourceService;
|
||||
|
||||
public List<ReportDTO> getRecentReportList(ReportRequest request) {
|
||||
List<OrderRequest> orders = new ArrayList<>();
|
||||
OrderRequest orderRequest = new OrderRequest();
|
||||
orderRequest.setName("update_time");
|
||||
orderRequest.setType("desc");
|
||||
orders.add(orderRequest);
|
||||
request.setOrders(orders);
|
||||
return extLoadTestReportMapper.getReportList(request);
|
||||
}
|
||||
|
||||
public List<ReportDTO> getReportList(ReportRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extLoadTestReportMapper.getReportList(request);
|
||||
}
|
||||
|
||||
|
@ -159,21 +167,13 @@ public class ReportService {
|
|||
return extLoadTestReportMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public List<LogDetailDTO> logs(String reportId) {
|
||||
LoadTestReportLogExample example = new LoadTestReportLogExample();
|
||||
example.createCriteria().andReportIdEqualTo(reportId);
|
||||
example.setOrderByClause("part");
|
||||
List<LoadTestReportLog> loadTestReportLogs = loadTestReportLogMapper.selectByExampleWithBLOBs(example);
|
||||
Map<String, List<LoadTestReportLog>> reportLogs = loadTestReportLogs.stream().collect(Collectors.groupingBy(LoadTestReportLog::getResourceId));
|
||||
public List<LogDetailDTO> getReportLogResource(String reportId) {
|
||||
List<LogDetailDTO> result = new ArrayList<>();
|
||||
reportLogs.forEach((resourceId, resourceLogs) -> {
|
||||
List<String> resourceIds = extLoadTestReportMapper.selectResourceId(reportId);
|
||||
resourceIds.forEach(resourceId -> {
|
||||
LogDetailDTO detailDTO = new LogDetailDTO();
|
||||
TestResource testResource = testResourceService.getTestResource(resourceId);
|
||||
String content = resourceLogs.stream().map(LoadTestReportLog::getContent).reduce("", (a, b) -> a + b);
|
||||
// 显示前 2048
|
||||
content = StringUtils.substring(content, 0, 2048);
|
||||
detailDTO.setResourceId(resourceId);
|
||||
detailDTO.setContent(content);
|
||||
if (testResource == null) {
|
||||
detailDTO.setResourceName(resourceId);
|
||||
result.add(detailDTO);
|
||||
|
@ -199,6 +199,12 @@ public class ReportService {
|
|||
return result;
|
||||
}
|
||||
|
||||
public List<LoadTestReportLog> getReportLogs(String reportId, String resourceId) {
|
||||
LoadTestReportLogExample example = new LoadTestReportLogExample();
|
||||
example.createCriteria().andReportIdEqualTo(reportId).andResourceIdEqualTo(resourceId);
|
||||
example.setOrderByClause("part desc");
|
||||
return loadTestReportLogMapper.selectByExampleWithBLOBs(example);
|
||||
}
|
||||
|
||||
public byte[] downloadLog(String reportId, String resourceId) {
|
||||
LoadTestReportLogExample example = new LoadTestReportLogExample();
|
||||
|
|
|
@ -71,25 +71,17 @@ public class OrganizationService {
|
|||
MSException.throwException(Translator.get("organization_name_is_null"));
|
||||
}
|
||||
|
||||
String id = organization.getId();
|
||||
String name = organization.getName();
|
||||
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
Organization org = organizationMapper.selectByPrimaryKey(id);
|
||||
if (!StringUtils.equals(org.getName(), name)) {
|
||||
checkOrgNameRepeat(name);
|
||||
}
|
||||
} else {
|
||||
checkOrgNameRepeat(name);
|
||||
OrganizationExample example = new OrganizationExample();
|
||||
OrganizationExample.Criteria criteria = example.createCriteria();
|
||||
criteria.andNameEqualTo(organization.getName());
|
||||
if (StringUtils.isNotBlank(organization.getId())) {
|
||||
criteria.andIdNotEqualTo(organization.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void checkOrgNameRepeat(String orgName) {
|
||||
OrganizationExample organizationExample = new OrganizationExample();
|
||||
organizationExample.createCriteria().andNameEqualTo(orgName);
|
||||
if (organizationMapper.countByExample(organizationExample) > 0) {
|
||||
if (organizationMapper.countByExample(example) > 0) {
|
||||
MSException.throwException(Translator.get("organization_name_already_exists"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void deleteOrganization(String organizationId) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import io.metersphere.base.mapper.LoadTestMapper;
|
|||
import io.metersphere.base.mapper.ProjectMapper;
|
||||
import io.metersphere.base.mapper.ext.*;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.request.ProjectRequest;
|
||||
import io.metersphere.dto.ProjectDTO;
|
||||
|
@ -81,6 +82,7 @@ public class ProjectService {
|
|||
if (StringUtils.isNotBlank(request.getName())) {
|
||||
request.setName(StringUtils.wrapIfMissing(request.getName(), "%"));
|
||||
}
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
return extProjectMapper.getProjectWithWorkspace(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QueryTestPlanRequest extends TestPlanRequest {
|
||||
private String workspaceId;
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ workspace_name_already_exists=The workspace name already exists
|
|||
workspace_does_not_belong_to_user=The current workspace does not belong to the current user
|
||||
workspace_not_exists=Workspace is not exists
|
||||
#test resource pool
|
||||
test_resource_pool_id_is_null=Test Resource Pool ID cannot be null
|
||||
test_resource_pool_name_is_null=Test Resource Pool name cannot be null
|
||||
test_resource_pool_name_already_exists=The test resource pool name already exists
|
||||
#project
|
||||
|
@ -94,4 +95,5 @@ options=options
|
|||
please_input_workspace_member=Please input workspace merber
|
||||
test_case_report_template_repeat=The workspace has the same name template
|
||||
plan_name_already_exists=Test plan name already exists
|
||||
test_case_already_exists_excel=There are duplicate test cases in the import file
|
||||
test_case_already_exists_excel=There are duplicate test cases in the import file
|
||||
api_test_name_already_exists=Test name already exists
|
|
@ -36,6 +36,7 @@ workspace_name_already_exists=工作空间名已存在
|
|||
workspace_does_not_belong_to_user=当前工作空间不属于当前用户
|
||||
workspace_not_exists=工作空间不存在
|
||||
#test resource pool
|
||||
test_resource_pool_id_is_null=资源池ID不能为空
|
||||
test_resource_pool_name_is_null=资源池名称不能为空
|
||||
test_resource_pool_name_already_exists=资源池名称已存在
|
||||
#project
|
||||
|
@ -95,3 +96,4 @@ please_input_workspace_member=请填写该工作空间相关人员
|
|||
test_case_report_template_repeat=同一工作空间下不能存在同名模版
|
||||
plan_name_already_exists=测试计划名称已存在
|
||||
test_case_already_exists_excel=导入文件中存在重复用例
|
||||
api_test_name_already_exists=测试名称已经存在
|
||||
|
|
|
@ -36,6 +36,7 @@ workspace_name_already_exists=工作空間名已存在
|
|||
workspace_does_not_belong_to_user=當前工作空間不屬於當前用戶
|
||||
workspace_not_exists=工作空間不存在
|
||||
#test resource pool
|
||||
test_resource_pool_id_is_null=資源池ID不能為空
|
||||
test_resource_pool_name_is_null=資源池名稱不能為空
|
||||
test_resource_pool_name_already_exists=資源池名稱已存在
|
||||
#project
|
||||
|
@ -94,4 +95,5 @@ options=選項
|
|||
please_input_workspace_member=請填寫該工作空間相關人員
|
||||
test_case_report_template_repeat=同壹工作空間下不能存在同名模版
|
||||
plan_name_already_exists=測試計劃名稱已存在
|
||||
test_case_already_exists_excel=導入文件中存在重復用例
|
||||
test_case_already_exists_excel=導入文件中存在重復用例
|
||||
api_test_name_already_exists=測試名稱已經存在
|
|
@ -2,38 +2,35 @@
|
|||
<div id="menu-bar">
|
||||
<el-row type="flex">
|
||||
<el-col :span="8">
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'
|
||||
menu-trigger="click">
|
||||
<el-menu-item :index="'/api/home'">
|
||||
{{ $t("i18n.home") }}
|
||||
</el-menu-item>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="3" popper-class="submenu">
|
||||
<el-submenu v-if="isCurrentWorkspaceUser" index="3">
|
||||
<template v-slot:title>{{$t('commons.project')}}</template>
|
||||
<ms-recent-list :options="projectRecent"/>
|
||||
<el-divider/>
|
||||
<el-divider class="menu-divider"/>
|
||||
<ms-show-all :index="'/api/project/all'"/>
|
||||
<ms-create-button v-permission="['test_manager', 'test_user']" :index="'/api/project/create'" :title="$t('project.create')"/>
|
||||
<ms-create-button v-permission="['test_manager', 'test_user']" :index="'/api/project/create'"
|
||||
:title="$t('project.create')"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="4" popper-class="submenu">
|
||||
<el-submenu v-if="isCurrentWorkspaceUser" index="4">
|
||||
<template v-slot:title>{{$t('commons.test')}}</template>
|
||||
<ms-recent-list :options="testRecent"/>
|
||||
<el-divider/>
|
||||
<el-divider class="menu-divider"/>
|
||||
<ms-show-all :index="'/api/test/list/all'"/>
|
||||
<ms-create-button v-permission="['test_manager', 'test_user']" :index="'/api/test/create'" :title="$t('load_test.create')"/>
|
||||
<!-- <el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>-->
|
||||
<!-- <el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>-->
|
||||
<ms-create-button v-permission="['test_manager', 'test_user']" :index="'/api/test/create'"
|
||||
:title="$t('load_test.create')"/>
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
index="5" popper-class="submenu">
|
||||
<el-submenu v-if="isCurrentWorkspaceUser" index="5">
|
||||
<template v-slot:title>{{$t('commons.report')}}</template>
|
||||
<ms-recent-list :options="reportRecent"/>
|
||||
<el-divider/>
|
||||
<el-divider class="menu-divider"/>
|
||||
<ms-show-all :index="'/api/report/list/all'"/>
|
||||
<!-- <el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>-->
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
|
@ -62,10 +59,6 @@
|
|||
data() {
|
||||
return {
|
||||
isCurrentWorkspaceUser: false,
|
||||
// testCaseProjectPath: '',
|
||||
// testEditPath: '',
|
||||
// reportViewPath: '',
|
||||
// isRouterAlive: true,
|
||||
projectRecent: {
|
||||
title: this.$t('project.recent'),
|
||||
url: "/project/recent/5",
|
||||
|
@ -96,55 +89,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
// watch: {
|
||||
// '$route'(to, from) {
|
||||
// let path = to.path;
|
||||
// //激活菜单栏
|
||||
// if (path.indexOf("/api/test/") >= 0) {
|
||||
// this.testCaseProjectPath = '/api/test/' + this.$route.params.projectId;
|
||||
// this.reload();
|
||||
// }
|
||||
// if (path.indexOf("/api/test/edit/") >= 0) {
|
||||
// this.testEditPath = '/api/test/edit/' + this.$route.params.testId;
|
||||
// this.reload();
|
||||
// }
|
||||
// if (path.indexOf("/api/report/view/") >= 0) {
|
||||
// this.reportViewPath = '/api/report/view/' + this.$route.params.reportId;
|
||||
// this.reload();
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
mounted() {
|
||||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||
},
|
||||
// methods: {
|
||||
// reload() {
|
||||
// this.isRouterAlive = false;
|
||||
// this.$nextTick(function () {
|
||||
// this.isRouterAlive = true;
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-divider--horizontal {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-menu.el-menu--horizontal {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#menu-bar {
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.blank_item {
|
||||
display: none;
|
||||
.menu-divider {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
<ms-main-container>
|
||||
<el-card class="table-card" v-loading="result.loading">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" :title="$t('api_report.title')"
|
||||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search"
|
||||
:title="$t('api_report.title')"
|
||||
:show-create="false"/>
|
||||
</template>
|
||||
<el-table :data="tableData" class="table-content">
|
||||
<el-table :data="tableData" class="table-content" @sort-change="sort"
|
||||
@filter-change="filter">
|
||||
<el-table-column :label="$t('commons.name')" width="200" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<el-link type="info" @click="handleView(scope.row)">{{ scope.row.name }}</el-link>
|
||||
|
@ -15,20 +17,25 @@
|
|||
<el-table-column prop="testName" :label="$t('api_report.test_name')" width="200" show-overflow-tooltip/>
|
||||
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="150" show-overflow-tooltip/>
|
||||
<el-table-column prop="userName" :label="$t('api_test.creator')" width="150" show-overflow-tooltip/>
|
||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||
<el-table-column width="250" :label="$t('commons.create_time')" sortable
|
||||
prop="createTime">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" :label="$t('commons.status')">
|
||||
<el-table-column prop="status" :label="$t('commons.status')"
|
||||
column-key="status"
|
||||
:filters="statusFilters">
|
||||
<template v-slot:default="{row}">
|
||||
<ms-api-report-status :row="row"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="150" :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<el-button :is-tester-permission="true" @click="handleView(scope.row)" type="primary" icon="el-icon-s-data" size="mini" circle/>
|
||||
<el-button :is-tester-permission="true" @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
||||
<el-button :is-tester-permission="true" @click="handleView(scope.row)" type="primary"
|
||||
icon="el-icon-s-data" size="mini" circle/>
|
||||
<el-button :is-tester-permission="true" @click="handleDelete(scope.row)" type="danger"
|
||||
icon="el-icon-delete" size="mini" circle/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -45,19 +52,28 @@
|
|||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsApiReportStatus from "./ApiReportStatus";
|
||||
import {_filter, _sort} from "../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
components: {MsApiReportStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
condition: {name: ""},
|
||||
condition: {},
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
currentPage: 1,
|
||||
pageSize: 5,
|
||||
total: 0,
|
||||
loading: false
|
||||
loading: false,
|
||||
statusFilters: [
|
||||
{text: 'Saved', value: 'Saved'},
|
||||
{text: 'Starting', value: 'Starting'},
|
||||
{text: 'Running', value: 'Running'},
|
||||
{text: 'Reporting', value: 'Reporting'},
|
||||
{text: 'Completed', value: 'Completed'},
|
||||
{text: 'Error', value: 'Error'}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -67,16 +83,14 @@
|
|||
|
||||
methods: {
|
||||
search() {
|
||||
let param = {
|
||||
name: this.condition.name,
|
||||
};
|
||||
|
||||
|
||||
if (this.testId !== 'all') {
|
||||
param.testId = this.testId;
|
||||
this.condition.testId = this.testId;
|
||||
}
|
||||
|
||||
let url = "/api/report/list/" + this.currentPage + "/" + this.pageSize
|
||||
this.result = this.$post(url, param, response => {
|
||||
this.result = this.$post(url, this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
|
@ -106,7 +120,19 @@
|
|||
init() {
|
||||
this.testId = this.$route.params.testId;
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
/* filter(value, row) {
|
||||
return row.status === value;
|
||||
},*/
|
||||
sort(column) {
|
||||
_sort(column, this.condition);
|
||||
this.init();
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.init();
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
created() {
|
||||
|
|
|
@ -85,9 +85,7 @@
|
|||
|
||||
methods: {
|
||||
init() {
|
||||
this.result = this.$get("/project/listAll", response => {
|
||||
this.projects = response.data;
|
||||
})
|
||||
let projectId;
|
||||
if (this.id) {
|
||||
this.create = false;
|
||||
this.getTest(this.id);
|
||||
|
@ -97,7 +95,14 @@
|
|||
if (this.$refs.config) {
|
||||
this.$refs.config.reset();
|
||||
}
|
||||
// 仅创建时获取选择的项目
|
||||
projectId = this.$store.state.common.projectId;
|
||||
}
|
||||
this.result = this.$get("/project/listAll", response => {
|
||||
this.projects = response.data;
|
||||
// 等待项目列表加载完
|
||||
if (projectId) this.test.projectId = projectId;
|
||||
})
|
||||
},
|
||||
getTest(id) {
|
||||
this.result = this.$get("/api/get/" + id, response => {
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
:title="$t('commons.test')"
|
||||
@create="create" :createTip="$t('load_test.create')"/>
|
||||
</template>
|
||||
<el-table :data="tableData" class="table-content">
|
||||
<el-table :data="tableData" class="table-content" @sort-change="sort"
|
||||
@filter-change="filter">
|
||||
<el-table-column :label="$t('commons.name')" width="250" show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<el-link type="info" @click="handleEdit(scope.row)">{{ scope.row.name }}</el-link>
|
||||
|
@ -15,17 +16,21 @@
|
|||
</el-table-column>
|
||||
<el-table-column prop="projectName" :label="$t('load_test.project_name')" width="200" show-overflow-tooltip/>
|
||||
<el-table-column prop="userName" :label="$t('api_test.creator')" width="150" show-overflow-tooltip/>
|
||||
<el-table-column width="250" :label="$t('commons.create_time')">
|
||||
<el-table-column width="250" :label="$t('commons.create_time')" sortable
|
||||
prop="createTime">
|
||||
<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')">
|
||||
<el-table-column width="250" :label="$t('commons.update_time')" sortable
|
||||
prop="updateTime">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" :label="$t('commons.status')">
|
||||
<el-table-column prop="status" :label="$t('commons.status')"
|
||||
column-key="status"
|
||||
:filters="statusFilters">
|
||||
<template v-slot:default="{row}">
|
||||
<ms-api-test-status :row="row"/>
|
||||
</template>
|
||||
|
@ -51,6 +56,7 @@
|
|||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsApiTestStatus from "./ApiTestStatus";
|
||||
import MsTableOperators from "../../common/components/MsTableOperators";
|
||||
import {_filter, _sort} from "../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -60,7 +66,7 @@
|
|||
data() {
|
||||
return {
|
||||
result: {},
|
||||
condition: {name: ""},
|
||||
condition: {},
|
||||
projectId: null,
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
|
@ -79,6 +85,14 @@
|
|||
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
|
||||
exec: this.handleDelete
|
||||
}
|
||||
],
|
||||
statusFilters: [
|
||||
{text: 'Saved', value: 'Saved'},
|
||||
{text: 'Starting', value: 'Starting'},
|
||||
{text: 'Running', value: 'Running'},
|
||||
{text: 'Reporting', value: 'Reporting'},
|
||||
{text: 'Completed', value: 'Completed'},
|
||||
{text: 'Error', value: 'Error'}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -92,16 +106,14 @@
|
|||
this.$router.push('/api/test/create');
|
||||
},
|
||||
search() {
|
||||
let param = {
|
||||
name: this.condition.name,
|
||||
};
|
||||
|
||||
|
||||
if (this.projectId !== 'all') {
|
||||
param.projectId = this.projectId;
|
||||
this.condition.projectId = this.projectId;
|
||||
}
|
||||
|
||||
let url = "/api/list/" + this.currentPage + "/" + this.pageSize
|
||||
this.result = this.$post(url, param, response => {
|
||||
this.result = this.$post(url, this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
|
@ -136,12 +148,27 @@
|
|||
},
|
||||
init() {
|
||||
this.projectId = this.$route.params.projectId;
|
||||
if (this.projectId && this.projectId !== "all") {
|
||||
this.$store.commit('setProjectId', this.projectId);
|
||||
}
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
/* filter(value, row) {
|
||||
return row.status === value;
|
||||
}*/
|
||||
sort(column) {
|
||||
_sort(column, this.condition);
|
||||
this.init();
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-radio-group v-model="body.type" size="mini">
|
||||
<el-radio-button :label="type.KV">
|
||||
<el-radio-button :disabled="isReadOnly" :label="type.KV">
|
||||
{{$t('api_test.request.body_kv')}}
|
||||
</el-radio-button>
|
||||
<el-radio-button :label="type.RAW">
|
||||
<el-radio-button :disabled="isReadOnly" :label="type.RAW">
|
||||
{{$t('api_test.request.body_text')}}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<ms-api-key-value :items="body.kvs" v-if="body.isKV()"/>
|
||||
<ms-api-key-value :is-read-only="isReadOnly" :items="body.kvs" v-if="body.isKV()"/>
|
||||
|
||||
<el-input class="textarea" type="textarea" v-model="body.raw" :autosize="{ minRows: 10, maxRows: 25}" resize="none"
|
||||
<el-input :disabled="isReadOnly" class="textarea" type="textarea" v-model="body.raw" :autosize="{ minRows: 10, maxRows: 25}" resize="none"
|
||||
v-else/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -24,7 +24,11 @@
|
|||
name: "MsApiBody",
|
||||
components: {MsApiKeyValue},
|
||||
props: {
|
||||
body: Body
|
||||
body: Body,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
<el-col>
|
||||
<el-input v-model="item.name" size="small" maxlength="100" @change="change"
|
||||
<el-input :disabled="isReadOnly" v-model="item.name" size="small" maxlength="100" @change="change"
|
||||
:placeholder="$t('api_test.key')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input v-model="item.value" size="small" maxlength="100" @change="change"
|
||||
<el-input :disabled="isReadOnly" v-model="item.value" size="small" maxlength="100" @change="change"
|
||||
:placeholder="$t('api_test.value')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col class="kv-delete">
|
||||
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||
:disabled="isDisable(index)"/>
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -30,7 +30,11 @@
|
|||
|
||||
props: {
|
||||
description: String,
|
||||
items: Array
|
||||
items: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<el-dropdown trigger="click" @command="handleCommand">
|
||||
<span class="el-dropdown-link el-icon-more"/>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item :command="{type: 'copy', index: index}">
|
||||
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}">
|
||||
{{$t('api_test.request.copy')}}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="{type: 'delete', index: index}">
|
||||
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'delete', index: index}">
|
||||
{{$t('api_test.request.delete')}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
|
@ -26,7 +26,7 @@
|
|||
</el-row>
|
||||
</div>
|
||||
</draggable>
|
||||
<el-button class="request-create" type="primary" size="mini" icon="el-icon-plus" plain @click="createRequest"/>
|
||||
<el-button :disabled="isReadOnly" class="request-create" type="primary" size="mini" icon="el-icon-plus" plain @click="createRequest"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -41,7 +41,11 @@
|
|||
|
||||
props: {
|
||||
requests: Array,
|
||||
open: Function
|
||||
open: Function,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<el-form :model="request" :rules="rules" ref="request" label-width="100px">
|
||||
<el-form-item :label="$t('api_test.request.name')" prop="name">
|
||||
<el-input v-model="request.name" maxlength="100" show-word-limit/>
|
||||
<el-input :disabled="isReadOnly" v-model="request.name" maxlength="100" show-word-limit/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('api_test.request.url')" prop="url">
|
||||
<el-input v-model="request.url" maxlength="100" :placeholder="$t('api_test.request.url_description')"
|
||||
<el-input :disabled="isReadOnly" v-model="request.url" maxlength="100" :placeholder="$t('api_test.request.url_description')"
|
||||
@change="urlChange" clearable>
|
||||
<el-select v-model="request.method" slot="prepend" class="request-method-select" @change="methodChange">
|
||||
<el-select :disabled="isReadOnly" v-model="request.method" slot="prepend" class="request-method-select" @change="methodChange">
|
||||
<el-option label="GET" value="GET"/>
|
||||
<el-option label="POST" value="POST"/>
|
||||
<el-option label="PUT" value="PUT"/>
|
||||
|
@ -22,20 +22,20 @@
|
|||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('api_test.request.parameters')" name="parameters">
|
||||
<ms-api-key-value :items="request.parameters" :description="$t('api_test.request.parameters_desc')"
|
||||
<ms-api-key-value :is-read-only="isReadOnly" :items="request.parameters" :description="$t('api_test.request.parameters_desc')"
|
||||
@change="parametersChange"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.headers')" name="headers">
|
||||
<ms-api-key-value :items="request.headers"/>
|
||||
<ms-api-key-value :is-read-only="isReadOnly" :items="request.headers"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.body')" name="body" v-if="isNotGet">
|
||||
<ms-api-body :body="request.body"/>
|
||||
<ms-api-body :is-read-only="isReadOnly" :body="request.body"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.assertions.label')" name="assertions">
|
||||
<ms-api-assertions :assertions="request.assertions"/>
|
||||
<ms-api-assertions :is-read-only="isReadOnly" :assertions="request.assertions"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.extract.label')" name="extract">
|
||||
<ms-api-extract :extract="request.extract"/>
|
||||
<ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
|
@ -52,7 +52,11 @@
|
|||
name: "MsApiRequestForm",
|
||||
components: {MsApiExtract, MsApiAssertions, MsApiBody, MsApiKeyValue},
|
||||
props: {
|
||||
request: Request
|
||||
request: Request,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -16,27 +16,27 @@
|
|||
<el-dropdown trigger="click" @command="handleCommand">
|
||||
<span class="el-dropdown-link el-icon-more scenario-btn"/>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item :command="{type: 'copy', index: index}">
|
||||
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}">
|
||||
{{$t('api_test.scenario.copy')}}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="{type:'delete', index:index}">
|
||||
<el-dropdown-item :disabled="isReadOnly" :command="{type:'delete', index:index}">
|
||||
{{$t('api_test.scenario.delete')}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<ms-api-request-config :requests="scenario.requests" :open="select"/>
|
||||
<ms-api-request-config :is-read-only="isReadOnly" :requests="scenario.requests" :open="select"/>
|
||||
</ms-api-collapse-item>
|
||||
</draggable>
|
||||
</ms-api-collapse>
|
||||
</div>
|
||||
<el-button class="scenario-create" type="primary" size="mini" icon="el-icon-plus" plain @click="createScenario"/>
|
||||
<el-button :disabled="isReadOnly" class="scenario-create" type="primary" size="mini" icon="el-icon-plus" plain @click="createScenario"/>
|
||||
</el-aside>
|
||||
|
||||
<el-main class="scenario-main">
|
||||
<div class="scenario-form">
|
||||
<ms-api-scenario-form :scenario="selected" v-if="isScenario"/>
|
||||
<ms-api-request-form :request="selected" v-if="isRequest"/>
|
||||
<ms-api-scenario-form :is-read-only="isReadOnly" :scenario="selected" v-if="isScenario"/>
|
||||
<ms-api-request-form :is-read-only="isReadOnly" :request="selected" v-if="isRequest"/>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
@ -65,7 +65,11 @@
|
|||
},
|
||||
|
||||
props: {
|
||||
scenarios: Array
|
||||
scenarios: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<el-form :model="scenario" :rules="rules" ref="scenario" label-width="100px">
|
||||
<el-form-item :label="$t('api_test.scenario.name')" prop="name">
|
||||
<el-input v-model="scenario.name" maxlength="100" show-word-limit/>
|
||||
<el-input :disabled="isReadOnly" v-model="scenario.name" maxlength="100" show-word-limit/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- <el-form-item :label="$t('api_test.scenario.base_url')" prop="url">-->
|
||||
|
@ -10,10 +10,10 @@
|
|||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('api_test.scenario.variables')" name="parameters">
|
||||
<ms-api-scenario-variables :items="scenario.variables" :description="$t('api_test.scenario.kv_description')"/>
|
||||
<ms-api-scenario-variables :is-read-only="isReadOnly" :items="scenario.variables" :description="$t('api_test.scenario.kv_description')"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.scenario.headers')" name="headers">
|
||||
<ms-api-key-value :items="scenario.headers" :description="$t('api_test.scenario.kv_description')"/>
|
||||
<ms-api-key-value :is-read-only="isReadOnly" :items="scenario.headers" :description="$t('api_test.scenario.kv_description')"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
|
@ -28,7 +28,11 @@
|
|||
name: "MsApiScenarioForm",
|
||||
components: {MsApiScenarioVariables, MsApiKeyValue},
|
||||
props: {
|
||||
scenario: Scenario
|
||||
scenario: Scenario,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
<el-col>
|
||||
<ms-api-variable-input v-model="item.name" size="small" maxlength="100" @change="change"
|
||||
<ms-api-variable-input :is-read-only="isReadOnly" v-model="item.name" size="small" maxlength="100" @change="change"
|
||||
:placeholder="$t('api_test.variable_name')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input v-model="item.value" size="small" maxlength="100" @change="change"
|
||||
<el-input :disabled="isReadOnly" v-model="item.value" size="small" maxlength="100" @change="change"
|
||||
:placeholder="$t('api_test.value')" show-word-limit/>
|
||||
</el-col>
|
||||
<el-col class="kv-delete">
|
||||
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||
:disabled="isDisable(index)"/>
|
||||
:disabled="isDisable(index) || isReadOnly"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -31,7 +31,11 @@
|
|||
components: {MsApiVariableInput},
|
||||
props: {
|
||||
description: String,
|
||||
items: Array
|
||||
items: Array,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="variable-input">
|
||||
<el-input :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<el-input :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<div class="variable-combine" v-if="value">
|
||||
<div class="variable">{{variable}}</div>
|
||||
<el-tooltip :content="$t('api_test.copied')" manual v-model="visible" placement="top" :visible-arrow="false">
|
||||
|
@ -14,7 +14,14 @@
|
|||
export default {
|
||||
name: "MsApiVariableInput",
|
||||
|
||||
props: ['value', 'size'],
|
||||
props: {
|
||||
value: String,
|
||||
size: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
||||
<el-col class="assertion-select">
|
||||
<el-select class="assertion-item" v-model="regex.subject" size="small"
|
||||
<el-select :disabled="isReadOnly" class="assertion-item" v-model="regex.subject" size="small"
|
||||
:placeholder="$t('api_test.request.assertions.select_subject')">
|
||||
<el-option label="Response Code" :value="subjects.RESPONSE_CODE"/>
|
||||
<el-option label="Response Headers" :value="subjects.RESPONSE_HEADERS"/>
|
||||
|
@ -10,12 +10,12 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input v-model="regex.expression" maxlength="255" size="small" show-word-limit
|
||||
<el-input :disabled="isReadOnly" v-model="regex.expression" maxlength="255" size="small" show-word-limit
|
||||
:placeholder="$t('api_test.request.assertions.expression')"/>
|
||||
</el-col>
|
||||
<el-col class="assertion-btn">
|
||||
<el-button type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button :disabled="isReadOnly" type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -40,7 +40,11 @@
|
|||
},
|
||||
index: Number,
|
||||
list: Array,
|
||||
callback: Function
|
||||
callback: Function,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<div>
|
||||
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
||||
<el-col>
|
||||
<el-input :value="value" v-bind="$attrs" step="100" size="small" type="number" @change="change" @input="input"
|
||||
<el-input :disabled="isReadOnly" :value="value" v-bind="$attrs" step="100" size="small" type="number" @change="change" @input="input"
|
||||
:placeholder="$t('api_test.request.assertions.response_in_time')"/>
|
||||
</el-col>
|
||||
<el-col class="assertion-btn">
|
||||
<el-button type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button :disabled="isReadOnly" type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -24,7 +24,11 @@
|
|||
duration: ResponseTime,
|
||||
value: [Number, String],
|
||||
edit: Boolean,
|
||||
callback: Function
|
||||
callback: Function,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
||||
<el-col class="assertion-select">
|
||||
<el-select class="assertion-item" v-model="subject" size="small"
|
||||
<el-select :disabled="isReadOnly" class="assertion-item" v-model="subject" size="small"
|
||||
:placeholder="$t('api_test.request.assertions.select_subject')">
|
||||
<el-option label="Response Code" :value="subjects.RESPONSE_CODE"/>
|
||||
<el-option label="Response Headers" :value="subjects.RESPONSE_HEADERS"/>
|
||||
|
@ -10,7 +10,7 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col class="assertion-select">
|
||||
<el-select class="assertion-item" v-model="condition" size="small"
|
||||
<el-select :disabled="isReadOnly" class="assertion-item" v-model="condition" size="small"
|
||||
:placeholder="$t('api_test.request.assertions.select_condition')">
|
||||
<el-option :label="$t('api_test.request.assertions.contains')" value="CONTAINS"/>
|
||||
<el-option :label="$t('api_test.request.assertions.not_contains')" value="NOT_CONTAINS"/>
|
||||
|
@ -20,11 +20,11 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input v-model="value" maxlength="200" size="small" show-word-limit
|
||||
<el-input :disabled="isReadOnly" v-model="value" maxlength="200" size="small" show-word-limit
|
||||
:placeholder="$t('api_test.request.assertions.value')"/>
|
||||
</el-col>
|
||||
<el-col class="assertion-btn">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" plain @click="add"/>
|
||||
<el-button :disabled="isReadOnly" type="primary" size="small" icon="el-icon-plus" plain @click="add"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -38,7 +38,11 @@
|
|||
|
||||
props: {
|
||||
list: Array,
|
||||
callback: Function
|
||||
callback: Function,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="4">
|
||||
<el-select class="assertion-item" v-model="type" :placeholder="$t('api_test.request.assertions.select_type')"
|
||||
<el-select :disabled="isReadOnly" class="assertion-item" v-model="type" :placeholder="$t('api_test.request.assertions.select_type')"
|
||||
size="small">
|
||||
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
|
||||
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
|
||||
|
@ -10,14 +10,14 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<ms-api-assertion-text :list="assertions.regex" v-if="type === options.TEXT" :callback="after"/>
|
||||
<ms-api-assertion-regex :list="assertions.regex" v-if="type === options.REGEX" :callback="after"/>
|
||||
<ms-api-assertion-response-time v-model="time" :duration="assertions.duration"
|
||||
<ms-api-assertion-text :is-read-only="isReadOnly" :list="assertions.regex" v-if="type === options.TEXT" :callback="after"/>
|
||||
<ms-api-assertion-regex :is-read-only="isReadOnly" :list="assertions.regex" v-if="type === options.REGEX" :callback="after"/>
|
||||
<ms-api-assertion-response-time :is-read-only="isReadOnly" v-model="time" :duration="assertions.duration"
|
||||
v-if="type === options.RESPONSE_TIME" :callback="after"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ms-api-assertions-edit :assertions="assertions"/>
|
||||
<ms-api-assertions-edit :is-read-only="isReadOnly" :assertions="assertions"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -34,7 +34,11 @@
|
|||
components: {MsApiAssertionsEdit, MsApiAssertionResponseTime, MsApiAssertionRegex, MsApiAssertionText},
|
||||
|
||||
props: {
|
||||
assertions: Assertions
|
||||
assertions: Assertions,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{$t("api_test.request.assertions.regex")}}
|
||||
</div>
|
||||
<div class="regex-item" v-for="(regex, index) in assertions.regex" :key="index">
|
||||
<ms-api-assertion-regex :list="assertions.regex" :regex="regex" :edit="true" :index="index"/>
|
||||
<ms-api-assertion-regex :is-read-only="isReadOnly" :list="assertions.regex" :regex="regex" :edit="true" :index="index"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
<div>
|
||||
{{$t("api_test.request.assertions.response_time")}}
|
||||
</div>
|
||||
<ms-api-assertion-response-time v-model="assertions.duration.value" :duration="assertions.duration" :edit="true"/>
|
||||
<ms-api-assertion-response-time :is-read-only="isReadOnly" v-model="assertions.duration.value" :duration="assertions.duration" :edit="true"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -30,7 +30,11 @@
|
|||
components: {MsApiAssertionResponseTime, MsApiAssertionRegex},
|
||||
|
||||
props: {
|
||||
assertions: Assertions
|
||||
assertions: Assertions,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</div>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="4">
|
||||
<el-select class="extract-item" v-model="type" :placeholder="$t('api_test.request.extract.select_type')"
|
||||
<el-select :disabled="isReadOnly" class="extract-item" v-model="type" :placeholder="$t('api_test.request.extract.select_type')"
|
||||
size="small">
|
||||
<el-option :label="$t('api_test.request.extract.regex')" :value="options.REGEX"/>
|
||||
<el-option label="JSONPath" :value="options.JSON_PATH"/>
|
||||
|
@ -13,11 +13,11 @@
|
|||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<ms-api-extract-common :extract-type="type" :list="list" v-if="type" :callback="after"/>
|
||||
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type" :list="list" v-if="type" :callback="after"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ms-api-extract-edit :extract="extract"/>
|
||||
<ms-api-extract-edit :is-read-only="isReadOnly" :extract="extract"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -35,7 +35,11 @@
|
|||
},
|
||||
|
||||
props: {
|
||||
extract: Extract
|
||||
extract: Extract,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
<div>
|
||||
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
|
||||
<el-col :span="10">
|
||||
<ms-api-variable-input v-model="common.variable" size="small" maxlength="60" @change="change"
|
||||
<ms-api-variable-input :is-read-only="isReadOnly" v-model="common.variable" size="small" maxlength="60" @change="change"
|
||||
:placeholder="$t('api_test.variable_name')"/>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-input v-model="common.expression" maxlength="255" size="small" :placeholder="expression"/>
|
||||
<el-input :disabled="isReadOnly" v-model="common.expression" maxlength="255" size="small" :placeholder="expression"/>
|
||||
</el-col>
|
||||
<el-col class="extract-btn">
|
||||
<el-button type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
<el-button :disabled="isReadOnly" type="danger" size="mini" icon="el-icon-delete" circle @click="remove" v-if="edit"/>
|
||||
<el-button :disabled="isReadOnly" type="primary" size="small" icon="el-icon-plus" plain @click="add" v-else/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -42,7 +42,11 @@
|
|||
},
|
||||
index: Number,
|
||||
list: Array,
|
||||
callback: Function
|
||||
callback: Function,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{$t("api_test.request.extract.regex")}}
|
||||
</div>
|
||||
<div class="regex-item" v-for="(regex, index) in extract.regex" :key="index">
|
||||
<ms-api-extract-common :extract-type="type.REGEX" :list="extract.regex" :common="regex"
|
||||
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.REGEX" :list="extract.regex" :common="regex"
|
||||
:edit="true" :index="index"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@
|
|||
JSONPath
|
||||
</div>
|
||||
<div class="regex-item" v-for="(json, index) in extract.json" :key="index">
|
||||
<ms-api-extract-common :extract-type="type.JSON_PATH" :list="extract.json" :common="json"
|
||||
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.JSON_PATH" :list="extract.json" :common="json"
|
||||
:edit="true" :index="index"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -25,7 +25,7 @@
|
|||
XPath
|
||||
</div>
|
||||
<div class="regex-item" v-for="(xpath, index) in extract.xpath" :key="index">
|
||||
<ms-api-extract-common :extract-type="type.XPATH" :list="extract.xpath" :common="xpath"
|
||||
<ms-api-extract-common :is-read-only="isReadOnly" :extract-type="type.XPATH" :list="extract.xpath" :common="xpath"
|
||||
:edit="true" :index="index"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,7 +43,11 @@
|
|||
components: {MsApiExtractCommon},
|
||||
|
||||
props: {
|
||||
extract: Extract
|
||||
extract: Extract,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -231,6 +231,7 @@ export class HTTPSamplerProxy extends DefaultTestElement {
|
|||
}
|
||||
|
||||
this.boolProp("HTTPSampler.follow_redirects", this.request.follow, true);
|
||||
this.boolProp("HTTPSampler.use_keepalive", this.request.keepalive, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,6 @@
|
|||
export default {
|
||||
name: "MsTableOperatorButton",
|
||||
components: {MsTipButton, MsTableButton},
|
||||
data() {
|
||||
return{
|
||||
disabled: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
|
@ -33,6 +28,10 @@
|
|||
tip: {
|
||||
type: String
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isTesterPermission: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
|
|
@ -205,7 +205,7 @@ const router = new VueRouter({
|
|||
component: TrackHome,
|
||||
},
|
||||
{
|
||||
path: 'case/create/',
|
||||
path: 'case/create',
|
||||
name: 'testCaseCreate',
|
||||
component: TestCase,
|
||||
},
|
||||
|
|
|
@ -10,14 +10,15 @@
|
|||
<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/>
|
||||
v-model="condition.name" @change="search" clearable/>
|
||||
</span>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="tableData" class="test-content"
|
||||
:default-sort="{prop: 'createTime', order: 'descending'}"
|
||||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
|
@ -47,6 +48,8 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="updateTime"-->
|
||||
<!-- sortable-->
|
||||
<!-- width="250"-->
|
||||
<!-- :label="$t('commons.update_time')">-->
|
||||
<!-- <template v-slot:default="scope">-->
|
||||
|
@ -55,7 +58,7 @@
|
|||
<!-- </el-table-column>-->
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:filter-method="filter"
|
||||
column-key="status"
|
||||
:filters="statusFilters"
|
||||
:label="$t('commons.status')">
|
||||
<template v-slot:default="{row}">
|
||||
|
@ -83,6 +86,7 @@
|
|||
import MsContainer from "../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../common/components/MsMainContainer";
|
||||
import MsPerformanceReportStatus from "./PerformanceReportStatus";
|
||||
import {_filter, _sort} from "../../../../common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "PerformanceTestReport",
|
||||
|
@ -95,7 +99,7 @@
|
|||
result: {},
|
||||
queryPath: "/performance/report/list/all",
|
||||
deletePath: "/performance/report/delete/",
|
||||
condition: "",
|
||||
condition: {},
|
||||
projectId: null,
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
|
@ -115,10 +119,7 @@
|
|||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
let param = {
|
||||
name: this.condition,
|
||||
};
|
||||
this.result = this.$post(this.buildPagePath(this.queryPath), param, response => {
|
||||
this.result = this.$post(this.buildPagePath(this.queryPath), this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
|
@ -161,8 +162,13 @@
|
|||
this.initTableData();
|
||||
});
|
||||
},
|
||||
filter(value, row) {
|
||||
return row.status === value;
|
||||
sort(column) {
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<template>
|
||||
<div v-loading="result.loading">
|
||||
<el-tabs type="border-card" :stretch="true">
|
||||
<el-tab-pane v-for="item in logContent" :key="item.resourceId" :label="item.resourceName" class="logging-content">
|
||||
{{item.content}}...
|
||||
<el-tab-pane v-for="item in resource" :key="item.resourceId" :label="item.resourceName" class="logging-content">
|
||||
<ul class="infinite-list" v-infinite-scroll="load(item.resourceId)" infinite-scroll-disabled="disabled">
|
||||
<li class="infinite-list-item" v-for="log in logContent" :key="log.id">{{ log.content }}</li>
|
||||
</ul>
|
||||
<el-link type="primary" @click="downloadLogFile(item)">{{$t('load_test.download_log_file')}}</el-link>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
@ -14,17 +16,40 @@
|
|||
name: "LogDetails",
|
||||
data() {
|
||||
return {
|
||||
logContent: null,
|
||||
resource: [],
|
||||
logContent: [],
|
||||
result: {},
|
||||
id: ''
|
||||
id: '',
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
disabled() {
|
||||
return this.loading || this.page > this.pageCount;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
initTableData() {
|
||||
this.result = this.$get("/performance/report/log/" + this.id).then(res => {
|
||||
this.logContent = res.data.data;
|
||||
}).catch(() => {
|
||||
this.logContent = null;
|
||||
getResource() {
|
||||
this.result = this.$get("/performance/report/log/resource/" + this.id, data => {
|
||||
this.resource = data.data;
|
||||
})
|
||||
},
|
||||
load(resourceId) {
|
||||
if (this.loading || this.page > this.pageCount) return;
|
||||
this.loading = true;
|
||||
let url = "/performance/report/log/" + this.id + "/" + resourceId + "/" + this.page;
|
||||
this.$get(url, res => {
|
||||
let data = res.data;
|
||||
this.pageCount = data.pageCount;
|
||||
data.listObject.forEach(log => {
|
||||
this.logContent.push(log);
|
||||
})
|
||||
this.page++;
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
downloadLogFile(item) {
|
||||
|
@ -53,16 +78,16 @@
|
|||
},
|
||||
watch: {
|
||||
report: {
|
||||
handler(val){
|
||||
handler(val) {
|
||||
let status = val.status;
|
||||
this.id = val.id;
|
||||
if (status === "Completed") {
|
||||
this.initTableData();
|
||||
this.getResource();
|
||||
} else {
|
||||
this.logContent = null;
|
||||
this.resource = [];
|
||||
}
|
||||
},
|
||||
deep:true
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
props: ['report']
|
||||
|
@ -75,4 +100,16 @@
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.infinite-list {
|
||||
height: 500px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
overflow: auto
|
||||
}
|
||||
|
||||
.infinite-list-item {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
<el-card v-loading="result.loading">
|
||||
<el-row>
|
||||
<el-col :span="10">
|
||||
<el-input :placeholder="$t('load_test.input_name')" v-model="testPlan.name" class="input-with-select">
|
||||
<el-input :placeholder="$t('load_test.input_name')" v-model="testPlan.name" class="input-with-select"
|
||||
maxlength="30"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<el-select v-model="testPlan.projectId" :placeholder="$t('load_test.select_project')">
|
||||
<el-option
|
||||
|
@ -30,7 +32,7 @@
|
|||
<performance-basic-config :test-plan="testPlan" ref="basicConfig"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('load_test.pressure_config')">
|
||||
<performance-pressure-config :test-plan="testPlan" :test-id="testId" ref="pressureConfig"/>
|
||||
<performance-pressure-config :test-plan="testPlan" :test-id="testId" ref="pressureConfig" @changeActive="changeTabActive"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('load_test.advanced_config')" class="advanced-config">
|
||||
<performance-advanced-config :test-id="testId" ref="advancedConfig"/>
|
||||
|
@ -154,9 +156,9 @@
|
|||
});
|
||||
},
|
||||
saveAndRun() {
|
||||
// if (!this.validTestPlan()) {
|
||||
// return;
|
||||
// }
|
||||
if (!this.validTestPlan()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let options = this.getSaveOption();
|
||||
|
||||
|
@ -208,9 +210,13 @@
|
|||
this.$router.push({path: '/performance/test/all'})
|
||||
},
|
||||
validTestPlan() {
|
||||
let reg = /^[\u4e00-\u9fa5_a-zA-Z0-9\s.·-]+$/;
|
||||
if (!this.testPlan.name) {
|
||||
this.$error(this.$t('load_test.test_name_is_null'));
|
||||
return false;
|
||||
} else if (!reg.test(this.testPlan.name)) {
|
||||
this.$error(this.$t('load_test.special_characters_are_not_supported'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.testPlan.projectId) {
|
||||
|
@ -233,6 +239,11 @@
|
|||
/// todo: 其他校验
|
||||
|
||||
return true;
|
||||
},
|
||||
changeTabActive(activeName) {
|
||||
this.$nextTick(()=> {
|
||||
this.active = activeName;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- @sort-change="sort"-->
|
||||
<el-table :data="tableData" class="test-content"
|
||||
:default-sort="{prop: 'createTime', order: 'descending'}"
|
||||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
|
@ -61,7 +61,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:filter-method="filter"
|
||||
column-key="status"
|
||||
:filters="statusFilters"
|
||||
:label="$t('commons.status')">
|
||||
<template v-slot:default="{row}">
|
||||
|
@ -200,12 +200,13 @@
|
|||
this.initTableData();
|
||||
});
|
||||
},
|
||||
// sort(column) {
|
||||
// _sort(column, this.condition);
|
||||
// this.initTableData();
|
||||
// },
|
||||
filter(value, row) {
|
||||
return row.status === value;
|
||||
sort(column) {
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
link(row) {
|
||||
this.$router.push({
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<el-row type="flex" justify="start">
|
||||
<el-col :span="8">
|
||||
<h3>{{$t('load_test.domain_bind')}}</h3>
|
||||
<el-button icon="el-icon-circle-plus-outline" plain size="mini" @click="add('domains')">{{$t('commons.add')}}
|
||||
<el-button :disabled="readOnly" icon="el-icon-circle-plus-outline" plain size="mini" @click="add('domains')">{{$t('commons.add')}}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -19,7 +19,7 @@
|
|||
<template v-slot:default="{row}">
|
||||
<el-input
|
||||
size="mini"
|
||||
v-if="readOnly"
|
||||
v-if="!readOnly"
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
class="edit-input"
|
||||
|
@ -36,7 +36,7 @@
|
|||
show-overflow-tooltip>
|
||||
<template v-slot:default="{row}">
|
||||
<el-switch
|
||||
:disabled="!row.edit"
|
||||
:disabled="!row.edit || readOnly"
|
||||
size="mini"
|
||||
v-model="row.enable"
|
||||
active-color="#13ce66"
|
||||
|
@ -54,7 +54,7 @@
|
|||
<template v-slot:default="{row}">
|
||||
<el-input
|
||||
size="mini"
|
||||
v-if="readOnly"
|
||||
v-if="!readOnly"
|
||||
type="textarea"
|
||||
class="edit-input"
|
||||
:rows="1"
|
||||
|
@ -66,7 +66,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column align="center" :label="$t('load_test.operating')">
|
||||
<template v-slot:default="{row, $index}">
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" type="danger"
|
||||
<ms-table-operator-button :disabled="readOnly" :tip="$t('commons.delete')" icon="el-icon-delete" type="danger"
|
||||
@exec="del(row, 'domains', $index)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<el-row>
|
||||
<el-col :span="8">
|
||||
<h3>{{$t('load_test.params')}}</h3>
|
||||
<el-button icon="el-icon-circle-plus-outline" plain size="mini" @click="add('params')">{{$t('commons.add')}}
|
||||
<el-button :disabled="readOnly" icon="el-icon-circle-plus-outline" plain size="mini" @click="add('params')">{{$t('commons.add')}}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<template v-slot:default="{row}">
|
||||
<el-input
|
||||
size="mini"
|
||||
v-if="readOnly"
|
||||
v-if="!readOnly"
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
class="edit-input"
|
||||
|
@ -109,7 +109,7 @@
|
|||
show-overflow-tooltip>
|
||||
<template v-slot:default="{row}">
|
||||
<el-switch
|
||||
:disabled="!row.edit"
|
||||
:disabled="!row.edit || readOnly"
|
||||
size="mini"
|
||||
v-model="row.enable"
|
||||
active-color="#13ce66"
|
||||
|
@ -127,7 +127,7 @@
|
|||
<span v-else>{{ row.value }}</span>-->
|
||||
<el-input
|
||||
size="mini"
|
||||
v-if="readOnly"
|
||||
v-if="!readOnly"
|
||||
type="textarea"
|
||||
class="edit-input"
|
||||
:rows="1"
|
||||
|
@ -139,7 +139,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column align="center" :label="$t('load_test.operating')">
|
||||
<template v-slot:default="{row, $index}">
|
||||
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" type="danger"
|
||||
<ms-table-operator-button :disabled="readOnly" :tip="$t('commons.delete')" icon="el-icon-delete" type="danger"
|
||||
@exec="del(row, 'params', $index)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -154,7 +154,7 @@
|
|||
<div>{{$t('load_test.connect_timeout')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number size="mini" v-model="timeout" :min="10" :max="100000"></el-input-number>
|
||||
<el-input-number :disabled="readOnly" size="mini" v-model="timeout" :min="10" :max="100000"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
ms
|
||||
|
@ -169,7 +169,7 @@
|
|||
<div>{{$t('load_test.custom_http_code')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input size="mini" v-model="statusCodeStr" :placeholder="$t('load_test.separated_by_commas')"
|
||||
<el-input :disabled="readOnly" size="mini" v-model="statusCodeStr" :placeholder="$t('load_test.separated_by_commas')"
|
||||
@input="checkStatusCode"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -196,7 +196,7 @@
|
|||
props: {
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: false
|
||||
},
|
||||
testId: String,
|
||||
},
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
:before-upload="beforeUpload"
|
||||
:http-request="handleUpload"
|
||||
:on-exceed="handleExceed"
|
||||
:disabled="isReadOnly"
|
||||
:file-list="fileList">
|
||||
<i class="el-icon-upload"/>
|
||||
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
|
||||
|
@ -41,9 +42,9 @@
|
|||
<el-table-column
|
||||
:label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<el-button @click="handleDownload(scope.row)" :disabled="!scope.row.id" type="primary" icon="el-icon-download"
|
||||
<el-button @click="handleDownload(scope.row)" :disabled="!scope.row.id || isReadOnly" type="primary" icon="el-icon-download"
|
||||
size="mini" circle/>
|
||||
<el-button @click="handleDelete(scope.row, scope.$index)" type="danger" icon="el-icon-delete" size="mini"
|
||||
<el-button :disabled="isReadOnly" @click="handleDelete(scope.row, scope.$index)" type="danger" icon="el-icon-delete" size="mini"
|
||||
circle/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -56,7 +57,15 @@
|
|||
|
||||
export default {
|
||||
name: "PerformanceBasicConfig",
|
||||
props: ["testPlan"],
|
||||
props: {
|
||||
testPlan: {
|
||||
type: Object
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number
|
||||
:disabled="isReadOnly"
|
||||
:placeholder="$t('load_test.input_thread_num')"
|
||||
v-model="threadNumber"
|
||||
@change="calculateChart"
|
||||
|
@ -21,6 +22,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number
|
||||
:disabled="isReadOnly"
|
||||
:placeholder="$t('load_test.duration')"
|
||||
v-model="duration"
|
||||
:min="1"
|
||||
|
@ -35,6 +37,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number
|
||||
:disabled="isReadOnly"
|
||||
:placeholder="$t('load_test.input_rps_limit')"
|
||||
v-model="rpsLimit"
|
||||
@change="calculateChart"
|
||||
|
@ -50,6 +53,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number
|
||||
:disabled="isReadOnly"
|
||||
placeholder=""
|
||||
:min="1"
|
||||
:max="duration"
|
||||
|
@ -62,6 +66,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input-number
|
||||
:disabled="isReadOnly"
|
||||
placeholder=""
|
||||
:min="1"
|
||||
:max="Math.min(threadNumber, rampUpTime)"
|
||||
|
@ -78,7 +83,7 @@
|
|||
<div>{{$t('load_test.select_resource_pool')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="resourcePool" size="mini">
|
||||
<el-select v-model="resourcePool" :disabled="isReadOnly" size="mini">
|
||||
<el-option
|
||||
v-for="item in resourcePools"
|
||||
:key="item.id"
|
||||
|
@ -108,7 +113,18 @@
|
|||
|
||||
export default {
|
||||
name: "PerformancePressureConfig",
|
||||
props: ['testPlan','testId'],
|
||||
props: {
|
||||
testPlan: {
|
||||
type: Object
|
||||
},
|
||||
testId: {
|
||||
type: String
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
|
@ -283,6 +299,8 @@
|
|||
validConfig() {
|
||||
if (!this.resourcePool) {
|
||||
this.$warning(this.$t('load_test.resource_pool_is_null'));
|
||||
// 资源池为空,设置参数为资源池所在Tab的name
|
||||
this.$emit('changeActive', '1');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" @create="create"
|
||||
:create-tip="btnTips" :title="title"/>
|
||||
</template>
|
||||
<el-table :data="items" style="width: 100%">
|
||||
<el-table :data="items" style="width: 100%" @sort-change="sort">
|
||||
<el-table-column prop="name" :label="$t('commons.name')">
|
||||
<template v-slot:default="scope">
|
||||
<el-link type="info" @click="link(scope.row)">{{ scope.row.name }}</el-link>
|
||||
|
@ -15,6 +15,8 @@
|
|||
<el-table-column prop="description" :label="$t('commons.description')"/>
|
||||
<!--<el-table-column prop="workspaceName" :label="$t('project.owning_workspace')"/>-->
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="createTime"
|
||||
:label="$t('commons.create_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
|
@ -22,6 +24,8 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
|
@ -67,7 +71,7 @@
|
|||
import MsTableHeader from "../common/components/MsTableHeader";
|
||||
import MsTableOperator from "../common/components/MsTableOperator";
|
||||
import MsDialogFooter from "../common/components/MsDialogFooter";
|
||||
import {getCurrentUser} from "../../../common/js/utils";
|
||||
import {_sort, getCurrentUser} from "../../../common/js/utils";
|
||||
import MsContainer from "../common/components/MsContainer";
|
||||
import MsMainContainer from "../common/components/MsMainContainer";
|
||||
|
||||
|
@ -223,8 +227,16 @@
|
|||
this.$router.push({
|
||||
path: '/performance/test/' + row.id,
|
||||
})
|
||||
} else if (this.$route.name === 'fucProject') {
|
||||
this.$router.push({
|
||||
path: '/api/test/list/' + row.id
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
sort(column) {
|
||||
_sort(column, this.condition);
|
||||
this.list();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -199,10 +199,6 @@
|
|||
});
|
||||
} else {
|
||||
this.testCaseReadOnly = false;
|
||||
if (this.treeNodes.length < 1) {
|
||||
this.$warning(this.$t('test_track.case.create_module_first'));
|
||||
return;
|
||||
}
|
||||
this.$refs.testCaseEditDialog.open();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<el-row type="flex" justify="start" :gutter="20" class="status-button">
|
||||
<el-col>
|
||||
<el-button type="success" round size="mini"
|
||||
<el-button :disabled="isReadOnly" type="success" round size="mini"
|
||||
:icon="status == 'Pass' ? 'el-icon-check' : ''"
|
||||
@click="setStatus('Pass')"> {{$t('test_track.plan_view.pass')}}</el-button>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-button type="danger" round size="mini"
|
||||
<el-button :disabled="isReadOnly" type="danger" round size="mini"
|
||||
:icon="status == 'Failure' ? 'el-icon-check' : ''"
|
||||
@click="setStatus('Failure')"> {{$t('test_track.plan_view.failure')}}</el-button>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-button type="warning" round size="mini"
|
||||
<el-button :disabled="isReadOnly" type="warning" round size="mini"
|
||||
:icon="status == 'Blocking' ? 'el-icon-check' : ''"
|
||||
@click="setStatus('Blocking')"> {{$t('test_track.plan_view.blocking')}}</el-button>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-button type="info" round size="mini"
|
||||
<el-button :disabled="isReadOnly" type="info" round size="mini"
|
||||
:icon="status == 'Skip' ? 'el-icon-check' : ''"
|
||||
@click="setStatus('Skip')"> {{$t('test_track.plan_view.skip')}}</el-button>
|
||||
</el-col>
|
||||
|
@ -29,6 +29,10 @@
|
|||
props: {
|
||||
status: {
|
||||
type: String
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
@click="handleNext()"/>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
|
||||
<el-button type="primary" size="mini" @click="saveCase()">{{$t('test_track.save')}}</el-button>
|
||||
<el-button type="primary" size="mini" :disabled="isReadOnly" @click="saveCase()">{{$t('test_track.save')}}</el-button>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
|
@ -69,6 +69,7 @@
|
|||
<el-col :span="13">
|
||||
<test-plan-test-case-status-button class="status-button"
|
||||
@statusChange="statusChange"
|
||||
:is-read-only="isReadOnly"
|
||||
:status="testCase.status"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -89,12 +90,12 @@
|
|||
<el-col class="test-detail" :span="20" :offset="1">
|
||||
<el-tabs v-model="activeTab" type="border-card" @tab-click="testTabChange">
|
||||
<el-tab-pane name="detail" :label="$t('test_track.plan_view.test_detail')">
|
||||
<api-test-detail v-if="testCase.type == 'api'" @runTest="testRun" :id="testCase.testId" ref="apiTestDetail"/>
|
||||
<performance-test-detail v-if="testCase.type == 'performance'" @runTest="testRun" :id="testCase.testId" ref="performanceTestDetail"/>
|
||||
<api-test-detail :is-read-only="isReadOnly" v-if="testCase.type == 'api'" @runTest="testRun" :id="testCase.testId" ref="apiTestDetail"/>
|
||||
<performance-test-detail :is-read-only="isReadOnly" v-if="testCase.type == 'performance'" @runTest="testRun" :id="testCase.testId" ref="performanceTestDetail"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="result" :label="$t('test_track.plan_view.test_result')">
|
||||
<api-test-result :report-id="testCase.reportId" v-if=" testCase.type == 'api'" ref="apiTestResult"/>
|
||||
<performance-test-result :report-id="testCase.reportId" v-if="testCase.type == 'performance'" ref="performanceTestResult"/>
|
||||
<performance-test-result :is-read-only="isReadOnly" :report-id="testCase.reportId" v-if="testCase.type == 'performance'" ref="performanceTestResult"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
|
@ -130,6 +131,7 @@
|
|||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:rows="2"
|
||||
:disabled="isReadOnly"
|
||||
v-model="scope.row.actualResult"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
clearable></el-input>
|
||||
|
@ -139,6 +141,7 @@
|
|||
<el-table-column :label="$t('test_track.plan_view.step_result')" min-width="9%">
|
||||
<template v-slot:default="scope">
|
||||
<el-select
|
||||
:disabled="isReadOnly"
|
||||
v-model="scope.row.executeResult"
|
||||
size="mini">
|
||||
<el-option :label="$t('test_track.plan_view.pass')" value="Pass" style="color: #7ebf50;"></el-option>
|
||||
|
@ -155,6 +158,7 @@
|
|||
<el-row v-if="testCase.issues">
|
||||
<el-col :span="5" :offset="1">
|
||||
<el-switch
|
||||
:disabled="isReadOnly"
|
||||
v-model="testCase.issues.hasIssues"
|
||||
@change="issuesChange"
|
||||
:active-text="$t('test_track.plan_view.submit_issues')">
|
||||
|
@ -164,7 +168,7 @@
|
|||
|
||||
<el-row v-if="testCase.issues && testCase.issues.hasIssues">
|
||||
<el-col :span="20" :offset="1" class="step-edit">
|
||||
<ckeditor :editor="editor" v-model="testCase.issues.content"/>
|
||||
<ckeditor :editor="editor" :disabled="isReadOnly" :config="editorConfig" v-model="testCase.issues.content"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
@ -220,6 +224,10 @@
|
|||
index: 0,
|
||||
testCases: [],
|
||||
editor: ClassicEditor,
|
||||
editorConfig: {
|
||||
// 'increaseIndent','decreaseIndent'
|
||||
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ,'insertTable', '|','undo', 'redo'],
|
||||
},
|
||||
test: {},
|
||||
activeTab: 'detail'
|
||||
};
|
||||
|
@ -230,6 +238,10 @@
|
|||
},
|
||||
searchParam: {
|
||||
type: Object
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -334,10 +346,8 @@
|
|||
},
|
||||
testTabChange(data) {
|
||||
if (this.testCase.type == 'performance' && data.paneName == 'result') {
|
||||
console.log(data);
|
||||
this.$refs.performanceTestResult.checkReportStatus();
|
||||
}
|
||||
// console.log(data);
|
||||
},
|
||||
saveReport(reportId) {
|
||||
this.$post('/test/plan/case/edit', {id: this.testCase.id, reportId: reportId});
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
@sort-change="sort"
|
||||
@select="handleSelectionChange"
|
||||
row-key="id"
|
||||
@row-click="showDetail"
|
||||
:data="tableData">
|
||||
|
||||
<el-table-column
|
||||
|
@ -134,6 +135,7 @@
|
|||
ref="testPlanTestCaseEdit"
|
||||
:search-param="condition"
|
||||
@refresh="initTableData"
|
||||
:is-read-only="isReadOnly"
|
||||
@refreshTable="search"/>
|
||||
|
||||
<test-report-template-list @openReport="openReport" :plan-id="planId" ref="testReporTtemplateList"/>
|
||||
|
@ -188,6 +190,7 @@
|
|||
total: 0,
|
||||
selectIds: new Set(),
|
||||
testPlan: {},
|
||||
isReadOnly: false,
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
|
@ -247,6 +250,10 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
showDetail(row, event, column) {
|
||||
this.isReadOnly = true;
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
},
|
||||
refresh() {
|
||||
this.condition = {};
|
||||
this.selectIds.clear();
|
||||
|
@ -271,6 +278,7 @@
|
|||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
handleEdit(testCase, index) {
|
||||
this.isReadOnly = false;
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(testCase);
|
||||
},
|
||||
handleDelete(testCase) {
|
||||
|
@ -390,7 +398,7 @@
|
|||
width: 240px;
|
||||
}
|
||||
|
||||
.test-case-status {
|
||||
.test-case-status,.el-table {
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
editor: ClassicEditor,
|
||||
// editorData: '<p>Content of the editor.</p>',
|
||||
editorConfig: {
|
||||
// The configuration of the editor.
|
||||
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ,'insertTable', '|','undo', 'redo']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
:placeholder="$t('api_test.select_project')">
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-button type="primary" plain @click="runTest">
|
||||
<el-button :disabled="isReadOnly" type="primary" plain @click="runTest">
|
||||
{{$t('api_test.run')}}
|
||||
</el-button>
|
||||
</el-row>
|
||||
</el-header>
|
||||
|
||||
<ms-api-scenario-config :scenarios="test.scenarioDefinition" ref="config"/>
|
||||
<ms-api-scenario-config :is-read-only="true" :scenarios="test.scenarioDefinition" ref="config"/>
|
||||
|
||||
</el-container>
|
||||
</el-card>
|
||||
|
@ -31,7 +31,13 @@
|
|||
export default {
|
||||
name: "ApiTestDetail",
|
||||
components: {MsMainContainer, MsContainer, MsApiScenarioConfig},
|
||||
props: ["id"],
|
||||
props: {
|
||||
id: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<ms-container>
|
||||
<ms-main-container>
|
||||
<span v-if="!reportId">尚未执行</span>
|
||||
<span v-if="!reportId">{{$t('commons.not_performed_yet')}}</span>
|
||||
<el-card v-if="reportId">
|
||||
<section class="report-container" v-loading="loading">
|
||||
<header class="report-header">
|
||||
|
|
|
@ -13,19 +13,19 @@
|
|||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="2">
|
||||
<el-button type="primary" plain @click="runTest">执行</el-button>
|
||||
<el-button :disabled="isReadOnly" type="primary" plain @click="runTest">执行</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-tabs class="test-config" v-model="active" type="border-card" :stretch="true">
|
||||
<el-tab-pane :label="$t('load_test.basic_config')">
|
||||
<performance-basic-config :test-plan="test" ref="basicConfig"/>
|
||||
<performance-basic-config :is-read-only="true" :test-plan="test" ref="basicConfig"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('load_test.pressure_config')">
|
||||
<performance-pressure-config :test-plan="test" :test-id="id" ref="pressureConfig"/>
|
||||
<performance-pressure-config :is-read-only="true" :test-plan="test" :test-id="id" ref="pressureConfig"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('load_test.advanced_config')" class="advanced-config">
|
||||
<performance-advanced-config :test-id="id" ref="advancedConfig"/>
|
||||
<performance-advanced-config :read-only="true" :test-id="id" ref="advancedConfig"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
@ -74,7 +74,13 @@
|
|||
}]
|
||||
}
|
||||
},
|
||||
props: ['id'],
|
||||
props: {
|
||||
id: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getTest();
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<ms-container>
|
||||
<ms-main-container>
|
||||
<el-card v-loading="result.loading">
|
||||
<span v-if="!reportId">{{$t('commons.not_performed_yet')}}</span>
|
||||
<el-card v-loading="result.loading" v-if="reportId">
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
<el-row>
|
||||
|
@ -13,12 +14,12 @@
|
|||
<el-breadcrumb-item>{{reportName}}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</el-row>
|
||||
<el-row class="ms-report-view-btns">
|
||||
<el-button type="primary" plain size="mini">{{$t('report.test_stop_now')}}</el-button>
|
||||
<el-button type="success" plain size="mini">{{$t('report.test_execute_again')}}</el-button>
|
||||
<el-button type="info" plain size="mini">{{$t('report.export')}}</el-button>
|
||||
<el-button type="warning" plain size="mini">{{$t('report.compare')}}</el-button>
|
||||
</el-row>
|
||||
<!--<el-row class="ms-report-view-btns">-->
|
||||
<!--<el-button :disabled="isReadOnly" type="primary" plain size="mini">{{$t('report.test_stop_now')}}</el-button>-->
|
||||
<!--<el-button :disabled="isReadOnly" type="success" plain size="mini">{{$t('report.test_execute_again')}}</el-button>-->
|
||||
<!--<el-button :disabled="isReadOnly" type="info" plain size="mini">{{$t('report.export')}}</el-button>-->
|
||||
<!--<el-button :disabled="isReadOnly" type="warning" plain size="mini">{{$t('report.compare')}}</el-button>-->
|
||||
<!--</el-row>-->
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<span class="ms-report-time-desc">
|
||||
|
@ -91,7 +92,13 @@
|
|||
report: {}
|
||||
}
|
||||
},
|
||||
props: ['reportId'],
|
||||
props: {
|
||||
reportId: String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
|
@ -141,13 +148,13 @@
|
|||
this.$warning(this.$t('report.generation_error'));
|
||||
break;
|
||||
case 'Starting':
|
||||
this.$warning("测试处于开始状态,请稍后查看报告!");
|
||||
this.$warning(this.$t('report.start_status'));
|
||||
break;
|
||||
case 'Reporting':
|
||||
this.$info(this.$t('report.being_generated'));
|
||||
break;
|
||||
case 'Running':
|
||||
this.$warning("测试处于运行状态,请稍后查看报告!");
|
||||
this.$warning(this.$t('report.run_status'));
|
||||
break;
|
||||
case 'Completed':
|
||||
default:
|
||||
|
@ -177,7 +184,6 @@
|
|||
this.$set(this.report, "id", this.reportId);
|
||||
this.$set(this.report, "status", data.status);
|
||||
|
||||
// this.checkReportStatus(data.status);
|
||||
if (this.status === "Completed") {
|
||||
this.result = this.$get("/performance/report/content/report_time/" + this.reportId).then(res => {
|
||||
let data = res.data.data;
|
||||
|
@ -200,16 +206,17 @@
|
|||
}
|
||||
},
|
||||
getReport() {
|
||||
this.result = this.$get("/performance/report/" + this.reportId, res => {
|
||||
let data = res.data;
|
||||
this.status = data.status;
|
||||
this.$set(this.report, "id", this.reportId);
|
||||
this.$set(this.report, "status", data.status);
|
||||
// this.checkReportStatus(data.status);
|
||||
if (this.status === "Completed") {
|
||||
this.initReportTimeInfo();
|
||||
}
|
||||
});
|
||||
if (this.reportId) {
|
||||
this.result = this.$get("/performance/report/" + this.reportId, res => {
|
||||
let data = res.data;
|
||||
this.status = data.status;
|
||||
this.$set(this.report, "id", this.reportId);
|
||||
this.$set(this.report, "status", data.status);
|
||||
if (this.status === "Completed") {
|
||||
this.initReportTimeInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
this.initBreadcrumb();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,17 @@ import Vuex from 'vuex'
|
|||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const Common = {
|
||||
state: {
|
||||
projectId: ""
|
||||
},
|
||||
mutations: {
|
||||
setProjectId(state, projectId) {
|
||||
state.projectId = projectId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const API = {
|
||||
state: {
|
||||
test: {}
|
||||
|
@ -14,13 +25,12 @@ const API = {
|
|||
clearTest(state) {
|
||||
state.test = {};
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
getters: {}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
api: API
|
||||
api: API,
|
||||
common: Common
|
||||
}
|
||||
})
|
||||
|
|
|
@ -54,7 +54,9 @@ export default {
|
|||
result.loading = false;
|
||||
window.console.error(error.response || error.message);
|
||||
if (error.response && error.response.data) {
|
||||
Message.error({message: error.response.data.message, showClose: true});
|
||||
if (error.response.headers["authentication-status"] != "invalid") {
|
||||
Message.error({message: error.response.data.message, showClose: true});
|
||||
}
|
||||
} else {
|
||||
Message.error({message: error.message, showClose: true});
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ export default {
|
|||
'organization': 'Organization',
|
||||
'setting': 'Setting',
|
||||
'project': 'Project',
|
||||
current_project: 'Current Project',
|
||||
'name': 'Name',
|
||||
'description': 'Description',
|
||||
'clear': 'Clear',
|
||||
|
@ -92,7 +93,8 @@ export default {
|
|||
'remove': 'Remove',
|
||||
'remove_cancel': 'Remove Cancel',
|
||||
'remove_success': 'Remove Success',
|
||||
'tips': 'The authentication information has expired, please login again'
|
||||
'tips': 'The authentication information has expired, please login again',
|
||||
'not_performed_yet': 'Not performed yet',
|
||||
},
|
||||
workspace: {
|
||||
'create': 'Create Workspace',
|
||||
|
@ -254,7 +256,8 @@ export default {
|
|||
'select_resource_pool': 'Please Select Resource Pool',
|
||||
'resource_pool_is_null': 'Resource Pool is empty',
|
||||
'download_log_file': 'Download',
|
||||
'user_name': 'Creator'
|
||||
'user_name': 'Creator',
|
||||
'special_characters_are_not_supported': 'Test name does not support special characters',
|
||||
},
|
||||
api_test: {
|
||||
creator: "Creator",
|
||||
|
|
|
@ -4,6 +4,7 @@ export default {
|
|||
'organization': '组织',
|
||||
'setting': '设置',
|
||||
'project': '项目',
|
||||
current_project: '当前项目',
|
||||
'name': '名称',
|
||||
'description': '描述',
|
||||
'clear': '清空',
|
||||
|
@ -91,7 +92,8 @@ export default {
|
|||
'remove': '移除',
|
||||
'remove_cancel': '移除取消',
|
||||
'remove_success': '移除成功',
|
||||
'tips': '认证信息已过期,请重新登录'
|
||||
'tips': '认证信息已过期,请重新登录',
|
||||
'not_performed_yet': '尚未执行',
|
||||
},
|
||||
workspace: {
|
||||
'create': '创建工作空间',
|
||||
|
@ -252,7 +254,8 @@ export default {
|
|||
'resource_pool_is_null': '资源池为空',
|
||||
'download_log_file': '下载完整日志文件',
|
||||
'pressure_prediction_chart': '压力预估图',
|
||||
'user_name': '创建人'
|
||||
'user_name': '创建人',
|
||||
'special_characters_are_not_supported': '测试名称不支持特殊字符',
|
||||
},
|
||||
api_test: {
|
||||
creator: "创建人",
|
||||
|
|
|
@ -4,6 +4,7 @@ export default {
|
|||
'organization': '組織',
|
||||
'setting': '設置',
|
||||
'project': '項目',
|
||||
current_project: '當前項目',
|
||||
'name': '名稱',
|
||||
'description': '描述',
|
||||
'clear': '清空',
|
||||
|
@ -91,7 +92,8 @@ export default {
|
|||
'remove': '移除',
|
||||
'remove_cancel': '移除取消',
|
||||
'remove_success': '移除成功',
|
||||
'tips': '认認證資訊已過期,請重新登入'
|
||||
'tips': '认認證資訊已過期,請重新登入',
|
||||
'not_performed_yet': '尚未執行',
|
||||
},
|
||||
workspace: {
|
||||
'create': '創建工作空間',
|
||||
|
@ -253,7 +255,8 @@ export default {
|
|||
'resource_pool_is_null': '資源池為空',
|
||||
'download_log_file': '下載完整日誌文件',
|
||||
'pressure_prediction_chart': '壓力預估圖',
|
||||
'user_name': '創建人'
|
||||
'user_name': '創建人',
|
||||
'special_characters_are_not_supported': '測試名稱不支持特殊字符',
|
||||
},
|
||||
api_test: {
|
||||
title: "測試",
|
||||
|
|
Loading…
Reference in New Issue