Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
3445ac4656
|
@ -155,8 +155,8 @@
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.python</groupId>
|
<groupId>org.python</groupId>
|
||||||
<artifactId>jython</artifactId>
|
<artifactId>jython-standalone</artifactId>
|
||||||
<version>2.7.2</version>
|
<version>2.7.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -104,9 +104,6 @@ public class APITestService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
private void createBodyFiles(ApiTest test, List<String> bodyUploadIds, List<MultipartFile> bodyFiles) {
|
||||||
if (bodyFiles == null || bodyFiles.isEmpty()) {
|
|
||||||
|
|
||||||
}
|
|
||||||
String dir = BODY_FILE_DIR + "/" + test.getId();
|
String dir = BODY_FILE_DIR + "/" + test.getId();
|
||||||
File testDir = new File(dir);
|
File testDir = new File(dir);
|
||||||
if (!testDir.exists()) {
|
if (!testDir.exists()) {
|
||||||
|
@ -115,24 +112,12 @@ public class APITestService {
|
||||||
for (int i = 0; i < bodyUploadIds.size(); i++) {
|
for (int i = 0; i < bodyUploadIds.size(); i++) {
|
||||||
MultipartFile item = bodyFiles.get(i);
|
MultipartFile item = bodyFiles.get(i);
|
||||||
File file = new File(testDir + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
|
File file = new File(testDir + "/" + bodyUploadIds.get(i) + "_" + item.getOriginalFilename());
|
||||||
InputStream in = null;
|
try (InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(file)) {
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
in = item.getInputStream();
|
|
||||||
out = new FileOutputStream(file);
|
|
||||||
FileUtil.copyStream(in, out);
|
FileUtil.copyStream(in, out);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
MSException.throwException(Translator.get("upload_fail"));
|
MSException.throwException(Translator.get("upload_fail"));
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
out.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LogUtil.error(e);
|
|
||||||
MSException.throwException(Translator.get("upload_fail"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,9 +97,7 @@
|
||||||
|
|
||||||
<select id="list" resultMap="BaseResultMap"
|
<select id="list" resultMap="BaseResultMap"
|
||||||
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
|
||||||
select test_plan.*, project.name as project_name
|
select test_plan.* from test_plan
|
||||||
from test_plan
|
|
||||||
left join project on test_plan.project_id = project.id
|
|
||||||
<where>
|
<where>
|
||||||
<if test="request.combine != null">
|
<if test="request.combine != null">
|
||||||
<include refid="combine">
|
<include refid="combine">
|
||||||
|
@ -111,10 +109,7 @@
|
||||||
and test_plan.name like CONCAT('%', #{request.name},'%')
|
and test_plan.name like CONCAT('%', #{request.name},'%')
|
||||||
</if>
|
</if>
|
||||||
<if test="request.workspaceId != null">
|
<if test="request.workspaceId != null">
|
||||||
AND project.workspace_id = #{request.workspaceId}
|
AND test_plan.workspace_id = #{request.workspaceId}
|
||||||
</if>
|
|
||||||
<if test="request.projectId != null">
|
|
||||||
AND project.id = #{request.projectId}
|
|
||||||
</if>
|
</if>
|
||||||
<if test="request.id != null">
|
<if test="request.id != null">
|
||||||
AND test_plan.id = #{request.id}
|
AND test_plan.id = #{request.id}
|
||||||
|
@ -150,9 +145,7 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric">
|
<select id="listRelate" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric">
|
||||||
select test_plan.*, project.name as project_name
|
select test_plan.* from test_plan
|
||||||
from test_plan
|
|
||||||
left join project on test_plan.project_id = project.id
|
|
||||||
where test_plan.workspace_id = #{request.workspaceId}
|
where test_plan.workspace_id = #{request.workspaceId}
|
||||||
and (test_plan.principal = #{request.principal}
|
and (test_plan.principal = #{request.principal}
|
||||||
<if test="request.planIds != null and request.planIds.size() > 0">
|
<if test="request.planIds != null and request.planIds.size() > 0">
|
||||||
|
|
|
@ -115,10 +115,11 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
|
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
|
||||||
select test_case.remark, test_plan_test_case.id as id, test_plan_test_case.*,test_case.*,test_case_node.name as model
|
select test_case.remark, test_plan_test_case.id as id, test_plan_test_case.*,test_case.*,test_case_node.name as model, project.name as projectName
|
||||||
from test_plan_test_case
|
from test_plan_test_case
|
||||||
inner join test_case on test_plan_test_case.case_id = test_case.id left join test_case_node on
|
inner join test_case on test_plan_test_case.case_id = test_case.id
|
||||||
test_case_node.id=test_case.node_id
|
left join test_case_node on test_case_node.id=test_case.node_id
|
||||||
|
inner join project on project.id = test_case.project_id
|
||||||
<where>
|
<where>
|
||||||
<if test="request.combine != null">
|
<if test="request.combine != null">
|
||||||
<include refid="combine">
|
<include refid="combine">
|
||||||
|
|
|
@ -39,18 +39,6 @@ public class ScheduleManager {
|
||||||
.startNow().build();
|
.startNow().build();
|
||||||
|
|
||||||
scheduler.scheduleJob(jd, trigger);
|
scheduler.scheduleJob(jd, trigger);
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (!scheduler.isShutdown()) {
|
|
||||||
scheduler.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (SchedulerException e) {
|
|
||||||
LogUtil.error(e.getMessage(), e);
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntervalTime) throws SchedulerException {
|
public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntervalTime) throws SchedulerException {
|
||||||
|
@ -89,9 +77,6 @@ public class ScheduleManager {
|
||||||
|
|
||||||
scheduler.scheduleJob(jobDetail, trigger);
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
|
||||||
if (!scheduler.isShutdown()) {
|
|
||||||
scheduler.start();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||||
import io.metersphere.commons.constants.ParamConstants;
|
import io.metersphere.commons.constants.ParamConstants;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.EncryptUtils;
|
import io.metersphere.commons.utils.EncryptUtils;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.controller.request.LoginRequest;
|
import io.metersphere.controller.request.LoginRequest;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.service.SystemParameterService;
|
import io.metersphere.service.SystemParameterService;
|
||||||
|
@ -47,6 +48,7 @@ public class LdapService {
|
||||||
// 执行登录认证
|
// 执行登录认证
|
||||||
authenticate(String.valueOf(dirContextOperations.getDn()), credentials);
|
authenticate(String.valueOf(dirContextOperations.getDn()), credentials);
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
MSException.throwException(Translator.get("authentication_failed"));
|
MSException.throwException(Translator.get("authentication_failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +95,10 @@ public class LdapService {
|
||||||
return result.get(0);
|
return result.get(0);
|
||||||
}
|
}
|
||||||
} catch (NameNotFoundException | InvalidNameException e) {
|
} catch (NameNotFoundException | InvalidNameException e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
MSException.throwException(Translator.get("login_fail_ou_error"));
|
MSException.throwException(Translator.get("login_fail_ou_error"));
|
||||||
} catch (InvalidSearchFilterException e) {
|
} catch (InvalidSearchFilterException e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
MSException.throwException(Translator.get("login_fail_filter_error"));
|
MSException.throwException(Translator.get("login_fail_filter_error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,8 +165,10 @@ public class LdapService {
|
||||||
try {
|
try {
|
||||||
authenticate(dn, credentials, ldapTemplate);
|
authenticate(dn, credentials, ldapTemplate);
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
MSException.throwException(Translator.get("ldap_connect_fail_user"));
|
MSException.throwException(Translator.get("ldap_connect_fail_user"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
MSException.throwException(Translator.get("ldap_connect_fail"));
|
MSException.throwException(Translator.get("ldap_connect_fail"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
||||||
System.out.println("================= 应用启动 =================");
|
System.out.println("================= 应用启动 =================");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(5 * 60 * 1000);
|
Thread.sleep(3 * 60 * 1000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,14 @@ import io.metersphere.controller.request.ProjectRequest;
|
||||||
import io.metersphere.dto.ProjectDTO;
|
import io.metersphere.dto.ProjectDTO;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.performance.service.PerformanceTestService;
|
import io.metersphere.performance.service.PerformanceTestService;
|
||||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
|
||||||
import io.metersphere.track.request.testplan.DeleteTestPlanRequest;
|
import io.metersphere.track.request.testplan.DeleteTestPlanRequest;
|
||||||
import io.metersphere.track.service.TestCaseService;
|
import io.metersphere.track.service.TestCaseService;
|
||||||
|
import io.metersphere.track.service.TestPlanProjectService;
|
||||||
import io.metersphere.track.service.TestPlanService;
|
import io.metersphere.track.service.TestPlanService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -54,6 +55,8 @@ public class ProjectService {
|
||||||
private TestCaseService testCaseService;
|
private TestCaseService testCaseService;
|
||||||
@Resource
|
@Resource
|
||||||
private APITestService apiTestService;
|
private APITestService apiTestService;
|
||||||
|
@Resource
|
||||||
|
private TestPlanProjectService testPlanProjectService;
|
||||||
|
|
||||||
public Project addProject(Project project) {
|
public Project addProject(Project project) {
|
||||||
if (StringUtils.isBlank(project.getName())) {
|
if (StringUtils.isBlank(project.getName())) {
|
||||||
|
@ -96,21 +99,22 @@ public class ProjectService {
|
||||||
performanceTestService.delete(deleteTestPlanRequest);
|
performanceTestService.delete(deleteTestPlanRequest);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO 删除项目下 测试跟踪 相关
|
// 删除项目下 测试跟踪 相关
|
||||||
deleteTrackResourceByProjectId(projectId);
|
deleteTrackResourceByProjectId(projectId);
|
||||||
|
|
||||||
// TODO 删除项目下 接口测试 相关
|
// 删除项目下 接口测试 相关
|
||||||
deleteAPIResourceByProjectId(projectId);
|
deleteAPIResourceByProjectId(projectId);
|
||||||
// delete project
|
// delete project
|
||||||
projectMapper.deleteByPrimaryKey(projectId);
|
projectMapper.deleteByPrimaryKey(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTrackResourceByProjectId(String projectId) {
|
private void deleteTrackResourceByProjectId(String projectId) {
|
||||||
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
List<String> testPlanIds = testPlanProjectService.getPlanIdByProjectId(projectId);
|
||||||
request.setProjectId(projectId);
|
if (!CollectionUtils.isEmpty(testPlanIds)) {
|
||||||
testPlanService.listTestPlan(request).forEach(testPlan -> {
|
testPlanIds.forEach(testPlanId -> {
|
||||||
testPlanService.deleteTestPlan(testPlan.getId());
|
testPlanService.deleteTestPlan(testPlanId);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
testCaseService.deleteTestCaseByProjectId(projectId);
|
testCaseService.deleteTestCaseByProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import io.metersphere.base.domain.TestCaseNode;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.track.dto.TestCaseNodeDTO;
|
import io.metersphere.track.dto.TestCaseNodeDTO;
|
||||||
import io.metersphere.track.request.testcase.DragNodeRequest;
|
import io.metersphere.track.request.testcase.DragNodeRequest;
|
||||||
|
import io.metersphere.track.request.testcase.QueryNodeRequest;
|
||||||
import io.metersphere.track.service.TestCaseNodeService;
|
import io.metersphere.track.service.TestCaseNodeService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
@ -26,9 +27,9 @@ public class TestCaseNodeController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*模块列表列表*/
|
/*模块列表列表*/
|
||||||
@GetMapping("/list/all/plan/{planId}")
|
@PostMapping("/list/all/plan")
|
||||||
public List<TestCaseNodeDTO> getAllNodeByPlanId(@PathVariable String planId) {
|
public List<TestCaseNodeDTO> getAllNodeByPlanId(@RequestBody QueryNodeRequest request) {
|
||||||
return testCaseNodeService.getAllNodeByPlanId(planId);
|
return testCaseNodeService.getAllNodeByPlanId(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list/plan/{planId}")
|
@GetMapping("/list/plan/{planId}")
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.track.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.Project;
|
||||||
import io.metersphere.base.domain.TestPlan;
|
import io.metersphere.base.domain.TestPlan;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
import io.metersphere.commons.utils.PageUtils;
|
import io.metersphere.commons.utils.PageUtils;
|
||||||
|
@ -12,6 +13,9 @@ import io.metersphere.track.dto.TestPlanDTO;
|
||||||
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
||||||
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
|
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
|
||||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
||||||
|
import io.metersphere.track.request.testplan.AddTestPlanRequest;
|
||||||
|
import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest;
|
||||||
|
import io.metersphere.track.service.TestPlanProjectService;
|
||||||
import io.metersphere.track.service.TestPlanService;
|
import io.metersphere.track.service.TestPlanService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
@ -26,6 +30,8 @@ public class TestPlanController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
TestPlanService testPlanService;
|
TestPlanService testPlanService;
|
||||||
|
@Resource
|
||||||
|
TestPlanProjectService testPlanProjectService;
|
||||||
|
|
||||||
@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) {
|
||||||
|
@ -37,7 +43,7 @@ public class TestPlanController {
|
||||||
|
|
||||||
/*jenkins测试计划*/
|
/*jenkins测试计划*/
|
||||||
@GetMapping("/list/all/{projectId}/{workspaceId}")
|
@GetMapping("/list/all/{projectId}/{workspaceId}")
|
||||||
public List<TestPlanDTO> listByprojectId(@PathVariable String projectId, @PathVariable String workspaceId) {
|
public List<TestPlanDTO> listByProjectId(@PathVariable String projectId, @PathVariable String workspaceId) {
|
||||||
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||||
request.setWorkspaceId(workspaceId);
|
request.setWorkspaceId(workspaceId);
|
||||||
request.setProjectId(projectId);
|
request.setProjectId(projectId);
|
||||||
|
@ -69,7 +75,7 @@ public class TestPlanController {
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
public void addTestPlan(@RequestBody TestPlan testPlan) {
|
public void addTestPlan(@RequestBody AddTestPlanRequest testPlan) {
|
||||||
testPlanService.addTestPlan(testPlan);
|
testPlanService.addTestPlan(testPlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,4 +106,24 @@ public class TestPlanController {
|
||||||
public TestCaseReportMetricDTO getMetric(@PathVariable String planId) {
|
public TestCaseReportMetricDTO getMetric(@PathVariable String planId) {
|
||||||
return testPlanService.getMetric(planId);
|
return testPlanService.getMetric(planId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/project/name/{planId}")
|
||||||
|
public String getProjectNameByPlanId(@PathVariable String planId) {
|
||||||
|
return testPlanService.getProjectNameByPlanId(planId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/project")
|
||||||
|
public List<Project> getProjectByPlanId(@RequestBody TestCaseRelevanceRequest request) {
|
||||||
|
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(request.getPlanId());
|
||||||
|
request.setProjectIds(projectIds);
|
||||||
|
return testPlanProjectService.getProjectByPlanId(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/project/{goPage}/{pageSize}")
|
||||||
|
public Pager<List<Project>> getProjectByPlanId(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody TestCaseRelevanceRequest request) {
|
||||||
|
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(request.getPlanId());
|
||||||
|
request.setProjectIds(projectIds);
|
||||||
|
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||||
|
return PageUtils.setPageInfo(page, testPlanProjectService.getProjectByPlanId(request));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package io.metersphere.track.domain;
|
package io.metersphere.track.domain;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import io.metersphere.base.domain.Issues;
|
|
||||||
import io.metersphere.base.domain.TestCaseNode;
|
import io.metersphere.base.domain.TestCaseNode;
|
||||||
import io.metersphere.base.domain.TestCaseNodeExample;
|
import io.metersphere.base.domain.TestCaseNodeExample;
|
||||||
import io.metersphere.base.mapper.TestCaseNodeMapper;
|
import io.metersphere.base.mapper.TestCaseNodeMapper;
|
||||||
|
@ -11,6 +9,7 @@ import io.metersphere.commons.utils.MathUtils;
|
||||||
import io.metersphere.track.dto.*;
|
import io.metersphere.track.dto.*;
|
||||||
import io.metersphere.track.service.IssuesService;
|
import io.metersphere.track.service.IssuesService;
|
||||||
import io.metersphere.track.service.TestCaseNodeService;
|
import io.metersphere.track.service.TestCaseNodeService;
|
||||||
|
import io.metersphere.track.service.TestPlanProjectService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -30,8 +29,9 @@ public class ReportResultComponent extends ReportComponent {
|
||||||
public void init() {
|
public void init() {
|
||||||
TestCaseNodeService testCaseNodeService = (TestCaseNodeService) CommonBeanFactory.getBean("testCaseNodeService");
|
TestCaseNodeService testCaseNodeService = (TestCaseNodeService) CommonBeanFactory.getBean("testCaseNodeService");
|
||||||
TestCaseNodeMapper testCaseNodeMapper = (TestCaseNodeMapper) CommonBeanFactory.getBean("testCaseNodeMapper");
|
TestCaseNodeMapper testCaseNodeMapper = (TestCaseNodeMapper) CommonBeanFactory.getBean("testCaseNodeMapper");
|
||||||
|
TestPlanProjectService testPlanProjectService = (TestPlanProjectService) CommonBeanFactory.getBean("testPlanProjectService");
|
||||||
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
|
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
|
||||||
testCaseNodeExample.createCriteria().andProjectIdEqualTo(testPlan.getProjectId());
|
testCaseNodeExample.createCriteria().andProjectIdIn(testPlanProjectService.getProjectIdsByPlanId(testPlan.getId()));
|
||||||
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
|
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
|
||||||
nodeTrees = testCaseNodeService.getNodeTrees(nodes);
|
nodeTrees = testCaseNodeService.getNodeTrees(nodes);
|
||||||
nodeTrees.forEach(item -> {
|
nodeTrees.forEach(item -> {
|
||||||
|
|
|
@ -17,4 +17,5 @@ public class TestPlanCaseDTO extends TestCaseWithBLOBs {
|
||||||
private String issues;
|
private String issues;
|
||||||
private String reportId;
|
private String reportId;
|
||||||
private String model;
|
private String model;
|
||||||
|
private String projectName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.track.request.testcase;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class QueryNodeRequest {
|
||||||
|
|
||||||
|
private String testPlanId;
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.metersphere.track.request.testplan;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.TestPlan;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AddTestPlanRequest extends TestPlan {
|
||||||
|
private List<String> projectIds;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.metersphere.track.request.testplancase;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TestCaseRelevanceRequest {
|
||||||
|
private String planId;
|
||||||
|
private String name;
|
||||||
|
private List<String> projectIds;
|
||||||
|
}
|
|
@ -346,10 +346,19 @@ public class IssuesService {
|
||||||
String body = responseEntity.getBody();
|
String body = responseEntity.getBody();
|
||||||
|
|
||||||
JSONObject obj = JSONObject.parseObject(body);
|
JSONObject obj = JSONObject.parseObject(body);
|
||||||
|
LogUtil.info(obj);
|
||||||
|
|
||||||
|
String lastmodify = "";
|
||||||
|
String status = "";
|
||||||
|
|
||||||
JSONObject fields = (JSONObject) obj.get("fields");
|
JSONObject fields = (JSONObject) obj.get("fields");
|
||||||
JSONObject statusObj = (JSONObject) fields.get("status");
|
JSONObject statusObj = (JSONObject) fields.get("status");
|
||||||
JSONObject assignee = (JSONObject) fields.get("assignee");
|
JSONObject assignee = (JSONObject) fields.get("assignee");
|
||||||
JSONObject statusCategory = (JSONObject) statusObj.get("statusCategory");
|
|
||||||
|
if (statusObj != null) {
|
||||||
|
JSONObject statusCategory = (JSONObject) statusObj.get("statusCategory");
|
||||||
|
status = statusCategory.getString("key");
|
||||||
|
}
|
||||||
|
|
||||||
String id = obj.getString("id");
|
String id = obj.getString("id");
|
||||||
String title = fields.getString("summary");
|
String title = fields.getString("summary");
|
||||||
|
@ -360,9 +369,8 @@ public class IssuesService {
|
||||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||||
description = renderer.render(document);
|
description = renderer.render(document);
|
||||||
|
|
||||||
String status = statusCategory.getString("key");
|
|
||||||
Long createTime = fields.getLong("created");
|
Long createTime = fields.getLong("created");
|
||||||
String lastmodify = "";
|
|
||||||
if (assignee != null) {
|
if (assignee != null) {
|
||||||
lastmodify = assignee.getString("displayName");
|
lastmodify = assignee.getString("displayName");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,7 @@ package io.metersphere.track.service;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.TestCaseMapper;
|
import io.metersphere.base.mapper.*;
|
||||||
import io.metersphere.base.mapper.TestCaseNodeMapper;
|
|
||||||
import io.metersphere.base.mapper.TestPlanMapper;
|
|
||||||
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
|
|
||||||
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
|
||||||
import io.metersphere.commons.constants.TestCaseConstants;
|
import io.metersphere.commons.constants.TestCaseConstants;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
@ -15,6 +12,7 @@ import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.track.dto.TestCaseDTO;
|
import io.metersphere.track.dto.TestCaseDTO;
|
||||||
import io.metersphere.track.dto.TestCaseNodeDTO;
|
import io.metersphere.track.dto.TestCaseNodeDTO;
|
||||||
import io.metersphere.track.request.testcase.DragNodeRequest;
|
import io.metersphere.track.request.testcase.DragNodeRequest;
|
||||||
|
import io.metersphere.track.request.testcase.QueryNodeRequest;
|
||||||
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
|
@ -43,6 +41,10 @@ public class TestCaseNodeService {
|
||||||
ExtTestCaseMapper extTestCaseMapper;
|
ExtTestCaseMapper extTestCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
SqlSessionFactory sqlSessionFactory;
|
SqlSessionFactory sqlSessionFactory;
|
||||||
|
@Resource
|
||||||
|
TestPlanProjectService testPlanProjectService;
|
||||||
|
@Resource
|
||||||
|
ProjectMapper projectMapper;
|
||||||
|
|
||||||
public String addNode(TestCaseNode node) {
|
public String addNode(TestCaseNode node) {
|
||||||
validateNode(node);
|
validateNode(node);
|
||||||
|
@ -182,8 +184,22 @@ public class TestCaseNodeService {
|
||||||
*/
|
*/
|
||||||
public List<TestCaseNodeDTO> getNodeByPlanId(String planId) {
|
public List<TestCaseNodeDTO> getNodeByPlanId(String planId) {
|
||||||
|
|
||||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
List<TestCaseNodeDTO> list = new ArrayList<>();
|
||||||
|
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(planId);
|
||||||
|
projectIds.forEach(id -> {
|
||||||
|
String name = projectMapper.selectByPrimaryKey(id).getName();
|
||||||
|
List<TestCaseNodeDTO> nodeList = getNodeDTO(id, planId);
|
||||||
|
TestCaseNodeDTO testCaseNodeDTO = new TestCaseNodeDTO();
|
||||||
|
testCaseNodeDTO.setName(name);
|
||||||
|
testCaseNodeDTO.setLabel(name);
|
||||||
|
testCaseNodeDTO.setChildren(nodeList);
|
||||||
|
list.add(testCaseNodeDTO);
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TestCaseNodeDTO> getNodeDTO(String projectId, String planId) {
|
||||||
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
|
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
|
||||||
testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(planId);
|
testPlanTestCaseExample.createCriteria().andPlanIdEqualTo(planId);
|
||||||
List<TestPlanTestCase> testPlanTestCases = testPlanTestCaseMapper.selectByExample(testPlanTestCaseExample);
|
List<TestPlanTestCase> testPlanTestCases = testPlanTestCaseMapper.selectByExample(testPlanTestCaseExample);
|
||||||
|
@ -193,7 +209,7 @@ public class TestCaseNodeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
|
TestCaseNodeExample testCaseNodeExample = new TestCaseNodeExample();
|
||||||
testCaseNodeExample.createCriteria().andProjectIdEqualTo(testPlan.getProjectId());
|
testCaseNodeExample.createCriteria().andProjectIdEqualTo(projectId);
|
||||||
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
|
List<TestCaseNode> nodes = testCaseNodeMapper.selectByExample(testCaseNodeExample);
|
||||||
|
|
||||||
List<String> caseIds = testPlanTestCases.stream()
|
List<String> caseIds = testPlanTestCases.stream()
|
||||||
|
@ -254,12 +270,15 @@ public class TestCaseNodeService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TestCaseNodeDTO> getAllNodeByPlanId(String planId) {
|
public List<TestCaseNodeDTO> getAllNodeByPlanId(QueryNodeRequest request) {
|
||||||
|
String planId = request.getTestPlanId();
|
||||||
|
String projectId = request.getProjectId();
|
||||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||||
if (testPlan == null) {
|
if (testPlan == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return getNodeTreeByProjectId(testPlan.getProjectId());
|
|
||||||
|
return getNodeTreeByProjectId(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> createNodeByTestCases(List<TestCaseWithBLOBs> testCases, String projectId) {
|
public Map<String, String> createNodeByTestCases(List<TestCaseWithBLOBs> testCases, String projectId) {
|
||||||
|
|
|
@ -182,9 +182,7 @@ public class TestCaseService {
|
||||||
public List<TestCase> getTestCaseNames(QueryTestCaseRequest request) {
|
public List<TestCase> getTestCaseNames(QueryTestCaseRequest request) {
|
||||||
if (StringUtils.isNotBlank(request.getPlanId())) {
|
if (StringUtils.isNotBlank(request.getPlanId())) {
|
||||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
||||||
if (testPlan != null) {
|
// request 传入要查询的 projectId 切换的项目ID
|
||||||
request.setProjectId(testPlan.getProjectId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TestCase> testCaseNames = extTestCaseMapper.getTestCaseNames(request);
|
List<TestCase> testCaseNames = extTestCaseMapper.getTestCaseNames(request);
|
||||||
|
@ -386,7 +384,13 @@ public class TestCaseService {
|
||||||
data.setPrerequisite(t.getPrerequisite());
|
data.setPrerequisite(t.getPrerequisite());
|
||||||
if (t.getMethod().equals("manual")) {
|
if (t.getMethod().equals("manual")) {
|
||||||
String steps = t.getSteps();
|
String steps = t.getSteps();
|
||||||
JSONArray jsonArray = JSON.parseArray(steps);
|
String setp = "";
|
||||||
|
if (steps.contains("null")) {
|
||||||
|
setp = steps.replace("null", "");
|
||||||
|
} else {
|
||||||
|
setp = steps;
|
||||||
|
}
|
||||||
|
JSONArray jsonArray = JSON.parseArray(setp);
|
||||||
for (int j = 0; j < jsonArray.size(); j++) {
|
for (int j = 0; j < jsonArray.size(); j++) {
|
||||||
int num = j + 1;
|
int num = j + 1;
|
||||||
step.append(num + "." + jsonArray.getJSONObject(j).getString("desc") + "\n");
|
step.append(num + "." + jsonArray.getJSONObject(j).getString("desc") + "\n");
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package io.metersphere.track.service;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.Project;
|
||||||
|
import io.metersphere.base.domain.ProjectExample;
|
||||||
|
import io.metersphere.base.domain.TestPlanProject;
|
||||||
|
import io.metersphere.base.domain.TestPlanProjectExample;
|
||||||
|
import io.metersphere.base.mapper.ProjectMapper;
|
||||||
|
import io.metersphere.base.mapper.TestPlanProjectMapper;
|
||||||
|
import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class TestPlanProjectService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
TestPlanProjectMapper testPlanProjectMapper;
|
||||||
|
@Resource
|
||||||
|
ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
public List<String> getProjectIdsByPlanId(String planId) {
|
||||||
|
TestPlanProjectExample example = new TestPlanProjectExample();
|
||||||
|
example.createCriteria().andTestPlanIdEqualTo(planId);
|
||||||
|
List<String> projectIds = testPlanProjectMapper.selectByExample(example)
|
||||||
|
.stream()
|
||||||
|
.map(TestPlanProject::getProjectId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (projectIds.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Project> getProjectByPlanId(TestCaseRelevanceRequest request) {
|
||||||
|
ProjectExample projectExample = new ProjectExample();
|
||||||
|
ProjectExample.Criteria criteria = projectExample.createCriteria();
|
||||||
|
criteria.andIdIn(request.getProjectIds());
|
||||||
|
if (StringUtils.isNotBlank(request.getName())) {
|
||||||
|
criteria.andNameLike(StringUtils.wrapIfMissing(request.getName(), "%"));
|
||||||
|
}
|
||||||
|
return projectMapper.selectByExample(projectExample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteTestPlanProjectByPlanId(String planId) {
|
||||||
|
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
|
||||||
|
testPlanProjectExample.createCriteria().andTestPlanIdEqualTo(planId);
|
||||||
|
testPlanProjectMapper.deleteByExample(testPlanProjectExample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPlanIdByProjectId(String projectId) {
|
||||||
|
TestPlanProjectExample testPlanProjectExample = new TestPlanProjectExample();
|
||||||
|
testPlanProjectExample.createCriteria().andProjectIdEqualTo(projectId);
|
||||||
|
List<TestPlanProject> testPlanProjects = testPlanProjectMapper.selectByExample(testPlanProjectExample);
|
||||||
|
if (CollectionUtils.isEmpty(testPlanProjects)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return testPlanProjects
|
||||||
|
.stream()
|
||||||
|
.map(TestPlanProject::getTestPlanId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,7 @@ package io.metersphere.track.service;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.TestCaseMapper;
|
import io.metersphere.base.mapper.*;
|
||||||
import io.metersphere.base.mapper.TestCaseReportMapper;
|
|
||||||
import io.metersphere.base.mapper.TestPlanMapper;
|
|
||||||
import io.metersphere.base.mapper.TestPlanTestCaseMapper;
|
|
||||||
import io.metersphere.base.mapper.ext.ExtProjectMapper;
|
import io.metersphere.base.mapper.ext.ExtProjectMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
|
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
||||||
|
@ -28,6 +25,7 @@ import io.metersphere.track.dto.TestPlanDTO;
|
||||||
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
||||||
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
|
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
|
||||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
||||||
|
import io.metersphere.track.request.testplan.AddTestPlanRequest;
|
||||||
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
|
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
|
@ -72,12 +70,29 @@ public class TestPlanService {
|
||||||
@Resource
|
@Resource
|
||||||
TestCaseReportMapper testCaseReportMapper;
|
TestCaseReportMapper testCaseReportMapper;
|
||||||
|
|
||||||
public void addTestPlan(TestPlan testPlan) {
|
@Resource
|
||||||
|
TestPlanProjectMapper testPlanProjectMapper;
|
||||||
|
@Resource
|
||||||
|
TestPlanProjectService testPlanProjectService;
|
||||||
|
@Resource
|
||||||
|
ProjectMapper projectMapper;
|
||||||
|
|
||||||
|
public void addTestPlan(AddTestPlanRequest testPlan) {
|
||||||
if (getTestPlanByName(testPlan.getName()).size() > 0) {
|
if (getTestPlanByName(testPlan.getName()).size() > 0) {
|
||||||
MSException.throwException(Translator.get("plan_name_already_exists"));
|
MSException.throwException(Translator.get("plan_name_already_exists"));
|
||||||
}
|
}
|
||||||
;
|
|
||||||
testPlan.setId(UUID.randomUUID().toString());
|
String testPlanId = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
List<String> projectIds = testPlan.getProjectIds();
|
||||||
|
projectIds.forEach(id -> {
|
||||||
|
TestPlanProject testPlanProject = new TestPlanProject();
|
||||||
|
testPlanProject.setProjectId(id);
|
||||||
|
testPlanProject.setTestPlanId(testPlanId);
|
||||||
|
testPlanProjectMapper.insertSelective(testPlanProject);
|
||||||
|
});
|
||||||
|
|
||||||
|
testPlan.setId(testPlanId);
|
||||||
testPlan.setStatus(TestPlanStatus.Prepare.name());
|
testPlan.setStatus(TestPlanStatus.Prepare.name());
|
||||||
testPlan.setCreateTime(System.currentTimeMillis());
|
testPlan.setCreateTime(System.currentTimeMillis());
|
||||||
testPlan.setUpdateTime(System.currentTimeMillis());
|
testPlan.setUpdateTime(System.currentTimeMillis());
|
||||||
|
@ -116,6 +131,7 @@ public class TestPlanService {
|
||||||
|
|
||||||
public int deleteTestPlan(String planId) {
|
public int deleteTestPlan(String planId) {
|
||||||
deleteTestCaseByPlanId(planId);
|
deleteTestCaseByPlanId(planId);
|
||||||
|
testPlanProjectService.deleteTestPlanProjectByPlanId(planId);
|
||||||
return testPlanMapper.deleteByPrimaryKey(planId);
|
return testPlanMapper.deleteByPrimaryKey(planId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,4 +332,23 @@ public class TestPlanService {
|
||||||
testPlan.setStatus(TestPlanStatus.Completed.name());
|
testPlan.setStatus(TestPlanStatus.Completed.name());
|
||||||
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getProjectNameByPlanId(String testPlanId) {
|
||||||
|
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(testPlanId);
|
||||||
|
ProjectExample projectExample = new ProjectExample();
|
||||||
|
projectExample.createCriteria().andIdIn(projectIds);
|
||||||
|
|
||||||
|
List<Project> projects = projectMapper.selectByExample(projectExample);
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
String projectName = "";
|
||||||
|
|
||||||
|
if (projects.size() > 0) {
|
||||||
|
for (Project project : projects) {
|
||||||
|
stringBuilder.append(project.getName()).append("、");
|
||||||
|
}
|
||||||
|
projectName = stringBuilder.toString().substring(0, stringBuilder.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ecb30d83c575c6ed14adb1a1ebea389730f410a9
|
Subproject commit b86032cbbda9a9e6028308aa95a887cff2192f1c
|
|
@ -2,7 +2,7 @@
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-aside class="scenario-aside">
|
<el-aside class="scenario-aside">
|
||||||
<div class="scenario-list">
|
<div class="scenario-list">
|
||||||
<ms-api-collapse v-model="activeName" @change="handleChange" accordion>
|
<ms-api-collapse v-model="activeName" @change="handleChange">
|
||||||
<draggable :list="scenarios" group="Scenario" class="scenario-draggable" ghost-class="scenario-ghost">
|
<draggable :list="scenarios" group="Scenario" class="scenario-draggable" ghost-class="scenario-ghost">
|
||||||
<ms-api-collapse-item v-for="(scenario, index) in scenarios" :key="index"
|
<ms-api-collapse-item v-for="(scenario, index) in scenarios" :key="index"
|
||||||
:title="scenario.name" :name="index" :class="{'disable-scenario': !scenario.enable}">
|
:title="scenario.name" :name="index" :class="{'disable-scenario': !scenario.enable}">
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
:environment="scenario.environment"
|
:environment="scenario.environment"
|
||||||
:description="$t('api_test.scenario.kv_description')"/>
|
:description="$t('api_test.scenario.kv_description')"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="'数据库配置'" name="database">
|
||||||
|
<ms-database-config :configs="scenario.databaseConfigs"/>
|
||||||
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('api_test.scenario.dubbo')" name="dubbo">
|
<el-tab-pane :label="$t('api_test.scenario.dubbo')" name="dubbo">
|
||||||
<div class="dubbo-config-title">Config Center</div>
|
<div class="dubbo-config-title">Config Center</div>
|
||||||
<ms-dubbo-config-center :config="scenario.dubboConfig.configCenter" :is-read-only="isReadOnly"/>
|
<ms-dubbo-config-center :config="scenario.dubboConfig.configCenter" :is-read-only="isReadOnly"/>
|
||||||
|
@ -62,10 +65,12 @@ import {REQUEST_HEADERS} from "@/common/js/constants";
|
||||||
import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter";
|
import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter";
|
||||||
import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter";
|
import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter";
|
||||||
import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService";
|
import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService";
|
||||||
|
import MsDatabaseConfig from "./request/database/DatabaseConfig";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiScenarioForm",
|
name: "MsApiScenarioForm",
|
||||||
components: {
|
components: {
|
||||||
|
MsDatabaseConfig,
|
||||||
MsDubboConsumerService,
|
MsDubboConsumerService,
|
||||||
MsDubboConfigCenter, MsDubboRegistryCenter, ApiEnvironmentConfig, MsApiScenarioVariables, MsApiKeyValue
|
MsDubboConfigCenter, MsDubboRegistryCenter, ApiEnvironmentConfig, MsApiScenarioVariables, MsApiKeyValue
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="request-container">
|
<div class="request-container">
|
||||||
<draggable :list="this.scenario.requests" group="Request" class="request-draggable" ghost-class="request-ghost">
|
<draggable :list="this.scenario.requests" group="Request" class="request-draggable" ghost-class="request-ghost"
|
||||||
|
:disabled="isReference">
|
||||||
<div class="request-item" v-for="(request, index) in this.scenario.requests" :key="index" @click="select(request)"
|
<div class="request-item" v-for="(request, index) in this.scenario.requests" :key="index" @click="select(request)"
|
||||||
:class="{'selected': isSelected(request), 'disable-request': !request.enable || !scenario.enable}">
|
:class="{'selected': isSelected(request), 'disable-request': !request.enable || !scenario.enable}">
|
||||||
<el-row type="flex" align="middle">
|
<el-row type="flex" align="middle">
|
||||||
<div class="request-type">
|
<div class="request-type">
|
||||||
{{request.showType()}}
|
{{ request.showType() }}
|
||||||
</div>
|
</div>
|
||||||
<div class="request-method">
|
<div class="request-method">
|
||||||
{{request.showMethod()}}
|
{{ request.showMethod() }}
|
||||||
</div>
|
</div>
|
||||||
<div class="request-name">
|
<div class="request-name">
|
||||||
{{request.name}}
|
{{ request.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="request-btn">
|
<div class="request-btn">
|
||||||
<el-dropdown trigger="click" @command="handleCommand">
|
<el-dropdown trigger="click" @command="handleCommand">
|
||||||
<span class="el-dropdown-link el-icon-more"/>
|
<span class="el-dropdown-link el-icon-more"/>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}">
|
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'copy', index: index}">
|
||||||
{{$t('api_test.request.copy')}}
|
{{ $t('api_test.request.copy') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'delete', index: index}">
|
<el-dropdown-item :disabled="isReadOnly" :command="{type: 'delete', index: index}">
|
||||||
{{$t('api_test.request.delete')}}
|
{{ $t('api_test.request.delete') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="request.enable" :disabled="isReadOnly" :command="{type: 'disable', index: index}">
|
<el-dropdown-item v-if="request.enable" :disabled="isReadOnly"
|
||||||
{{$t('api_test.scenario.disable')}}
|
:command="{type: 'disable', index: index}">
|
||||||
|
{{ $t('api_test.scenario.disable') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="!request.enable" :disabled="isReadOnly" :command="{type: 'enable', index: index}">
|
<el-dropdown-item v-if="!request.enable" :disabled="isReadOnly"
|
||||||
{{$t('api_test.scenario.enable')}}
|
:command="{type: 'enable', index: index}">
|
||||||
|
{{ $t('api_test.scenario.enable') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
@ -48,173 +51,176 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {RequestFactory} from "../../model/ScenarioModel";
|
import {RequestFactory} from "../../model/ScenarioModel";
|
||||||
import draggable from 'vuedraggable';
|
import draggable from 'vuedraggable';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsApiRequestConfig",
|
name: "MsApiRequestConfig",
|
||||||
|
|
||||||
components: {draggable},
|
components: {draggable},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
scenario: Object,
|
scenario: Object,
|
||||||
isReadOnly: {
|
isReadOnly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selected: 0,
|
|
||||||
visible: false,
|
|
||||||
types: RequestFactory.TYPES,
|
|
||||||
type: ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
isSelected() {
|
|
||||||
return function (request) {
|
|
||||||
return this.selected === request;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
createRequest: function (type) {
|
|
||||||
let request = new RequestFactory({type: type});
|
|
||||||
if (this.scenario.environmentId) {
|
|
||||||
request.useEnvironment = true;
|
|
||||||
}
|
|
||||||
this.scenario.requests.push(request);
|
|
||||||
this.type = "";
|
|
||||||
this.visible = false;
|
|
||||||
},
|
|
||||||
copyRequest: function (index) {
|
|
||||||
let request = this.scenario.requests[index];
|
|
||||||
this.scenario.requests.push(new RequestFactory(request));
|
|
||||||
},
|
|
||||||
disableRequest: function (index) {
|
|
||||||
this.scenario.requests[index].enable = false;
|
|
||||||
},
|
|
||||||
enableRequest: function (index) {
|
|
||||||
this.scenario.requests[index].enable = true;
|
|
||||||
},
|
|
||||||
deleteRequest: function (index) {
|
|
||||||
this.scenario.requests.splice(index, 1);
|
|
||||||
if (this.scenario.requests.length === 0) {
|
|
||||||
this.createRequest();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleCommand: function (command) {
|
|
||||||
switch (command.type) {
|
|
||||||
case "copy":
|
|
||||||
this.copyRequest(command.index);
|
|
||||||
break;
|
|
||||||
case "delete":
|
|
||||||
this.deleteRequest(command.index);
|
|
||||||
break;
|
|
||||||
case "disable":
|
|
||||||
this.disableRequest(command.index);
|
|
||||||
break;
|
|
||||||
case "enable":
|
|
||||||
this.enableRequest(command.index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
select: function (request) {
|
|
||||||
request.environment = this.scenario.environment;
|
|
||||||
if (!request.useEnvironment) {
|
|
||||||
request.useEnvironment = false;
|
|
||||||
}
|
|
||||||
request.dubboConfig = this.scenario.dubboConfig;
|
|
||||||
this.selected = request;
|
|
||||||
this.$emit("select", request, this.scenario);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.select(this.scenario.requests[0]);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selected: 0,
|
||||||
|
visible: false,
|
||||||
|
types: RequestFactory.TYPES,
|
||||||
|
type: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
isSelected() {
|
||||||
|
return function (request) {
|
||||||
|
return this.selected === request;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isReference() {
|
||||||
|
return this.scenario.isReference();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
createRequest: function (type) {
|
||||||
|
let request = new RequestFactory({type: type});
|
||||||
|
if (this.scenario.environmentId) {
|
||||||
|
request.useEnvironment = true;
|
||||||
|
}
|
||||||
|
this.scenario.requests.push(request);
|
||||||
|
this.type = "";
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
copyRequest: function (index) {
|
||||||
|
let request = this.scenario.requests[index];
|
||||||
|
this.scenario.requests.push(new RequestFactory(request));
|
||||||
|
},
|
||||||
|
disableRequest: function (index) {
|
||||||
|
this.scenario.requests[index].enable = false;
|
||||||
|
},
|
||||||
|
enableRequest: function (index) {
|
||||||
|
this.scenario.requests[index].enable = true;
|
||||||
|
},
|
||||||
|
deleteRequest: function (index) {
|
||||||
|
this.scenario.requests.splice(index, 1);
|
||||||
|
if (this.scenario.requests.length === 0) {
|
||||||
|
this.createRequest();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCommand: function (command) {
|
||||||
|
switch (command.type) {
|
||||||
|
case "copy":
|
||||||
|
this.copyRequest(command.index);
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
this.deleteRequest(command.index);
|
||||||
|
break;
|
||||||
|
case "disable":
|
||||||
|
this.disableRequest(command.index);
|
||||||
|
break;
|
||||||
|
case "enable":
|
||||||
|
this.enableRequest(command.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
select: function (request) {
|
||||||
|
request.environment = this.scenario.environment;
|
||||||
|
if (!request.useEnvironment) {
|
||||||
|
request.useEnvironment = false;
|
||||||
|
}
|
||||||
|
request.dubboConfig = this.scenario.dubboConfig;
|
||||||
|
this.selected = request;
|
||||||
|
this.$emit("select", request, this.scenario);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.select(this.scenario.requests[0]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.request-item {
|
.request-item {
|
||||||
border-left: 5px solid #1E90FF;
|
border-left: 5px solid #1E90FF;
|
||||||
max-height: 40px;
|
max-height: 40px;
|
||||||
border-top: 1px solid #EBEEF5;
|
border-top: 1px solid #EBEEF5;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-item:first-child {
|
.request-item:first-child {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-item:hover, .request-item.selected:hover {
|
.request-item:hover, .request-item.selected:hover {
|
||||||
background-color: #ECF5FF;
|
background-color: #ECF5FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-item.selected {
|
.request-item.selected {
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-type {
|
.request-type {
|
||||||
background-color: #409eff;
|
background-color: #409eff;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-method {
|
.request-method {
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
color: #1E90FF;
|
color: #1E90FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-name {
|
.request-name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-btn {
|
.request-btn {
|
||||||
float: right;
|
float: right;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-btn .el-icon-more {
|
.request-btn .el-icon-more {
|
||||||
padding: 13px;
|
padding: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-create {
|
.request-create {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-ghost {
|
.request-ghost {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
background-color: #909399;
|
background-color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
.request-item.disable-request {
|
.request-item.disable-request {
|
||||||
border-left-color: #909399;
|
border-left-color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disable-request .request-type {
|
.disable-request .request-type {
|
||||||
background-color: #909399;
|
background-color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disable-request .request-method {
|
.disable-request .request-method {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ms-database-from :config="currentConfig" @save="addConfig" ref="databaseFrom"/>
|
||||||
|
<ms-database-config-list v-if="configs.length > 0" :table-data="configs"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsDatabaseConfigList from "./DatabaseConfigList";
|
||||||
|
import {DatabaseConfig} from "../../../model/ScenarioModel";
|
||||||
|
import MsDatabaseFrom from "./DatabaseFrom";
|
||||||
|
import {getUUID} from "../../../../../../../common/js/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsDatabaseConfig",
|
||||||
|
components: {MsDatabaseFrom, MsDatabaseConfigList},
|
||||||
|
props: {
|
||||||
|
configs: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
drivers: DatabaseConfig.DRIVER_CLASS,
|
||||||
|
currentConfig: new DatabaseConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addConfig(config) {
|
||||||
|
for (let item of this.configs) {
|
||||||
|
if (item.name === config.name) {
|
||||||
|
this.$warning("名称重复");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.id = getUUID();
|
||||||
|
this.configs.push(config);
|
||||||
|
this.currentConfig = new DatabaseConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.addButton {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.database-from {
|
||||||
|
padding: 10px;
|
||||||
|
border: #DCDFE6 solid 1px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :title="'数据库配置'" :visible.sync="visible">
|
||||||
|
<ms-database-from :config="config" @save="editConfig"/>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsDatabaseConfigList from "./DatabaseConfigList";
|
||||||
|
import MsDatabaseFrom from "./DatabaseFrom";
|
||||||
|
import {DatabaseConfig} from "../../../model/ScenarioModel";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsDatabaseConfigDialog",
|
||||||
|
components: {MsDatabaseFrom, MsDatabaseConfigList},
|
||||||
|
props: {
|
||||||
|
configs: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
config: new DatabaseConfig(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open(config) {
|
||||||
|
this.visible = true;
|
||||||
|
Object.assign(this.config, config);
|
||||||
|
},
|
||||||
|
editConfig(config) {
|
||||||
|
let currentConfig = undefined;
|
||||||
|
for (let item of this.configs) {
|
||||||
|
if (item.name === config.name && item.id != config.id) {
|
||||||
|
this.$warning("名称重复");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (item.id === config.id) {
|
||||||
|
currentConfig = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentConfig) {
|
||||||
|
Object.assign(currentConfig, config)
|
||||||
|
} else {
|
||||||
|
//copy
|
||||||
|
this.configs.push(config);
|
||||||
|
}
|
||||||
|
this.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,92 @@
|
||||||
|
<template>
|
||||||
|
<ms-main-container>
|
||||||
|
|
||||||
|
<el-table border :data="tableData" class="adjust-table table-content"
|
||||||
|
@row-click="handleView">
|
||||||
|
|
||||||
|
<el-table-column prop="name" :label="'连接池名称'" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="driver" :label="'数据库驱动'" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="dbUrl" :label="'数据库连接URL'" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="username" :label="'用户名'" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="poolMax" :label="'最大连接数'" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="timeout" :label="'最大等待时间'" show-overflow-tooltip/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('commons.operating')" min-width="100">
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
||||||
|
@deleteClick="handleDelete(scope.$index)">
|
||||||
|
<template v-slot:middle>
|
||||||
|
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.copy')"
|
||||||
|
icon="el-icon-document-copy"
|
||||||
|
type="success" @exec="handleCopy(scope.row)"/>
|
||||||
|
</template>
|
||||||
|
</ms-table-operator>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<ms-database-config-dialog :configs="tableData" ref="databaseConfigEdit"/>
|
||||||
|
|
||||||
|
</ms-main-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import {DatabaseConfig} from "../../../model/ScenarioModel";
|
||||||
|
import MsMainContainer from "../../../../../common/components/MsMainContainer";
|
||||||
|
import MsTableOperator from "../../../../../common/components/MsTableOperator";
|
||||||
|
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
|
||||||
|
import MsDatabaseConfigDialog from "./DatabaseConfigDialog";
|
||||||
|
import {getUUID} from "../../../../../../../common/js/utils";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsDatabaseConfigList",
|
||||||
|
components: {MsDatabaseConfigDialog, MsTableOperatorButton, MsTableOperator, MsMainContainer},
|
||||||
|
props: {
|
||||||
|
tableData: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
drivers: DatabaseConfig.DRIVER_CLASS,
|
||||||
|
result: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleView() {
|
||||||
|
},
|
||||||
|
handleEdit(config) {
|
||||||
|
this.$refs.databaseConfigEdit.open(config);
|
||||||
|
},
|
||||||
|
handleDelete(index) {
|
||||||
|
this.tableData.splice(index, 1);
|
||||||
|
},
|
||||||
|
handleCopy(config) {
|
||||||
|
let copy = {};
|
||||||
|
Object.assign(copy, config);
|
||||||
|
copy.id = getUUID();
|
||||||
|
this.$refs.databaseConfigEdit.open(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.addButton {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.database-from {
|
||||||
|
padding: 10px;
|
||||||
|
border: #DCDFE6 solid 1px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-form :model="config" :rules="rules" label-width="150px" size="small" :disabled="isReadOnly" class="database-from" ref="databaseFrom">
|
||||||
|
|
||||||
|
<el-form-item :label="'连接池名称'" prop="name">
|
||||||
|
<el-input v-model="config.name" maxlength="300" show-word-limit
|
||||||
|
:placeholder="$t('commons.input_content')"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'数据库连接URL'" prop="dbUrl">
|
||||||
|
<el-input v-model="config.dbUrl" maxlength="300" show-word-limit
|
||||||
|
:placeholder="$t('commons.input_content')"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'数据库驱动'" prop="driver">
|
||||||
|
<el-select v-model="config.driver" class="select-100" clearable>
|
||||||
|
<el-option v-for="p in drivers" :key="p" :label="p" :value="p"/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'用户名'" prop="username">
|
||||||
|
<el-input v-model="config.username" maxlength="300" show-word-limit
|
||||||
|
:placeholder="$t('commons.input_content')"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'密码'" prop="password">
|
||||||
|
<el-input v-model="config.password" maxlength="300" show-word-limit
|
||||||
|
:placeholder="$t('commons.input_content')"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="'最大连接数'" prop="poolMax">
|
||||||
|
<el-input-number size="small" :disabled="isReadOnly" v-model="config.poolMax" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
|
||||||
|
<el-form-item :label="'最大等待时间(ms)'" prop="timeout">
|
||||||
|
<el-input-number size="small" :disabled="isReadOnly" v-model="config.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" size="small" class="addButton" @click="save">添加</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {DatabaseConfig} from "../../../model/ScenarioModel";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MsDatabaseFrom",
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return new DatabaseConfig();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
drivers: DatabaseConfig.DRIVER_CLASS,
|
||||||
|
// config: new DatabaseConfig(),
|
||||||
|
rules: {
|
||||||
|
name: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
|
||||||
|
],
|
||||||
|
driver: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{max: 200, message: this.$t('commons.input_limit', [0, 200]), trigger: 'blur'}
|
||||||
|
],
|
||||||
|
dbUrl: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
{max: 500, message: this.$t('commons.input_limit', [0, 500]), trigger: 'blur'}
|
||||||
|
],
|
||||||
|
username: [
|
||||||
|
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
|
||||||
|
{max: 200, message: this.$t('commons.input_limit', [0, 200]), trigger: 'blur'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
save() {
|
||||||
|
this.$refs['databaseFrom'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$emit('save', this.config);
|
||||||
|
// this.config = new DatabaseConfig();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.addButton {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.database-from {
|
||||||
|
padding: 10px;
|
||||||
|
border: #DCDFE6 solid 1px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -211,14 +211,16 @@ export class Scenario extends BaseConfig {
|
||||||
this.environment = undefined;
|
this.environment = undefined;
|
||||||
this.enableCookieShare = false;
|
this.enableCookieShare = false;
|
||||||
this.enable = true;
|
this.enable = true;
|
||||||
|
this.databaseConfigs = undefined;
|
||||||
|
|
||||||
this.set(options);
|
this.set(options);
|
||||||
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory}, options);
|
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory, databaseConfigs: DatabaseConfig}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
initOptions(options = {}) {
|
initOptions(options = {}) {
|
||||||
options.id = options.id || uuid();
|
options.id = options.id || uuid();
|
||||||
options.requests = options.requests || [new RequestFactory()];
|
options.requests = options.requests || [new RequestFactory()];
|
||||||
|
options.databaseConfigs = options.databaseConfigs || [];
|
||||||
options.dubboConfig = new DubboConfig(options.dubboConfig);
|
options.dubboConfig = new DubboConfig(options.dubboConfig);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +407,7 @@ export class DubboRequest extends Request {
|
||||||
this.debugReport = undefined;
|
this.debugReport = undefined;
|
||||||
this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor);
|
this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor);
|
||||||
this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor);
|
this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor);
|
||||||
this.enable = options.enable == undefined ? true : options.enable;
|
this.enable = options.enable === undefined ? true : options.enable;
|
||||||
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||||
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||||
|
|
||||||
|
@ -479,6 +481,51 @@ export class ConfigCenter extends BaseConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DatabaseConfig extends BaseConfig {
|
||||||
|
static DRIVER_CLASS = ["com.mysql.jdbc.Driver"];
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
this.id = undefined;
|
||||||
|
this.name = undefined;
|
||||||
|
this.poolMax = undefined;
|
||||||
|
this.timeout = undefined;
|
||||||
|
this.driver = undefined;
|
||||||
|
this.dbUrl = undefined;
|
||||||
|
this.username = undefined;
|
||||||
|
this.password = undefined;
|
||||||
|
|
||||||
|
this.set(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
initOptions(options = {}) {
|
||||||
|
// options.id = options.id || uuid();
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
// <JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configurationqqq" enabled="true">
|
||||||
|
// <boolProp name="autocommit">true</boolProp>
|
||||||
|
// <stringProp name="checkQuery"></stringProp>
|
||||||
|
// <stringProp name="connectionAge">5000</stringProp>
|
||||||
|
// <stringProp name="connectionProperties"></stringProp>
|
||||||
|
// <stringProp name="dataSource">test</stringProp>
|
||||||
|
// <stringProp name="dbUrl">jdbc:mysql://localhost:3306/metersphere?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true</stringProp>
|
||||||
|
// <stringProp name="driver">com.mysql.jdbc.Driver</stringProp>
|
||||||
|
// <stringProp name="initQuery"></stringProp>
|
||||||
|
// <boolProp name="keepAlive">true</boolProp>
|
||||||
|
// <stringProp name="password">root</stringProp>
|
||||||
|
// <stringProp name="poolMax">10</stringProp>
|
||||||
|
// <boolProp name="preinit">false</boolProp>
|
||||||
|
// <stringProp name="timeout">10000</stringProp>
|
||||||
|
// <stringProp name="transactionIsolation">DEFAULT</stringProp>
|
||||||
|
// <stringProp name="trimInterval">60000</stringProp>
|
||||||
|
// <stringProp name="username">root</stringProp>
|
||||||
|
// </JDBCDataSource>
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return !!this.name || !!this.poolMax || !!this.timeout || !!this.driver || !!this.dbUrl || !!this.username || !!this.password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class RegistryCenter extends BaseConfig {
|
export class RegistryCenter extends BaseConfig {
|
||||||
static PROTOCOLS = ["none", "zookeeper", "nacos", "apollo", "multicast", "redis", "simple"];
|
static PROTOCOLS = ["none", "zookeeper", "nacos", "apollo", "multicast", "redis", "simple"];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog v-loading="result.loading"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
class="ms-switch-project"
|
||||||
|
>
|
||||||
|
<ms-table-header :condition.sync="condition" @search="initData" title="" :show-create="false"/>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
highlight-current-row
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
{{ scope.row.description }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="createTime"
|
||||||
|
:label="$t('commons.create_time')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="updateTime"
|
||||||
|
:label="$t('commons.update_time')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot:default="scope">
|
||||||
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<ms-table-pagination :change="initData" :current-page.sync="currentPage" :page-size.sync="pageSize"
|
||||||
|
:total="total"/>
|
||||||
|
<template v-slot:footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<ms-dialog-footer
|
||||||
|
@cancel="dialogVisible = false"
|
||||||
|
@confirm="submit()"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsDialogFooter from "../../../common/components/MsDialogFooter";
|
||||||
|
import MsTableHeader from "../../../common/components/MsTableHeader";
|
||||||
|
import MsTablePagination from "../../../common/pagination/TablePagination";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "SwitchProject",
|
||||||
|
components: {MsDialogFooter, MsTableHeader, MsTablePagination},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData: [],
|
||||||
|
result: {},
|
||||||
|
dialogVisible: false,
|
||||||
|
projectId: '',
|
||||||
|
planId: '',
|
||||||
|
condition: {},
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open(planId) {
|
||||||
|
this.dialogVisible = true;
|
||||||
|
this.planId = planId;
|
||||||
|
this.initData();
|
||||||
|
},
|
||||||
|
initData() {
|
||||||
|
this.condition.planId = this.planId;
|
||||||
|
this.result = this.$post("/test/plan/project/" + this.currentPage + "/" + this.pageSize, this.condition, res => {
|
||||||
|
const data = res.data;
|
||||||
|
this.total = data.itemCount;
|
||||||
|
this.tableData = data.listObject;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleCurrentChange(currentRow) {
|
||||||
|
// initData 改变表格数据会触发此方法
|
||||||
|
if (currentRow) {
|
||||||
|
this.projectId = currentRow.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
this.$emit('getProjectNode', this.projectId);
|
||||||
|
this.dialogVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.ms-switch-project >>> .el-dialog__body {
|
||||||
|
padding: 0 15px !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -230,10 +230,14 @@ export default {
|
||||||
this.$emit("refresh");
|
this.$emit("refresh");
|
||||||
},
|
},
|
||||||
nodeExpand(data) {
|
nodeExpand(data) {
|
||||||
this.expandedNode.push(data.id);
|
if (data.id) {
|
||||||
|
this.expandedNode.push(data.id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
nodeCollapse(data) {
|
nodeCollapse(data) {
|
||||||
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1);
|
if (data.id) {
|
||||||
|
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,6 +90,12 @@
|
||||||
initTableData() {
|
initTableData() {
|
||||||
this.result = this.$post('/test/plan/list/all/relate', this.condition, response => {
|
this.result = this.$post('/test/plan/list/all/relate', this.condition, response => {
|
||||||
this.tableData = response.data;
|
this.tableData = response.data;
|
||||||
|
for (let i = 0; i < this.tableData.length; i++) {
|
||||||
|
let path = "/test/plan/project/name/" + this.tableData[i].id;
|
||||||
|
this.$get(path, res => {
|
||||||
|
this.$set(this.tableData[i], "projectName", res.data);
|
||||||
|
})
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
intoPlan(row, event, column) {
|
intoPlan(row, event, column) {
|
||||||
|
|
|
@ -22,11 +22,14 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="11" :offset="2">
|
<el-col :span="11" :offset="2">
|
||||||
<el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectId">
|
<el-form-item :label="$t('test_track.plan.plan_project')" :label-width="formLabelWidth" prop="projectIds">
|
||||||
<el-select
|
<el-select
|
||||||
:disabled="(form.status == null) ? false : true"
|
:disabled="(form.status == null) ? false : true"
|
||||||
v-model="form.projectId"
|
v-model="form.projectIds"
|
||||||
:placeholder="$t('test_track.plan.input_plan_project')"
|
:placeholder="$t('test_track.plan.input_plan_project')"
|
||||||
|
multiple
|
||||||
|
style="width: 100%"
|
||||||
|
collapse-tags
|
||||||
filterable>
|
filterable>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in projects"
|
v-for="item in projects"
|
||||||
|
@ -68,7 +71,7 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row type="flex" justify="left" style="margin-top: 10px;">
|
<el-row type="flex" justify="left" style="margin-top: 10px;">
|
||||||
<el-col :span="19" :offset="1">
|
<el-col :span="23" :offset="1">
|
||||||
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
|
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
|
||||||
<el-input v-model="form.description"
|
<el-input v-model="form.description"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
|
@ -124,7 +127,7 @@ export default {
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
form: {
|
form: {
|
||||||
name: '',
|
name: '',
|
||||||
projectId: '',
|
projectIds: [],
|
||||||
principal: '',
|
principal: '',
|
||||||
stage: '',
|
stage: '',
|
||||||
description: ''
|
description: ''
|
||||||
|
@ -134,7 +137,7 @@ export default {
|
||||||
{required: true, message: this.$t('test_track.plan.input_plan_name'), trigger: 'blur'},
|
{required: true, message: this.$t('test_track.plan.input_plan_name'), trigger: 'blur'},
|
||||||
{max: 30, message: this.$t('test_track.length_less_than') + '30', trigger: 'blur'}
|
{max: 30, message: this.$t('test_track.length_less_than') + '30', trigger: 'blur'}
|
||||||
],
|
],
|
||||||
projectId: [{required: true, message: this.$t('test_track.plan.input_plan_project'), trigger: 'change'}],
|
projectIds: [{required: true, message: this.$t('test_track.plan.input_plan_project'), trigger: 'change'}],
|
||||||
principal: [{required: true, message: this.$t('test_track.plan.input_plan_principal'), trigger: 'change'}],
|
principal: [{required: true, message: this.$t('test_track.plan.input_plan_principal'), trigger: 'change'}],
|
||||||
stage: [{required: true, message: this.$t('test_track.plan.input_plan_stage'), trigger: 'change'}],
|
stage: [{required: true, message: this.$t('test_track.plan.input_plan_stage'), trigger: 'change'}],
|
||||||
description: [{max: 200, message: this.$t('test_track.length_less_than') + '200', trigger: 'blur'}]
|
description: [{max: 200, message: this.$t('test_track.length_less_than') + '200', trigger: 'blur'}]
|
||||||
|
@ -213,7 +216,7 @@ export default {
|
||||||
this.$refs['planFrom'].validate((valid) => {
|
this.$refs['planFrom'].validate((valid) => {
|
||||||
this.$refs['planFrom'].resetFields();
|
this.$refs['planFrom'].resetFields();
|
||||||
this.form.name = '';
|
this.form.name = '';
|
||||||
this.form.projectId = '';
|
this.form.projectIds = [];
|
||||||
this.form.principal = '';
|
this.form.principal = '';
|
||||||
this.form.stage = '';
|
this.form.stage = '';
|
||||||
this.form.description = '';
|
this.form.description = '';
|
||||||
|
|
|
@ -191,6 +191,16 @@ export default {
|
||||||
let data = response.data;
|
let data = response.data;
|
||||||
this.total = data.itemCount;
|
this.total = data.itemCount;
|
||||||
this.tableData = data.listObject;
|
this.tableData = data.listObject;
|
||||||
|
for (let i = 0; i < this.tableData.length; i++) {
|
||||||
|
let path = "/test/plan/project";
|
||||||
|
this.$post(path,{planId: this.tableData[i].id}, res => {
|
||||||
|
let arr = res.data;
|
||||||
|
let projectName = arr.map(data => data.name).join("、");
|
||||||
|
let projectIds = arr.map(data => data.id);
|
||||||
|
this.$set(this.tableData[i], "projectName", projectName);
|
||||||
|
this.$set(this.tableData[i], "projectIds", projectIds);
|
||||||
|
})
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
buildPagePath(path) {
|
buildPagePath(path) {
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
:visible.sync="dialogFormVisible"
|
:visible.sync="dialogFormVisible"
|
||||||
@close="close"
|
@close="close"
|
||||||
width="60%" v-loading="result.loading"
|
width="60%" v-loading="result.loading"
|
||||||
|
:close-on-click-modal="false"
|
||||||
top="50px">
|
top="50px">
|
||||||
|
|
||||||
<el-container class="main-content">
|
<el-container class="main-content">
|
||||||
<el-aside class="tree-aside" width="250px">
|
<el-aside class="tree-aside" width="250px">
|
||||||
|
<el-link type="primary" class="project-link" @click="switchProject">{{projectName ? projectName : '切换项目' }}</el-link>
|
||||||
<node-tree class="node-tree"
|
<node-tree class="node-tree"
|
||||||
@nodeSelectEvent="nodeChange"
|
@nodeSelectEvent="nodeChange"
|
||||||
@refresh="refresh"
|
@refresh="refresh"
|
||||||
|
@ -71,6 +73,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<switch-project ref="switchProject" @getProjectNode="getProjectNode"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -86,6 +90,7 @@
|
||||||
import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar";
|
import MsTableAdvSearchBar from "../../../../common/components/search/MsTableAdvSearchBar";
|
||||||
import MsTableHeader from "../../../../common/components/MsTableHeader";
|
import MsTableHeader from "../../../../common/components/MsTableHeader";
|
||||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||||
|
import SwitchProject from "../../../case/components/SwitchProject";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestCaseRelevance",
|
name: "TestCaseRelevance",
|
||||||
|
@ -96,7 +101,8 @@
|
||||||
TypeTableItem,
|
TypeTableItem,
|
||||||
MsTableSearchBar,
|
MsTableSearchBar,
|
||||||
MsTableAdvSearchBar,
|
MsTableAdvSearchBar,
|
||||||
MsTableHeader
|
MsTableHeader,
|
||||||
|
SwitchProject
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -108,6 +114,9 @@
|
||||||
treeNodes: [],
|
treeNodes: [],
|
||||||
selectNodeIds: [],
|
selectNodeIds: [],
|
||||||
selectNodeNames: [],
|
selectNodeNames: [],
|
||||||
|
projectId: '',
|
||||||
|
projectName: '',
|
||||||
|
projects: [],
|
||||||
condition: {
|
condition: {
|
||||||
components: TEST_CASE_CONFIGS
|
components: TEST_CASE_CONFIGS
|
||||||
},
|
},
|
||||||
|
@ -135,6 +144,9 @@
|
||||||
},
|
},
|
||||||
selectNodeIds() {
|
selectNodeIds() {
|
||||||
this.getCaseNames();
|
this.getCaseNames();
|
||||||
|
},
|
||||||
|
projectId() {
|
||||||
|
this.getProjectNode();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updated() {
|
updated() {
|
||||||
|
@ -157,7 +169,6 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getCaseNames() {
|
getCaseNames() {
|
||||||
let param = {};
|
|
||||||
if (this.planId) {
|
if (this.planId) {
|
||||||
// param.planId = this.planId;
|
// param.planId = this.planId;
|
||||||
this.condition.planId = this.planId;
|
this.condition.planId = this.planId;
|
||||||
|
@ -168,12 +179,17 @@
|
||||||
} else {
|
} else {
|
||||||
this.condition.nodeIds = [];
|
this.condition.nodeIds = [];
|
||||||
}
|
}
|
||||||
this.result = this.$post('/test/case/name', this.condition, response => {
|
|
||||||
this.testCases = response.data;
|
if (this.projectId) {
|
||||||
this.testCases.forEach(item => {
|
this.condition.projectId = this.projectId;
|
||||||
item.checked = false;
|
this.result = this.$post('/test/case/name', this.condition, response => {
|
||||||
|
this.testCases = response.data;
|
||||||
|
this.testCases.forEach(item => {
|
||||||
|
item.checked = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
handleSelectAll(selection) {
|
handleSelectAll(selection) {
|
||||||
if (selection.length > 0) {
|
if (selection.length > 0) {
|
||||||
|
@ -203,13 +219,18 @@
|
||||||
initData() {
|
initData() {
|
||||||
this.getCaseNames();
|
this.getCaseNames();
|
||||||
this.getAllNodeTreeByPlanId();
|
this.getAllNodeTreeByPlanId();
|
||||||
|
this.getProject();
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
getAllNodeTreeByPlanId() {
|
getAllNodeTreeByPlanId() {
|
||||||
if (this.planId) {
|
if (this.planId) {
|
||||||
this.result = this.$get("/case/node/list/all/plan/" + this.planId, response => {
|
let param = {
|
||||||
|
testPlanId: this.planId,
|
||||||
|
projectId: this.projectId
|
||||||
|
};
|
||||||
|
this.result = this.$post("/case/node/list/all/plan", param , response => {
|
||||||
this.treeNodes = response.data;
|
this.treeNodes = response.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -233,6 +254,36 @@
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
getProject() {
|
||||||
|
if (this.planId) {
|
||||||
|
this.$post("/test/plan/project/", {planId: this.planId},res => {
|
||||||
|
let data = res.data;
|
||||||
|
if (data) {
|
||||||
|
this.projects = data;
|
||||||
|
this.projectId = data[0].id;
|
||||||
|
this.projectName = data[0].name;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
switchProject() {
|
||||||
|
this.$refs.switchProject.open(this.planId);
|
||||||
|
},
|
||||||
|
getProjectNode(projectId) {
|
||||||
|
const index = this.projects.findIndex(project => project.id === projectId);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.projectName = this.projects[index].name;
|
||||||
|
}
|
||||||
|
if (projectId) {
|
||||||
|
this.projectId = projectId;
|
||||||
|
}
|
||||||
|
this.result = this.$post("/case/node/list/all/plan",
|
||||||
|
{testPlanId: this.planId, projectId: this.projectId} , response => {
|
||||||
|
this.treeNodes = response.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.selectNodeIds = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -281,4 +332,10 @@
|
||||||
/*border: 1px solid #EBEEF5;*/
|
/*border: 1px solid #EBEEF5;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project-link {
|
||||||
|
float: right;
|
||||||
|
margin-right: 12px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -89,6 +89,13 @@
|
||||||
<span class="cast_item">{{testCase.nodePath}}</span>
|
<span class="cast_item">{{testCase.nodePath}}</span>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" :offset="1">
|
<el-col :span="4" :offset="1">
|
||||||
|
<span class="cast_label">{{$t('test_track.plan.plan_project')}}:</span>
|
||||||
|
<span class="cast_item">{{testCase.projectName}}</span>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :offset="1">
|
||||||
<span class="cast_label">{{$t('test_track.case.prerequisite')}}:</span>
|
<span class="cast_label">{{$t('test_track.case.prerequisite')}}:</span>
|
||||||
<span class="cast_item">{{testCase.prerequisite}}</span>
|
<span class="cast_item">{{testCase.prerequisite}}</span>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
|
@ -15,13 +15,6 @@
|
||||||
<ms-table-button :is-tester-permission="true" icon="el-icon-connection"
|
<ms-table-button :is-tester-permission="true" icon="el-icon-connection"
|
||||||
:content="$t('test_track.plan_view.relevance_test_case')"
|
:content="$t('test_track.plan_view.relevance_test_case')"
|
||||||
@click="$emit('openTestCaseRelevanceDialog')"/>
|
@click="$emit('openTestCaseRelevanceDialog')"/>
|
||||||
<!-- <ms-table-button :is-tester-permission="true" icon="el-icon-unlock"-->
|
|
||||||
<!-- :content="$t('test_track.plan_view.cancel_relevance')" @click="handleBatch('delete')"/>-->
|
|
||||||
<!-- <ms-table-button :is-tester-permission="true" icon="el-icon-edit-outline"-->
|
|
||||||
<!-- :content="$t('test_track.plan_view.change_execution_results')"-->
|
|
||||||
<!-- @click="handleBatch('status')"/>-->
|
|
||||||
<!-- <ms-table-button :is-tester-permission="true" icon="el-icon-user"-->
|
|
||||||
<!-- :content="$t('test_track.plan_view.change_executor')" @click="handleBatch('executor')"/>-->
|
|
||||||
<ms-table-button :is-tester-permission="true" v-if="!testPlan.reportId" icon="el-icon-document"
|
<ms-table-button :is-tester-permission="true" v-if="!testPlan.reportId" icon="el-icon-document"
|
||||||
:content="$t('test_track.plan_view.create_report')" @click="openTestReport"/>
|
:content="$t('test_track.plan_view.create_report')" @click="openTestReport"/>
|
||||||
<ms-table-button :is-tester-permission="true" v-if="testPlan.reportId" icon="el-icon-document"
|
<ms-table-button :is-tester-permission="true" v-if="testPlan.reportId" icon="el-icon-document"
|
||||||
|
@ -103,7 +96,12 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="nodePath"
|
prop="projectName"
|
||||||
|
:label="$t('test_track.plan.plan_project')"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
:label="$t('test_track.issue.issue')"
|
:label="$t('test_track.issue.issue')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -112,7 +110,6 @@
|
||||||
width="400"
|
width="400"
|
||||||
trigger="hover">
|
trigger="hover">
|
||||||
<el-table border class="adjust-table" :data="scope.row.issuesContent" style="width: 100%">
|
<el-table border class="adjust-table" :data="scope.row.issuesContent" style="width: 100%">
|
||||||
<!-- <el-table-column prop="id" label="缺陷ID" show-overflow-tooltip/>-->
|
|
||||||
<el-table-column prop="title" :label="$t('test_track.issue.title')" show-overflow-tooltip/>
|
<el-table-column prop="title" :label="$t('test_track.issue.title')" show-overflow-tooltip/>
|
||||||
<el-table-column prop="description" :label="$t('test_track.issue.description')">
|
<el-table-column prop="description" :label="$t('test_track.issue.description')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -127,7 +124,6 @@
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- <el-table-column prop="status" label="缺陷状态"/>-->
|
|
||||||
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-button slot="reference" type="text">{{scope.row.issuesSize}}</el-button>
|
<el-button slot="reference" type="text">{{scope.row.issuesSize}}</el-button>
|
||||||
|
@ -262,7 +258,6 @@
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
// selectIds: new Set(),
|
|
||||||
selectRows: new Set(),
|
selectRows: new Set(),
|
||||||
testPlan: {},
|
testPlan: {},
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -369,7 +364,6 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// this.selectIds.clear();
|
|
||||||
this.selectRows.clear();
|
this.selectRows.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -380,7 +374,6 @@
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.condition = {components: TEST_CASE_CONFIGS};
|
this.condition = {components: TEST_CASE_CONFIGS};
|
||||||
// this.selectIds.clear();
|
|
||||||
this.selectRows.clear();
|
this.selectRows.clear();
|
||||||
this.$emit('refresh');
|
this.$emit('refresh');
|
||||||
},
|
},
|
||||||
|
@ -443,13 +436,6 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSelectAll(selection) {
|
handleSelectAll(selection) {
|
||||||
// if (selection.length > 0) {
|
|
||||||
// this.tableData.forEach(item => {
|
|
||||||
// this.selectIds.add(item.id);
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// this.selectIds.clear();
|
|
||||||
// }
|
|
||||||
if (selection.length > 0) {
|
if (selection.length > 0) {
|
||||||
if (selection.length === 1) {
|
if (selection.length === 1) {
|
||||||
this.selectRows.add(selection[0]);
|
this.selectRows.add(selection[0]);
|
||||||
|
@ -467,11 +453,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleSelectionChange(selection, row) {
|
handleSelectionChange(selection, row) {
|
||||||
// if (this.selectIds.has(row.id)) {
|
|
||||||
// this.selectIds.delete(row.id);
|
|
||||||
// } else {
|
|
||||||
// this.selectIds.add(row.id);
|
|
||||||
// }
|
|
||||||
if (this.selectRows.has(row)) {
|
if (this.selectRows.has(row)) {
|
||||||
this.$set(row, "showMore", false);
|
this.$set(row, "showMore", false);
|
||||||
this.selectRows.delete(row);
|
this.selectRows.delete(row);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 390943d21e7d0196e0d7d5faa66f0131cb631614
|
Subproject commit 7e4d80cc2b870a8cac6dbb9fe6711ab6041faf6d
|
Loading…
Reference in New Issue