Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
3f877ef845
|
@ -7,4 +7,6 @@ public class CountController {
|
|||
private int loops;
|
||||
private int interval;
|
||||
private boolean proceed;
|
||||
private Object requestResult;
|
||||
|
||||
}
|
||||
|
|
|
@ -7,4 +7,6 @@ public class MsForEachController {
|
|||
private String inputVal;
|
||||
private String returnVal;
|
||||
private String interval;
|
||||
private Object requestResult;
|
||||
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ public class MsWhileController {
|
|||
private String operator;
|
||||
private String value;
|
||||
private int timeout;
|
||||
private Object requestResult;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,26 @@
|
|||
<if test="request.name != null">
|
||||
and (lt.name like CONCAT('%', #{request.name},'%') or lt.num like CONCAT('%', #{request.name},'%'))
|
||||
</if>
|
||||
<if test="request.filters != null and request.filters.size() > 0">
|
||||
<foreach collection="request.filters.entrySet()" index="key" item="values">
|
||||
<if test="values != null and values.size() > 0">
|
||||
<choose>
|
||||
<when test="key=='status'">
|
||||
and lt.status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
<if test="request.orders != null and request.orders.size() > 0">
|
||||
order by
|
||||
<foreach collection="request.orders" separator="," item="order">
|
||||
tplc.${order.name} ${order.type}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
|
@ -4,9 +4,10 @@
|
|||
|
||||
<select id="list" resultType="io.metersphere.track.dto.TestPlanReportDTO"
|
||||
parameterType="io.metersphere.track.request.report.QueryTestPlanReportRequest">
|
||||
SELECT tpr.id AS id, tpr.`name` AS `name`, tp.`name` AS testPlanName, tpr.creator AS creator, tpr.create_time AS createTime,tpr.trigger_Mode AS triggerMode,tpr.status AS status
|
||||
SELECT tpr.id AS id, tpr.`name` AS `name`, tp.`name` AS testPlanName, u.name AS creator, tpr.create_time AS createTime,tpr.trigger_Mode AS triggerMode,tpr.status AS status
|
||||
FROM test_plan tp
|
||||
INNER JOIN test_plan_report tpr on tp.id = tpr.test_plan_id
|
||||
INNER JOIN user u on tpr.creator = u.id
|
||||
<where>
|
||||
<if test="name != null">
|
||||
and tpr.name like CONCAT('%', #{name},'%')
|
||||
|
|
|
@ -54,6 +54,12 @@ public class TestPlanReportController {
|
|||
testPlanReportService.delete(testPlanReportIdList);
|
||||
}
|
||||
|
||||
@PostMapping("/deleteBatchByParams")
|
||||
public void deleteBatchByParams(@RequestBody QueryTestPlanReportRequest request) {
|
||||
testPlanReportService.delete(request);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/apiExecuteFinish/{planId}/{userId}")
|
||||
public void apiExecuteFinish(@PathVariable String planId,@PathVariable String userId) {
|
||||
TestPlanReport report = testPlanReportService.genTestPlanReport(planId,userId,ReportTriggerMode.API.name());
|
||||
|
|
|
@ -25,5 +25,11 @@ public class QueryTestPlanReportRequest {
|
|||
|
||||
private List<OrderRequest> orders;
|
||||
private Map<String, List<String>> filters;
|
||||
// private Map<String, Object> combine;
|
||||
|
||||
/**
|
||||
* 批量操作的参数,用于判断是前台表格的当前页数据还是全库数据
|
||||
*/
|
||||
private boolean isSelectAllDate;
|
||||
private List<String> unSelectIds;
|
||||
private List<String> dataIds;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package io.metersphere.track.request.testplan;
|
||||
|
||||
import io.metersphere.base.domain.TestPlanLoadCase;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
@ -12,4 +14,6 @@ public class LoadCaseRequest extends TestPlanLoadCase {
|
|||
private String projectId;
|
||||
private List<String> caseIds;
|
||||
private String name;
|
||||
private Map<String, List<String>> filters;
|
||||
private List<OrderRequest> orders;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.base.mapper.LoadTestMapper;
|
|||
import io.metersphere.base.mapper.LoadTestReportMapper;
|
||||
import io.metersphere.base.mapper.TestPlanLoadCaseMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import io.metersphere.track.dto.TestPlanLoadCaseDTO;
|
||||
import io.metersphere.track.request.testplan.LoadCaseReportRequest;
|
||||
|
@ -50,6 +51,15 @@ public class TestPlanLoadCaseService {
|
|||
}
|
||||
|
||||
public List<TestPlanLoadCaseDTO> list(LoadCaseRequest request) {
|
||||
List<OrderRequest> orders = request.getOrders();
|
||||
if (orders == null || orders.size() < 1) {
|
||||
OrderRequest orderRequest = new OrderRequest();
|
||||
orderRequest.setName("create_time");
|
||||
orderRequest.setType("desc");
|
||||
orders = new ArrayList<>();
|
||||
orders.add(orderRequest);
|
||||
}
|
||||
request.setOrders(orders);
|
||||
return extTestPlanLoadCaseMapper.selectTestPlanLoadCaseList(request);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package io.metersphere.track.service;
|
|||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionRequest;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionResult;
|
||||
import io.metersphere.api.jmeter.TestResult;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
|
@ -413,4 +415,33 @@ public class TestPlanReportService {
|
|||
testPlanReportDataMapper.deleteByExample(example);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(QueryTestPlanReportRequest request) {
|
||||
List<String> deleteReportIds = request.getDataIds();
|
||||
if (request.isSelectAllDate()) {
|
||||
deleteReportIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getProjectId(), request.getUnSelectIds());
|
||||
}
|
||||
TestPlanReportExample deleteReportExample = new TestPlanReportExample();
|
||||
deleteReportExample.createCriteria().andIdIn(deleteReportIds);
|
||||
testPlanReportMapper.deleteByExample(deleteReportExample);
|
||||
|
||||
TestPlanReportDataExample example = new TestPlanReportDataExample();
|
||||
example.createCriteria().andTestPlanReportIdIn(deleteReportIds);
|
||||
testPlanReportDataMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
private List<String> getAllApiIdsByFontedSelect(Map<String, List<String>> filters, String name, String projectId, List<String> unSelectIds) {
|
||||
QueryTestPlanReportRequest request = new QueryTestPlanReportRequest();
|
||||
request.setFilters(filters);
|
||||
request.setName(name);
|
||||
request.setProjectId(projectId);
|
||||
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||
List<TestPlanReportDTO> resList = extTestPlanReportMapper.list(request);
|
||||
List<String> ids = new ArrayList<>(0);
|
||||
if (!resList.isEmpty()) {
|
||||
List<String> allIds = resList.stream().map(TestPlanReportDTO::getId).collect(Collectors.toList());
|
||||
ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 77a4db3ee59003d88aed53601d0d2bfa09ec272f
|
||||
Subproject commit e4521190f0f1be113c8b84fbdcdf8ff273bf274e
|
|
@ -110,7 +110,6 @@
|
|||
if (this.isNotRunning) {
|
||||
try {
|
||||
this.content = JSON.parse(this.report.content);
|
||||
console.log(this.content)
|
||||
if (!this.content) {
|
||||
this.content = {scenarios: []};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
</span>
|
||||
|
||||
<div class="header-right" @click.stop>
|
||||
<slot name="message"></slot>
|
||||
<el-switch v-model="data.enable" class="enable-switch"/>
|
||||
<slot name="button"></slot>
|
||||
<el-button size="mini" icon="el-icon-copy-document" circle @click="copyRow"/>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:draggable="true"
|
||||
color="#02A7F0"
|
||||
background-color="#F4F4F5"
|
||||
:title="$t('api_test.automation.loop_controller')">
|
||||
:title="$t('api_test.automation.loop_controller')" v-loading="loading">
|
||||
|
||||
<template v-slot:headerLeft>
|
||||
<i class="icon el-icon-arrow-right" :class="{'is-active': controller.active}" @click="active(controller)" style="margin-right: 10px"/>
|
||||
|
@ -16,6 +16,15 @@
|
|||
<el-radio @change="changeRadio" class="ms-radio" v-model="controller.loopType" label="WHILE">{{$t('loop.while')}}</el-radio>
|
||||
</template>
|
||||
|
||||
<template v-slot:message>
|
||||
<span v-if="requestResult && requestResult.scenarios && requestResult.scenarios.length > 0 " style="color: #8c939d;margin-right: 10px">
|
||||
循环{{requestResult.scenarios.length}}次 成功{{success}}次 失败{{error}}次
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:button>
|
||||
<el-button @click="runDebug" :tip="$t('api_test.run')" icon="el-icon-video-play" style="background-color: #409EFF;color: white;" size="mini" circle/>
|
||||
</template>
|
||||
<div v-if="controller.loopType==='LOOP_COUNT'" draggable>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
|
@ -69,17 +78,34 @@
|
|||
<span class="ms-span ms-radio">ms</span>
|
||||
</div>
|
||||
|
||||
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="item.name" :name="item.name" v-for="(item,index) in requestResult.scenarios" :key="index">
|
||||
<div v-for="(result,i) in item.requestResults" :key="i" style="margin-bottom: 5px">
|
||||
<api-response-component :result="result"/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<ms-run :debug="true" :environment="currentEnvironmentId" :reportId="reportId" :run-data="debugData"
|
||||
@runRefresh="runRefresh" ref="runTest"/>
|
||||
|
||||
</api-base-component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ApiBaseComponent from "../common/ApiBaseComponent";
|
||||
import ApiResponseComponent from "./ApiResponseComponent";
|
||||
import MsRun from "../DebugRun";
|
||||
import {getUUID, getCurrentProjectID} from "@/common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "MsLoopController",
|
||||
components: {ApiBaseComponent},
|
||||
components: {ApiBaseComponent, ApiResponseComponent, MsRun},
|
||||
props: {
|
||||
controller: {},
|
||||
currentEnvironmentId: String,
|
||||
currentScenario: {},
|
||||
node: {},
|
||||
index: Object,
|
||||
draggable: {
|
||||
|
@ -87,9 +113,19 @@
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initResult();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
activeName: "first",
|
||||
requestResult: {responseResult: {}},
|
||||
success: 0,
|
||||
error: 0,
|
||||
debugData: {},
|
||||
report: [],
|
||||
reportId: "",
|
||||
operators: {
|
||||
EQ: {
|
||||
label: "commons.adv_search.operators.equals",
|
||||
|
@ -127,6 +163,25 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
initResult() {
|
||||
if (this.controller) {
|
||||
switch (this.controller.loopType) {
|
||||
case "LOOP_COUNT":
|
||||
this.requestResult = this.controller.countController && this.controller.countController.requestResult ? this.controller.countController.requestResult : {};
|
||||
break;
|
||||
case "FOREACH":
|
||||
this.requestResult = this.controller.forEachController && this.controller.forEachController.requestResult ? this.controller.forEachController.requestResult : {};
|
||||
break;
|
||||
case "WHILE":
|
||||
this.requestResult = this.controller.whileController && this.controller.whileController.requestResult ? this.controller.whileController.requestResult : {};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.getFails();
|
||||
this.activeName = this.requestResult && this.requestResult.scenarios && this.requestResult.scenarios.length > 0 ? this.requestResult.scenarios[0].name : "";
|
||||
},
|
||||
switchChange() {
|
||||
if (this.controller.hashTree && this.controller.hashTree.length > 1) {
|
||||
this.$warning("当前循环下超过一个请求,不能关闭状态")
|
||||
|
@ -134,6 +189,26 @@
|
|||
return;
|
||||
}
|
||||
},
|
||||
runDebug() {
|
||||
/*触发执行操作*/
|
||||
if (!this.currentEnvironmentId) {
|
||||
this.$error(this.$t('api_test.environment.select_environment'));
|
||||
return;
|
||||
}
|
||||
if (!this.controller.hashTree || this.controller.hashTree.length < 1) {
|
||||
this.$warning("当前循环下没有请求,不能执行")
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
|
||||
this.debugData = {
|
||||
id: this.currentScenario.id, name: this.currentScenario.name, type: "scenario",
|
||||
variables: this.currentScenario.variables, referenced: 'Created', enableCookieShare: this.enableCookieShare,
|
||||
environmentId: this.currentEnvironmentId, hashTree: [this.controller]
|
||||
};
|
||||
this.reportId = getUUID().substring(0, 8);
|
||||
},
|
||||
|
||||
remove() {
|
||||
this.$emit('remove', this.controller, this.node);
|
||||
},
|
||||
|
@ -146,6 +221,7 @@
|
|||
},
|
||||
changeRadio() {
|
||||
this.controller.active = true;
|
||||
this.initResult();
|
||||
this.reload();
|
||||
},
|
||||
change(value) {
|
||||
|
@ -159,11 +235,77 @@
|
|||
this.loading = false
|
||||
})
|
||||
},
|
||||
runRefresh() {
|
||||
this.getReport();
|
||||
},
|
||||
getFails() {
|
||||
this.error = 0;
|
||||
this.success = 0;
|
||||
if (this.requestResult.scenarios) {
|
||||
this.requestResult.scenarios.forEach((scenario) => {
|
||||
if (scenario.requestResults) {
|
||||
scenario.requestResults.forEach(item => {
|
||||
if (item.error > 0) {
|
||||
this.error++;
|
||||
return;
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
this.success = this.requestResult.scenarios.length - this.error;
|
||||
}
|
||||
},
|
||||
getReport() {
|
||||
if (this.reportId) {
|
||||
let url = "/api/scenario/report/get/" + this.reportId;
|
||||
this.$get(url, response => {
|
||||
this.report = response.data || {};
|
||||
if (response.data) {
|
||||
if (this.isNotRunning) {
|
||||
try {
|
||||
this.requestResult = JSON.parse(this.report.content);
|
||||
this.controller.requestResult = this.requestResult;
|
||||
switch (this.controller.loopType) {
|
||||
case "LOOP_COUNT":
|
||||
this.controller.countController.requestResult = this.requestResult;
|
||||
break;
|
||||
case "FOREACH":
|
||||
this.controller.forEachController.requestResult = this.requestResult;
|
||||
break;
|
||||
case "WHILE":
|
||||
this.controller.whileController.requestResult = this.requestResult;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.getFails();
|
||||
if (!this.requestResult) {
|
||||
this.requestResult = {scenarios: []};
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
this.loading = false;
|
||||
this.activeName = this.requestResult && this.requestResult.scenarios ? this.requestResult.scenarios[0].name : "";
|
||||
} else {
|
||||
setTimeout(this.getReport, 2000)
|
||||
}
|
||||
} else {
|
||||
this.loading = false;
|
||||
this.$error(this.$t('api_report.not_exist'));
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasEmptyOperator() {
|
||||
return !!this.controller.operator && this.controller.operator.indexOf("empty") > 0;
|
||||
},
|
||||
isNotRunning() {
|
||||
return "Running" !== this.report.status;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -180,6 +322,14 @@
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 3px 5px;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #783887;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.icon.is-active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
|
|
@ -317,6 +317,15 @@
|
|||
case 'coverage':
|
||||
this.condition.apiCaseCoverage = 'coverage';
|
||||
break;
|
||||
case 'Prepare':
|
||||
this.condition.filters.status = [this.selectDataRange];
|
||||
break;
|
||||
case 'Completed':
|
||||
this.condition.filters.status = [this.selectDataRange];
|
||||
break;
|
||||
case 'Underway':
|
||||
this.condition.filters.status = [this.selectDataRange];
|
||||
break;
|
||||
}
|
||||
if (this.condition.projectId) {
|
||||
this.result = this.$post("/api/definition/list/" + this.currentPage + "/" + this.pageSize, this.condition, response => {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<template>
|
||||
<div class="metric-container">
|
||||
<el-row type="flex">
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">请求名称 :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{response.name}}</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div style="font-size: 14px;color: #AAAAAA;float: left">{{$t('api_report.response_code')}} :</div>
|
||||
<div style="font-size: 14px;color:#61C550;margin-top:2px;margin-left:10px;float: left">{{response.responseResult.responseCode ? response.responseResult.responseCode :'0'}}</div>
|
||||
|
|
|
@ -1024,9 +1024,9 @@ export class LoopController extends Controller {
|
|||
this.type = "LoopController";
|
||||
this.active = false;
|
||||
this.loopType = "LOOP_COUNT";
|
||||
this.countController = {loops: 0, interval: 0, proceed: true};
|
||||
this.forEachController = {inputVal: "", returnVal: "", interval: 0};
|
||||
this.whileController = {variable: "", operator: "", value: "", timeout: 0};
|
||||
this.countController = {loops: 0, interval: 0, proceed: true, requestResult: {}};
|
||||
this.forEachController = {inputVal: "", returnVal: "", interval: 0, requestResult: {}};
|
||||
this.whileController = {variable: "", operator: "", value: "", timeout: 0, requestResult: {}};
|
||||
this.hashTree = [];
|
||||
this.set(options);
|
||||
}
|
||||
|
|
|
@ -284,15 +284,15 @@ export default {
|
|||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
// if (this.condition.orders) {
|
||||
// this.condition.orders = [];
|
||||
// }
|
||||
// _sort(column, this.condition);
|
||||
// this.initTable();
|
||||
if (this.condition.orders) {
|
||||
this.condition.orders = [];
|
||||
}
|
||||
_sort(column, this.condition);
|
||||
this.initTable();
|
||||
},
|
||||
filter(filters) {
|
||||
// _filter(filters, this.condition);
|
||||
// this.initTable();
|
||||
_filter(filters, this.condition);
|
||||
this.initTable();
|
||||
},
|
||||
getReport(data) {
|
||||
const {loadReportId} = data;
|
||||
|
|
|
@ -5,8 +5,25 @@
|
|||
@search="initTableData"
|
||||
:title="$t('test_track.report.name')"/>
|
||||
</template>
|
||||
<el-table border class="adjust-table" :data="tableData"
|
||||
@filter-change="filter" @sort-change="sort">
|
||||
<el-table border :data="tableData"
|
||||
@select-all="handleSelectAll"
|
||||
@select="handleSelect"
|
||||
row-key="id" class="test-content adjust-table ms-select-all"
|
||||
@filter-change="filter" @sort-change="sort" ref="testPlanReportTable">
|
||||
|
||||
<el-table-column width="50" type="selection"/>
|
||||
<ms-table-select-all
|
||||
:page-size="pageSize>total?total:pageSize"
|
||||
:total="total"
|
||||
@selectPageAll="isSelectDataAll(false)"
|
||||
@selectAll="isSelectDataAll(true)"/>
|
||||
|
||||
<el-table-column width="30" :resizable="false" align="center">
|
||||
<template v-slot:default="scope">
|
||||
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column min-width="300" prop="name" :label="$t('test_track.report.list.name')" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="testPlanName" sortable :label="$t('test_track.report.list.test_plan')" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="creator" :label="$t('test_track.report.list.creator')" show-overflow-tooltip></el-table-column>
|
||||
|
@ -25,9 +42,6 @@
|
|||
<ms-tag v-if="scope.row.status == 'RUNNING'" type="success" effect="plain" :content="'Running'"/>
|
||||
<ms-tag v-else-if="scope.row.status == 'COMPLETED'||scope.row.status == 'SUCCESS'||scope.row.status == 'FAILED'" type="info" effect="plain" :content="'Completed'"/>
|
||||
<ms-tag v-else type="effect" effect="plain" :content="scope.row.status"/>
|
||||
<!-- <el-tag size="mini" type="success" v-if="row.status === 'Running'">{{ row.status }}</el-tag>-->
|
||||
<!-- <el-tag size="mini" type="info" v-else-if="row.status === 'Completed'">{{ row.status }}</el-tag>-->
|
||||
<!-- <el-tag size="mini" type="info" v-if="row.status === 'Completed'">{{ row.status }}</el-tag>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column min-width="150" :label="$t('commons.operating')">
|
||||
|
@ -56,13 +70,16 @@ import {getCurrentProjectID} from "../../../../../common/js/utils";
|
|||
import TestPlanReportView from "@/business/components/track/report/components/TestPlanReportView";
|
||||
import ReportTriggerModeItem from "@/business/components/common/tableItem/ReportTriggerModeItem";
|
||||
import MsTag from "@/business/components/common/components/MsTag";
|
||||
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
|
||||
import MsTableSelectAll from "@/business/components/common/components/table/MsTableSelectAll";
|
||||
|
||||
export default {
|
||||
name: "TestPlanReportList",
|
||||
components: {
|
||||
TestPlanReportView,
|
||||
MsTableOperator, MsTableOperatorButton, MsTableHeader, MsTablePagination,
|
||||
ReportTriggerModeItem,MsTag
|
||||
ReportTriggerModeItem,MsTag,
|
||||
ShowMoreBtn,MsTableSelectAll,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -75,6 +92,7 @@ export default {
|
|||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
isTestManagerOrTestUser: false,
|
||||
selectRows: new Set(),
|
||||
total: 0,
|
||||
tableData: [],
|
||||
statusFilters: [
|
||||
|
@ -87,13 +105,16 @@ export default {
|
|||
{text: this.$t('test_track.plan.system_test'), value: 'system'},
|
||||
{text: this.$t('test_track.plan.regression_test'), value: 'regression'},
|
||||
],
|
||||
buttons: [
|
||||
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
|
||||
],
|
||||
selectAll: false,
|
||||
unSelection: [],
|
||||
selectDataCounts: 0,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
// if (to.path.indexOf("/track/plan/all") >= 0) {
|
||||
// this.initTableData();
|
||||
// }
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
|
@ -106,6 +127,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
this.selectRows = new Set();
|
||||
this.selectAll = false;
|
||||
this.unSelection = [];
|
||||
this.selectDataCounts = 0;
|
||||
if (this.planId) {
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
|
@ -119,19 +144,52 @@ export default {
|
|||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
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 projectIds = arr.filter(d => d.id !== this.tableData[i].projectId).map(data => data.id);
|
||||
// this.$set(this.tableData[i], "projectIds", projectIds);
|
||||
// })
|
||||
// }
|
||||
this.unSelection = data.listObject.map(s => s.id);
|
||||
});
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
handleSelect(selection, row) {
|
||||
row.hashTree = [];
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
let arr = Array.from(this.selectRows);
|
||||
// 选中1个以上的用例时显示更多操作
|
||||
if (this.selectRows.size === 1) {
|
||||
this.$set(arr[0], "showMore", true);
|
||||
} else if (this.selectRows.size === 2) {
|
||||
arr.forEach(row => {
|
||||
this.$set(row, "showMore", true);
|
||||
})
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
if (selection.length === 1) {
|
||||
selection.hashTree = [];
|
||||
this.selectRows.add(selection[0]);
|
||||
} else {
|
||||
this.tableData.forEach(item => {
|
||||
item.hashTree = [];
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
this.selectRowsCount(this.selectRows)
|
||||
},
|
||||
handleDelete(testPlanReport) {
|
||||
this.$alert(this.$t('report.delete_confirm') + ' ' + testPlanReport.name + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
|
@ -146,7 +204,32 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleDeleteBatch(){
|
||||
this.$alert(this.$t('report.delete_batch_confirm') + ' ' + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
let deleteParam = {};
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
deleteParam.dataIds = ids;
|
||||
deleteParam.projectId = getCurrentProjectID();
|
||||
deleteParam.selectAllDate = this.isSelectAllDate;
|
||||
deleteParam.unSelectIds = this.unSelection;
|
||||
deleteParam = Object.assign(deleteParam, this.condition);
|
||||
this.$post('/test/plan/report/deleteBatchByParams/', deleteParam, () => {
|
||||
this.$success(this.$t('commons.delete_success'));
|
||||
this.initTableData();
|
||||
this.selectRows.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getIds(rowSets) {
|
||||
let rowArray = Array.from(rowSets)
|
||||
let ids = rowArray.map(s => s.id);
|
||||
return ids;
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
|
@ -160,6 +243,26 @@ export default {
|
|||
this.$refs.testPlanReportView.open(planId);
|
||||
}
|
||||
},
|
||||
isSelectDataAll(dataType) {
|
||||
this.isSelectAllDate = dataType;
|
||||
this.selectRowsCount(this.selectRows)
|
||||
//如果已经全选,不需要再操作了
|
||||
if (this.selectRows.size != this.tableData.length) {
|
||||
this.$refs.testPlanReportTable.toggleAllSelection(true);
|
||||
}
|
||||
},
|
||||
selectRowsCount(selection) {
|
||||
let selectedIDs = this.getIds(selection);
|
||||
let allIDs = this.tableData.map(s => s.id);
|
||||
this.unSelection = allIDs.filter(function (val) {
|
||||
return selectedIDs.indexOf(val) === -1
|
||||
});
|
||||
if (this.isSelectAllDate) {
|
||||
this.selectDataCounts = this.total - this.unSelection.length;
|
||||
} else {
|
||||
this.selectDataCounts = selection.size;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -175,4 +278,22 @@ export default {
|
|||
.el-table {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.operate-button > div {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.request-method {
|
||||
padding: 0 5px;
|
||||
color: #1E90FF;
|
||||
}
|
||||
|
||||
.ms-select-all >>> th:first-child {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.ms-select-all >>> th:nth-child(2) .el-icon-arrow-down {
|
||||
top: -2px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9e64da846793401150260fc50262d82932cf5d8a
|
||||
Subproject commit 5abe43dc1f65b529ad59c17bfdc58aea33d23cad
|
|
@ -129,6 +129,7 @@ export default {
|
|||
validate: "Validate",
|
||||
batch_add: "Batch add",
|
||||
check_project_tip: "Create or select the project first",
|
||||
auth_redirect_tip: 'Jump to the authentication source page for authentication',
|
||||
table: {
|
||||
select_tip: "Item {0} data is selected"
|
||||
},
|
||||
|
@ -831,8 +832,8 @@ export default {
|
|||
swagger_export_tip: "Export jSON-formatted files via Swagger website",
|
||||
suffixFormatErr: "The file format does not meet the requirements",
|
||||
swagger_url_import: "Import using URL",
|
||||
timing_synchronization:"Timing synchronization",
|
||||
next_synchronization_time:"Next synchronization time",
|
||||
timing_synchronization: "Timing synchronization",
|
||||
next_synchronization_time: "Next synchronization time",
|
||||
|
||||
},
|
||||
home_page: {
|
||||
|
@ -1493,6 +1494,6 @@ export default {
|
|||
format: "Output format",
|
||||
},
|
||||
auth_source: {
|
||||
delete_prompt:'This operation will delete the authentication source, do you want to continue? '
|
||||
delete_prompt: 'This operation will delete the authentication source, do you want to continue? '
|
||||
}
|
||||
};
|
||||
|
|
|
@ -129,6 +129,7 @@ export default {
|
|||
validate: "校验",
|
||||
batch_add: "批量添加",
|
||||
check_project_tip: "请先创建或选择项目",
|
||||
auth_redirect_tip: '即将跳转到认证源页面进行认证',
|
||||
table: {
|
||||
select_tip: "已选中 {0} 条数据"
|
||||
},
|
||||
|
@ -833,8 +834,8 @@ export default {
|
|||
swagger_export_tip: "通过 Swagger 页面导出",
|
||||
suffixFormatErr: "文件格式不符合要求",
|
||||
swagger_url_import: "使用URL导入",
|
||||
timing_synchronization:"定时同步",
|
||||
next_synchronization_time:"下次同步时间"
|
||||
timing_synchronization: "定时同步",
|
||||
next_synchronization_time: "下次同步时间"
|
||||
|
||||
|
||||
},
|
||||
|
|
|
@ -129,6 +129,7 @@ export default {
|
|||
validate: "校驗",
|
||||
batch_add: "批量添加",
|
||||
check_project_tip: "請先創建或選擇項目",
|
||||
auth_redirect_tip: '即將跳轉到認證源頁面進行認證',
|
||||
table: {
|
||||
select_tip: "已选中 {0} 条数据"
|
||||
},
|
||||
|
@ -256,8 +257,8 @@ export default {
|
|||
nail_robot: '釘釘機器人',
|
||||
enterprise_wechat_robot: '企業微信機器人',
|
||||
notes: '1.釘釘和企業群裏新建壹個自定義機器人,然後復制 webhook 地址在我們平臺上;\n' +
|
||||
' 2.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知";\n' +
|
||||
' 3.選擇接收人時必須是妳所建的群裏包含的人,接收人手機號為必填項且為釘釘企業所使用的手機號,',
|
||||
' 2.機器人選擇為群機器人,安全驗證選擇“自定義關鍵詞” :"任務通知";\n' +
|
||||
' 3.選擇接收人時必須是妳所建的群裏包含的人,接收人手機號為必填項且為釘釘企業所使用的手機號,',
|
||||
message: '事件,接收人,接收方式為必填項',
|
||||
message_webhook: '接收方式為釘釘和企業機器人時,webhook為必填項',
|
||||
template: "模版"
|
||||
|
@ -832,8 +833,8 @@ export default {
|
|||
swagger_export_tip: "通過 Swagger 頁面導出",
|
||||
suffixFormatErr: "文件格式不符合要求",
|
||||
swagger_url_import: "使用URL導入",
|
||||
timing_synchronization:"定時同步",
|
||||
next_synchronization_time:"下次同步時間",
|
||||
timing_synchronization: "定時同步",
|
||||
next_synchronization_time: "下次同步時間",
|
||||
|
||||
},
|
||||
home_page: {
|
||||
|
|
|
@ -174,25 +174,9 @@ export default {
|
|||
}
|
||||
},
|
||||
redirectAuth(authId) {
|
||||
if (authId === 'LDAP' || authId === 'LOCAL') {
|
||||
return;
|
||||
if (auth.default) {
|
||||
auth.default.redirectAuth(this, authId);
|
||||
}
|
||||
let source = this.authSources.filter(auth => auth.id === authId)[0];
|
||||
if (source.type === 'CAS') {
|
||||
return;
|
||||
}
|
||||
this.$confirm(this.$t('即将跳转到认证源页面进行认证'), '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let config = JSON.parse(source.configuration);
|
||||
let url = config.authUrl + "/auth?client_id=" + config.clientId + "&redirect_uri=" + config.redirectUrl +
|
||||
"&response_type=code&scope=openid+profile+email+offline_access&state=" + authId;
|
||||
window.location.href = url;
|
||||
}).catch(() => {
|
||||
this.form.authenticate = 'LOCAL';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue