This commit is contained in:
chenjianxing 2021-02-01 18:51:26 +08:00
commit b136576c40
12 changed files with 706 additions and 509 deletions

View File

@ -33,4 +33,6 @@ public class ApiBatchRequest extends ApiDefinitionWithBLOBs {
private List<String> unSelectIds; private List<String> unSelectIds;
private String moduleId;
} }

View File

@ -42,10 +42,10 @@ public class MsIfController extends MsTestElement {
private IfController ifController() { private IfController ifController() {
IfController ifController = new IfController(); IfController ifController = new IfController();
ifController.setEnabled(true); ifController.setEnabled(true);
ifController.setName(this.getLabelName()); ifController.setName(StringUtils.isEmpty(this.getName()) ? "IfController" : this.getName());
ifController.setCondition(this.getCondition());
ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName()); ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName());
ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel")); ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel"));
ifController.setCondition(this.getCondition());
ifController.setEvaluateAll(false); ifController.setEvaluateAll(false);
ifController.setUseExpression(true); ifController.setUseExpression(true);
return ifController; return ifController;

View File

@ -60,6 +60,18 @@ public class TestResult {
item.getSubRequestResults().forEach(subItem -> { item.getSubRequestResults().forEach(subItem -> {
subItem.setName(item.getName()); subItem.setName(item.getName());
}); });
} else {
if (requestResultMap.containsKey(result.getName())) {
requestResultMap.get(result.getName()).add(item);
} else {
List<RequestResult> requestResults = new LinkedList<>();
requestResults.add(item);
requestResultMap.put(result.getName(), requestResults);
}
item.getSubRequestResults().forEach(subItem -> {
subItem.setName(item.getName());
});
} }
}); });
} }

View File

@ -1,4 +1,5 @@
<template> <template>
<div>
<ms-container v-if="renderComponent"> <ms-container v-if="renderComponent">
<ms-aside-container> <ms-aside-container>
<ms-api-module <ms-api-module
@ -9,6 +10,7 @@
@debug="debug" @debug="debug"
@saveAsEdit="editApi" @saveAsEdit="editApi"
@setModuleOptions="setModuleOptions" @setModuleOptions="setModuleOptions"
@setNodeTree="setNodeTree"
@enableTrash="enableTrash" @enableTrash="enableTrash"
:type="'edit'" :type="'edit'"
ref="nodeTree"/> ref="nodeTree"/>
@ -25,6 +27,8 @@
<!-- 列表集合 --> <!-- 列表集合 -->
<ms-api-list <ms-api-list
v-if="item.type === 'list' && isApiListEnable" v-if="item.type === 'list' && isApiListEnable"
:module-tree="nodeTree"
:module-options="moduleOptions"
:current-protocol="currentProtocol" :current-protocol="currentProtocol"
:visible="visible" :visible="visible"
:currentRow="currentRow" :currentRow="currentRow"
@ -102,8 +106,12 @@
</template> </template>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</ms-main-container> </ms-main-container>
</ms-container> </ms-container>
</div>
</template> </template>
<script> <script>
import MsApiList from './components/list/ApiList'; import MsApiList from './components/list/ApiList';
@ -177,7 +185,7 @@
currentModule: null, currentModule: null,
selectNodeIds: [], selectNodeIds: [],
currentApi: {}, currentApi: {},
moduleOptions: {}, moduleOptions: [],
trashEnable: false, trashEnable: false,
apiTabs: [{ apiTabs: [{
title: this.$t('api_test.definition.api_title'), title: this.$t('api_test.definition.api_title'),
@ -187,7 +195,8 @@
}], }],
isApiListEnable: true, isApiListEnable: true,
syncTabs: [], syncTabs: [],
projectId: "" projectId: "",
nodeTree: []
} }
}, },
mounted() { mounted() {
@ -215,6 +224,7 @@
} }
}, },
methods: { methods: {
changeRedirectParam(redirectIDParam) { changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam; this.redirectID = redirectIDParam;
}, },
@ -394,6 +404,10 @@
setModuleOptions(data) { setModuleOptions(data) {
this.moduleOptions = data; this.moduleOptions = data;
}, },
setNodeTree(data) {
this.nodeTree = data;
console.log( this.nodeTree)
},
changeSelectDataRangeAll(tableType) { changeSelectDataRangeAll(tableType) {
this.$route.params.dataSelectRange = 'all'; this.$route.params.dataSelectRange = 'all';
}, },

View File

@ -0,0 +1,127 @@
<template>
<div v-if="dialogVisible" class="batch-move" v-loading="result.loading">
<el-dialog :title="this.$t('test_track.case.select_catalog')"
:visible.sync="dialogVisible"
:before-close="close"
:destroy-on-close="true"
width="20%"
>
<div>
<el-input :placeholder="$t('test_track.module.search')" v-model="filterText" size="small"/>
<el-tree
class="filter-tree node-tree"
:data="treeNodes"
node-key="id"
:filter-node-method="filterNode"
:expand-on-click-node="false"
highlight-current
style="overflow: auto"
@node-click="nodeClick"
ref="tree"
>
<template v-slot:default="{node}">
<span>
<span class="node-icon">
<i class="el-icon-folder"/>
</span>
<span class="node-title">{{node.label}}</span>
</span>
</template>
</el-tree>
</div>
<template v-slot:footer>
<ms-dialog-footer
@cancel="close"
@confirm="save"/>
</template>
</el-dialog>
</div>
</template>
<script>
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
export default {
name: "CaseBatchMove",
components: {
MsDialogFooter
},
data() {
return {
treeNodes: [],
selectIds: [],
selectNode: {},
dialogVisible: false,
currentKey: "",
moduleOptions: [],
filterText: "",
result: {},
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
console.log( this.treeNodes)
}
},
methods: {
open(treeNodes, selectIds, moduleOptions) {
this.dialogVisible = true;
this.treeNodes = treeNodes;
this.selectIds = selectIds;
this.moduleOptions = moduleOptions;
},
save() {
if (!this.currentKey) {
this.$warning(this.$t('test_track.case.input_module'));
return;
}
let param = {};
param.nodeId = this.currentKey;
if (this.moduleOptions) {
this.moduleOptions.forEach(item => {
if (item.id === this.currentKey) {
param.nodePath = item.path;
}
});
}
param.ids = this.selectIds;
this.$emit('moveSave', param);
},
refresh() {
this.$emit("refresh");
},
close() {
this.filterText = "";
this.dialogVisible = false;
this.selectNode = {};
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
nodeClick() {
this.currentKey = this.$refs.tree.getCurrentKey();
}
}
}
</script>
<style scoped>
.node-title {
width: 0;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1 1 auto;
padding: 0 5px;
overflow: hidden;
}
.batch-move {
height: 500px;
}
</style>

View File

@ -4,8 +4,10 @@
:is-api-list-enable="isApiListEnable" :is-api-list-enable="isApiListEnable"
@isApiListEnableChange="isApiListEnableChange"> @isApiListEnableChange="isApiListEnableChange">
<el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{$t('commons.adv_search.title')}}</el-link> <el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{ $t('commons.adv_search.title') }}
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" class="search-input" size="small" @keyup.enter.native="search" </el-link>
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" class="search-input" size="small"
@keyup.enter.native="search"
v-model="condition.name"/> v-model="condition.name"/>
<el-table v-loading="result.loading" <el-table v-loading="result.loading"
@ -24,7 +26,7 @@
@selectPageAll="isSelectDataAll(false)" @selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/> @selectAll="isSelectDataAll(true)"/>
<el-table-column min-width="30" :resizable="false" align="center"> <el-table-column width="30" :resizable="false" align="center">
<template v-slot:default="scope"> <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="buttons" :size="selectDataCounts"/>
</template> </template>
@ -67,7 +69,8 @@
:label="$t('api_test.definition.api_type')" :label="$t('api_test.definition.api_type')"
show-overflow-tooltip min-width="120px"> show-overflow-tooltip min-width="120px">
<template v-slot:default="scope" class="request-method"> <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)}" <el-tag size="mini"
:style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}"
class="api-el-tag"> class="api-el-tag">
{{ scope.row.method }} {{ scope.row.method }}
</el-tag> </el-tag>
@ -133,23 +136,27 @@
:label="$t('api_test.definition.api_case_passing_rate')" :label="$t('api_test.definition.api_case_passing_rate')"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column fixed="right" v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130" align="center"> <el-table-column fixed="right" v-if="!isReadOnly" :label="$t('commons.operating')" min-width="130"
align="center">
<template v-slot:default="scope"> <template v-slot:default="scope">
<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.reduction')" icon="el-icon-refresh-left"
<ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="editApi(scope.row)" v-else v-tester/> @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')" <el-tooltip :content="$t('test_track.case.case_list')"
placement="bottom" placement="bottom"
:enterable="false" :enterable="false"
effect="dark" > effect="dark">
<el-button @click="handleTestCase(scope.row)" <el-button @click="handleTestCase(scope.row)"
@keydown.enter.native.prevent @keydown.enter.native.prevent
type="primary" type="primary"
circle circle
style="color:white;padding: 0px 0.1px;font-size: 11px;width: 28px;height: 28px;" style="color:white;padding: 0px 0.1px;font-size: 11px;width: 28px;height: 28px;"
size="mini" >case size="mini">case
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)" type="danger" v-tester/> <ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" @exec="handleDelete(scope.row)"
type="danger" v-tester/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -161,37 +168,39 @@
<ms-batch-edit ref="batchEdit" @batchEdit="batchEdit" :typeArr="typeArr" :value-arr="valueArr"/> <ms-batch-edit ref="batchEdit" @batchEdit="batchEdit" :typeArr="typeArr" :value-arr="valueArr"/>
<!--高级搜索--> <!--高级搜索-->
<ms-table-adv-search-bar :condition.sync="condition" :showLink="false" ref="searchBar" @search="search"/> <ms-table-adv-search-bar :condition.sync="condition" :showLink="false" ref="searchBar" @search="search"/>
<case-batch-move @refresh="initTable" @moveSave="moveSave" ref="testCaseBatchMove"></case-batch-move>
</div> </div>
</template> </template>
<script> <script>
import MsTableHeader from '../../../../common/components/MsTableHeader'; import MsTableHeader from '../../../../common/components/MsTableHeader';
import MsTableOperator from "../../../../common/components/MsTableOperator"; import MsTableOperator from "../../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
import MsTableButton from "../../../../common/components/MsTableButton"; import MsTableButton from "../../../../common/components/MsTableButton";
import MsTablePagination from "../../../../common/pagination/TablePagination"; import MsTablePagination from "../../../../common/pagination/TablePagination";
import MsTag from "../../../../common/components/MsTag"; import MsTag from "../../../../common/components/MsTag";
import MsApiCaseList from "../case/ApiCaseList"; import MsApiCaseList from "../case/ApiCaseList";
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsBottomContainer from "../BottomContainer"; import MsBottomContainer from "../BottomContainer";
import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn"; import ShowMoreBtn from "../../../../track/case/components/ShowMoreBtn";
import MsBatchEdit from "../basis/BatchEdit"; import MsBatchEdit from "../basis/BatchEdit";
import {API_METHOD_COLOUR, API_STATUS, REQ_METHOD,TCP_METHOD,SQL_METHOD,DUBBO_METHOD} from "../../model/JsonData"; import {API_METHOD_COLOUR, API_STATUS, REQ_METHOD, TCP_METHOD, SQL_METHOD, DUBBO_METHOD} from "../../model/JsonData";
import {_filter, _sort, getCurrentProjectID} from "@/common/js/utils"; import {_filter, _sort, getCurrentProjectID} from "@/common/js/utils";
import {WORKSPACE_ID} from '@/common/js/constants'; import {WORKSPACE_ID} from '@/common/js/constants';
import ApiListContainer from "./ApiListContainer"; import ApiListContainer from "./ApiListContainer";
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover"; import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus"; import ApiStatus from "@/business/components/api/definition/components/list/ApiStatus";
import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar"; import MsTableAdvSearchBar from "@/business/components/common/components/search/MsTableAdvSearchBar";
import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components"; import {API_DEFINITION_CONFIGS} from "@/business/components/common/components/search/search-components";
import MsTipButton from "@/business/components/common/components/MsTipButton"; import MsTipButton from "@/business/components/common/components/MsTipButton";
import CaseBatchMove from "@/business/components/api/definition/components/basis/BatchMove";
export default { export default {
name: "ApiList", name: "ApiList",
components: { components: {
CaseBatchMove,
ApiStatus, ApiStatus,
MsTableHeaderSelectPopover, MsTableHeaderSelectPopover,
ApiListContainer, ApiListContainer,
@ -222,7 +231,10 @@
selectRows: new Set(), selectRows: new Set(),
buttons: [ buttons: [
{name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch}, {name: this.$t('api_test.definition.request.batch_delete'), handleClick: this.handleDeleteBatch},
{name: this.$t('api_test.definition.request.batch_edit'), handleClick: this.handleEditBatch} {name: this.$t('api_test.definition.request.batch_edit'), handleClick: this.handleEditBatch},
{
name: this.$t('api_test.definition.request.batch_move'), handleClick: this.handleBatchMove
}
], ],
typeArr: [ typeArr: [
{id: 'status', name: this.$t('api_test.definition.api_status')}, {id: 'status', name: this.$t('api_test.definition.api_status')},
@ -288,12 +300,23 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
moduleTree: {
type: Array,
default() {
return []
},
},
moduleOptions: {
type: Array,
default() {
return []
},
}
}, },
created: function () { created: function () {
if (this.trashEnable) { if (this.trashEnable) {
this.condition.filters = {status: ["Trash"]}; this.condition.filters = {status: ["Trash"]};
} } else {
else {
this.condition.filters = {status: ["Prepare", "Underway", "Completed"]}; this.condition.filters = {status: ["Prepare", "Underway", "Completed"]};
} }
this.initTable(); this.initTable();
@ -317,6 +340,10 @@
} }
}, },
methods: { methods: {
handleBatchMove() {
this.$refs.testCaseBatchMove.open(this.moduleTree, [], this.moduleOptions);
},
isApiListEnableChange(data) { isApiListEnableChange(data) {
this.$emit('isApiListEnableChange', data); this.$emit('isApiListEnableChange', data);
}, },
@ -369,8 +396,8 @@
}); });
} }
}, },
genProtocalFilter(protocalType){ genProtocalFilter(protocalType) {
if(protocalType === "HTTP"){ if (protocalType === "HTTP") {
this.methodFilters = [ this.methodFilters = [
{text: 'GET', value: 'GET'}, {text: 'GET', value: 'GET'},
{text: 'POST', value: 'POST'}, {text: 'POST', value: 'POST'},
@ -381,20 +408,20 @@
{text: 'HEAD', value: 'HEAD'}, {text: 'HEAD', value: 'HEAD'},
{text: 'CONNECT', value: 'CONNECT'}, {text: 'CONNECT', value: 'CONNECT'},
]; ];
}else if(protocalType === "TCP"){ } else if (protocalType === "TCP") {
this.methodFilters = [ this.methodFilters = [
{text: 'TCP', value: 'TCP'}, {text: 'TCP', value: 'TCP'},
]; ];
}else if(protocalType === "SQL"){ } else if (protocalType === "SQL") {
this.methodFilters = [ this.methodFilters = [
{text: 'SQL', value: 'SQL'}, {text: 'SQL', value: 'SQL'},
]; ];
}else if(protocalType === "DUBBO"){ } else if (protocalType === "DUBBO") {
this.methodFilters = [ this.methodFilters = [
{text: 'DUBBO', value: 'DUBBO'}, {text: 'DUBBO', value: 'DUBBO'},
{text: 'dubbo://', value: 'dubbo://'}, {text: 'dubbo://', value: 'dubbo://'},
]; ];
}else{ } else {
this.methodFilters = [ this.methodFilters = [
{text: 'GET', value: 'GET'}, {text: 'GET', value: 'GET'},
{text: 'POST', value: 'POST'}, {text: 'POST', value: 'POST'},
@ -529,13 +556,13 @@
} }
}, },
handleEditBatch() { handleEditBatch() {
if(this.currentProtocol =='HTTP'){ if (this.currentProtocol == 'HTTP') {
this.valueArr.method = REQ_METHOD; this.valueArr.method = REQ_METHOD;
}else if(this.currentProtocol =='TCP'){ } else if (this.currentProtocol == 'TCP') {
this.valueArr.method = TCP_METHOD; this.valueArr.method = TCP_METHOD;
}else if(this.currentProtocol =='SQL'){ } else if (this.currentProtocol == 'SQL') {
this.valueArr.method = SQL_METHOD; this.valueArr.method = SQL_METHOD;
}else if(this.currentProtocol =='DUBBO'){ } else if (this.currentProtocol == 'DUBBO') {
this.valueArr.method = DUBBO_METHOD; this.valueArr.method = DUBBO_METHOD;
} }
this.$refs.batchEdit.open(); this.$refs.batchEdit.open();
@ -557,6 +584,21 @@
this.initTable(); this.initTable();
}); });
}, },
moveSave(param) {
let arr = Array.from(this.selectRows);
let ids = arr.map(row => row.id);
param.ids = ids;
param.projectId = getCurrentProjectID();
param.selectAllDate = this.isSelectAllDate;
param.unSelectIds = this.unSelection;
param = Object.assign(param, this.condition);
param.moduleId=param.nodeId;
this.$post('/api/definition/batch/editByParams', param, () => {
this.$success(this.$t('commons.save_success'));
this.$refs.testCaseBatchMove.close();
this.initTable();
});
},
handleTestCase(api) { handleTestCase(api) {
this.selectApi = api; this.selectApi = api;
let request = {}; let request = {};
@ -666,36 +708,36 @@
</script> </script>
<style scoped> <style scoped>
.operate-button > div { .operate-button > div {
display: inline-block; display: inline-block;
margin-left: 10px; margin-left: 10px;
} }
.request-method { .request-method {
padding: 0 5px; padding: 0 5px;
color: #1E90FF; color: #1E90FF;
} }
.api-el-tag { .api-el-tag {
color: white; color: white;
} }
.search-input { .search-input {
float: right; float: right;
width: 300px; width: 300px;
margin-right: 10px; margin-right: 10px;
} }
.el-tag { .el-tag {
margin-left: 10px; margin-left: 10px;
} }
.ms-select-all >>> th:first-child { .ms-select-all >>> th:first-child {
margin-top: 20px; margin-top: 20px;
} }
.ms-select-all >>> th:nth-child(2) .el-icon-arrow-down { .ms-select-all >>> th:nth-child(2) .el-icon-arrow-down {
top: -2px; top: -2px;
} }
</style> </style>

View File

@ -126,6 +126,7 @@
buildNodePath(node, {path: ''}, moduleOptions); buildNodePath(node, {path: ''}, moduleOptions);
}); });
this.$emit('setModuleOptions', moduleOptions); this.$emit('setModuleOptions', moduleOptions);
this.$emit('setNodeTree', this.data);
if (this.$refs.nodeTree) { if (this.$refs.nodeTree) {
this.$refs.nodeTree.filter(this.condition.filterText); this.$refs.nodeTree.filter(this.condition.filterText);
} }

View File

@ -114,9 +114,7 @@ export default {
} }
], ],
phone: [ phone: [
{required: true, message: this.$t('user.input_phone'), trigger: 'blur'},
{ {
required: false,
pattern: PHONE_REGEX, pattern: PHONE_REGEX,
message: this.$t('member.mobile_number_format_is_incorrect'), message: this.$t('member.mobile_number_format_is_incorrect'),
trigger: 'blur' trigger: 'blur'

View File

@ -399,9 +399,7 @@ export default {
} }
], ],
phone: [ phone: [
{required: true, message: this.$t('user.input_phone'), trigger: 'blur'},
{ {
required: true,
pattern: PHONE_REGEX, pattern: PHONE_REGEX,
message: this.$t('user.mobile_number_format_is_incorrect'), message: this.$t('user.mobile_number_format_is_incorrect'),
trigger: 'blur' trigger: 'blur'

View File

@ -583,6 +583,7 @@ export default {
create_info: 'Create', create_info: 'Create',
update_info: 'Update', update_info: 'Update',
batch_edit: "Batch edit", batch_edit: "Batch edit",
batch_move:"Batch move",
path_valid_info: "The request path is invalid", path_valid_info: "The request path is invalid",
other_config: "Other Config", other_config: "Other Config",
message_template: "Message Template", message_template: "Message Template",

View File

@ -584,6 +584,7 @@ export default {
create_info: '创建', create_info: '创建',
update_info: '更新', update_info: '更新',
batch_edit: "批量编辑", batch_edit: "批量编辑",
batch_move:"批量移动",
path_valid_info: "请求路径无效", path_valid_info: "请求路径无效",
other_config: "其他设置", other_config: "其他设置",
message_template: "报文模版", message_template: "报文模版",

View File

@ -583,6 +583,7 @@ export default {
create_info: '創建', create_info: '創建',
update_info: '更新', update_info: '更新',
batch_edit: "批量編輯", batch_edit: "批量編輯",
batch_move:"批量移動",
path_valid_info: "請求路徑無效", path_valid_info: "請求路徑無效",
other_config: "其他設置", other_config: "其他設置",
message_template: "報文模版", message_template: "報文模版",