feat(测试计划): 测试计划增加停止

This commit is contained in:
wxg0103 2024-06-14 17:21:22 +08:00 committed by wxg0103
parent b5acc24a3c
commit 572b527b96
13 changed files with 615 additions and 45 deletions

View File

@ -91,7 +91,7 @@ public class ApiTaskCenterController {
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
apiTaskCenterService.stopById(moduleType, id, SessionUtils.getUserId(),
OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER, "/task/center/api/project/stop");
OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER);
}
@GetMapping("/api/org/stop/{moduleType}/{id}")
@ -101,7 +101,7 @@ public class ApiTaskCenterController {
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
apiTaskCenterService.stopById(moduleType, id, SessionUtils.getUserId(),
OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER, "/task/center/api/org/stop");
OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER);
}
@GetMapping("/api/system/stop/{moduleType}/{id}")
@ -112,6 +112,6 @@ public class ApiTaskCenterController {
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
apiTaskCenterService.stopById(moduleType, id, SessionUtils.getUserId(),
OperationLogModule.SETTING_SYSTEM_TASK_CENTER, "/task/center/api/system/stop");
OperationLogModule.SETTING_SYSTEM_TASK_CENTER);
}
}

View File

@ -27,6 +27,8 @@ public class ReportDTO implements Serializable {
private String resourceId;
@Schema(description = "测试计划id")
private String testPlanId;
@Schema(description = "测试计划名称")
private String testPlanReportId;
}

View File

@ -25,6 +25,7 @@ import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;
import io.metersphere.system.log.aspect.OperationLogAspect;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
@ -222,10 +223,10 @@ public class ApiTaskCenterService {
}
public void systemStop(TaskCenterBatchRequest request, String userId) {
stopApiTask(request, new ArrayList<>(), userId, SYSTEM_STOP, HttpMethodConstants.POST.name(), OperationLogModule.SETTING_SYSTEM_TASK_CENTER);
stopApiTask(request, new ArrayList<>(), userId, OperationLogModule.SETTING_SYSTEM_TASK_CENTER);
}
private void stopApiTask(TaskCenterBatchRequest request, List<String> projectIds, String userId, String path, String method, String module) {
private void stopApiTask(TaskCenterBatchRequest request, List<String> projectIds, String userId, String module) {
List<ReportDTO> reports = new ArrayList<>();
if (request.getModuleType().equals(TaskCenterResourceType.API_CASE.toString())) {
if (request.isSelectAll()) {
@ -241,15 +242,13 @@ public class ApiTaskCenterService {
}
}
if (CollectionUtils.isNotEmpty(reports)) {
detailReport(request, reports, userId, path, method, module);
detailReport(request, reports, userId, module);
}
}
private void detailReport(TaskCenterBatchRequest request,
List<ReportDTO> reports,
String userId,
String path,
String method,
String module) {
Map<String, List<String>> poolIdMap = reports.stream()
.collect(Collectors.groupingBy(ReportDTO::getPoolId, Collectors.mapping(ReportDTO::getId, Collectors.toList())));
@ -257,7 +256,7 @@ public class ApiTaskCenterService {
TestResourcePoolReturnDTO testResourcePoolDTO = testResourcePoolService.getTestResourcePoolDetail(poolId);
List<TestResourceNodeDTO> nodesList = testResourcePoolDTO.getTestResourceReturnDTO().getNodesList();
if (CollectionUtils.isNotEmpty(nodesList)) {
stopTask(request, reportList, nodesList, userId, path, method, module, reports);
stopTask(request, reportList, nodesList, userId, module, reports);
}
});
}
@ -266,8 +265,6 @@ public class ApiTaskCenterService {
List<String> reportList,
List<TestResourceNodeDTO> nodesList,
String userId,
String path,
String method,
String module,
List<ReportDTO> reports) {
// 根据报告id分组 key是报告id value是 是否集成
@ -326,16 +323,16 @@ public class ApiTaskCenterService {
if (request.getModuleType().equals(TaskCenterResourceType.API_CASE.toString())) {
//记录日志
saveLog(subList, userId, path, method, StringUtils.join(module, "_REAL_TIME_API_CASE"), TaskCenterResourceType.API_CASE.toString());
saveLog(subList, userId, StringUtils.join(module, "_REAL_TIME_API_CASE"), TaskCenterResourceType.API_CASE.toString());
} else if (request.getModuleType().equals(TaskCenterResourceType.API_SCENARIO.toString())) {
saveLog(subList, userId, path, method, StringUtils.join(module, "_REAL_TIME_API_SCENARIO"), TaskCenterResourceType.API_SCENARIO.toString());
saveLog(subList, userId, StringUtils.join(module, "_REAL_TIME_API_SCENARIO"), TaskCenterResourceType.API_SCENARIO.toString());
}
}
});
});
}
private void saveLog(List<String> ids, String userId, String path, String method, String module, String type) {
private void saveLog(List<String> ids, String userId, String module, String type) {
List<ReportDTO> reports = new ArrayList<>();
if (StringUtils.equals(type, TaskCenterResourceType.API_CASE.toString())) {
reports = extApiReportMapper.selectByIds(ids);
@ -355,8 +352,8 @@ public class ApiTaskCenterService {
.organizationId(orgMap.get(reportDTO.getProjectId()))
.type(OperationLogType.UPDATE.name())
.module(module)
.method(method)
.path(path)
.method(OperationLogAspect.getMethod())
.path(OperationLogAspect.getPath())
.sourceId(reportDTO.getId())
.content(String.format("停止任务:%s", reportDTO.getName()))
.createUser(userId)
@ -370,22 +367,22 @@ public class ApiTaskCenterService {
checkOrganizationExist(orgId);
List<OptionDTO> projectList = getOrgProjectList(orgId);
List<String> projectIds = projectList.stream().map(OptionDTO::getId).toList();
stopApiTask(request, projectIds, userId, ORG_STOP, HttpMethodConstants.POST.name(), OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER);
stopApiTask(request, projectIds, userId, OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER);
}
public void projectStop(TaskCenterBatchRequest request, String currentProjectId, String userId) {
checkProjectExist(currentProjectId);
stopApiTask(request, List.of(currentProjectId), userId, PROJECT_STOP, HttpMethodConstants.POST.name(), OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER);
stopApiTask(request, List.of(currentProjectId), userId, OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER);
}
public void stopById(String moduleType, String id, String userId, String module, String path) {
public void stopById(String moduleType, String id, String userId, String module) {
List<String> reportIds = new ArrayList<>();
reportIds.add(id);
TaskCenterBatchRequest request = new TaskCenterBatchRequest();
request.setSelectIds(reportIds);
request.setModuleType(moduleType);
stopApiTask(request, null, userId, path, HttpMethodConstants.GET.name(), module);
stopApiTask(request, null, userId, module);
}

View File

@ -311,7 +311,7 @@ public class ApiTaskCenterControllerTests extends BaseTest {
baseResourcePoolTestService.insertResourcePoolProject(testResourcePool);
baseResourcePoolTestService.insertProjectApplication(testResourcePool);
}

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.definition.ApiReportDTO;
import io.metersphere.api.dto.definition.ApiReportDetailDTO;
import io.metersphere.api.service.definition.ApiReportService;
import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
@ -27,6 +28,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -146,7 +148,7 @@ public class TestPlanApiCaseController {
@GetMapping("/report/get/{id}")
@Operation(summary = "测试计划-用例列表-执行结果获取")
@CheckOwner(resourceId = "#id", resourceType = "api_report")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_READ, PermissionConstants.TEST_PLAN_REPORT_READ}, logical = Logical.OR)
public ApiReportDTO get(@PathVariable String id) {
testPlanApiCaseService.checkReportIsTestPlan(id);
return apiReportService.get(id);
@ -155,7 +157,7 @@ public class TestPlanApiCaseController {
@GetMapping("/report/get/detail/{reportId}/{stepId}")
@Operation(summary = "测试计划-用例列表-执行结果获取-报告详情获取")
@CheckOwner(resourceId = "#reportId", resourceType = "api_report")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_READ, PermissionConstants.TEST_PLAN_REPORT_READ}, logical = Logical.OR)
public List<ApiReportDetailDTO> getDetail(@PathVariable String reportId,
@PathVariable String stepId) {
testPlanApiCaseService.checkReportIsTestPlan(reportId);

View File

@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -127,7 +128,7 @@ public class TestPlanApiScenarioController {
@GetMapping("/report/get/{id}")
@Operation(summary = "测试计划-计划详情-场景用例列表-查看执行结果")
@CheckOwner(resourceId = "#id", resourceType = "api_scenario_report")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_READ, PermissionConstants.TEST_PLAN_REPORT_READ}, logical = Logical.OR)
public ApiScenarioReportDTO get(@PathVariable String id) {
testPlanApiScenarioService.checkReportIsTestPlan(id);
return apiScenarioReportService.get(id);
@ -136,7 +137,7 @@ public class TestPlanApiScenarioController {
@GetMapping("report/get/detail/{reportId}/{stepId}")
@Operation(summary = "测试计划-计划详情-场景用例列表-执行结果详情获取")
@CheckOwner(resourceId = "#reportId", resourceType = "api_scenario_report")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
@RequiresPermissions(value = {PermissionConstants.TEST_PLAN_READ, PermissionConstants.TEST_PLAN_REPORT_READ}, logical = Logical.OR)
public List<ApiScenarioReportDetailDTO> getDetail(@PathVariable String reportId,
@PathVariable String stepId) {
testPlanApiScenarioService.checkReportIsTestPlan(reportId);

View File

@ -3,7 +3,9 @@ package io.metersphere.plan.controller;
import io.metersphere.plan.service.TestPlanTaskCenterService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
@ -11,10 +13,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -51,5 +50,64 @@ public class TestPlanTaskCenterController {
return testPlanTaskCenterService.getSystemPage(request);
}
@GetMapping("/project/stop/{id}")
@Operation(summary = "项目-任务中心-接口用例/场景-停止任务")
public void stopById(@PathVariable String id) {
testPlanTaskCenterService.hasPermission(PROJECT,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.stopById(id, SessionUtils.getUserId(),
OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER);
}
@GetMapping("/org/stop/{id}")
@Operation(summary = "组织-任务中心-接口用例/场景-停止任务")
public void stopOrgById(@PathVariable String id) {
testPlanTaskCenterService.hasPermission(ORG,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.stopById(id, SessionUtils.getUserId(),
OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER);
}
@GetMapping("/system/stop/{id}")
@Operation(summary = "系统-任务中心-接口用例/场景-停止任务")
@RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ)
public void stopSystemById(@PathVariable String id) {
testPlanTaskCenterService.hasPermission(SYSTEM,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.stopById(id, SessionUtils.getUserId(),
OperationLogModule.SETTING_SYSTEM_TASK_CENTER);
}
@PostMapping("/system/stop")
@Operation(summary = "系统-任务中心-接口用例/场景-停止任务")
public void systemStop(@Validated @RequestBody TaskCenterBatchRequest request) {
testPlanTaskCenterService.hasPermission(SYSTEM,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.systemStop(request, SessionUtils.getUserId());
}
@PostMapping("/org/stop")
@Operation(summary = "组织-任务中心-接口用例/场景-停止任务")
public void orgStop(@Validated @RequestBody TaskCenterBatchRequest request) {
testPlanTaskCenterService.hasPermission(ORG,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.orgStop(request, SessionUtils.getCurrentOrganizationId(), SessionUtils.getUserId());
}
@PostMapping("/project/stop")
@Operation(summary = "项目-任务中心-接口用例/场景-停止任务")
public void projectStop(@Validated @RequestBody TaskCenterBatchRequest request) {
testPlanTaskCenterService.hasPermission(PROJECT,
SessionUtils.getCurrentOrganizationId(),
SessionUtils.getCurrentProjectId());
testPlanTaskCenterService.projectStop(request, SessionUtils.getCurrentProjectId(), SessionUtils.getUserId());
}
}

View File

@ -64,4 +64,7 @@ public class TestPlanReportDetailResponse {
private CaseCount apiScenarioCount;
private boolean deleted;
@Schema(description = "报告状态")
private String resultStatus;
}

View File

@ -1,5 +1,7 @@
package io.metersphere.plan.mapper;
import io.metersphere.api.dto.definition.ExecuteReportDTO;
import io.metersphere.api.dto.report.ReportDTO;
import io.metersphere.plan.domain.TestPlanReport;
import io.metersphere.plan.dto.request.TestPlanReportBatchRequest;
import io.metersphere.plan.dto.request.TestPlanReportDetailPageRequest;
@ -8,6 +10,7 @@ import io.metersphere.plan.dto.response.TestPlanReportDetailResponse;
import io.metersphere.plan.dto.response.TestPlanReportPageResponse;
import io.metersphere.system.dto.sdk.ApiReportMessageDTO;
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;
import org.apache.ibatis.annotations.Param;
@ -45,4 +48,15 @@ public interface ExtTestPlanReportMapper {
@Param("startTime") long startTime, @Param("endTime") long endTime);
List<TestPlanReportDetailResponse> getPlanReportListById(@Param("request") TestPlanReportDetailPageRequest request);
List<ReportDTO> getReports(@Param("request") TaskCenterBatchRequest request, @Param("projectIds") List<String> projectIds,
@Param("ids") List<String> ids, @Param("startTime") long startTime, @Param("endTime") long endTime);
List<ExecuteReportDTO> getHistoryDeleted(@Param("ids") List<String> ids);
List<ReportDTO> selectByParentIds(@Param("ids") List<String> ids);
List<ReportDTO> getCaseReports(@Param("ids") List<String> ids);
List<ReportDTO> getScenarioReports(@Param("ids") List<String> ids);
}

View File

@ -115,6 +115,107 @@
<include refid="queryWhereConditionByParentId"/>
</select>
<select id="getReports" resultType="io.metersphere.api.dto.report.ReportDTO">
select
distinct tpr.id,
tpr.project_id,
tpr.integrated,
project.organization_id,
tp.id AS resourceId
FROM
test_plan_report tpr
INNER JOIN test_plan tp ON tpr.test_plan_id = tp.id
left join project on tpr.project_id = project.id
where
tpr.start_time BETWEEN #{startTime} AND #{endTime}
and tpr.exec_status in ('PENDING', 'RUNNING', 'RERUNNING')
<if test="ids != null and ids.size() > 0">
and tpr.id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="projectIds != null and projectIds.size() > 0">
and
tpr.project_id IN
<foreach collection="projectIds" item="projectId" separator="," open="(" close=")">
#{projectId}
</foreach>
</if>
<if test="request.condition.keyword != null and request.condition.keyword != ''">
and (tp.num like concat('%', #{request.condition.keyword},'%')
or tp.name like concat('%', #{request.condition.keyword},'%')
)
</if>
<include refid="filterByCondition"/>
</select>
<select id="getHistoryDeleted" resultType="io.metersphere.api.dto.definition.ExecuteReportDTO">
select distinct tpr.* from test_plan_report tpr INNER JOIN test_plan_report_summary tprs on tpr.id = tprs.test_plan_report_id
<if test="ids != null and ids.size() > 0">
where tpr.id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</select>
<select id="selectByParentIds" resultType="io.metersphere.api.dto.report.ReportDTO">
select
distinct tpr.id,
tpr.project_id,
tpr.integrated,
project.organization_id,
tp.id AS resourceId
FROM
test_plan_report tpr
INNER JOIN test_plan tp ON tpr.test_plan_id = tp.id
left join project on tpr.project_id = project.id
where
tpr.exec_status in ('PENDING', 'RUNNING', 'RERUNNING')
and tpr.parent_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<select id="getCaseReports" resultType="io.metersphere.api.dto.report.ReportDTO">
SELECT DISTINCT
ar.*,
project.organization_id,
ar.test_plan_case_id AS testPlanId,
tprac.test_plan_report_id AS testPlanReportId,
ar.test_plan_case_id AS resourceId
FROM
api_report ar
LEFT JOIN project ON ar.project_id = project.id
LEFT JOIN test_plan_report_api_case tprac ON ar.id = tprac.api_case_execute_report_id
WHERE
ar.deleted = FALSE
AND ar.plan = 1
AND ar.exec_status IN ( 'PENDING', 'RUNNING', 'RERUNNING' )
AND tprac.test_plan_report_id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<select id="getScenarioReports" resultType="io.metersphere.api.dto.report.ReportDTO">
SELECT DISTINCT
asr.*,
project.organization_id,
asr.test_plan_scenario_id AS testPlanId,
asr.test_plan_scenario_id AS resourceId
FROM
api_scenario_report asr
LEFT JOIN test_plan_report_api_scenario tpras ON asr.id = tpras.test_plan_report_id
LEFT JOIN project ON asr.project_id = project.id
WHERE
asr.deleted = FALSE
AND asr.plan = 1
AND asr.exec_status IN ( 'PENDING', 'RUNNING', 'RERUNNING' )
AND tpras.api_scenario_execute_report_id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<sql id="queryWhereConditionByParentId">
<where>

View File

@ -3,17 +3,33 @@ package io.metersphere.plan.service;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import io.metersphere.api.dto.definition.ExecuteReportDTO;
import io.metersphere.api.dto.report.ReportDTO;
import io.metersphere.api.mapper.ExtApiReportMapper;
import io.metersphere.api.mapper.ExtApiScenarioReportMapper;
import io.metersphere.engine.MsHttpClient;
import io.metersphere.plan.mapper.ExtTestPlanReportMapper;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.ApiExecuteResourceType;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.TaskCenterResourceType;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.DateUtils;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.SubListUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.Organization;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.system.dto.pool.TestResourceNodeDTO;
import io.metersphere.system.dto.pool.TestResourcePoolReturnDTO;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.dto.taskcenter.TaskCenterDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;
import io.metersphere.system.log.aspect.OperationLogAspect;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.mapper.BaseProjectMapper;
import io.metersphere.system.mapper.ExtOrganizationMapper;
@ -22,15 +38,17 @@ import io.metersphere.system.service.TestResourcePoolService;
import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -56,15 +74,14 @@ public class TestPlanTaskCenterService {
@Resource
OrganizationMapper organizationMapper;
@Resource
ExtApiScenarioReportMapper extApiScenarioReportMapper;
@Resource
TestResourcePoolService testResourcePoolService;
@Resource
OperationLogService operationLogService;
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
ExtApiReportMapper extApiReportMapper;
@Resource
ExtApiScenarioReportMapper extApiScenarioReportMapper;
private static final String DEFAULT_SORT = "start_time desc";
private final static String PROJECT_STOP = "/task/center/api/project/stop";
private final static String ORG_STOP = "/task/center/api/org/stop";
@ -118,11 +135,11 @@ public class TestPlanTaskCenterService {
Map<String, ExecuteReportDTO> historyDeletedMap = new HashMap<>();
list = extTestPlanReportMapper.taskCenterlist(request, isSystem ? new ArrayList<>() : projectIds, DateUtils.getDailyStartTime(), DateUtils.getDailyEndTime());
//执行历史列表
/*List<String> reportIds = list.stream().map(TaskCenterDTO::getId).toList();
if (CollectionUtils.isNotEmpty(reportIds)) {
List<ExecuteReportDTO> historyDeletedList = extTestPlanReportMapper.getHistoryDeleted(reportIds);
historyDeletedMap = historyDeletedList.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, Function.identity()));
}*/
List<String> reportIds = list.stream().map(TaskCenterDTO::getId).toList();
if (CollectionUtils.isNotEmpty(reportIds)) {
List<ExecuteReportDTO> historyDeletedList = extTestPlanReportMapper.getHistoryDeleted(reportIds);
historyDeletedMap = historyDeletedList.stream().collect(Collectors.toMap(ExecuteReportDTO::getId, Function.identity()));
}
processTaskCenter(list, projectList, projectIds, historyDeletedMap);
}
@ -191,4 +208,154 @@ public class TestPlanTaskCenterService {
}
}
public void hasPermission(String type, String orgId, String projectId) {
List<String> orgPermission = List.of(PermissionConstants.ORGANIZATION_TASK_CENTER_READ_STOP, PermissionConstants.TEST_PLAN_READ_EXECUTE);
List<String> projectPermission = List.of(PermissionConstants.TEST_PLAN_READ_EXECUTE);
List<String> systemPermission = List.of(PermissionConstants.SYSTEM_TASK_CENTER_READ_STOP, PermissionConstants.TEST_PLAN_READ_EXECUTE);
boolean hasPermission = switch (type) {
case "org" -> orgPermission.stream().anyMatch(item -> SessionUtils.hasPermission(orgId, projectId, item));
case "project" ->
projectPermission.stream().anyMatch(item -> SessionUtils.hasPermission(orgId, projectId, item));
case "system" ->
systemPermission.stream().anyMatch(item -> SessionUtils.hasPermission(orgId, projectId, item));
default -> false;
};
if (!hasPermission) {
throw new MSException(Translator.get("no_permission_to_resource"));
}
}
public void systemStop(TaskCenterBatchRequest request, String userId) {
stopApiTask(request, new ArrayList<>(), userId, OperationLogModule.SETTING_SYSTEM_TASK_CENTER);
}
public void orgStop(TaskCenterBatchRequest request, String orgId, String userId) {
checkOrganizationExist(orgId);
List<OptionDTO> projectList = getOrgProjectList(orgId);
List<String> projectIds = projectList.stream().map(OptionDTO::getId).toList();
stopApiTask(request, projectIds, userId, OperationLogModule.SETTING_ORGANIZATION_TASK_CENTER);
}
public void projectStop(TaskCenterBatchRequest request, String currentProjectId, String userId) {
checkProjectExist(currentProjectId);
stopApiTask(request, List.of(currentProjectId), userId, OperationLogModule.PROJECT_MANAGEMENT_TASK_CENTER);
}
public void stopById(String id, String userId, String logModule) {
List<String> reportIds = new ArrayList<>();
reportIds.add(id);
TaskCenterBatchRequest request = new TaskCenterBatchRequest();
request.setSelectIds(reportIds);
request.setModuleType(TaskCenterResourceType.TEST_PLAN.name());
stopApiTask(request, null, userId, logModule);
}
private void stopApiTask(TaskCenterBatchRequest request, List<String> projectIds, String userId, String module) {
List<ReportDTO> reports = new ArrayList<>();
if (request.isSelectAll()) {
reports = extTestPlanReportMapper.getReports(request, projectIds, null, DateUtils.getDailyStartTime(), DateUtils.getDailyEndTime());
} else {
reports = extTestPlanReportMapper.getReports(request, projectIds, request.getSelectIds(), DateUtils.getDailyStartTime(), DateUtils.getDailyEndTime());
}
// 需要处理 如果是集成报告 需要找到计划组下面的所有的测试计划 然后全部停掉
if (CollectionUtils.isNotEmpty(reports)) {
//过滤所有为集合的报告取测试计划ID
List<String> reportIds = reports.stream().filter(item -> BooleanUtils.isTrue(item.getIntegrated()))
.map(ReportDTO::getId).toList();
// 取集合报告的所有子报告
if (CollectionUtils.isNotEmpty(reportIds)) {
List<ReportDTO> childReports = extTestPlanReportMapper.selectByParentIds(reportIds);
if (CollectionUtils.isNotEmpty(childReports)) {
reports.addAll(childReports);
}
}
//根据id去重
List<String> allReportIds = reports.stream().distinct().map(ReportDTO::getId).toList();
if (CollectionUtils.isNotEmpty(allReportIds)) {
// 查找和测试计划管理的接口用例的所有数据
List<ReportDTO> apiReports = extTestPlanReportMapper.getCaseReports(allReportIds);
detailReport(request, apiReports, userId, module, ApiExecuteResourceType.TEST_PLAN_API_CASE.name());
List<ReportDTO> scenarioReports = extTestPlanReportMapper.getScenarioReports(allReportIds);
detailReport(request, scenarioReports, userId, module, ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name());
}
}
}
private void detailReport(TaskCenterBatchRequest request,
List<ReportDTO> reports,
String userId,
String module,
String resourceType) {
Map<String, List<String>> poolIdMap = reports.stream()
.collect(Collectors.groupingBy(ReportDTO::getPoolId, Collectors.mapping(ReportDTO::getId, Collectors.toList())));
poolIdMap.forEach((poolId, reportList) -> {
TestResourcePoolReturnDTO testResourcePoolDTO = testResourcePoolService.getTestResourcePoolDetail(poolId);
List<TestResourceNodeDTO> nodesList = testResourcePoolDTO.getTestResourceReturnDTO().getNodesList();
if (CollectionUtils.isNotEmpty(nodesList)) {
stopTask(request, reportList, nodesList, userId, module, resourceType);
}
});
}
public void stopTask(TaskCenterBatchRequest request,
List<String> reportList,
List<TestResourceNodeDTO> nodesList,
String userId,
String module,
String resourceType) {
nodesList.parallelStream().forEach(node -> {
String endpoint = MsHttpClient.getEndpoint(node.getIp(), node.getPort());
//需要去除取消勾选的report
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
reportList.removeAll(request.getExcludeIds());
}
SubListUtils.dealForSubList(reportList, 100, (subList) -> {
try {
LogUtils.info(String.format("开始发送停止请求到 %s 节点执行", endpoint), subList.toString());
MsHttpClient.stopApi(endpoint, subList);
} catch (Exception e) {
LogUtils.error(e);
} finally {
saveLog(subList, userId, StringUtils.join(module, "_REAL_TIME_TEST_PLAN"), resourceType);
}
});
});
}
private void saveLog(List<String> ids, String userId, String module, String type) {
List<ReportDTO> reports = new ArrayList<>();
if (StringUtils.equals(type, ApiExecuteResourceType.TEST_PLAN_API_CASE.name())) {
reports = extApiReportMapper.selectByIds(ids);
} else if (StringUtils.equals(type, ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name())) {
reports = extApiScenarioReportMapper.selectByIds(ids);
}
//取出所有的项目id
List<String> projectIds = reports.stream().map(ReportDTO::getProjectId).distinct().toList();
//根据项目id取出组织id
List<ReportDTO> orgList = extApiScenarioReportMapper.getOrgListByProjectIds(projectIds);
//生成map key:项目id value:组织id
Map<String, String> orgMap = orgList.stream().collect(Collectors.toMap(ReportDTO::getProjectId, ReportDTO::getOrganizationId));
List<LogDTO> logs = new ArrayList<>();
reports.forEach(reportDTO -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(reportDTO.getProjectId())
.organizationId(orgMap.get(reportDTO.getProjectId()))
.type(OperationLogType.UPDATE.name())
.module(module)
.method(OperationLogAspect.getMethod())
.path(OperationLogAspect.getPath())
.sourceId(reportDTO.getId())
.content(String.format("停止任务:%s", reportDTO.getName()))
.createUser(userId)
.build().getLogDTO();
logs.add(dto);
});
operationLogService.batchAdd(logs);
}
}

View File

@ -1,14 +1,34 @@
package io.metersphere.plan.controller;
import io.metersphere.api.domain.ApiReport;
import io.metersphere.api.domain.ApiScenarioRecord;
import io.metersphere.api.domain.ApiScenarioReport;
import io.metersphere.api.domain.ApiTestCaseRecord;
import io.metersphere.api.service.definition.ApiReportService;
import io.metersphere.api.service.scenario.ApiScenarioReportService;
import io.metersphere.plan.domain.TestPlanReportApiCase;
import io.metersphere.plan.domain.TestPlanReportApiScenario;
import io.metersphere.plan.mapper.TestPlanReportApiCaseMapper;
import io.metersphere.plan.mapper.TestPlanReportApiScenarioMapper;
import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.project.mapper.ProjectTestResourcePoolMapper;
import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.constants.TaskCenterResourceType;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseCondition;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.dto.taskcenter.request.TaskCenterBatchRequest;
import io.metersphere.system.dto.taskcenter.request.TaskCenterPageRequest;
import io.metersphere.system.mapper.TestResourcePoolBlobMapper;
import io.metersphere.system.mapper.TestResourcePoolMapper;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
@ -19,6 +39,7 @@ import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -36,9 +57,33 @@ public class TestPlanTaskCenterControllerTests extends BaseTest {
private final static String REAL_TIME_PROJECT_PAGE = BASE_PATH + "project/real-time/page";
private final static String REAL_TIME_ORG_PAGE = BASE_PATH + "org/real-time/page";
private final static String REAL_TIME_SYSTEM_PAGE = BASE_PATH + "system/real-time/page";
private final static String REAL_TIME_PROJECT_STOP = BASE_PATH + "project/stop";
private final static String REAL_TIME_ORG_STOP = BASE_PATH + "org/stop";
private final static String REAL_TIME_SYSTEM_STOP = BASE_PATH + "system/stop";
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
@Resource
private ApiReportService apiReportService;
@Resource
private ApiScenarioReportService apiScenarioReportService;
@Resource
private TestResourcePoolMapper testResourcePoolMapper;
@Resource
private TestResourcePoolBlobMapper testResourcePoolBlobMapper;
@Resource
private ProjectTestResourcePoolMapper projectTestResourcePoolMapper;
@Resource
private ProjectApplicationMapper projectApplicationMapper;
@Resource
private TestPlanReportApiCaseMapper testPlanReportApiCaseMapper;
@Resource
private TestPlanReportApiScenarioMapper testPlanReportApiScenarioMapper;
@Value("${embedded.mockserver.host}")
private String host;
@Value("${embedded.mockserver.port}")
private int port;
@Test
@Order(9)
@ -119,7 +164,7 @@ public class TestPlanTaskCenterControllerTests extends BaseTest {
private void configureFilterSearch(TaskCenterPageRequest request) {
Map<String, List<String>> filters = new HashMap<>();
request.setSort(Map.of());
filters.put("triggerMode", List.of("MANUAL"));
filters.put("execStatus", List.of("RUNNING"));
request.setFilter(filters);
}
@ -128,8 +173,186 @@ public class TestPlanTaskCenterControllerTests extends BaseTest {
public void getPageError() throws Exception {
doTaskCenterPageError(REAL_TIME_PROJECT_PAGE, TaskCenterResourceType.TEST_PLAN.toString());
doTaskCenterPageError(REAL_TIME_ORG_PAGE, TaskCenterResourceType.TEST_PLAN.toString());
}
@Test
@Order(11)
public void stop() throws Exception {
testInsertData();
doStop("KEYWORD", REAL_TIME_PROJECT_STOP, false);
doStop("FILTER", REAL_TIME_PROJECT_STOP, true);
doStop("KEYWORD", REAL_TIME_ORG_STOP, true);
doStop("FILTER", REAL_TIME_ORG_STOP, false);
doStop("KEYWORD", REAL_TIME_SYSTEM_STOP, true);
doStop("FILTER", REAL_TIME_SYSTEM_STOP, false);
}
@Test
@Order(12)
public void stopById() throws Exception {
mockPost("/api/stop", "");
mockMvc.perform(MockMvcRequestBuilders.get("/task/center/plan/project/stop/test-plan-report-id-2")
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)
.header(SessionConstants.CURRENT_PROJECT, DEFAULT_PROJECT_ID)
.header(SessionConstants.CURRENT_ORGANIZATION, DEFAULT_ORGANIZATION_ID))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
mockPost("/api/stop", "");
mockMvc.perform(MockMvcRequestBuilders.get("/task/center/plan/org/stop/test-plan-report-id-3")
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)
.header(SessionConstants.CURRENT_PROJECT, DEFAULT_PROJECT_ID)
.header(SessionConstants.CURRENT_ORGANIZATION, DEFAULT_ORGANIZATION_ID))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
mockMvc.perform(MockMvcRequestBuilders.get("/task/center/plan/system/stop/test-plan-report-id-4")
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)
.header(SessionConstants.CURRENT_PROJECT, DEFAULT_PROJECT_ID)
.header(SessionConstants.CURRENT_ORGANIZATION, DEFAULT_ORGANIZATION_ID))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
}
private void configureKeywordBatch(TaskCenterBatchRequest request) {
TableBatchProcessDTO batchProcessDTO = new TableBatchProcessDTO();
BaseCondition condition = new BaseCondition();
condition.setKeyword("task-report-name");
batchProcessDTO.setCondition(condition);
request.setCondition(condition);
}
private void configureFilterBatch(TaskCenterBatchRequest request) {
Map<String, List<String>> filters = new HashMap<>();
BaseCondition condition = new BaseCondition();
filters.put("triggerMode", List.of("MANUAL"));
condition.setFilter(filters);
request.setCondition(condition);
}
private void doStop(String search, String url, boolean isSelectAll) throws Exception {
TaskCenterBatchRequest request = new TaskCenterBatchRequest();
switch (search) {
case "KEYWORD" -> configureKeywordBatch(request);
case "FILTER" -> configureFilterBatch(request);
default -> {
}
}
if (isSelectAll) {
request.setSelectAll(true);
} else {
request.setSelectIds(List.of("test-plan-report-id-1", "test-plan-report-id-2"));
}
request.setExcludeIds(List.of("test-plan-report-id-3", "test-plan-report-id-4"));
mockPost("/api/stop", "");
mockMvc.perform(MockMvcRequestBuilders.post(url)
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)
.header(SessionConstants.CURRENT_PROJECT, DEFAULT_PROJECT_ID)
.header(SessionConstants.CURRENT_ORGANIZATION, DEFAULT_ORGANIZATION_ID)
.content(JSON.toJSONString(request))
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andReturn();
}
public void testInsertData() {
TestPlanReportApiCase testPlanReportApiCase = new TestPlanReportApiCase();
testPlanReportApiCase.setId("task-report-id0");
testPlanReportApiCase.setTestPlanCollectionId("task-report-id1");
testPlanReportApiCase.setTestPlanReportId("test-plan-report-id-1-1");
testPlanReportApiCase.setTestPlanApiCaseId("task-api-resource-id0");
testPlanReportApiCase.setApiCaseId("apiCaseId");
testPlanReportApiCase.setApiCaseNum(1L);
testPlanReportApiCase.setPos(1L);
testPlanReportApiCase.setApiCaseName("apiCaseName");
testPlanReportApiCase.setApiCaseExecuteReportId("plan-task-report-id1");
testPlanReportApiCaseMapper.insertSelective(testPlanReportApiCase);
testPlanReportApiCase.setId("task-report-id1");
testPlanReportApiCase.setTestPlanCollectionId("task-report-id1");
testPlanReportApiCase.setTestPlanReportId("test-plan-report-id-1-2");
testPlanReportApiCase.setTestPlanApiCaseId("task-api-resource-id0");
testPlanReportApiCase.setApiCaseId("apiCaseId");
testPlanReportApiCase.setApiCaseNum(1L);
testPlanReportApiCase.setPos(1L);
testPlanReportApiCase.setApiCaseName("apiCaseName");
testPlanReportApiCaseMapper.insertSelective(testPlanReportApiCase);
List<ApiReport> reports = new ArrayList<>();
List<ApiTestCaseRecord> records = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ApiReport apiReport = new ApiReport();
apiReport.setId("plan-task-report-id" + i);
apiReport.setProjectId(DEFAULT_PROJECT_ID);
apiReport.setTestPlanCaseId("task-test-plan-case-id" + i);
apiReport.setName("task-report-name" + i);
apiReport.setStartTime(System.currentTimeMillis());
apiReport.setCreateUser("admin");
apiReport.setUpdateUser("admin");
apiReport.setUpdateTime(System.currentTimeMillis());
apiReport.setPoolId("100001100001");
apiReport.setEnvironmentId("api-environment-id" + i);
apiReport.setRunMode("api-run-mode" + i);
apiReport.setPlan(true);
if (i % 2 == 0) {
apiReport.setTestPlanCaseId("task-api-resource-id" + i);
apiReport.setStatus(ExecStatus.PENDING.name());
} else {
apiReport.setStatus(ExecStatus.RUNNING.name());
}
apiReport.setTriggerMode("MANUAL");
reports.add(apiReport);
ApiTestCaseRecord record = new ApiTestCaseRecord();
record.setApiTestCaseId("task-api-resource-id" + i);
record.setApiReportId(apiReport.getId());
records.add(record);
}
apiReportService.insertApiReport(reports, records);
TestPlanReportApiScenario testPlanApiScenario = new TestPlanReportApiScenario();
testPlanApiScenario.setId("task-report-id0");
testPlanApiScenario.setTestPlanCollectionId("task-report-id1");
testPlanApiScenario.setApiScenarioId("test-plan-report-id-1-1");
testPlanApiScenario.setApiScenarioExecuteReportId("plan-task-report-id1");
testPlanApiScenario.setTestPlanReportId("test-plan-report-id-1-1");
testPlanApiScenario.setApiScenarioName("apiScenarioName");
testPlanApiScenario.setTestPlanApiScenarioId("task-api-resource-id0");
testPlanApiScenario.setPos(1L);
testPlanApiScenario.setApiScenarioNum(1L);
testPlanReportApiScenarioMapper.insertSelective(testPlanApiScenario);
List<ApiScenarioReport> scenarioReports = new ArrayList<>();
List<ApiScenarioRecord> scenarioRecords = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ApiScenarioReport scenarioReport = new ApiScenarioReport();
scenarioReport.setId("plan-task-report-id" + i);
scenarioReport.setProjectId(DEFAULT_PROJECT_ID);
scenarioReport.setTestPlanScenarioId("task-test-plan-case-id" + i);
scenarioReport.setName("task-report-name" + i);
scenarioReport.setStartTime(System.currentTimeMillis());
scenarioReport.setCreateUser("admin");
scenarioReport.setUpdateUser("admin");
if (i % 2 == 0) {
scenarioReport.setTestPlanScenarioId("task-api-resource-id" + i);
scenarioReport.setStatus(ExecStatus.PENDING.name());
} else {
scenarioReport.setStatus(ExecStatus.RUNNING.name());
}
scenarioReport.setUpdateTime(System.currentTimeMillis());
scenarioReport.setPoolId("100001100001");
scenarioReport.setEnvironmentId("api-environment-id" + i);
scenarioReport.setRunMode("api-run-mode" + i);
scenarioReport.setTriggerMode("task-MANUAL");
scenarioReport.setPlan(true);
scenarioReports.add(scenarioReport);
ApiScenarioRecord scenarioRecord = new ApiScenarioRecord();
scenarioRecord.setApiScenarioId("task-api-resource-id" + i);
scenarioRecord.setApiScenarioReportId(scenarioReport.getId());
scenarioRecords.add(scenarioRecord);
}
apiScenarioReportService.insertApiScenarioReport(scenarioReports, scenarioRecords);
}
}

View File

@ -2,11 +2,13 @@ replace INTO `test_plan`(`id`, `num`, `project_id`, `group_id`, `module_id`, `na
VALUES ('test_plan_id_1', 5000, '100001100001', 'NONE', '1', '测试一下计划', 'PREPARED', 'TEST_PLAN', NULL,
1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
replace INTO `test_plan_report`(`id`, `test_plan_id`, `name`, `create_user`, `create_time`, `start_time`, `end_time`, `trigger_mode`, `exec_status`, `result_status`, `pass_threshold`, `pass_rate`, `project_id`, `integrated`, `deleted`)
replace INTO `test_plan_report`(`id`, `test_plan_id`, `name`, `create_user`, `create_time`, `start_time`, `end_time`, `trigger_mode`, `exec_status`, `result_status`, `pass_threshold`, `pass_rate`, `project_id`, `integrated`, `deleted`, `parent_id`)
VALUES
('test-plan-report-id-1', 'test_plan_id_1', '测试一下计划报告1', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'PENDING', 'SUCCESS', '99.99', 100.00, '100001100001', 0, 0),
('test-plan-report-id-2', 'test_plan_id_1', '测试一下计划报告1', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001', 0, 0),
('test-plan-report-id-3', 'test_plan_id_1', '测试一下计划报告3', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001',1, 0),
('test-plan-report-id-4', 'test_plan_id_1', '测试一下计划报告4', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'PENDING', '-', '99.99', 100.00, '100001100001', 1, 0);
('test-plan-report-id-1', 'test_plan_id_1', '测试一下计划报告1', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', 'SUCCESS', '99.99', 100.00, '100001100001', 1, 0, null),
('test-plan-report-id-2', 'test_plan_id_1', '测试一下计划报告1', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', '-', '99.99', 100.00, '100001100001', 0, 0, null),
('test-plan-report-id-3', 'test_plan_id_1', '测试一下计划报告3', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', '-', '99.99', 100.00, '100001100001',1, 0, null),
('test-plan-report-id-4', 'test_plan_id_1', '测试一下计划报告4', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', '-', '99.99', 100.00, '100001100001', 1, 0, null),
('test-plan-report-id-1-1', 'test_plan_id_1', '测试一下计划报告1-1', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', '-', '99.99', 100.00, '100001100001', 1, 0, 'test-plan-report-id-1'),
('test-plan-report-id-1-2', 'test_plan_id_1', '测试一下计划报告1-2', 'admin', UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000, 'MANUAL', 'RUNNING', '-', '99.99', 100.00, '100001100001', 1, 0, 'test-plan-report-id-1');