refactor: 创建项目时默认创建Mock环境等一系列优化

重写接口定义页面的接口列表表格,制作表格统一化;批量菜单选项选中高亮;创建项目时默认创建Mock环境
This commit is contained in:
song-tianyang 2021-04-20 19:13:43 +08:00 committed by 刘瑞斌
parent 195fd95687
commit 79d7c0e01e
11 changed files with 457 additions and 163 deletions

View File

@ -272,8 +272,7 @@ public class ApiDefinitionController {
@GetMapping("/getMockEnvironment/{projectId}")
public ApiTestEnvironmentWithBLOBs getMockEnvironment(@PathVariable String projectId, HttpServletRequest request) {
System.out.println(request.getRequestURL());
String requestUrl = request.getRequestURI();
String requestUrl = request.getRequestURL().toString();
String baseUrl = "";
if (requestUrl.contains("/api/definition")) {
baseUrl = requestUrl.split("/api/definition")[0];

View File

@ -194,7 +194,11 @@ public class ApiDefinitionService {
}
public void reduction(ApiBatchRequest request) {
extApiDefinitionMapper.reduction(request.getIds());
ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiDefinitionMapper.selectIds(query));
if (request.getIds() != null || !request.getIds().isEmpty()) {
extApiDefinitionMapper.reduction(request.getIds());
}
}
public void deleteBodyFiles(String apiId) {

View File

@ -94,6 +94,7 @@ public class ApiTestEnvironmentService {
private ApiTestEnvironmentWithBLOBs genHttpApiTestEnvironmentByUrl(String projectId, String name, String url) {
String protocol = "";
String socket = "";
if (url.startsWith("http://")) {
protocol = "http";
url = url.substring(7);
@ -101,6 +102,7 @@ public class ApiTestEnvironmentService {
protocol = "https";
url = url.substring(8);
}
socket = url;
String portStr = "";
String ipStr = protocol;
@ -127,13 +129,42 @@ public class ApiTestEnvironmentService {
commonConfigObj.put("hosts", new String[]{});
JSONObject httpConfig = new JSONObject();
httpConfig.put("socket", url);
httpConfig.put("domain", ipStr);
httpConfig.put("headers", variablesArr);
httpConfig.put("protocol", protocol);
// httpConfig.put("socket", url);
// httpConfig.put("domain", ipStr);
// httpConfig.put("headers", variablesArr);
// httpConfig.put("protocol", protocol);
// if (StringUtils.isNotEmpty(portStr)) {
// httpConfig.put("port", portStr);
// }
httpConfig.put("socket", null);
httpConfig.put("domain", null);
httpConfig.put("headers", new JSONArray(variablesArr));
httpConfig.put("protocol", null);
httpConfig.put("port", null);
JSONArray httpItemArr = new JSONArray();
JSONObject httpItem = new JSONObject();
httpItem.put("id", UUID.randomUUID().toString());
httpItem.put("type", "NONE");
httpItem.put("socket", socket);
httpItem.put("protocol", protocol);
httpItem.put("headers", new JSONArray(variablesArr));
httpItem.put("domain", ipStr);
if (StringUtils.isNotEmpty(portStr)) {
httpConfig.put("port", portStr);
httpItem.put("port", portStr);
} else {
httpItem.put("port", "");
}
JSONArray detailArr = new JSONArray();
JSONObject detailObj = new JSONObject();
detailObj.put("name", "");
detailObj.put("value", "contains");
detailObj.put("enable", true);
detailArr.add(detailObj);
httpItem.put("details", detailArr);
httpItemArr.add(httpItem);
httpConfig.put("conditions", httpItemArr);
httpConfig.put("defaultCondition", "NONE");
JSONArray databaseConfigObj = new JSONArray();

View File

@ -1,9 +1,9 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import java.io.Serializable;
@Data
public class MockConfig implements Serializable {
private String id;
@ -23,4 +23,5 @@ public class MockConfig implements Serializable {
private String createUserId;
private static final long serialVersionUID = 1L;
}

View File

@ -2,6 +2,7 @@ package io.metersphere.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.FileMetadata;
import io.metersphere.base.domain.Project;
import io.metersphere.commons.constants.RoleConstants;
@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@ -27,6 +29,8 @@ public class ProjectController {
private ProjectService projectService;
@Resource
private CheckPermissionService checkPermissionService;
@Resource
private ApiTestEnvironmentService apiTestEnvironmentService;
@GetMapping("/listAll")
public List<ProjectDTO> listAll() {
@ -62,8 +66,18 @@ public class ProjectController {
@PostMapping("/add")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER,}, logical = Logical.OR)
public Project addProject(@RequestBody Project project) {
return projectService.addProject(project);
public Project addProject(@RequestBody Project project, HttpServletRequest request) {
Project returnModel = projectService.addProject(project);
//创建项目的时候默认增加Mock环境
String requestUrl = request.getRequestURL().toString();
String baseUrl = "";
if (requestUrl.contains("/project/add")) {
baseUrl = requestUrl.split("/project/add")[0];
}
apiTestEnvironmentService.getMockEnvironmentByProjectId(returnModel.getId(), baseUrl);
return returnModel;
}
@PostMapping("/list/{goPage}/{pageSize}")

View File

@ -8,38 +8,20 @@
@keyup.enter.native="search"
v-model="condition.name"/>
<el-table v-loading="result.loading"
<ms-table :data="tableData" :select-node-ids="selectNodeIds" :condition="condition" :page-size="pageSize"
:total="total" enableSelection
:batch-operators="trashEnable ? trashButtons : buttons" :screenHeight="screenHeight"
:operators="tableOperatorButtons" operator-width="170px"
ref="apiDefinitionTable"
border
@sort-change="sort"
@filter-change="filter"
:data="tableData" row-key="id" class="test-content adjust-table ms-select-all-fixed"
@select-all="handleSelectAll"
@header-dragend="headerDragend"
@select="handleSelect" :height="screenHeight">
<el-table-column width="50" type="selection"/>
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize>total?total:pageSize"
:total="total"
:select-data-counts="selectDataCounts"
@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="trashEnable ? trashButtons : buttons" :size="selectDataCounts" v-tester/>
</template>
</el-table-column>
>
<template v-for="(item, index) in tableLabel">
<el-table-column
<ms-table-column
v-if="item.id == 'num'"
prop="num"
label="ID"
show-overflow-tooltip
min-width="80px"
sortable="custom"
sortable=true
:key="index">
<template slot-scope="scope">
<!-- 判断为只读用户的话不可点击ID进行编辑操作 -->
@ -48,39 +30,40 @@
<a style="cursor:pointer" @click="editApi(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
</ms-table-column>
<ms-table-column
v-if="item.id == 'name'"
prop="name"
:label="$t('api_test.definition.api_name')"
show-overflow-tooltip
sortable="custom"
min-width="120px"
width="120px"
:key="index"/>
<el-table-column
<ms-table-column
v-if="item.id == 'status'"
prop="status"
column-key="status"
sortable="custom"
:filters="statusFilters"
:label="$t('api_test.definition.api_status')"
min-width="120px"
width="120px"
:key="index">
<template v-slot:default="scope">
<span class="el-dropdown-link">
<api-status :value="scope.row.status"/>
</span>
</template>
</el-table-column>
</ms-table-column>
<el-table-column
<ms-table-column
v-if="item.id == 'method'"
prop="method"
sortable="custom"
column-key="method"
:filters="methodFilters"
:label="$t('api_test.definition.api_type')"
show-overflow-tooltip min-width="120px"
show-overflow-tooltip
width="120px"
:key="index">
<template v-slot:default="scope" class="request-method">
<el-tag size="mini"
@ -89,9 +72,9 @@
{{ scope.row.method }}
</el-tag>
</template>
</el-table-column>
</ms-table-column>
<el-table-column
<ms-table-column
v-if="item.id == 'userName'"
prop="userName"
sortable="custom"
@ -99,105 +82,260 @@
column-key="user_id"
:label="$t('api_test.definition.api_principal')"
show-overflow-tooltip
min-width="100px"
width="100px"
:key="index"/>
<el-table-column
<ms-table-column
v-if="item.id == 'path'"
prop="path"
min-width="120px"
width="120px"
:label="$t('api_test.definition.api_path')"
show-overflow-tooltip
:key="index"/>
<el-table-column
<ms-table-column
v-if="item.id == 'tags'"
prop="tags"
:label="$t('commons.tag')"
min-width="120px"
width="120px"
:key="index">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :show-tooltip="true" :content="itemName"
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:show-tooltip="true" :content="itemName"
style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
</ms-table-column>
<el-table-column
<ms-table-column
v-if="item.id == 'updateTime'"
width="160"
:label="$t('api_test.definition.api_last_time')"
sortable="custom"
min-width="160px"
prop="updateTime"
:key="index">
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
</ms-table-column>
<el-table-column
<ms-table-column
v-if="item.id == 'caseTotal'"
prop="caseTotal"
min-width="80px"
width="80px"
:label="$t('api_test.definition.api_case_number')"
show-overflow-tooltip
:key="index"/>
<el-table-column
<ms-table-column
v-if="item.id == 'caseStatus'"
prop="caseStatus"
min-width="80px"
width="80px"
:label="$t('api_test.definition.api_case_status')"
show-overflow-tooltip
:key="index"/>
<el-table-column
<ms-table-column
v-if="item.id == 'casePassingRate'"
width="100px"
prop="casePassingRate"
:width="100"
min-width="100px"
:label="$t('api_test.definition.api_case_passing_rate')"
show-overflow-tooltip
:key="index"/>
</template>
<!-- 操作 -->
<el-table-column fixed="right" v-if="!isReadOnly" min-width="180"
align="center">
<template slot="header">
<header-label-operate @exec="customHeader"/>
</template>
<template v-slot:default="scope">
<ms-table-operator-button class="run-button" :is-tester-permission="true"
:tip="$t('api_test.automation.execute')"
icon="el-icon-video-play"
@exec="runApi(scope.row)"/>
<!-- 回收站的恢复按钮 -->
<ms-table-operator-button :tip="$t('commons.reduction')" icon="el-icon-refresh-left"
@exec="reductionApi(scope.row)" v-if="trashEnable" v-tester/>
<ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="editApi(scope.row)" v-else
v-tester/>
<el-tooltip :content="$t('test_track.case.case_list')"
placement="bottom"
:enterable="false"
effect="dark">
<el-button @click="handleTestCase(scope.row)"
@keydown.enter.native.prevent
type="primary"
:disabled="isReadOnly"
circle
style="color:white;padding: 0px 0.1px;font-size: 11px;width: 28px;height: 28px;"
size="mini">case
</el-button>
</el-tooltip>
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)"
type="danger" v-tester/>
</template>
</el-table-column>
<header-custom ref="headerCustom" :initTableData="initTable" :optionalFields=headerItems
:type=type></header-custom>
</el-table>
</ms-table>
<!-- <el-table v-loading="result.loading"-->
<!-- ref="apiDefinitionTable"-->
<!-- border-->
<!-- @sort-change="sort"-->
<!-- @filter-change="filter"-->
<!-- :data="tableData" row-key="id" class="test-content adjust-table ms-select-all-fixed"-->
<!-- @select-all="handleSelectAll"-->
<!-- @header-dragend="headerDragend"-->
<!-- @select="handleSelect" :height="screenHeight">-->
<!-- <el-table-column width="50" type="selection"/>-->
<!-- <ms-table-header-select-popover v-show="total>0"-->
<!-- :page-size="pageSize>total?total:pageSize"-->
<!-- :total="total"-->
<!-- :select-data-counts="selectDataCounts"-->
<!-- @selectPageAll="isSelectDataAll(false)"-->
<!-- @selectAll="isSelectDataAll(true)"/>-->
<!-- <el-table-column width="30" :resizable="false" align="center">-->
<!-- <template v-slot:default="scope">-->
<!-- &lt;!&ndash; 选中记录后浮现的按钮提供对记录的批量操作 &ndash;&gt;-->
<!-- <show-more-btn :is-show="scope.row.showMore" :buttons="trashEnable ? trashButtons : buttons" :size="selectDataCounts" v-tester/>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <template v-for="(item, index) in tableLabel">-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'num'"-->
<!-- prop="num"-->
<!-- label="ID"-->
<!-- show-overflow-tooltip-->
<!-- min-width="80px"-->
<!-- sortable="custom"-->
<!-- :key="index">-->
<!-- <template slot-scope="scope">-->
<!-- &lt;!&ndash; 判断为只读用户的话不可点击ID进行编辑操作 &ndash;&gt;-->
<!-- <span style="cursor:pointer" v-if="isReadOnly"> {{ scope.row.num }} </span>-->
<!-- <el-tooltip v-else content="编辑">-->
<!-- <a style="cursor:pointer" @click="editApi(scope.row)"> {{ scope.row.num }} </a>-->
<!-- </el-tooltip>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'name'"-->
<!-- prop="name"-->
<!-- :label="$t('api_test.definition.api_name')"-->
<!-- show-overflow-tooltip-->
<!-- sortable="custom"-->
<!-- min-width="120px"-->
<!-- :key="index"/>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'status'"-->
<!-- prop="status"-->
<!-- column-key="status"-->
<!-- sortable="custom"-->
<!-- :filters="statusFilters"-->
<!-- :label="$t('api_test.definition.api_status')"-->
<!-- min-width="120px"-->
<!-- :key="index">-->
<!-- <template v-slot:default="scope">-->
<!-- <span class="el-dropdown-link">-->
<!-- <api-status :value="scope.row.status"/>-->
<!-- </span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'method'"-->
<!-- prop="method"-->
<!-- sortable="custom"-->
<!-- column-key="method"-->
<!-- :filters="methodFilters"-->
<!-- :label="$t('api_test.definition.api_type')"-->
<!-- show-overflow-tooltip min-width="120px"-->
<!-- :key="index">-->
<!-- <template v-slot:default="scope" class="request-method">-->
<!-- <el-tag size="mini"-->
<!-- :style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}"-->
<!-- class="api-el-tag">-->
<!-- {{ scope.row.method }}-->
<!-- </el-tag>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'userName'"-->
<!-- prop="userName"-->
<!-- sortable="custom"-->
<!-- :filters="userFilters"-->
<!-- column-key="user_id"-->
<!-- :label="$t('api_test.definition.api_principal')"-->
<!-- show-overflow-tooltip-->
<!-- min-width="100px"-->
<!-- :key="index"/>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'path'"-->
<!-- prop="path"-->
<!-- min-width="120px"-->
<!-- :label="$t('api_test.definition.api_path')"-->
<!-- show-overflow-tooltip-->
<!-- :key="index"/>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'tags'"-->
<!-- prop="tags"-->
<!-- :label="$t('commons.tag')"-->
<!-- min-width="120px"-->
<!-- :key="index">-->
<!-- <template v-slot:default="scope">-->
<!-- <ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain" :show-tooltip="true" :content="itemName"-->
<!-- style="margin-left: 0px; margin-right: 2px"/>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'updateTime'"-->
<!-- width="160"-->
<!-- :label="$t('api_test.definition.api_last_time')"-->
<!-- sortable="custom"-->
<!-- min-width="160px"-->
<!-- prop="updateTime"-->
<!-- :key="index">-->
<!-- <template v-slot:default="scope">-->
<!-- <span>{{ scope.row.updateTime | timestampFormatDate }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'caseTotal'"-->
<!-- prop="caseTotal"-->
<!-- min-width="80px"-->
<!-- :label="$t('api_test.definition.api_case_number')"-->
<!-- show-overflow-tooltip-->
<!-- :key="index"/>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'caseStatus'"-->
<!-- prop="caseStatus"-->
<!-- min-width="80px"-->
<!-- :label="$t('api_test.definition.api_case_status')"-->
<!-- show-overflow-tooltip-->
<!-- :key="index"/>-->
<!-- <el-table-column-->
<!-- v-if="item.id == 'casePassingRate'"-->
<!-- prop="casePassingRate"-->
<!-- :width="100"-->
<!-- min-width="100px"-->
<!-- :label="$t('api_test.definition.api_case_passing_rate')"-->
<!-- show-overflow-tooltip-->
<!-- :key="index"/>-->
<!-- </template>-->
<!-- &lt;!&ndash; 操作 &ndash;&gt;-->
<!-- <el-table-column fixed="right" v-if="!isReadOnly" min-width="180"-->
<!-- align="center">-->
<!-- <template slot="header">-->
<!-- <header-label-operate @exec="customHeader"/>-->
<!-- </template>-->
<!-- <template v-slot:default="scope">-->
<!-- <ms-table-operator-button class="run-button" :is-tester-permission="true"-->
<!-- :tip="$t('api_test.automation.execute')"-->
<!-- icon="el-icon-video-play"-->
<!-- @exec="runApi(scope.row)"/>-->
<!-- &lt;!&ndash; 回收站的恢复按钮 &ndash;&gt;-->
<!-- <ms-table-operator-button :tip="$t('commons.reduction')" icon="el-icon-refresh-left"-->
<!-- @exec="reductionApi(scope.row)" v-if="trashEnable" v-tester/>-->
<!-- <ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="editApi(scope.row)" v-else-->
<!-- v-tester/>-->
<!-- <el-tooltip :content="$t('test_track.case.case_list')"-->
<!-- placement="bottom"-->
<!-- :enterable="false"-->
<!-- effect="dark">-->
<!-- <el-button @click="handleTestCase(scope.row)"-->
<!-- @keydown.enter.native.prevent-->
<!-- type="primary"-->
<!-- :disabled="isReadOnly"-->
<!-- circle-->
<!-- style="color:white;padding: 0px 0.1px;font-size: 11px;width: 28px;height: 28px;"-->
<!-- size="mini">case-->
<!-- </el-button>-->
<!-- </el-tooltip>-->
<!-- <ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)"-->
<!-- type="danger" v-tester/>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <header-custom ref="headerCustom" :initTableData="initTable" :optionalFields=headerItems-->
<!-- :type=type></header-custom>-->
<!-- </el-table>-->
<ms-table-pagination :change="initTable" :current-page.sync="currentPage" :page-size.sync="pageSize"
:total="total"/>
</div>
@ -218,9 +356,11 @@ import MsTableOperator from "../../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
import MsTableButton from "../../../../common/components/MsTableButton";
import MsTablePagination from "../../../../common/pagination/TablePagination";
import MsTable from "@/business/components/common/components/table/MsTable";
import MsTag from "../../../../common/components/MsTag";
import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer";
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
import MsBottomContainer from "../BottomContainer";
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
import MsBatchEdit from "../basis/BatchEdit";
@ -272,7 +412,9 @@ export default {
ShowMoreBtn,
MsBatchEdit,
MsTipButton,
MsTableAdvSearchBar
MsTableAdvSearchBar,
MsTable,
MsTableColumn
},
data() {
return {
@ -301,6 +443,17 @@ export default {
name: "批量恢复", handleClick: this.handleBatchRestore
},
],
tableOperatorButtons: [],
tableUsualOperatorButtons: [
{tip: this.$t('api_test.automation.execute'), icon: "el-icon-video-play", exec: this.runApi},
{tip: this.$t('commons.edit'), icon: "el-icon-edit", exec: this.editApi},
{tip: "CASE", exec: this.handleTestCase, isDivButton: true, type: "primary"},
{tip: this.$t('commons.delete'), exec: this.handleDelete, icon: "el-icon-delete", type: "danger"},
],
tableTrashOperatorButtons: [
{tip: this.$t('api_test.automation.execute'), icon: "el-icon-video-play", exec: this.runApi},
{tip: this.$t('commons.reduction'), icon: "el-icon-refresh-left", exec: this.reductionApi},
],
typeArr: [
{id: 'status', name: this.$t('api_test.definition.api_status')},
{id: 'method', name: this.$t('api_test.definition.api_type')},
@ -383,8 +536,10 @@ export default {
},
created: function () {
if (this.trashEnable) {
this.tableOperatorButtons = this.tableTrashOperatorButtons;
this.condition.filters = {status: ["Trash"]};
} else {
this.tableOperatorButtons = this.tableUsualOperatorButtons;
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
}
this.initTable();
@ -393,6 +548,8 @@ export default {
watch: {
selectNodeIds() {
initCondition(this.condition, false);
this.condition.moduleIds = [];
this.condition.moduleIds.push(this.selectNodeIds);
this.initTable();
},
currentProtocol() {
@ -401,9 +558,11 @@ export default {
},
trashEnable() {
if (this.trashEnable) {
this.tableOperatorButtons = this.tableTrashOperatorButtons;
this.condition.filters = {status: ["Trash"]};
this.condition.moduleIds = [];
} else {
this.tableOperatorButtons = this.tableUsualOperatorButtons;
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
}
initCondition(this.condition, false);
@ -465,37 +624,14 @@ export default {
// nexttick:
this.$nextTick(function () {
if (this.$refs.apiDefinitionTable) {
setTimeout(this.$refs.apiDefinitionTable.doLayout, 200);
this.$refs.apiDefinitionTable.checkTableRowIsSelect();
setTimeout(this.$refs.apiDefinitionTable.doLayout(), 200);
}
this.checkTableRowIsSelect();
})
});
}
getLabel(this, API_LIST);
},
checkTableRowIsSelect() {
//
if (this.condition.selectAll) {
let unSelectIds = this.condition.unSelectIds;
this.tableData.forEach(row => {
if (unSelectIds.indexOf(row.id) < 0) {
this.$refs.apiDefinitionTable.toggleRowSelection(row, true);
//selectRows
if (!this.selectRows.has(row)) {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
} else {
//selectRow
if (this.selectRows.has(row)) {
this.$set(row, "showMore", false);
this.selectRows.delete(row);
}
}
})
}
},
genProtocalFilter(protocalType) {
if (protocalType === "HTTP") {
this.methodFilters = [

View File

@ -1,11 +1,26 @@
<template>
<ms-tip-button
:disabled="disabled || isReadOnly"
@click="exec"
@clickStop="clickStop"
:type="type"
:tip="tip"
:icon="icon" size="mini" circle/>
<el-tooltip :content="tip" v-if=isDivButton
placement="bottom"
:enterable="false"
effect="dark">
<el-button @click="exec"
@keydown.enter.native.prevent
type="primary"
:disabled="isReadOnly"
circle
style="color:white;padding: 0px 0.1px;width: 28px;height: 28px;"
size="mini">
<span style=" font-size: 11px; transform: scale(0.8);">{{ tip }}</span>
</el-button>
</el-tooltip>
<ms-tip-button v-else
:disabled="disabled || isReadOnly"
@click="exec"
@clickStop="clickStop"
:type="type"
:tip="tip"
:icon="icon" size="mini" circle/>
</template>
<script>
@ -22,6 +37,10 @@
}
},
props: {
isDivButton: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: 'el-icon-question'
@ -59,4 +78,5 @@
</script>
<style scoped>
</style>

View File

@ -2,7 +2,7 @@
<span>
<ms-table-operator-button v-for="(btn, index) in buttons" :key="index" :isTesterPermission="isTesterPermission(btn)"
:disabled="isDisable(btn)"
:tip="btn.tip" :icon="btn.icon" :type="btn.type"
:tip="btn.tip" :icon="btn.icon" :type="btn.type" :isDivButton="btn.isDivButton"
@exec="click(btn)" @click.stop="clickStop(btn)"/>
</span>
</template>

View File

@ -1,14 +1,14 @@
<template>
<el-table-column
v-if="fields.has(prop) || fields.size < 1"
:width="width"
:fixed="fixed"
:filters="filters"
:prop="prop"
:column-key="prop"
:label="label"
:sortable="sortable"
:show-overflow-tooltip="showOverflowTooltip">
v-if="fields.has(prop) || fields.size < 1"
:min-width="width"
:fixed="fixed"
:filters="filters"
:prop="prop"
:column-key="prop"
:label="label"
:sortable="sortable"
:show-overflow-tooltip="showOverflowTooltip">
<template v-slot:default="scope">
<slot :row="scope.row" :$index="scope.$index">
{{scope.row[prop]}}
@ -35,7 +35,7 @@ export default {
},
// mapperExtBaseMapper.orders
sortable: {
type: Boolean,
type: [Boolean, String],
default() {
return false;
}

View File

@ -12,19 +12,22 @@
@cell-mouse-enter="showPopover"
row-key="id"
class="test-content adjust-table ms-select-all-fixed"
:height="screenHeight"
ref="table" @row-click="handleRowClick">
<el-table-column v-if="enableSelection" width="50" type="selection"/>
<ms-table-header-select-popover v-if="enableSelection" v-show="total > 0"
<ms-table-header-select-popover v-if="enableSelection" ref="selectPopover"
:page-size="pageSize > total ? total : pageSize"
:total="total"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
<el-table-column v-if="enableSelection && buttons && buttons.length > 0" width="40" :resizable="false" align="center">
<el-table-column v-if="enableSelection && batchOperators && batchOperators.length > 0" width="40"
:resizable="false" align="center">
<template v-slot:default="scope">
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
<!-- 选中记录后浮现的按钮提供对记录的批量操作 -->
<show-more-btn :is-show="scope.row.showMore" :buttons="batchOperators" :size="selectDataCounts" v-tester/>
</template>
</el-table-column>
@ -55,12 +58,13 @@ import {
_handleSelectAll, _sort, getLabel,
getSelectDataCounts,
setUnSelectIds,
toggleAllSelection
toggleAllSelection,
checkTableRowIsSelect,
} from "@/common/js/tableUtils";
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
import {TEST_CASE_LIST} from "@/common/js/constants";
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
import ShowMoreBtn from "@/business/components/api/automation/scenario/TableMoreBtn";
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
import MsTableOperators from "@/business/components/common/components/MsTableOperators";
@ -69,12 +73,21 @@ export default {
components: {MsTableOperators, MsTableColumn, ShowMoreBtn, MsTablePagination, MsTableHeaderSelectPopover},
data() {
return {
buttons: [],
selectDataCounts: 0,
selectRows: new Set(),
};
},
props: {
screenHeight: {
type: Number,
default: 400,
},
selectNodeIds: {
type: Array,
default() {
return [];
}
},
data: {
type: Array,
default() {
@ -106,11 +119,18 @@ export default {
return [];
}
},
//
batchOperators: {
type: Array,
default() {
return [];
}
},
//
operatorWidth: {
type: String,
default() {
return '150';
return "150px";
}
},
//
@ -124,6 +144,14 @@ export default {
mounted() {
getLabel(this, TEST_CASE_LIST);
},
created() {
},
watch: {
selectNodeIds() {
this.selectDataCounts = 0;
this.$refs.selectPopover.reload();
},
},
computed: {
selectIds() {
return Array.from(this.selectRows).map(o => o.id);
@ -145,9 +173,14 @@ export default {
},
isSelectDataAll(data) {
this.condition.selectAll = data;
setUnSelectIds(this.data, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
//
toggleAllSelection(this.$refs.table, this.data, this.selectRows);
//
_handleSelectAll(this, this.data, this.data, this.selectRows);
//ID()
this.condition.unSelectIds = [];
//
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
headerDragend(newWidth, oldWidth, column, event) {
// let finalWidth = newWidth;
@ -162,6 +195,9 @@ export default {
this.currentCaseId = row.id;
}
},
doLayout() {
this.$refs.table.doLayout();
},
filter(filters) {
_filter(filters, this.condition);
this.handleRefresh();
@ -182,7 +218,7 @@ export default {
this.$refs.testBatchMove.open(this.treeNodes, Array.from(this.selectRows).map(row => row.id), this.moduleOptions);
},
handleRowClick() {
this.$emit("handleRowClick");
},
handleRefresh() {
this.selectRows.clear();
@ -190,6 +226,9 @@ export default {
},
handlePageChange() {
this.$emit('pageChange');
},
checkTableRowIsSelect() {
checkTableRowIsSelect(this, this.condition, this.data, this.$refs.table, this.selectRows);
}
}
};

View File

@ -2,18 +2,25 @@
<el-table-column v-if="isShow" width="1" :resizable="false" align="center">
<el-popover slot="header" placement="right" trigger="click" style="margin-right: 0px;">
<el-link
:class="{'selected-link': selectDataCounts === this.total}"
:class="{'selected-link': selectDataCounts === total}"
@click.native.stop="click('selectAll')"
:type="selectAllLinkType"
ref="selectAllLink">
{{$t('api_test.batch_menus.select_all_data',[total])}}
<span>
{{ $t('api_test.batch_menus.select_all_data', [total]) }}
</span>
</el-link>
<br/>
<el-link
:class="{'selected-link': selectDataCounts === this.pageSize}"
@click.native.stop="click('selectPageAll')"
ref="selectPageAllLink">
{{$t('api_test.batch_menus.select_show_data',[pageSize])}}
<el-link
:class="{'selected-link': selectDataCounts === this.pageSize}"
@click.native.stop="click('selectPageAll')"
:type="selectPageLinkType"
ref="selectPageAllLink">
<span>
{{ $t('api_test.batch_menus.select_show_data', [pageSize]) }}
</span>
</el-link>
<i class="el-icon-arrow-down" slot="reference"></i>
@ -24,23 +31,66 @@
<script>
export default {
name: "MsTableHeaderSelectPopover",
props: ['total', 'pageSize', 'selectDataCounts'],
// props: ['total', 'pageSize', 'selectDataCounts'],
props: {
total: {
type: Number,
default() {
return 10;
}
},
pageSize: {
type: Number,
default() {
return 10;
}
},
selectDataCounts: {
type: Number,
default() {
return 0;
}
},
},
data() {
return {
isShow: true
selectType: "",
isShow: true,
selectAllLinkType: "info",
selectPageLinkType: "info",
};
},
watch: {
selectDataCounts() {
this.reload();
},
total() {
this.reload();
}
},
methods: {
click(even) {
if (even === 'selectPageAll') {
this.selectAllLinkType = "info";
this.selectPageLinkType = "primary";
} else if (even === 'selectAll') {
this.selectAllLinkType = "primary";
this.selectPageLinkType = "info";
} else {
this.selectAllLinkType = "info";
this.selectPageLinkType = "info";
}
this.$emit(even);
this.isShow = false;
this.$nextTick(() => {
this.isShow = true;
});
},
reload() {
this.isShow = false;
this.selectAllLinkType = "info";
this.selectPageLinkType = "info";
this.$nextTick(() => {
this.isShow = true;
});