feat (任务中心): 停止任务
This commit is contained in:
parent
a99c89d001
commit
b37d9a8425
|
@ -17,6 +17,7 @@ import io.metersphere.commons.utils.Pager;
|
|||
import io.metersphere.controller.request.ScheduleRequest;
|
||||
import io.metersphere.log.annotation.MsAuditLog;
|
||||
import io.metersphere.notice.annotation.SendNotice;
|
||||
import io.metersphere.task.service.TaskService;
|
||||
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
|
||||
import io.metersphere.track.request.testplan.FileOperationRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -35,7 +36,9 @@ import java.util.List;
|
|||
public class ApiAutomationController {
|
||||
|
||||
@Resource
|
||||
ApiAutomationService apiAutomationService;
|
||||
private ApiAutomationService apiAutomationService;
|
||||
@Resource
|
||||
private TaskService taskService;
|
||||
|
||||
@PostMapping("/list/{goPage}/{pageSize}")
|
||||
@RequiresPermissions("PROJECT_API_SCENARIO:READ")
|
||||
|
@ -315,5 +318,11 @@ public class ApiAutomationController {
|
|||
public void stop(@PathVariable String reportId) {
|
||||
new LocalRunner().stop(reportId);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/stop/batch")
|
||||
public String stopBatch(@RequestBody List<TaskRequest> reportIds) {
|
||||
return taskService.stop(reportIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TaskRequest {
|
||||
private String type;
|
||||
private String reportId;
|
||||
|
||||
}
|
|
@ -47,7 +47,7 @@ import java.lang.reflect.Field;
|
|||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class JMeterService {
|
||||
private static final String BASE_URL = "http://%s:%d";
|
||||
public static final String BASE_URL = "http://%s:%d";
|
||||
@Resource
|
||||
private JmeterProperties jmeterProperties;
|
||||
@Resource
|
||||
|
|
|
@ -6,6 +6,7 @@ import javax.websocket.Session;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
public class MessageCache {
|
||||
public static Map<String, ReportCounter> cache = new HashMap<>();
|
||||
|
@ -14,4 +15,5 @@ public class MessageCache {
|
|||
|
||||
public static ConcurrentHashMap<String, StandardJMeterEngine> runningEngine = new ConcurrentHashMap<>();
|
||||
|
||||
public static ConcurrentLinkedDeque<String> terminationOrderDeque = new ConcurrentLinkedDeque<>();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package io.metersphere.api.service.task;
|
|||
import io.metersphere.api.dto.RunModeDataDTO;
|
||||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.MessageCache;
|
||||
import io.metersphere.base.domain.ApiScenarioReport;
|
||||
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
|
@ -33,6 +34,10 @@ public class SerialScenarioExecTask<T> implements Callable<T> {
|
|||
@Override
|
||||
public T call() {
|
||||
try {
|
||||
if (MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) {
|
||||
MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId());
|
||||
return (T) report;
|
||||
}
|
||||
if (request.getConfig() != null && StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
||||
jMeterService.runTest(runModeDataDTO.getTestId(), runModeDataDTO.getReport().getId(), request.getRunMode(), request.getPlanScenarioId(), request.getConfig());
|
||||
} else {
|
||||
|
@ -47,6 +52,10 @@ public class SerialScenarioExecTask<T> implements Callable<T> {
|
|||
if (report != null && !report.getStatus().equals(APITestStatus.Running.name())) {
|
||||
break;
|
||||
}
|
||||
if (MessageCache.terminationOrderDeque.contains(runModeDataDTO.getReport().getId())) {
|
||||
MessageCache.terminationOrderDeque.remove(runModeDataDTO.getReport().getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 执行失败了,恢复报告状态
|
||||
if (index == 200 && report != null && report.getStatus().equals(APITestStatus.Running.name())) {
|
||||
|
|
|
@ -72,14 +72,14 @@
|
|||
SELECT count(tt.id) FROM (
|
||||
(select t.id,t.create_time as executionTime
|
||||
from api_scenario_report t left join `user` t1 ON t.user_id = t1.id left join test_resource_pool t2 on t.actuator = t2.id
|
||||
where to_days(FROM_UNIXTIME(t.create_time/1000))= to_days(now()) and t.execute_type !='Debug' and t.execute_type !='Marge' and t.project_id= #{request.projectId} and t.status not in ("saved","completed","success","error")
|
||||
where to_days(FROM_UNIXTIME(t.create_time/1000))= to_days(now()) and t.execute_type !='Debug' and t.execute_type !='Marge' and t.project_id= #{request.projectId} and t.status not in ("saved","completed","success","error","STOP")
|
||||
)
|
||||
UNION ALL
|
||||
(select t.id,t.create_time as executionTime
|
||||
from api_definition_exec_result t left join `user` t1 ON t.user_id = t1.id left join test_resource_pool t2 on t.actuator = t2.id
|
||||
left join api_definition t3 on t.resource_id = t3.id left join api_test_case t4 on t4.id = t.resource_id
|
||||
left join test_plan_api_case t5 on t.resource_id = t5.id left join test_plan t6 on t5.test_plan_id = t6.id
|
||||
where to_days(FROM_UNIXTIME(t.create_time/1000))= to_days(now()) and (t3.project_id =#{request.projectId} OR t4.project_id =#{request.projectId} OR t6.project_id = #{request.projectId}) and t.status not in ("saved","completed","success","error")
|
||||
where to_days(FROM_UNIXTIME(t.create_time/1000))= to_days(now()) and (t3.project_id =#{request.projectId} OR t4.project_id =#{request.projectId} OR t6.project_id = #{request.projectId}) and t.status not in ("saved","completed","success","error","STOP")
|
||||
)
|
||||
UNION ALL
|
||||
(select t.id,t.create_time as executionTime
|
||||
|
|
|
@ -1,21 +1,51 @@
|
|||
package io.metersphere.task.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.metersphere.api.dto.automation.TaskRequest;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.jmeter.LocalRunner;
|
||||
import io.metersphere.api.jmeter.MessageCache;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ApiScenarioReportMapper;
|
||||
import io.metersphere.base.mapper.TestResourceMapper;
|
||||
import io.metersphere.base.mapper.TestResourcePoolMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTaskMapper;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.dto.NodeDTO;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import io.metersphere.task.dto.TaskCenterDTO;
|
||||
import io.metersphere.task.dto.TaskCenterRequest;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TaskService {
|
||||
@Resource
|
||||
private ExtTaskMapper extTaskMapper;
|
||||
@Resource
|
||||
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
|
||||
@Resource
|
||||
private ApiScenarioReportMapper apiScenarioReportMapper;
|
||||
@Resource
|
||||
private PerformanceTestService performanceTestService;
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
@Resource
|
||||
private TestResourcePoolMapper testResourcePoolMapper;
|
||||
@Resource
|
||||
private TestResourceMapper testResourceMapper;
|
||||
|
||||
public List<TaskCenterDTO> getTasks(TaskCenterRequest request) {
|
||||
if (StringUtils.isEmpty(request.getProjectId())) {
|
||||
|
@ -38,4 +68,75 @@ public class TaskService {
|
|||
public List<TaskCenterDTO> getScenario(String id) {
|
||||
return extTaskMapper.getScenario(id);
|
||||
}
|
||||
|
||||
|
||||
public void send(Map<String, List<String>> poolMap) {
|
||||
try {
|
||||
for (String poolId : poolMap.keySet()) {
|
||||
TestResourcePoolExample example = new TestResourcePoolExample();
|
||||
example.createCriteria().andStatusEqualTo("VALID").andTypeEqualTo("NODE").andIdEqualTo(poolId);
|
||||
List<TestResourcePool> pools = testResourcePoolMapper.selectByExample(example);
|
||||
if (CollectionUtils.isNotEmpty(pools)) {
|
||||
List<String> poolIds = pools.stream().map(pool -> pool.getId()).collect(Collectors.toList());
|
||||
TestResourceExample resourceExample = new TestResourceExample();
|
||||
resourceExample.createCriteria().andTestResourcePoolIdIn(poolIds);
|
||||
List<TestResource> testResources = testResourceMapper.selectByExampleWithBLOBs(resourceExample);
|
||||
for (TestResource testResource : testResources) {
|
||||
String configuration = testResource.getConfiguration();
|
||||
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
|
||||
String nodeIp = node.getIp();
|
||||
Integer port = node.getPort();
|
||||
String uri = String.format(JMeterService.BASE_URL + "/jmeter/stop", nodeIp, port);
|
||||
restTemplate.postForEntity(uri, poolMap.get(poolId), void.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String stop(List<TaskRequest> reportIds) {
|
||||
if (CollectionUtils.isNotEmpty(reportIds)) {
|
||||
// 聚类,同一批资源池的一批发送
|
||||
Map<String, List<String>> poolMap = new HashMap<>();
|
||||
for (TaskRequest request : reportIds) {
|
||||
String actuator = null;
|
||||
if (StringUtils.equals(request.getType(), "API")) {
|
||||
ApiDefinitionExecResult result = apiDefinitionExecResultMapper.selectByPrimaryKey(request.getReportId());
|
||||
if (result != null) {
|
||||
result.setStatus("STOP");
|
||||
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
|
||||
actuator = result.getActuator();
|
||||
}
|
||||
} else if (StringUtils.equals(request.getType(), "SCENARIO")) {
|
||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
|
||||
if (report != null) {
|
||||
report.setStatus("STOP");
|
||||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||
actuator = report.getActuator();
|
||||
}
|
||||
} else if (StringUtils.equals(request.getType(), "PERFORMANCE")) {
|
||||
performanceTestService.stopTest(request.getReportId(), false);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(actuator)) {
|
||||
if (poolMap.containsKey(actuator)) {
|
||||
poolMap.get(actuator).add(request.getReportId());
|
||||
} else {
|
||||
poolMap.put(actuator, new ArrayList<String>() {{
|
||||
this.add(request.getReportId());
|
||||
}});
|
||||
}
|
||||
} else {
|
||||
new LocalRunner().stop(request.getReportId());
|
||||
}
|
||||
MessageCache.cache.remove(request.getReportId());
|
||||
MessageCache.terminationOrderDeque.add(request.getReportId());
|
||||
}
|
||||
if (!poolMap.isEmpty()) {
|
||||
this.send(poolMap);
|
||||
}
|
||||
}
|
||||
return "SUCCESS";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,23 +80,20 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import MsTablePagination from "../../../common/pagination/TablePagination";
|
||||
import MsTableHeader from "../../../common/components/MsTableHeader";
|
||||
import MsContainer from "../../../common/components/MsContainer";
|
||||
import MsMainContainer from "../../../common/components/MsMainContainer";
|
||||
import MsApiReportStatus from "./ApiReportStatus";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
|
||||
import ReportTriggerModeItem from "../../../common/tableItem/ReportTriggerModeItem";
|
||||
import {REPORT_CONFIGS} from "../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../track/case/components/ShowMoreBtn";
|
||||
import {_filter, _sort} from "@/common/js/tableUtils";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ReportTriggerModeItem,
|
||||
MsTableOperatorButton,
|
||||
MsApiReportStatus, MsMainContainer, MsContainer, MsTableHeader, MsTablePagination, ShowMoreBtn
|
||||
ReportTriggerModeItem: () => import("../../../common/tableItem/ReportTriggerModeItem"),
|
||||
MsTableOperatorButton: () => import("../../../common/components/MsTableOperatorButton"),
|
||||
MsApiReportStatus: () => import("./ApiReportStatus"),
|
||||
MsMainContainer: () => import("../../../common/components/MsMainContainer"),
|
||||
MsContainer: () => import("../../../common/components/MsContainer"),
|
||||
MsTableHeader: () => import("../../../common/components/MsTableHeader"),
|
||||
MsTablePagination: () => import("../../../common/pagination/TablePagination"),
|
||||
ShowMoreBtn: () => import("../../../track/case/components/ShowMoreBtn")
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -169,14 +166,14 @@ export default {
|
|||
},
|
||||
handleView(report) {
|
||||
this.reportId = report.id;
|
||||
if(report.status ==='Running'){
|
||||
if (report.status === 'Running') {
|
||||
this.$warning("正在运行中,请稍后查看")
|
||||
return;
|
||||
}
|
||||
this.currentProjectId = report.projectId;
|
||||
this.$router.push({
|
||||
path: 'report/view/' + report.id,
|
||||
})
|
||||
this.$router.push({
|
||||
path: 'report/view/' + report.id,
|
||||
})
|
||||
|
||||
},
|
||||
handleDelete(report) {
|
||||
|
|
|
@ -19,14 +19,11 @@
|
|||
</div>
|
||||
<ms-chart id="chart" ref="chart" :options="options" :autoresize="true" v-else/>
|
||||
<el-row type="flex" justify="center" align="middle">
|
||||
<!-- <i class="circle success"/>-->
|
||||
<span class="ms-point-success"/>
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.success }}</div>
|
||||
<div class="name">{{ $t('api_report.success') }}</div>
|
||||
</div>
|
||||
<div style="width: 40px"></div>
|
||||
<!-- <i class="circle fail"/>-->
|
||||
<span class="ms-point-error"/>
|
||||
<div class="metric-box">
|
||||
<div class="value">{{ content.error }}</div>
|
||||
|
|
|
@ -238,13 +238,16 @@ import {
|
|||
} from "@/common/js/tableUtils";
|
||||
import {API_SCENARIO_FILTERS} from "@/common/js/table-constants";
|
||||
import {scenario} from "@/business/components/track/plan/event-bus";
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/MsTableColumn";
|
||||
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioList",
|
||||
components: {
|
||||
MsTable: () => import("@/business/components/common/components/table/MsTable"),
|
||||
MsTableColumn: () => import("@/business/components/common/components/table/MsTableColumn"),
|
||||
HeaderLabelOperate: () => import("@/business/components/common/head/HeaderLabelOperate"),
|
||||
MsTable,
|
||||
MsTableColumn,
|
||||
HeaderLabelOperate,
|
||||
HeaderCustom: () => import("@/business/components/common/head/HeaderCustom"),
|
||||
BatchMove: () => import("../../../track/case/components/BatchMove"),
|
||||
EnvironmentSelect: () => import("../../definition/components/environment/EnvironmentSelect"),
|
||||
|
|
|
@ -22,89 +22,110 @@
|
|||
</el-menu>
|
||||
|
||||
<el-drawer :visible.sync="taskVisible" :destroy-on-close="true" direction="rtl"
|
||||
:withHeader="true" :modal="false" :title="$t('commons.task_center')" size="600px"
|
||||
:withHeader="true" :modal="false" :title="$t('commons.task_center')" :size="size"
|
||||
custom-class="ms-drawer-task">
|
||||
<div style="color: #2B415C;margin: 0px 20px 0px">
|
||||
<el-form label-width="68px">
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('test_track.report.list.trigger_mode')" prop="runMode">
|
||||
<el-select size="small" style="margin-right: 10px" v-model="condition.triggerMode" @change="init">
|
||||
<el-option v-for="item in runMode" :key="item.id" :value="item.id" :label="item.label"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('commons.status')" prop="status">
|
||||
<el-select size="small" style="margin-right: 10px" v-model="condition.executionStatus" @change="init">
|
||||
<el-option v-for="item in runStatus" :key="item.id" :value="item.id" :label="item.label"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="$t('commons.executor')" prop="status">
|
||||
<el-select v-model="condition.executor" :placeholder="$t('commons.executor')" filterable size="small"
|
||||
style="margin-right: 10px" @change="init">
|
||||
<el-option
|
||||
v-for="item in maintainerOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-card style="float: left;width: 800px" v-if="size > 550 ">
|
||||
|
||||
<div class="report-container">
|
||||
<div v-for="item in taskData" :key="item.id" style="margin-bottom: 5px">
|
||||
<el-card class="ms-card-task" @click.native="showReport(item,$event)">
|
||||
<span><el-link type="primary">{{ getModeName(item.executionModule) }} </el-link>: {{ item.name }} </span><br/>
|
||||
<span>
|
||||
<div class="ms-task-opt-btn" @click="packUp">收起</div>
|
||||
<!-- 接口用例结果 -->
|
||||
<ms-request-result-tail :response="response" ref="debugResult" v-if="reportType === 'API'"/>
|
||||
|
||||
<ms-api-report-detail :reportId="reportId" v-if="reportType === 'SCENARIO'"/>
|
||||
|
||||
<performance-report-view :reportId="reportId" v-if="reportType === 'PERFORMANCE'"/>
|
||||
|
||||
</el-card>
|
||||
<el-card style="width: 550px;float: right">
|
||||
<div style="color: #2B415C;margin: 0px 20px 0px;">
|
||||
<el-form label-width="68px" class="ms-el-form-item">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('test_track.report.list.trigger_mode')" prop="runMode">
|
||||
<el-select size="small" style="margin-right: 10px" v-model="condition.triggerMode" @change="init">
|
||||
<el-option v-for="item in runMode" :key="item.id" :value="item.id" :label="item.label"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.status')" prop="status">
|
||||
<el-select size="small" style="margin-right: 10px" v-model="condition.executionStatus" @change="init">
|
||||
<el-option v-for="item in runStatus" :key="item.id" :value="item.id" :label="item.label"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('commons.executor')" prop="status">
|
||||
<el-select v-model="condition.executor" :placeholder="$t('commons.executor')" filterable size="small"
|
||||
style="margin-right: 10px" @change="init">
|
||||
<el-option
|
||||
v-for="item in maintainerOptions"
|
||||
:key="item.id"
|
||||
:label="item.id + ' (' + item.name + ')'"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-button size="small" class="ms-task-stop" @click="stop(null)">
|
||||
{{ $t('report.stop_btn_all') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="report-container">
|
||||
<div v-for="item in taskData" :key="item.id" style="margin-bottom: 5px">
|
||||
<el-card class="ms-card-task" @click.native="showReport(item,$event)">
|
||||
<span class="ms-task-name-width"><el-link type="primary">
|
||||
{{ getModeName(item.executionModule) }} </el-link>: {{ item.name }} </span>
|
||||
<el-button size="mini" class="ms-task-stop" @click.stop @click="stop(item)" v-if="showStop(item.executionStatus)">
|
||||
{{ $t('report.stop_btn') }}
|
||||
</el-button>
|
||||
<br/>
|
||||
<span>
|
||||
执行器:{{ item.actuator }} 由 {{ item.executor }}
|
||||
{{ item.executionTime | timestampFormatDate }}
|
||||
{{ getMode(item.triggerMode) }}
|
||||
</span>
|
||||
<br/>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-progress :percentage="getPercentage(item.executionStatus)" :format="format"/>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<br/>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-progress :percentage="getPercentage(item.executionStatus)" :format="format"/>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<span v-if="item.executionStatus && item.executionStatus.toLowerCase() === 'error'" class="ms-task-error">
|
||||
error
|
||||
</span>
|
||||
<span v-else-if="item.executionStatus && item.executionStatus.toLowerCase() === 'success'" class="ms-task-success">
|
||||
<span v-else-if="item.executionStatus && item.executionStatus.toLowerCase() === 'success'" class="ms-task-success">
|
||||
success
|
||||
</span>
|
||||
<span v-else>{{ item.executionStatus ? item.executionStatus.toLowerCase() : item.executionStatus }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<i class="el-icon-video-pause" v-else-if="item.executionStatus && item.executionStatus.toLowerCase() === 'stop'"/>
|
||||
<span v-else>{{ item.executionStatus ? item.executionStatus.toLowerCase() : item.executionStatus }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
|
||||
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('test_track.plan_view.test_result')" width="60%"
|
||||
:visible.sync="visible" class="api-import" destroy-on-close @close="close">
|
||||
<ms-request-result-tail :response="response" ref="debugResult"/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsDrawer from "../common/components/MsDrawer";
|
||||
import {getCurrentProjectID, getCurrentUser, hasPermissions} from "@/common/js/utils";
|
||||
import MsRequestResultTail from "../../components/api/definition/components/response/RequestResultTail";
|
||||
|
||||
export default {
|
||||
name: "MsTaskCenter",
|
||||
components: {
|
||||
MsDrawer,
|
||||
MsRequestResultTail
|
||||
MsRequestResultTail: () => import("../../components/api/definition/components/response/RequestResultTail"),
|
||||
MsApiReportDetail: () => import("../../components/api/automation/report/ApiReportDetail"),
|
||||
PerformanceReportView: () => import("../../components/performance/report/PerformanceReportView")
|
||||
},
|
||||
inject: [
|
||||
'reload'
|
||||
|
@ -139,6 +160,9 @@ export default {
|
|||
condition: {triggerMode: "", executionStatus: ""},
|
||||
maintainerOptions: [],
|
||||
websocket: Object,
|
||||
size: 550,
|
||||
reportId: "",
|
||||
reportType: "",
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
@ -160,6 +184,31 @@ export default {
|
|||
format(item) {
|
||||
return '';
|
||||
},
|
||||
packUp(){
|
||||
this.size = 550;
|
||||
},
|
||||
stop(row) {
|
||||
let array = [];
|
||||
if (row) {
|
||||
let request = {type: row.executionModule, reportId: row.id};
|
||||
array = [request];
|
||||
} else {
|
||||
this.taskData.forEach(item => {
|
||||
if (this.showStop(item.executionStatus)) {
|
||||
let request = {type: item.executionModule, reportId: item.id};
|
||||
array.push(request);
|
||||
}
|
||||
})
|
||||
}
|
||||
if (array.length === 0) {
|
||||
this.$warning("没有需要停止的任务");
|
||||
return;
|
||||
}
|
||||
this.$post('/api/automation/stop/batch', array, response => {
|
||||
this.$success(this.$t('report.test_stop_success'));
|
||||
this.init();
|
||||
});
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
|
||||
this.maintainerOptions = response.data;
|
||||
|
@ -203,7 +252,7 @@ export default {
|
|||
},
|
||||
close() {
|
||||
this.visible = false;
|
||||
// this.taskVisible = false;
|
||||
this.size = 550;
|
||||
this.showType = "";
|
||||
if (this.websocket && this.websocket.close instanceof Function) {
|
||||
this.websocket.close();
|
||||
|
@ -225,6 +274,15 @@ export default {
|
|||
}
|
||||
return 60;
|
||||
},
|
||||
showStop(status) {
|
||||
if (status) {
|
||||
status = status.toLowerCase();
|
||||
if (status === "stop" || status === 'saved' || status === 'completed' || status === 'success' || status === 'error') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
getModeName(executionModule) {
|
||||
switch (executionModule) {
|
||||
case "SCENARIO":
|
||||
|
@ -240,18 +298,19 @@ export default {
|
|||
if (status) {
|
||||
status = row.executionStatus.toLowerCase();
|
||||
if (status === 'saved' || status === 'completed' || status === 'success' || status === 'error') {
|
||||
this.size = 1350;
|
||||
this.reportId = row.id;
|
||||
this.reportType = row.executionModule;
|
||||
switch (row.executionModule) {
|
||||
case "SCENARIO":
|
||||
this.taskVisible = false;
|
||||
this.$router.push({
|
||||
path: '/api/automation/report/view/' + row.id,
|
||||
});
|
||||
// this.$router.push({
|
||||
// path: '/api/automation/report/view/' + row.id,
|
||||
// });
|
||||
break;
|
||||
case "PERFORMANCE":
|
||||
this.taskVisible = false;
|
||||
this.$router.push({
|
||||
path: '/performance/report/view/' + row.id,
|
||||
});
|
||||
// this.$router.push({
|
||||
// path: '/performance/report/view/' + row.id,
|
||||
// });
|
||||
break;
|
||||
case "API":
|
||||
this.getExecResult(row.id);
|
||||
|
@ -354,7 +413,7 @@ export default {
|
|||
|
||||
.report-container {
|
||||
height: calc(100vh - 180px);
|
||||
min-height: 600px;
|
||||
min-height: 550px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
@ -437,7 +496,60 @@ export default {
|
|||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.ms-task-stop {
|
||||
color: #F56C6C;
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.ms-task-success {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.ms-task-name-width {
|
||||
display: inline-block;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 0;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.ms-el-form-item >>> .el-form-item {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.ms-task-opt-btn {
|
||||
position: fixed;
|
||||
right: 1322px;
|
||||
top: 50%;
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 60px;
|
||||
padding: 3px;
|
||||
line-height: 30px;
|
||||
border-radius: 0 15px 15px 0;
|
||||
background-color: #783887;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.ms-task-opt-btn i {
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
.ms-task-opt-btn:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.ms-task-opt-btn:hover i {
|
||||
margin-left: 0;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -596,6 +596,7 @@ export default {
|
|||
stop_tips: 'A <strong>Graceful shutdown</strong> will archive the JTL files and then stop the servers.',
|
||||
force_stop_btn: 'Terminating',
|
||||
stop_btn: 'Graceful shutdown',
|
||||
stop_btn_all: 'All Graceful shutdown ',
|
||||
not_exist: "Test report does not exist",
|
||||
batch_delete: "Delete reports in bulk",
|
||||
delete_batch_confirm: 'Confirm batch delete report',
|
||||
|
|
|
@ -600,6 +600,7 @@ export default {
|
|||
stop_tips: '<strong>停止</strong>测试会结束当前测试并保留报告数据',
|
||||
force_stop_btn: '强制停止',
|
||||
stop_btn: '停止',
|
||||
stop_btn_all: '全部停止',
|
||||
not_exist: "测试报告不存在",
|
||||
batch_delete: "批量删除报告",
|
||||
delete_batch_confirm: '确认批量删除报告',
|
||||
|
|
|
@ -600,6 +600,7 @@ export default {
|
|||
stop_tips: '<strong>停止</strong>測試會結束當前測試並保留報告數據',
|
||||
force_stop_btn: '強制停止',
|
||||
stop_btn: '停止',
|
||||
stop_btn_all: '全部停止',
|
||||
not_exist: "測試報告不存在",
|
||||
batch_delete: "批量刪除報告",
|
||||
delete_batch_confirm: '確認批量刪除報告',
|
||||
|
|
Loading…
Reference in New Issue