Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # frontend/src/business/components/api/head/ApiHeaderMenus.vue
This commit is contained in:
commit
ba64fa565c
|
@ -21,8 +21,8 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="getTestPlanTestCases" resultType="io.metersphere.dto.TestPlanCaseDTO">
|
<select id="getTestPlanTestCases" resultType="io.metersphere.dto.TestPlanCaseDTO">
|
||||||
select t1.id as id, t1.plan_id as planId, t1.executor as executor, t1.status as status, t1.results as results, t1.remark remard, t1.create_time as createTime, t1.update_time updateTime,
|
select t1.id as id, t1.plan_id as planId, t1.executor as executor, t1.status as status, t1.results as results, t1.create_time as createTime, t1.update_time updateTime,
|
||||||
t2.id as caseId, t2.node_id as nodeId, t2.node_path as nodePath, t2.project_id as projectId, t2.name as name,
|
t2.id as caseId, t2.node_id as nodeId, t2.node_path as nodePath, t2.project_id as projectId, t2.name as name, t2.remark remark, t2.steps steps,
|
||||||
t2.type as type, t2.maintainer as maintainer, t2.priority as priority, t2.method as method, t2.prerequisite as prerequisite
|
t2.type as type, t2.maintainer as maintainer, t2.priority as priority, t2.method as method, t2.prerequisite as prerequisite
|
||||||
from test_plan_test_case as t1
|
from test_plan_test_case as t1
|
||||||
inner join test_case as t2 on
|
inner join test_case as t2 on
|
||||||
|
|
|
@ -78,12 +78,12 @@ public class ReportController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/content/load_chart/{reportId}")
|
@GetMapping("/content/load_chart/{reportId}")
|
||||||
public ChartsData getLoadChartData(@PathVariable String reportId) {
|
public List<ChartsData> getLoadChartData(@PathVariable String reportId) {
|
||||||
return reportService.getLoadChartData(reportId);
|
return reportService.getLoadChartData(reportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/content/res_chart/{reportId}")
|
@GetMapping("/content/res_chart/{reportId}")
|
||||||
public ChartsData getResponseTimeChartData(@PathVariable String reportId) {
|
public List<ChartsData> getResponseTimeChartData(@PathVariable String reportId) {
|
||||||
return reportService.getResponseTimeChartData(reportId);
|
return reportService.getResponseTimeChartData(reportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,7 @@ package io.metersphere.controller;
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.base.domain.LoadTest;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.domain.TestCase;
|
|
||||||
import io.metersphere.base.domain.TestCaseNode;
|
|
||||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
import io.metersphere.commons.utils.Pager;
|
import io.metersphere.commons.utils.Pager;
|
||||||
import io.metersphere.controller.request.testcase.QueryTestCaseRequest;
|
import io.metersphere.controller.request.testcase.QueryTestCaseRequest;
|
||||||
|
@ -39,8 +36,7 @@ public class TestCaseController {
|
||||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
QueryTestCaseRequest request = new QueryTestCaseRequest();
|
||||||
request.setWorkspaceId(currentWorkspaceId);
|
request.setWorkspaceId(currentWorkspaceId);
|
||||||
PageHelper.startPage(1, count, true);
|
return testCaseService.recentTestPlans(request, count);
|
||||||
return testCaseService.recentTestPlans(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
|
@ -58,6 +54,11 @@ public class TestCaseController {
|
||||||
return testCaseService.getTestCase(testCaseId);
|
return testCaseService.getTestCase(testCaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/project/{testCaseId}")
|
||||||
|
public Project getProjectByTestCaseId(@PathVariable String testCaseId){
|
||||||
|
return testCaseService.getProjectByTestCaseId(testCaseId);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
public void addTestCase(@RequestBody TestCaseWithBLOBs testCase){
|
public void addTestCase(@RequestBody TestCaseWithBLOBs testCase){
|
||||||
testCaseService.addTestCase(testCase);
|
testCaseService.addTestCase(testCase);
|
||||||
|
|
|
@ -28,6 +28,8 @@ public class TestPlanController {
|
||||||
|
|
||||||
@PostMapping("/list/{goPage}/{pageSize}")
|
@PostMapping("/list/{goPage}/{pageSize}")
|
||||||
public Pager<List<TestPlanDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
|
public Pager<List<TestPlanDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
|
||||||
|
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
request.setWorkspaceId(currentWorkspaceId);
|
||||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
return PageUtils.setPageInfo(page, testPlanService.listTestPlan(request));
|
return PageUtils.setPageInfo(page, testPlanService.listTestPlan(request));
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,16 @@ public class WorkspaceController {
|
||||||
|
|
||||||
@PostMapping("special/update")
|
@PostMapping("special/update")
|
||||||
@RequiresRoles(RoleConstants.ADMIN)
|
@RequiresRoles(RoleConstants.ADMIN)
|
||||||
public void updateWorkspacebyAdmin(@RequestBody Workspace workspace) {
|
public void updateWorkspaceByAdmin(@RequestBody Workspace workspace) {
|
||||||
workspaceService.updateWorkspacebyAdmin(workspace);
|
workspaceService.updateWorkspacebyAdmin(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("special/delete/{workspaceId}")
|
||||||
|
@RequiresRoles(RoleConstants.ADMIN)
|
||||||
|
public void deleteWorkspaceByAdmin(@PathVariable String workspaceId) {
|
||||||
|
workspaceService.deleteWorkspace(workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("delete/{workspaceId}")
|
@GetMapping("delete/{workspaceId}")
|
||||||
@RequiresRoles(RoleConstants.ORG_ADMIN)
|
@RequiresRoles(RoleConstants.ORG_ADMIN)
|
||||||
public void deleteWorkspace(@PathVariable String workspaceId) {
|
public void deleteWorkspace(@PathVariable String workspaceId) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package io.metersphere.dto;
|
package io.metersphere.dto;
|
||||||
|
|
||||||
import io.metersphere.base.domain.TestCase;
|
import io.metersphere.base.domain.TestCase;
|
||||||
|
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||||
|
|
||||||
public class TestPlanCaseDTO extends TestCase {
|
public class TestPlanCaseDTO extends TestCaseWithBLOBs {
|
||||||
|
|
||||||
private String executor;
|
private String executor;
|
||||||
private String status;
|
private String status;
|
||||||
private String results;
|
private String results;
|
||||||
private String remark;
|
|
||||||
|
|
||||||
public String getExecutor() {
|
public String getExecutor() {
|
||||||
return executor;
|
return executor;
|
||||||
|
@ -32,12 +32,4 @@ public class TestPlanCaseDTO extends TestCase {
|
||||||
public void setResults(String results) {
|
public void setResults(String results) {
|
||||||
this.results = results;
|
this.results = results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRemark() {
|
|
||||||
return remark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRemark(String remark) {
|
|
||||||
this.remark = remark;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,8 +89,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
processCheckoutConfigTestElement(ele);
|
processCheckoutConfigTestElement(ele);
|
||||||
processCheckoutDnsCacheManager(ele);
|
processCheckoutDnsCacheManager(ele);
|
||||||
processCheckoutArguments(ele);
|
processCheckoutArguments(ele);
|
||||||
// TODO: 2020/4/3 使用断言导致backend-listener不可用
|
processCheckoutResponseAssertion(ele);
|
||||||
// processCheckoutResponseAssertion(ele);
|
|
||||||
} else if (nodeNameEquals(ele, CONCURRENCY_THREAD_GROUP)) {
|
} else if (nodeNameEquals(ele, CONCURRENCY_THREAD_GROUP)) {
|
||||||
processConcurrencyThreadGroup(ele);
|
processConcurrencyThreadGroup(ele);
|
||||||
processCheckoutTimer(ele);
|
processCheckoutTimer(ele);
|
||||||
|
@ -112,8 +111,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
} else if (nodeNameEquals(ele, ARGUMENTS)) {
|
} else if (nodeNameEquals(ele, ARGUMENTS)) {
|
||||||
processArguments(ele);
|
processArguments(ele);
|
||||||
} else if (nodeNameEquals(ele, RESPONSE_ASSERTION)) {
|
} else if (nodeNameEquals(ele, RESPONSE_ASSERTION)) {
|
||||||
// TODO: 2020/4/3 使用断言导致backend-listener不可用
|
processResponseAssertion(ele);
|
||||||
// processResponseAssertion(ele);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +158,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
item.appendChild(collectionProp);
|
item.appendChild(collectionProp);
|
||||||
item.appendChild(createStringProp(document, "Assertion.custom_message", ""));
|
item.appendChild(createStringProp(document, "Assertion.custom_message", ""));
|
||||||
item.appendChild(createStringProp(document, "Assertion.test_field", "Assertion.response_code"));
|
item.appendChild(createStringProp(document, "Assertion.test_field", "Assertion.response_code"));
|
||||||
item.appendChild(createBoolProp(document, "Assertion.assume_success", false));
|
item.appendChild(createBoolProp(document, "Assertion.assume_success", true));
|
||||||
item.appendChild(createIntProp(document, "Assertion.test_type", 40));
|
item.appendChild(createIntProp(document, "Assertion.test_type", 40));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +188,7 @@ public class JmeterDocumentParser implements DocumentParser {
|
||||||
responseAssertion.appendChild(collectionProp);
|
responseAssertion.appendChild(collectionProp);
|
||||||
responseAssertion.appendChild(createStringProp(document, "Assertion.custom_message", ""));
|
responseAssertion.appendChild(createStringProp(document, "Assertion.custom_message", ""));
|
||||||
responseAssertion.appendChild(createStringProp(document, "Assertion.test_field", "Assertion.response_code"));
|
responseAssertion.appendChild(createStringProp(document, "Assertion.test_field", "Assertion.response_code"));
|
||||||
responseAssertion.appendChild(createBoolProp(document, "Assertion.assume_success", false));
|
responseAssertion.appendChild(createBoolProp(document, "Assertion.assume_success", true));
|
||||||
responseAssertion.appendChild(createIntProp(document, "Assertion.test_type", 40));
|
responseAssertion.appendChild(createIntProp(document, "Assertion.test_type", 40));
|
||||||
hashTree.appendChild(responseAssertion);
|
hashTree.appendChild(responseAssertion);
|
||||||
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));
|
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package io.metersphere.report;
|
package io.metersphere.report;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.opencsv.bean.CsvToBean;
|
import com.opencsv.bean.CsvToBean;
|
||||||
import com.opencsv.bean.CsvToBeanBuilder;
|
import com.opencsv.bean.CsvToBeanBuilder;
|
||||||
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
||||||
|
@ -10,6 +9,7 @@ import io.metersphere.report.dto.RequestStatisticsDTO;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -312,18 +312,10 @@ public class JtlResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ChartsData getLoadChartData(String jtlString) {
|
public static List<ChartsData> getLoadChartData(String jtlString) {
|
||||||
ChartsData data = new ChartsData();
|
List<ChartsData> chartsDataList = new ArrayList<>();
|
||||||
List<Metric> totalMetricList = JtlResolver.resolver(jtlString);
|
List<Metric> totalMetricList = JtlResolver.resolver(jtlString);
|
||||||
|
|
||||||
List<String> users = new ArrayList<>();
|
|
||||||
List<String> hits = new ArrayList<>();
|
|
||||||
List<String> errors = new ArrayList<>();
|
|
||||||
List<String> timeList = new ArrayList<>();
|
|
||||||
Map<String, Object> resultMap = new HashMap<>(5);
|
|
||||||
|
|
||||||
DecimalFormat decimalFormat = new DecimalFormat("0.0");
|
|
||||||
|
|
||||||
if (totalMetricList != null) {
|
if (totalMetricList != null) {
|
||||||
for (Metric metric : totalMetricList) {
|
for (Metric metric : totalMetricList) {
|
||||||
metric.setTimestamp(stampToDate(metric.getTimestamp()));
|
metric.setTimestamp(stampToDate(metric.getTimestamp()));
|
||||||
|
@ -331,7 +323,6 @@ public class JtlResolver {
|
||||||
}
|
}
|
||||||
Map<String, List<Metric>> collect = Objects.requireNonNull(totalMetricList).stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
Map<String, List<Metric>> collect = Objects.requireNonNull(totalMetricList).stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
||||||
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(collect.entrySet());
|
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(collect.entrySet());
|
||||||
entries.sort(JtlResolver::sortByDate);
|
|
||||||
|
|
||||||
for (Map.Entry<String, List<Metric>> entry : entries) {
|
for (Map.Entry<String, List<Metric>> entry : entries) {
|
||||||
int failSize = 0;
|
int failSize = 0;
|
||||||
|
@ -344,27 +335,39 @@ public class JtlResolver {
|
||||||
failSize++;
|
failSize++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// todo
|
|
||||||
timeList.add(entry.getKey());
|
|
||||||
hits.add(decimalFormat.format(metrics.size() * 1.0 / maxUsers));
|
|
||||||
users.add(String.valueOf(maxUsers));
|
|
||||||
errors.add(String.valueOf(failSize));
|
|
||||||
|
|
||||||
|
String timeStamp = "";
|
||||||
|
try {
|
||||||
|
timeStamp = formatDate(entry.getKey());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
resultMap.put("users", users);
|
|
||||||
resultMap.put("hits", hits);
|
|
||||||
resultMap.put("errors", errors);
|
|
||||||
|
|
||||||
JSONObject serices = new JSONObject(resultMap);
|
|
||||||
data.setxAxis(StringUtils.join(",", timeList));
|
|
||||||
data.setSerices(serices.toString());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ChartsData getResponseTimeChartData(String jtlString) {
|
|
||||||
ChartsData chartsData = new ChartsData();
|
ChartsData chartsData = new ChartsData();
|
||||||
|
chartsData.setxAxis(timeStamp);
|
||||||
|
chartsData.setGroupName("hits");
|
||||||
|
chartsData.setyAxis(new BigDecimal(metrics.size() * 1.0 / maxUsers));
|
||||||
|
chartsDataList.add(chartsData);
|
||||||
|
|
||||||
|
chartsData = new ChartsData();
|
||||||
|
chartsData.setxAxis(timeStamp);
|
||||||
|
chartsData.setGroupName("users");
|
||||||
|
chartsData.setyAxis(new BigDecimal(maxUsers));
|
||||||
|
chartsDataList.add(chartsData);
|
||||||
|
|
||||||
|
chartsData = new ChartsData();
|
||||||
|
chartsData.setxAxis(timeStamp);
|
||||||
|
chartsData.setGroupName("errors");
|
||||||
|
chartsData.setyAxis(new BigDecimal(failSize));
|
||||||
|
chartsDataList.add(chartsData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return chartsDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ChartsData> getResponseTimeChartData(String jtlString) {
|
||||||
|
List<ChartsData> chartsDataList = new ArrayList<>();
|
||||||
List<Metric> totalMetricList = JtlResolver.resolver(jtlString);
|
List<Metric> totalMetricList = JtlResolver.resolver(jtlString);
|
||||||
|
|
||||||
totalMetricList.forEach(metric -> {
|
totalMetricList.forEach(metric -> {
|
||||||
|
@ -373,29 +376,34 @@ public class JtlResolver {
|
||||||
|
|
||||||
Map<String, List<Metric>> metricMap = totalMetricList.stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
Map<String, List<Metric>> metricMap = totalMetricList.stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
||||||
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(metricMap.entrySet());
|
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(metricMap.entrySet());
|
||||||
entries.sort(JtlResolver::sortByDate);
|
|
||||||
|
|
||||||
List<String> resTimeList = new ArrayList<>();
|
|
||||||
List<String> users = new ArrayList<>();
|
|
||||||
List<String> timestampList = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Map.Entry<String, List<Metric>> entry : entries) {
|
for (Map.Entry<String, List<Metric>> entry : entries) {
|
||||||
List<Metric> metricList = entry.getValue();
|
List<Metric> metricList = entry.getValue();
|
||||||
Map<String, List<Metric>> metricsMap = metricList.stream().collect(Collectors.groupingBy(Metric::getThreadName));
|
Map<String, List<Metric>> metricsMap = metricList.stream().collect(Collectors.groupingBy(Metric::getThreadName));
|
||||||
int maxUsers = metricsMap.size();
|
int maxUsers = metricsMap.size();
|
||||||
int sumElapsedTime = metricList.stream().mapToInt(metric -> Integer.parseInt(metric.getElapsed())).sum();
|
int sumElapsedTime = metricList.stream().mapToInt(metric -> Integer.parseInt(metric.getElapsed())).sum();
|
||||||
timestampList.add(entry.getKey());
|
String timeStamp = "";
|
||||||
users.add(String.valueOf(maxUsers));
|
try {
|
||||||
resTimeList.add(String.valueOf(sumElapsedTime / metricList.size()));
|
timeStamp = formatDate(entry.getKey());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> resultMap = new HashMap<>(2);
|
ChartsData chartsData = new ChartsData();
|
||||||
resultMap.put("users", users);
|
chartsData.setxAxis(timeStamp);
|
||||||
resultMap.put("resTime", resTimeList);
|
chartsData.setGroupName("users");
|
||||||
JSONObject serices = new JSONObject(resultMap);
|
chartsData.setyAxis(new BigDecimal(maxUsers));
|
||||||
chartsData.setxAxis(StringUtils.join(",", timestampList));
|
chartsDataList.add(chartsData);
|
||||||
chartsData.setSerices(serices.toString());
|
|
||||||
return chartsData;
|
ChartsData chartsData2 = new ChartsData();
|
||||||
|
chartsData2.setxAxis(timeStamp);
|
||||||
|
chartsData2.setGroupName("responseTime");
|
||||||
|
chartsData2.setyAxis(new BigDecimal(sumElapsedTime * 1.0 / metricList.size()));
|
||||||
|
chartsDataList.add(chartsData2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return chartsDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String stampToDate(String timeStamp) {
|
private static String stampToDate(String timeStamp) {
|
||||||
|
@ -405,24 +413,14 @@ public class JtlResolver {
|
||||||
return simpleDateFormat.format(date);
|
return simpleDateFormat.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sortByDate(Map.Entry<String, List<Metric>> map1, Map.Entry<String, List<Metric>> map2) {
|
/**
|
||||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
* @param "yyyy-MM-dd HH:mm:ss"
|
||||||
Date date1 = null, date2 = null;
|
* @return "HH:mm:ss"
|
||||||
try {
|
*/
|
||||||
date1 = simpleDateFormat.parse(map1.getKey());
|
private static String formatDate(String dateString) throws ParseException {
|
||||||
date2 = simpleDateFormat.parse(map2.getKey());
|
SimpleDateFormat before = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
} catch (ParseException e) {
|
SimpleDateFormat after = new SimpleDateFormat("HH:mm:ss");
|
||||||
e.printStackTrace();
|
return after.format(before.parse(dateString));
|
||||||
}
|
|
||||||
|
|
||||||
Long time1 = date1.getTime();
|
|
||||||
Long time2 = date2.getTime();
|
|
||||||
|
|
||||||
if (time1.equals(time2)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return time1 > time2 ? 1 : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
|
@ -1,9 +1,33 @@
|
||||||
package io.metersphere.report.base;
|
package io.metersphere.report.base;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
public class ChartsData {
|
public class ChartsData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X 轴
|
||||||
|
*/
|
||||||
private String xAxis;
|
private String xAxis;
|
||||||
private String serices;
|
|
||||||
|
/**
|
||||||
|
* Y 轴
|
||||||
|
*/
|
||||||
|
private BigDecimal yAxis = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Y 轴右侧
|
||||||
|
*/
|
||||||
|
private BigDecimal yAxis2 = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* series 名称
|
||||||
|
*/
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
public String getxAxis() {
|
public String getxAxis() {
|
||||||
return xAxis;
|
return xAxis;
|
||||||
|
@ -13,11 +37,35 @@ public class ChartsData {
|
||||||
this.xAxis = xAxis;
|
this.xAxis = xAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSerices() {
|
public BigDecimal getyAxis() {
|
||||||
return serices;
|
return yAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSerices(String serices) {
|
public void setyAxis(BigDecimal yAxis) {
|
||||||
this.serices=serices;
|
this.yAxis = yAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getyAxis2() {
|
||||||
|
return yAxis2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setyAxis2(BigDecimal yAxis2) {
|
||||||
|
this.yAxis2 = yAxis2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName() {
|
||||||
|
return groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupName(String groupName) {
|
||||||
|
this.groupName = groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,20 +84,20 @@ public class ReportService {
|
||||||
return testOverview;
|
return testOverview;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChartsData getLoadChartData(String id) {
|
public List<ChartsData> getLoadChartData(String id) {
|
||||||
checkReportStatus(id);
|
checkReportStatus(id);
|
||||||
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
|
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
|
||||||
String content = loadTestReport.getContent();
|
String content = loadTestReport.getContent();
|
||||||
ChartsData chartsData = JtlResolver.getLoadChartData(content);
|
List<ChartsData> chartsDataList = JtlResolver.getLoadChartData(content);
|
||||||
return chartsData;
|
return chartsDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChartsData getResponseTimeChartData(String id) {
|
public List<ChartsData> getResponseTimeChartData(String id) {
|
||||||
checkReportStatus(id);
|
checkReportStatus(id);
|
||||||
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
|
LoadTestReportWithBLOBs loadTestReport = loadTestReportMapper.selectByPrimaryKey(id);
|
||||||
String content = loadTestReport.getContent();
|
String content = loadTestReport.getContent();
|
||||||
ChartsData chartsData = JtlResolver.getResponseTimeChartData(content);
|
List<ChartsData> chartsDataList = JtlResolver.getResponseTimeChartData(content);
|
||||||
return chartsData;
|
return chartsDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkReportStatus(String reportId) {
|
public void checkReportStatus(String reportId) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.ProjectMapper;
|
import io.metersphere.base.mapper.ProjectMapper;
|
||||||
import io.metersphere.base.mapper.TestCaseMapper;
|
import io.metersphere.base.mapper.TestCaseMapper;
|
||||||
|
@ -114,7 +115,7 @@ public class TestCaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<TestCase> recentTestPlans(QueryTestCaseRequest request) {
|
public List<TestCase> recentTestPlans(QueryTestCaseRequest request, int count) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(request.getWorkspaceId())) {
|
if (StringUtils.isBlank(request.getWorkspaceId())) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -126,9 +127,23 @@ public class TestCaseService {
|
||||||
List<String> projectIds = projectMapper.selectByExample(projectExample).stream()
|
List<String> projectIds = projectMapper.selectByExample(projectExample).stream()
|
||||||
.map(Project::getId).collect(Collectors.toList());
|
.map(Project::getId).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (projectIds.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageHelper.startPage(1, count, true);
|
||||||
|
|
||||||
TestCaseExample testCaseExample = new TestCaseExample();
|
TestCaseExample testCaseExample = new TestCaseExample();
|
||||||
testCaseExample.createCriteria().andProjectIdIn(projectIds);
|
testCaseExample.createCriteria().andProjectIdIn(projectIds);
|
||||||
testCaseExample.setOrderByClause("update_time desc");
|
testCaseExample.setOrderByClause("update_time desc");
|
||||||
return testCaseMapper.selectByExample(testCaseExample);
|
return testCaseMapper.selectByExample(testCaseExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Project getProjectByTestCaseId(String testCaseId) {
|
||||||
|
TestCaseWithBLOBs testCaseWithBLOBs = testCaseMapper.selectByPrimaryKey(testCaseId);
|
||||||
|
if (testCaseWithBLOBs == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return projectMapper.selectByPrimaryKey(testCaseWithBLOBs.getProjectId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import io.metersphere.controller.request.resourcepool.QueryResourcePoolRequest;
|
||||||
import io.metersphere.dto.NodeDTO;
|
import io.metersphere.dto.NodeDTO;
|
||||||
import io.metersphere.dto.TestResourcePoolDTO;
|
import io.metersphere.dto.TestResourcePoolDTO;
|
||||||
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
|
import io.metersphere.engine.kubernetes.provider.KubernetesProvider;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -83,7 +84,7 @@ public class TestResourcePoolService {
|
||||||
|
|
||||||
private void validateNodes(TestResourcePoolDTO testResourcePool) {
|
private void validateNodes(TestResourcePoolDTO testResourcePool) {
|
||||||
if (CollectionUtils.isEmpty(testResourcePool.getResources())) {
|
if (CollectionUtils.isEmpty(testResourcePool.getResources())) {
|
||||||
MSException.throwException("没有节点信息");
|
MSException.throwException(Translator.get("no_nodes_message"));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteTestResource(testResourcePool.getId());
|
deleteTestResource(testResourcePool.getId());
|
||||||
|
@ -95,7 +96,7 @@ public class TestResourcePoolService {
|
||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (nodeIps.size() < testResourcePool.getResources().size()) {
|
if (nodeIps.size() < testResourcePool.getResources().size()) {
|
||||||
MSException.throwException("节点 IP 重复");
|
MSException.throwException(Translator.get("duplicate_node_ip"));
|
||||||
}
|
}
|
||||||
for (TestResource resource : testResourcePool.getResources()) {
|
for (TestResource resource : testResourcePool.getResources()) {
|
||||||
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
||||||
|
@ -124,7 +125,7 @@ public class TestResourcePoolService {
|
||||||
private void validateK8s(TestResourcePoolDTO testResourcePool) {
|
private void validateK8s(TestResourcePoolDTO testResourcePool) {
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(testResourcePool.getResources()) || testResourcePool.getResources().size() != 1) {
|
if (CollectionUtils.isEmpty(testResourcePool.getResources()) || testResourcePool.getResources().size() != 1) {
|
||||||
throw new RuntimeException("只能添加一个 K8s");
|
throw new RuntimeException(Translator.get("only_one_k8s"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResource testResource = testResourcePool.getResources().get(0);
|
TestResource testResource = testResourcePool.getResources().get(0);
|
||||||
|
|
|
@ -14,5 +14,8 @@
|
||||||
"run_load_test_file_content_not_found": "Cannot run test, cannot get test file content, test ID:",
|
"run_load_test_file_content_not_found": "Cannot run test, cannot get test file content, test ID:",
|
||||||
"run_load_test_file_init_error": "Failed to run test, failed to initialize run environment, test ID:",
|
"run_load_test_file_init_error": "Failed to run test, failed to initialize run environment, test ID:",
|
||||||
"load_test_is_running": "Load test is running, please wait.",
|
"load_test_is_running": "Load test is running, please wait.",
|
||||||
"node_deep_limit": "The node depth does not exceed 5 layers!"
|
"node_deep_limit": "The node depth does not exceed 5 layers!",
|
||||||
|
"no_nodes_message": "No node message",
|
||||||
|
"duplicate_node_ip": "Duplicate IPs",
|
||||||
|
"only_one_k8s": "Only one K8s can be added"
|
||||||
}
|
}
|
|
@ -14,5 +14,8 @@
|
||||||
"run_load_test_file_content_not_found": "无法运行测试,无法获取测试文件内容,测试ID:",
|
"run_load_test_file_content_not_found": "无法运行测试,无法获取测试文件内容,测试ID:",
|
||||||
"run_load_test_file_init_error": "无法运行测试,初始化运行环境失败,测试ID:",
|
"run_load_test_file_init_error": "无法运行测试,初始化运行环境失败,测试ID:",
|
||||||
"load_test_is_running": "测试正在运行, 请等待",
|
"load_test_is_running": "测试正在运行, 请等待",
|
||||||
"node_deep_limit": "节点深度不超过5层!"
|
"node_deep_limit": "节点深度不超过5层!",
|
||||||
|
"no_nodes_message": "没有节点信息",
|
||||||
|
"duplicate_node_ip": "节点 IP 重复",
|
||||||
|
"only_one_k8s": "只能添加一个 K8s"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-col>
|
<el-col>
|
||||||
<header-menus/>
|
<api-header-menus/>
|
||||||
<div>
|
<div>
|
||||||
<transition>
|
<transition>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
|
@ -12,11 +12,11 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import HeaderMenus from "./head/HeaderMenus";
|
import ApiHeaderMenus from "./head/ApiHeaderMenus";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ApiTest",
|
name: "ApiTest",
|
||||||
components: {HeaderMenus},
|
components: {ApiHeaderMenus},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
beaseUrl: "api"
|
beaseUrl: "api"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div id="menu-bar">
|
<div id="menu-bar" v-if="isRouterAlive">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router menu-trigger="click"
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
||||||
:default-active='$route.path'>
|
:default-active='$route.path'>
|
||||||
<el-menu-item :index="'/api/home'">
|
<el-menu-item :index="'/api/home'">
|
||||||
{{ $t("i18n.home") }}
|
{{ $t("i18n.home") }}
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||||
index="4" popper-class="submenu" v-permission="['test_manager', 'test_user']">
|
index="4" popper-class="submenu" v-permission="['test_manager', 'test_user']">
|
||||||
<template v-slot:title>{{$t('commons.test')}}</template>
|
<template v-slot:title>{{$t('commons.test')}}</template>
|
||||||
<api-recent-test-plan/>
|
<api-recent-test/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<el-menu-item :index="'/api/test/all'">
|
<el-menu-item :index="'/api/test/all'">
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
|
@ -33,6 +33,8 @@
|
||||||
<el-menu-item :index="'/api/test/create'">
|
<el-menu-item :index="'/api/test/create'">
|
||||||
<el-button type="text">{{$t('load_test.create')}}</el-button>
|
<el-button type="text">{{$t('load_test.create')}}</el-button>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
|
||||||
|
<el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||||
|
@ -44,6 +46,7 @@
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
<span>{{$t('commons.show_all')}}</span>
|
<span>{{$t('commons.show_all')}}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<router-link v-if="isCurrentWorkspaceUser"
|
<router-link v-if="isCurrentWorkspaceUser"
|
||||||
|
@ -64,15 +67,45 @@
|
||||||
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsMenus",
|
name: "ApiHeaderMenus",
|
||||||
components: {ApiRecentTest, ApiRecentReport, ApiRecentProject},
|
components: {ApiRecentTest, ApiRecentReport, ApiRecentProject},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isCurrentWorkspaceUser: false,
|
isCurrentWorkspaceUser: false,
|
||||||
|
testCaseProjectPath: '',
|
||||||
|
testEditPath: '',
|
||||||
|
reportViewPath: '',
|
||||||
|
isRouterAlive: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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() {
|
mounted() {
|
||||||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reload () {
|
||||||
|
this.isRouterAlive = false;
|
||||||
|
this.$nextTick(function () {
|
||||||
|
this.isRouterAlive = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,4 +148,9 @@
|
||||||
#menu-bar {
|
#menu-bar {
|
||||||
border-bottom: 1px solid #E6E6E6;
|
border-bottom: 1px solid #E6E6E6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blank_item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -214,7 +214,7 @@ const router = new VueRouter({
|
||||||
component: TestCase,
|
component: TestCase,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "plan/:projectId",
|
path: "plan/:type",
|
||||||
name: "testPlan",
|
name: "testPlan",
|
||||||
component: TestPlan
|
component: TestPlan
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-col>
|
<el-col>
|
||||||
<header-menus/>
|
<performance-header-menus/>
|
||||||
<div>
|
<div>
|
||||||
<transition>
|
<transition>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
|
@ -13,11 +13,11 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import HeaderMenus from "./head/HeaderMenus";
|
import PerformanceHeaderMenus from "./head/PerformanceHeaderMenus";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PerformanceTest",
|
name: "PerformanceTest",
|
||||||
components: {HeaderMenus},
|
components: {PerformanceHeaderMenus},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
beaseUrl: "performance"
|
beaseUrl: "performance"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div id="menu-bar">
|
<div id="menu-bar" v-if="isRouterAlive">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
||||||
:default-active='$route.path'>
|
:default-active='$route.path'>
|
||||||
<el-menu-item :index="'/performance/home'">
|
<el-menu-item :index="'/performance/home'">
|
||||||
|
@ -33,6 +33,8 @@
|
||||||
<el-menu-item :index="'/performance/test/create'">
|
<el-menu-item :index="'/performance/test/create'">
|
||||||
<el-button type="text">{{$t('load_test.create')}}</el-button>
|
<el-button type="text">{{$t('load_test.create')}}</el-button>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
|
||||||
|
<el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||||
|
@ -44,6 +46,7 @@
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<router-link v-if="isCurrentWorkspaceUser"
|
<router-link v-if="isCurrentWorkspaceUser"
|
||||||
|
@ -64,20 +67,45 @@
|
||||||
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsMenus",
|
name: "PerformanceHeaderMenus",
|
||||||
components: {PerformanceRecentReport, PerformanceRecentTestPlan, PerformanceRecentProject},
|
components: {PerformanceRecentReport, PerformanceRecentTestPlan, PerformanceRecentProject},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isCurrentWorkspaceUser: false,
|
isCurrentWorkspaceUser: false,
|
||||||
}
|
testCaseProjectPath: '',
|
||||||
},
|
testEditPath: '',
|
||||||
props: {
|
reportViewPath: '',
|
||||||
beaseUrl: {
|
isRouterAlive: true
|
||||||
type: String
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route'(to, from) {
|
||||||
|
let path = to.path;
|
||||||
|
//激活菜单栏
|
||||||
|
if (path.indexOf("/performance/test/") >= 0){
|
||||||
|
this.testCaseProjectPath = '/performance/test/' + this.$route.params.projectId;
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
if (path.indexOf("/performance/test/edit/") >= 0){
|
||||||
|
this.testEditPath = '/performance/test/edit/' + this.$route.params.testId;
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
if (path.indexOf("/performance/report/view/") >= 0){
|
||||||
|
this.reportViewPath = '/performance/report/view/' + this.$route.params.reportId;
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reload () {
|
||||||
|
this.isRouterAlive = false;
|
||||||
|
this.$nextTick(function () {
|
||||||
|
this.isRouterAlive = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,4 +139,8 @@
|
||||||
#menu-bar {
|
#menu-bar {
|
||||||
border-bottom: 1px solid #E6E6E6;
|
border-bottom: 1px solid #E6E6E6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blank_item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -70,7 +70,7 @@
|
||||||
width="150"
|
width="150"
|
||||||
:label="$t('commons.operating')">
|
:label="$t('commons.operating')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button @click="handleEdit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
|
<el-button @click="handleEdit(scope.row)" type="primary" icon="el-icon-s-data" size="mini" circle/>
|
||||||
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
|
@ -105,13 +105,8 @@
|
||||||
color: '#65A2FF'
|
color: '#65A2FF'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {},
|
||||||
bottom: 10,
|
xAxis: {},
|
||||||
data: ['Users', 'Hits/s', 'Error(s)']
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
},
|
|
||||||
yAxis: [{
|
yAxis: [{
|
||||||
name: 'User',
|
name: 'User',
|
||||||
type: 'value',
|
type: 'value',
|
||||||
|
@ -128,28 +123,9 @@
|
||||||
// interval: 5 / 5
|
// interval: 5 / 5
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: [
|
series: []
|
||||||
{
|
|
||||||
name: 'Users',
|
|
||||||
color: '#0CA74A',
|
|
||||||
type: 'line',
|
|
||||||
yAxisIndex: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Hits/s',
|
|
||||||
color: '#65A2FF',
|
|
||||||
type: 'line',
|
|
||||||
yAxisIndex: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Error(s)',
|
|
||||||
color: '#E6113C',
|
|
||||||
type: 'line',
|
|
||||||
yAxisIndex: 1
|
|
||||||
}
|
}
|
||||||
]
|
this.loadOption = this.generateOption(loadOption, data);
|
||||||
}
|
|
||||||
this.loadOption = this.generateLoadOption(loadOption, data);
|
|
||||||
})
|
})
|
||||||
this.$get("/report/content/res_chart/" + this.id, res => {
|
this.$get("/report/content/res_chart/" + this.id, res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
|
@ -162,13 +138,8 @@
|
||||||
color: '#99743C'
|
color: '#99743C'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {},
|
||||||
bottom: 10,
|
xAxis: {},
|
||||||
data: ['Users', 'Response Time']
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category'
|
|
||||||
},
|
|
||||||
yAxis: [{
|
yAxis: [{
|
||||||
name: 'User',
|
name: 'User',
|
||||||
type: 'value',
|
type: 'value',
|
||||||
|
@ -182,77 +153,40 @@
|
||||||
min: 0
|
min: 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: [
|
series: []
|
||||||
{
|
}
|
||||||
name: 'Users',
|
this.resOption = this.generateOption(resOption, data);
|
||||||
color: '#0CA74A',
|
})
|
||||||
|
},
|
||||||
|
generateOption(option, data) {
|
||||||
|
let chartData = data;
|
||||||
|
let legend = [], series = {}, xAxis = [], seriesData = [];
|
||||||
|
chartData.forEach(item => {
|
||||||
|
if (!xAxis.includes(item.xAxis)) {
|
||||||
|
xAxis.push(item.xAxis);
|
||||||
|
}
|
||||||
|
xAxis.sort()
|
||||||
|
let name = item.groupName
|
||||||
|
if (!legend.includes(name)) {
|
||||||
|
legend.push(name)
|
||||||
|
series[name] = []
|
||||||
|
}
|
||||||
|
series[name].splice(xAxis.indexOf(item.xAxis), 0, item.yAxis.toFixed(2));
|
||||||
|
})
|
||||||
|
this.$set(option.legend, "data", legend);
|
||||||
|
this.$set(option.legend, "bottom", 10);
|
||||||
|
this.$set(option.xAxis, "data", xAxis);
|
||||||
|
for (let name in series) {
|
||||||
|
let data = series[name];
|
||||||
|
let items = {
|
||||||
|
name: name,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
yAxisIndex: 0
|
data: data
|
||||||
},
|
};
|
||||||
{
|
seriesData.push(items);
|
||||||
name: 'Response Time',
|
|
||||||
color: '#99743C',
|
|
||||||
type: 'line',
|
|
||||||
yAxisIndex: 1
|
|
||||||
}
|
}
|
||||||
]
|
this.$set(option, "series", seriesData);
|
||||||
}
|
return option;
|
||||||
this.resOption = this.generateResponseOption(resOption, data);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
_objToStrMap(obj){
|
|
||||||
let strMap = new Map();
|
|
||||||
for (let k of Object.keys(obj)) {
|
|
||||||
strMap.set(k,obj[k]);
|
|
||||||
}
|
|
||||||
return strMap;
|
|
||||||
},
|
|
||||||
_jsonToMap(jsonStr){
|
|
||||||
return this._objToStrMap(JSON.parse(jsonStr));
|
|
||||||
},
|
|
||||||
generateLoadOption(loadOption, data) {
|
|
||||||
let map = this._jsonToMap(data.serices);
|
|
||||||
let xAxis = data.xAxis;
|
|
||||||
this.$set(loadOption.xAxis, "data", xAxis.split(','));
|
|
||||||
let user = map.get("users").slice(0);
|
|
||||||
let hit = map.get("hits").slice(0);
|
|
||||||
user.sort(function (a,b) {
|
|
||||||
return parseInt(a) - parseInt(b);
|
|
||||||
})
|
|
||||||
hit.sort(function (a,b) {
|
|
||||||
return parseFloat(a) - parseFloat(b);
|
|
||||||
})
|
|
||||||
this.$set(loadOption.yAxis[0], "max",user[user.length-1]);
|
|
||||||
this.$set(loadOption.yAxis[0], "interval", user[user.length-1]/5);
|
|
||||||
this.$set(loadOption.yAxis[1], "max", hit[hit.length-1]);
|
|
||||||
this.$set(loadOption.yAxis[1], "interval", hit[hit.length-1]/5);
|
|
||||||
|
|
||||||
this.$set(loadOption.series[0], "data", map.get("users"));
|
|
||||||
this.$set(loadOption.series[1], "data", map.get("hits"));
|
|
||||||
this.$set(loadOption.series[2], "data", map.get("errors"));
|
|
||||||
return loadOption;
|
|
||||||
},
|
|
||||||
generateResponseOption(resOption, data) {
|
|
||||||
let map = this._jsonToMap(data.serices);
|
|
||||||
let user = map.get("users").slice(0);
|
|
||||||
let res = map.get("resTime").slice(0);
|
|
||||||
user.sort(function (a,b) {
|
|
||||||
return parseInt(a) - parseInt(b);
|
|
||||||
})
|
|
||||||
res.sort(function (a,b) {
|
|
||||||
return parseFloat(a) - parseFloat(b);
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$set(resOption.yAxis[0], "max",user[user.length-1]);
|
|
||||||
this.$set(resOption.yAxis[0], "interval", user[user.length-1]/5);
|
|
||||||
this.$set(resOption.yAxis[1], "max", res[res.length-1]);
|
|
||||||
this.$set(resOption.yAxis[1], "interval", res[res.length-1]/5);
|
|
||||||
|
|
||||||
let xAxis = data.xAxis;
|
|
||||||
this.$set(resOption.xAxis, "data", xAxis.split(','));
|
|
||||||
this.$set(resOption.series[0], "data", map.get("users"));
|
|
||||||
this.$set(resOption.series[1], "data", map.get("resTime"));
|
|
||||||
return resOption;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<script>
|
<script>
|
||||||
import MsCreateBox from "../settings/CreateBox";
|
import MsCreateBox from "../settings/CreateBox";
|
||||||
import {Message} from "element-ui";
|
import {Message} from "element-ui";
|
||||||
import {CURRENT_PROJECT, TokenKey} from "../../../common/constants";
|
import {TokenKey} from "../../../common/constants";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsProject",
|
name: "MsProject",
|
||||||
|
@ -168,10 +168,6 @@
|
||||||
this.$get('/project/delete/' + row.id, () => {
|
this.$get('/project/delete/' + row.id, () => {
|
||||||
Message.success(this.$t('commons.delete_success'));
|
Message.success(this.$t('commons.delete_success'));
|
||||||
this.list();
|
this.list();
|
||||||
let currentProject = JSON.parse(localStorage.getItem(CURRENT_PROJECT));
|
|
||||||
if(currentProject && row.id === currentProject.id){
|
|
||||||
localStorage.removeItem(CURRENT_PROJECT);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
<el-table-column prop="organizationName" :label="$t('workspace.organization_name')"/>
|
<el-table-column prop="organizationName" :label="$t('workspace.organization_name')"/>
|
||||||
<el-table-column :label="$t('commons.member')">
|
<el-table-column :label="$t('commons.member')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-button type="text" class="member-size" @click="cellClick(scope.row)">{{scope.row.memberSize}}</el-button>
|
<el-button type="text" class="member-size" @click="cellClick(scope.row)">{{scope.row.memberSize}}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
|
@ -63,7 +64,8 @@
|
||||||
<el-input type="textarea" v-model="form.description"></el-input>
|
<el-input type="textarea" v-model="form.description"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
||||||
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')" class="select-width">
|
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||||
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in form.orgList"
|
v-for="item in form.orgList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -90,7 +92,8 @@
|
||||||
<el-input type="textarea" v-model="form.description"></el-input>
|
<el-input type="textarea" v-model="form.description"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
||||||
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')" class="select-width">
|
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||||
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in form.orgList1"
|
v-for="item in form.orgList1"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -102,7 +105,8 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" @click="updateWorkspace('updateForm')" size="medium">{{$t('commons.save')}}</el-button>
|
<el-button type="primary" @click="updateWorkspace('updateForm')"
|
||||||
|
size="medium">{{$t('commons.save')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -160,10 +164,13 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- add workspace member dialog -->
|
<!-- add workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.create')" :visible.sync="addMemberVisible" width="30%" :destroy-on-close="true"
|
||||||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px" size="small">
|
@close="closeFunc">
|
||||||
|
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
||||||
|
size="small">
|
||||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')" class="select-width">
|
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||||
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in memberForm.userList"
|
v-for="item in memberForm.userList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -175,7 +182,8 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||||
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in memberForm.roles"
|
v-for="item in memberForm.roles"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -193,7 +201,8 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- update workspace member dialog -->
|
<!-- update workspace member dialog -->
|
||||||
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true" @close="closeFunc">
|
<el-dialog :title="$t('member.modify')" :visible.sync="updateMemberVisible" width="30%" :destroy-on-close="true"
|
||||||
|
@close="closeFunc">
|
||||||
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
<el-form :model="memberForm" label-position="right" label-width="100px" size="small" ref="updateUserForm">
|
||||||
<el-form-item label="ID" prop="id">
|
<el-form-item label="ID" prop="id">
|
||||||
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
<el-input v-model="memberForm.id" autocomplete="off" :disabled="true"/>
|
||||||
|
@ -208,7 +217,8 @@
|
||||||
<el-input v-model="memberForm.phone" autocomplete="off"/>
|
<el-input v-model="memberForm.phone" autocomplete="off"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
|
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||||
|
class="select-width">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in memberForm.allroles"
|
v-for="item in memberForm.allroles"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
@ -220,7 +230,8 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button type="primary" @click="updateOrgMember('updateUserForm')" size="medium">{{$t('commons.save')}}</el-button>
|
<el-button type="primary" @click="updateOrgMember('updateUserForm')"
|
||||||
|
size="medium">{{$t('commons.save')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -254,7 +265,7 @@
|
||||||
if (this.form.id) {
|
if (this.form.id) {
|
||||||
saveType = 'update'
|
saveType = 'update'
|
||||||
}
|
}
|
||||||
this.$post("/workspace/" + saveType, this.form, () => {
|
this.result = this.$post("/workspace/" + saveType, this.form, () => {
|
||||||
this.createVisible = false;
|
this.createVisible = false;
|
||||||
this.list();
|
this.list();
|
||||||
Message.success(this.$t('commons.save_success'));
|
Message.success(this.$t('commons.save_success'));
|
||||||
|
@ -327,7 +338,7 @@
|
||||||
cancelButtonText: this.$t('commons.cancel'),
|
cancelButtonText: this.$t('commons.cancel'),
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$get('/workspace/delete/' + row.id, () => {
|
this.$get('/workspace/special/delete/' + row.id, () => {
|
||||||
Message.success(this.$t('commons.delete_success'));
|
Message.success(this.$t('commons.delete_success'));
|
||||||
this.list();
|
this.list();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-col>
|
<el-col>
|
||||||
<header-menus/>
|
<track-header-menus/>
|
||||||
<div>
|
<div>
|
||||||
<transition>
|
<transition>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
|
@ -13,11 +13,11 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import HeaderMenus from "./head/HeaderMenus";
|
import TrackHeaderMenus from "./head/TrackHeaderMenus";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TrackHome",
|
name: "TrackHome",
|
||||||
components: {HeaderMenus},
|
components: {TrackHeaderMenus},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
beaseUrl: "track"
|
beaseUrl: "track"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<label v-for="(item,index) in projects" :key="index">
|
<label v-for="(item,index) in projects" :key="index">
|
||||||
<el-menu-item @click="changeProject(item)">
|
<el-menu-item @click="changeProject(item)">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
<i class="el-icon-check" v-if="item.id === currentProject.id"></i>
|
<i class="el-icon-check" v-if="currentProject && item.id === currentProject.id"></i>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</label>
|
</label>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<node-tree class="node_tree"
|
<node-tree class="node_tree"
|
||||||
|
:current-project="currentProject"
|
||||||
@nodeSelectEvent="refreshTable"
|
@nodeSelectEvent="refreshTable"
|
||||||
@refresh="refreshTable"
|
@refresh="refreshTable"
|
||||||
ref="nodeTree"></node-tree>
|
ref="nodeTree"></node-tree>
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
<el-main class="main-content">
|
<el-main class="main-content">
|
||||||
|
|
||||||
<test-case-list
|
<test-case-list
|
||||||
|
:current-project="currentProject"
|
||||||
@openTestCaseEditDialog="openTestCaseEditDialog"
|
@openTestCaseEditDialog="openTestCaseEditDialog"
|
||||||
@testCaseEdit="openTestCaseEditDialog"
|
@testCaseEdit="openTestCaseEditDialog"
|
||||||
ref="testCaseList"></test-case-list>
|
ref="testCaseList"></test-case-list>
|
||||||
|
@ -67,50 +69,56 @@
|
||||||
total: 0,
|
total: 0,
|
||||||
loadingRequire: {project: true, testCase: true},
|
loadingRequire: {project: true, testCase: true},
|
||||||
projects: [],
|
projects: [],
|
||||||
initProjects: [],
|
|
||||||
currentProject: null,
|
currentProject: null,
|
||||||
treeNodes: []
|
treeNodes: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function () {
|
created() {
|
||||||
this.caseId = this.$route.params.caseId;
|
|
||||||
this.getProjects();
|
this.getProjects();
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.$route.path.indexOf("/track/case/edit") >= 0){
|
||||||
|
this.openRecentTestCaseEditDialog();
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to, from) {
|
'$route'(to, from) {
|
||||||
let path = to.path;
|
let path = to.path;
|
||||||
if (path.indexOf("/track/case/all") >= 0){
|
if (path.indexOf("/track/case/all") >= 0){
|
||||||
this.getProjects();
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
if (path.indexOf("/track/case/edit") >= 0){
|
if (path.indexOf("/track/case/edit") >= 0){
|
||||||
let caseId = this.$route.params.caseId;
|
this.openRecentTestCaseEditDialog();
|
||||||
this.$get('/test/case/get/' + caseId, response => {
|
this.$router.push('/track/case/all');
|
||||||
console.log(response.data);
|
|
||||||
this.openTestCaseEditDialog(response.data[0]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getProjects() {
|
getProjects() {
|
||||||
this.$get("/project/listAll", (response) => {
|
this.$get("/project/listAll", (response) => {
|
||||||
if (response.success) {
|
|
||||||
this.projects = response.data;
|
this.projects = response.data;
|
||||||
this.initProjects = this.projects.slice(0, 4);
|
|
||||||
if (localStorage.getItem(CURRENT_PROJECT)) {
|
if (localStorage.getItem(CURRENT_PROJECT)) {
|
||||||
this.currentProject = JSON.parse(localStorage.getItem(CURRENT_PROJECT));
|
let lastProject = JSON.parse(localStorage.getItem(CURRENT_PROJECT));
|
||||||
} else {
|
let hasCurrentProject = false;
|
||||||
this.currentProject = this.projects[0];
|
for (let i = 0; i < this.projects.length; i++) {
|
||||||
|
if (this.projects[i].id == lastProject.id) {
|
||||||
|
this.currentProject = lastProject;
|
||||||
|
hasCurrentProject = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasCurrentProject) {
|
||||||
|
this.currentProject = null;
|
||||||
|
}
|
||||||
if(this.projects.length > 0){
|
if(this.projects.length > 0){
|
||||||
|
this.currentProject = this.projects[0];
|
||||||
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(this.projects[0]));
|
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(this.projects[0]));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.$message()({
|
if(this.projects.length > 0){
|
||||||
type: 'warning',
|
this.currentProject = this.projects[0];
|
||||||
message: response.message
|
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(this.projects[0]));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
this.loadingRequire.project = false;
|
this.loadingRequire.project = false;
|
||||||
// this.checkProject();
|
// this.checkProject();
|
||||||
|
@ -164,9 +172,24 @@
|
||||||
this.$refs.testCaseEditDialog.maintainerOptions = response.data;
|
this.$refs.testCaseEditDialog.maintainerOptions = response.data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getProjectByCaseId(caseId) {
|
||||||
|
return this.$get('/test/case/project/' + caseId, async response => {
|
||||||
|
localStorage.setItem(CURRENT_PROJECT, JSON.stringify(response.data));
|
||||||
|
this.refresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.$refs.testCaseList.initTableData();
|
this.$refs.testCaseList.initTableData();
|
||||||
this.$refs.nodeTree.getNodeTree();
|
this.$refs.nodeTree.getNodeTree();
|
||||||
|
this.getProjects();
|
||||||
|
},
|
||||||
|
openRecentTestCaseEditDialog() {
|
||||||
|
let caseId = this.$route.params.caseId;
|
||||||
|
this.getProjectByCaseId(caseId);
|
||||||
|
this.refresh();
|
||||||
|
this.$get('/test/case/get/' + caseId, response => {
|
||||||
|
this.openTestCaseEditDialog(response.data[0]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,17 @@
|
||||||
defaultKeys: []
|
defaultKeys: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
currentProject: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
filterText(val) {
|
filterText(val) {
|
||||||
this.$refs.tree.filter(val);
|
this.$refs.tree.filter(val);
|
||||||
|
},
|
||||||
|
currentProject() {
|
||||||
|
this.getNodeTree();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -163,8 +171,8 @@
|
||||||
this.dialogFormVisible = true;
|
this.dialogFormVisible = true;
|
||||||
},
|
},
|
||||||
getNodeTree() {
|
getNodeTree() {
|
||||||
if (localStorage.getItem(CURRENT_PROJECT)) {
|
if (this.currentProject) {
|
||||||
let projectId = JSON.parse(localStorage.getItem(CURRENT_PROJECT)).id;
|
let projectId = this.currentProject.id;
|
||||||
this.$get("/case/node/list/" + projectId, response => {
|
this.$get("/case/node/list/" + projectId, response => {
|
||||||
this.treeNodes = response.data;
|
this.treeNodes = response.data;
|
||||||
});
|
});
|
||||||
|
|
|
@ -103,13 +103,16 @@
|
||||||
:data="form.steps"
|
:data="form.steps"
|
||||||
class="tb-edit"
|
class="tb-edit"
|
||||||
border
|
border
|
||||||
|
size="mini"
|
||||||
:default-sort = "{prop: 'num', order: 'ascending'}"
|
:default-sort = "{prop: 'num', order: 'ascending'}"
|
||||||
highlight-current-row>
|
highlight-current-row>
|
||||||
<el-table-column :label="$t('test_track.number')" prop="num" min-width="15%"></el-table-column>
|
<el-table-column :label="$t('test_track.number')" prop="num" min-width="15%"></el-table-column>
|
||||||
<el-table-column :label="$t('test_track.step_desc')" prop="desc" min-width="35%">
|
<el-table-column :label="$t('test_track.step_desc')" prop="desc" min-width="35%">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-input
|
<el-input
|
||||||
size="small"
|
size="mini"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
v-model="scope.row.desc"
|
v-model="scope.row.desc"
|
||||||
:placeholder="$t('commons.input_content')"
|
:placeholder="$t('commons.input_content')"
|
||||||
clearable></el-input>
|
clearable></el-input>
|
||||||
|
@ -119,7 +122,9 @@
|
||||||
<el-table-column :label="$t('test_track.expected_results')" prop="result" min-width="35%">
|
<el-table-column :label="$t('test_track.expected_results')" prop="result" min-width="35%">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-input
|
<el-input
|
||||||
size="small"
|
size="mini"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
v-model="scope.row.result"
|
v-model="scope.row.result"
|
||||||
:placeholder="$t('commons.input_content')"
|
:placeholder="$t('commons.input_content')"
|
||||||
clearable></el-input>
|
clearable></el-input>
|
||||||
|
@ -304,13 +309,13 @@
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.tb-edit .el-input {
|
.tb-edit .el-textarea {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.tb-edit .current-row .el-input {
|
.tb-edit .current-row .el-textarea {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.tb-edit .current-row .el-input+span {
|
.tb-edit .current-row .el-textarea+span {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,10 +139,19 @@
|
||||||
testId: null
|
testId: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
currentProject: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
|
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
currentProject() {
|
||||||
|
this.initTableData();
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initTableData(nodeIds) {
|
initTableData(nodeIds) {
|
||||||
let param = {
|
let param = {
|
||||||
|
@ -150,16 +159,15 @@
|
||||||
};
|
};
|
||||||
param.nodeIds = nodeIds;
|
param.nodeIds = nodeIds;
|
||||||
|
|
||||||
if(localStorage.getItem(CURRENT_PROJECT)) {
|
if (this.currentProject) {
|
||||||
param.projectId = JSON.parse(localStorage.getItem(CURRENT_PROJECT)).id;
|
param.projectId = this.currentProject.id;
|
||||||
}
|
|
||||||
|
|
||||||
this.$post(this.buildPagePath('/test/case/list'), param, response => {
|
this.$post(this.buildPagePath('/test/case/list'), param, response => {
|
||||||
this.loadingRequire.testCase = false;
|
this.loadingRequire.testCase = false;
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
this.total = data.itemCount;
|
this.total = data.itemCount;
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div id="menu-bar">
|
<div id="menu-bar" v-if="isRouterAlive">
|
||||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router
|
||||||
:default-active='$route.path'>
|
:default-active='$route.path'>
|
||||||
<el-menu-item :index="'/track/home'">
|
<el-menu-item :index="'/track/home'">
|
||||||
|
@ -30,9 +30,7 @@
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
<span style="padding-left: 5px;">{{$t('test_track.case_list')}}</span>
|
<span style="padding-left: 5px;">{{$t('test_track.case_list')}}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<!--<el-menu-item :index="'/' + beaseUrl + '/case/create'">-->
|
<el-menu-item :index="testCaseEditPath" class="blank_item"></el-menu-item>
|
||||||
<!--<el-button type="text">{{$t('test_track.create_case')}}</el-button>-->
|
|
||||||
<!--</el-menu-item>-->
|
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||||
|
@ -40,11 +38,12 @@
|
||||||
<template v-slot:title>{{$t('test_track.test_plan')}}</template>
|
<template v-slot:title>{{$t('test_track.test_plan')}}</template>
|
||||||
<recent-test-plan/>
|
<recent-test-plan/>
|
||||||
<el-divider/>
|
<el-divider/>
|
||||||
<el-menu-item :index="'/track/plan/all'">
|
<el-menu-item index="/track/plan/all">
|
||||||
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
<font-awesome-icon :icon="['fa', 'list-ul']"/>
|
||||||
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
<span style="padding-left: 5px;">{{$t('commons.show_all')}}</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<el-menu-item :index="'/track/plan/create'">
|
<el-menu-item :index="testPlanViewPath" class="blank_item"></el-menu-item>
|
||||||
|
<el-menu-item index="/track/plan/create">
|
||||||
<el-button type="text">{{$t('test_track.create_plan')}}</el-button>
|
<el-button type="text">{{$t('test_track.create_plan')}}</el-button>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
@ -53,7 +52,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
import {checkoutCurrentWorkspace} from "../../../../common/utils";
|
||||||
|
@ -62,25 +60,45 @@
|
||||||
import RecentTestPlan from "../plan/components/RecentTestPlan";
|
import RecentTestPlan from "../plan/components/RecentTestPlan";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsMenus",
|
name: "TrackHeaderMenus",
|
||||||
components: {RecentTestCase, TrackRecentProject, RecentTestPlan},
|
components: {RecentTestCase, TrackRecentProject, RecentTestPlan},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isCurrentWorkspaceUser: false,
|
isCurrentWorkspaceUser: false,
|
||||||
|
testPlanViewPath: '',
|
||||||
|
isRouterAlive: true,
|
||||||
|
testCaseEditPath: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
watch: {
|
||||||
beaseUrl: {
|
'$route'(to, from) {
|
||||||
type: String
|
let path = to.path;
|
||||||
|
if (path.indexOf("/track/plan/view") >= 0){
|
||||||
|
this.testPlanViewPath = '/track/plan/view/' + this.$route.params.planId;
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
if (path.indexOf("/track/case/edit") >= 0){
|
||||||
|
this.testCaseEditPath = '/track/case/edit/' + this.$route.params.caseId;
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reload () {
|
||||||
|
this.isRouterAlive = false;
|
||||||
|
this.$nextTick(function () {
|
||||||
|
this.isRouterAlive = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.header-menu.el-menu--horizontal > li {
|
.header-menu.el-menu--horizontal > li {
|
||||||
|
@ -100,6 +118,8 @@
|
||||||
margin-left: 20%;
|
margin-left: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -109,4 +129,8 @@
|
||||||
#menu-bar {
|
#menu-bar {
|
||||||
border-bottom: 1px solid #E6E6E6;
|
border-bottom: 1px solid #E6E6E6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blank_item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -25,6 +25,20 @@
|
||||||
return {
|
return {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.$route.path.indexOf("/track/plan/create") >= 0){
|
||||||
|
this.openTestPlanEditDialog();
|
||||||
|
this.$router.push('/track/plan/all');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$route'(to, from) {
|
||||||
|
if (to.path.indexOf("/track/plan/create") >= 0){
|
||||||
|
this.openTestPlanEditDialog();
|
||||||
|
this.$router.push('/track/plan/all');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openTestPlanEditDialog(data) {
|
openTestPlanEditDialog(data) {
|
||||||
this.$refs.testPlanEditDialog.openTestPlanEditDialog(data);
|
this.$refs.testPlanEditDialog.openTestPlanEditDialog(data);
|
||||||
|
|
|
@ -13,19 +13,20 @@
|
||||||
<test-case-plan-list
|
<test-case-plan-list
|
||||||
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
|
@openTestCaseRelevanceDialog="openTestCaseRelevanceDialog"
|
||||||
@editTestPlanTestCase="editTestPlanTestCase"
|
@editTestPlanTestCase="editTestPlanTestCase"
|
||||||
|
@refresh="refresh"
|
||||||
:plan-id="planId"
|
:plan-id="planId"
|
||||||
ref="testCasePlanList"></test-case-plan-list>
|
ref="testCasePlanList"></test-case-plan-list>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
|
|
||||||
<test-case-relevance
|
<test-case-relevance
|
||||||
@refresh="getPlanCases"
|
@refresh="refresh"
|
||||||
:plan-id="planId"
|
:plan-id="planId"
|
||||||
ref="testCaseRelevance"></test-case-relevance>
|
ref="testCaseRelevance"></test-case-relevance>
|
||||||
|
|
||||||
<test-plan-test-case-edit
|
<test-plan-test-case-edit
|
||||||
ref="testPlanTestCaseEdit"
|
ref="testPlanTestCaseEdit"
|
||||||
@refresh="getPlanCases">
|
@refresh="refresh">
|
||||||
</test-plan-test-case-edit>
|
</test-plan-test-case-edit>
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +66,8 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
refresh() {
|
refresh() {
|
||||||
|
this.getPlanCases();
|
||||||
|
this.getNodeTreeByPlanId();
|
||||||
},
|
},
|
||||||
getPlanCases(nodeIds) {
|
getPlanCases(nodeIds) {
|
||||||
this.$refs.testCasePlanList.initTableData(nodeIds);
|
this.$refs.testCasePlanList.initTableData(nodeIds);
|
||||||
|
@ -84,6 +86,16 @@
|
||||||
let item = {};
|
let item = {};
|
||||||
Object.assign(item, testCase);
|
Object.assign(item, testCase);
|
||||||
item.results = JSON.parse(item.results);
|
item.results = JSON.parse(item.results);
|
||||||
|
item.steps = JSON.parse(item.steps);
|
||||||
|
|
||||||
|
item.steptResults = [];
|
||||||
|
for (let i = 0; i < item.steps.length; i++){
|
||||||
|
if(item.results[i]){
|
||||||
|
item.steps[i].actualResult = item.results[i].actualResult;
|
||||||
|
item.steps[i].executeResult = item.results[i].executeResult;
|
||||||
|
}
|
||||||
|
item.steptResults.push(item.steps[i]);
|
||||||
|
}
|
||||||
this.$refs.testPlanTestCaseEdit.testCase = item;
|
this.$refs.testPlanTestCaseEdit.testCase = item;
|
||||||
this.$refs.testPlanTestCaseEdit.dialog = true;
|
this.$refs.testPlanTestCaseEdit.dialog = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@
|
||||||
let testCaseId = testCase.id;
|
let testCaseId = testCase.id;
|
||||||
this.$post('/test/plan/case/delete/' + testCaseId, {}, () => {
|
this.$post('/test/plan/case/delete/' + testCaseId, {}, () => {
|
||||||
this.initTableData();
|
this.initTableData();
|
||||||
|
this.$emit("refresh");
|
||||||
this.$message({
|
this.$message({
|
||||||
message: this.$t('commons.delete_success'),
|
message: this.$t('commons.delete_success'),
|
||||||
type: 'success'
|
type: 'success'
|
||||||
|
|
|
@ -237,4 +237,8 @@
|
||||||
margin-right: -9px;
|
margin-right: -9px;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
size="100%"
|
size="100%"
|
||||||
ref="drawer">
|
ref="drawer">
|
||||||
|
|
||||||
<div>
|
<div class="case_container">
|
||||||
|
|
||||||
<el-row >
|
<el-row >
|
||||||
<el-col :span="4" :offset="1">
|
<el-col :span="4" :offset="1">
|
||||||
<span class="cast_label">{{$t('test_track.priority')}}:</span>
|
<span class="cast_label">{{$t('test_track.priority')}}:</span>
|
||||||
|
@ -35,6 +34,70 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="20" :offset="1">
|
||||||
|
<el-table
|
||||||
|
:data="testCase.steptResults"
|
||||||
|
class="tb-edit"
|
||||||
|
size="mini"
|
||||||
|
height="200px"
|
||||||
|
:default-sort = "{prop: 'num', order: 'ascending'}"
|
||||||
|
highlight-current-row>
|
||||||
|
<el-table-column :label="$t('test_track.number')" prop="num" min-width="5%"></el-table-column>
|
||||||
|
<el-table-column :label="$t('test_track.step_desc')" prop="desc" min-width="29%">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{scope.row.desc}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('test_track.expected_results')" prop="result" min-width="28%">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{scope.row.result}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('test_track.actual_result')" min-width="29%">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<el-input
|
||||||
|
size="mini"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
|
v-model="scope.row.actualResult"
|
||||||
|
:placeholder="$t('commons.input_content')"
|
||||||
|
clearable></el-input>
|
||||||
|
<span>{{scope.row.actualResult}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('test_track.step_result')" min-width="9%">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<el-select
|
||||||
|
v-model="scope.row.executeResult"
|
||||||
|
size="mini">
|
||||||
|
<el-option :label="$t('test_track.pass')" value="Pass"></el-option>
|
||||||
|
<el-option :label="$t('test_track.failure')" value="Failure"></el-option>
|
||||||
|
<el-option :label="$t('test_track.blocking')" value="Blocking"></el-option>
|
||||||
|
<el-option :label="$t('test_track.skip')" value="Skip"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row >
|
||||||
|
<el-col :span="15" :offset="1">
|
||||||
|
<div style="margin-bottom: 5px;">
|
||||||
|
<span class="cast_label">{{$t('commons.remark')}}:</span>
|
||||||
|
<span v-if="testCase.remark == null || testCase.remark == ''" style="color: darkgrey">{{$t('commons.not_filled')}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-input :rows="3"
|
||||||
|
type="textarea"
|
||||||
|
v-if="testCase.remark"
|
||||||
|
disabled
|
||||||
|
v-model="testCase.remark"></el-input>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :offset="1" :span="2">
|
<el-col :offset="1" :span="2">
|
||||||
<el-button type="success" round
|
<el-button type="success" round
|
||||||
|
@ -58,57 +121,6 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="20" :offset="1">
|
|
||||||
<el-table
|
|
||||||
:data="testCase.results"
|
|
||||||
class="tb-edit"
|
|
||||||
:default-sort = "{prop: 'num', order: 'ascending'}"
|
|
||||||
highlight-current-row>
|
|
||||||
<el-table-column :label="$t('test_track.number')" prop="num" min-width="8%"></el-table-column>
|
|
||||||
<el-table-column :label="$t('test_track.step_desc')" prop="desc" min-width="30%">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span>{{scope.row.desc}}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column :label="$t('test_track.expected_results')" prop="result" min-width="30%">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<span>{{scope.row.result}}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column :label="$t('test_track.actual_result')" min-width="30%">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-input
|
|
||||||
size="small"
|
|
||||||
v-model="scope.row.actualResult"
|
|
||||||
:placeholder="$t('commons.input_content')"
|
|
||||||
clearable></el-input>
|
|
||||||
<span>{{scope.row.actualResult}}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column :label="$t('test_track.step_result')" min-width="15%">
|
|
||||||
<template v-slot:default="scope">
|
|
||||||
<el-select v-model="scope.row.stepResult" :placeholder="$t('test_track.select_execute_result')">
|
|
||||||
<el-option :label="$t('test_track.pass')" value="Pass"></el-option>
|
|
||||||
<el-option :label="$t('test_track.failure')" value="Failure"></el-option>
|
|
||||||
<el-option :label="$t('test_track.blocking')" value="Blocking"></el-option>
|
|
||||||
<el-option :label="$t('test_track.skip')" value="Skip"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row >
|
|
||||||
<el-col :span="40" :offset="1">
|
|
||||||
<span>{{$t('commons.remark')}}:</span>
|
|
||||||
<span>{{testCase.remark}}</span>
|
|
||||||
<span v-if="testCase.remark == null" style="color: gainsboro">{{$t('commons.not_filled')}}</span>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row type="flex" justify="end">
|
<el-row type="flex" justify="end">
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<div>
|
<div>
|
||||||
|
@ -146,7 +158,14 @@
|
||||||
let param = {};
|
let param = {};
|
||||||
param.id = this.testCase.id;
|
param.id = this.testCase.id;
|
||||||
param.status = this.testCase.status;
|
param.status = this.testCase.status;
|
||||||
param.results = JSON.stringify(this.testCase.results);
|
param.results = [];
|
||||||
|
this.testCase.steptResults.forEach(item => {
|
||||||
|
let result = {};
|
||||||
|
result.actualResult = item.actualResult;
|
||||||
|
result.executeResult = item.executeResult;
|
||||||
|
param.results.push(result);
|
||||||
|
});
|
||||||
|
param.results = JSON.stringify(param.results);
|
||||||
this.$post('/test/plan/case/edit', param, () => {
|
this.$post('/test/plan/case/edit', param, () => {
|
||||||
this.$refs.drawer.closeDrawer();
|
this.$refs.drawer.closeDrawer();
|
||||||
this.$message.success("保存成功!");
|
this.$message.success("保存成功!");
|
||||||
|
@ -160,20 +179,22 @@
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
|
|
||||||
.tb-edit .el-input {
|
.tb-edit .el-textarea {
|
||||||
display: none;
|
display: none;
|
||||||
color: black;
|
|
||||||
}
|
}
|
||||||
.tb-edit .current-row .el-input {
|
.tb-edit .current-row .el-textarea {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.tb-edit .current-row .el-input+span {
|
.tb-edit .current-row .el-textarea+span {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-row {
|
.el-row {
|
||||||
margin-bottom: 3%;
|
margin-bottom: 2%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cast_label {
|
||||||
|
color: dimgray;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue