refactor: 接口定义模块树重构

This commit is contained in:
chenjianxing 2020-12-15 16:25:00 +08:00
parent 27c18ef8a3
commit 77ea5d43fd
12 changed files with 383 additions and 559 deletions

View File

@ -32,7 +32,7 @@
</template>
<script>
import MsNodeTree from '../../../definition/components/ApiModule';
import MsNodeTree from '../../../definition/components/module/ApiModule';
import MsApiList from './ApiList';
import MsContainer from "../../../../common/components/MsContainer";
import MsMainContainer from "../../../../common/components/MsMainContainer";

View File

@ -1,13 +1,17 @@
<template>
<ms-container>
<ms-aside-container>
<ms-node-tree @selectModule="selectModule"
@getApiModuleTree="initTree"
@changeProtocol="changeProtocol"
@refresh="refresh"
@saveAsEdit="editApi"
@debug="debug"
@exportAPI="exportAPI"/>
<ms-api-module
@nodeSelectEvent="nodeChange"
@protocolChange="handleProtocolChange"
@refreshTable="refresh"
@exportAPI="exportAPI"
@debug="debug"
@saveAsEdit="editApi"
@setModuleOptions="setModuleOptions"
@enableTrash="enableTrash"
:type="'edit'"
ref="nodeTree"/>
</ms-aside-container>
<ms-main-container>
@ -33,9 +37,10 @@
<ms-api-list
v-if="item.type === 'list'"
:current-protocol="currentProtocol"
:current-module="currentModule"
:visible="visible"
:currentRow="currentRow"
:select-node-ids="selectNodeIds"
:trash-enable="trashEnable"
@editApi="editApi"
@handleCase="handleCase"
@showExecResult="showExecResult"
@ -48,7 +53,6 @@
:currentProtocol="currentProtocol"
:moduleOptions="moduleOptions"/>
</div>
<!-- 快捷调试 -->
<div v-else-if="item.type=== 'debug'" class="ms-api-div">
<ms-debug-http-page :currentProtocol="currentProtocol" :testCase="item.api" @saveAs="editApi" v-if="currentProtocol==='HTTP'"/>
@ -70,7 +74,6 @@
</ms-container>
</template>
<script>
import MsNodeTree from './components/ApiModule';
import MsApiList from './components/ApiList';
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
@ -86,11 +89,12 @@
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
import {downloadFile, getCurrentUser, getUUID, getCurrentProjectID} from "@/common/js/utils";
import MsApiModule from "./components/module/ApiModule";
export default {
name: "ApiDefinition",
components: {
MsNodeTree,
MsApiModule,
MsApiList,
MsMainContainer,
MsContainer,
@ -120,9 +124,11 @@
apiDefaultTab: 'default',
currentProtocol: null,
currentModule: null,
selectNodeIds: [],
currentApi: {},
moduleOptions: {},
runTestData: {},
trashEnable: false,
apiTabs: [{
title: this.$t('api_test.definition.api_title'),
name: 'default',
@ -199,7 +205,7 @@
this.apiDefaultTab = newTabName;
},
debug(id) {
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug",id);
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug", id);
},
editApi(row) {
let name = this.$t('api_test.definition.request.edit_api');
@ -215,9 +221,6 @@
apiCaseClose() {
this.showCasePage = true;
},
selectModule(data) {
this.currentModule = data;
},
exportAPI() {
if (!this.$refs.apiList[0].tableData) {
return;
@ -254,6 +257,19 @@
},
showExecResult(row){
this.debug(row);
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
handleProtocolChange(protocol) {
this.currentProtocol = protocol;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
enableTrash(data) {
this.trashEnable = data;
}
}
}

View File

@ -3,9 +3,11 @@
<el-card class="card-content">
<el-input placeholder="搜索" @blur="search" class="search-input" size="small" v-model="condition.name"/>
<el-table border :data="tableData" row-key="id" class="test-content adjust-table"
@select-all="handleSelectAll"
@select="handleSelect" :height="screenHeight">
<el-table v-loading="result.loading"
border
:data="tableData" row-key="id" class="test-content adjust-table"
@select-all="handleSelectAll"
@select="handleSelect" :height="screenHeight">
<el-table-column type="selection"/>
<el-table-column width="40" :resizable="false" align="center">
<template v-slot:default="scope">
@ -71,7 +73,7 @@
<el-table-column :label="$t('commons.operating')" min-width="130" align="center">
<template v-slot:default="scope">
<el-button type="text" @click="reductionApi(scope.row)" v-if="currentModule!=undefined && currentModule.id === 'gc'">恢复</el-button>
<el-button type="text" @click="reductionApi(scope.row)" v-if="trashEnable">恢复</el-button>
<el-button type="text" @click="editApi(scope.row)" v-else>{{$t('commons.edit')}}</el-button>
<el-button type="text" @click="handleTestCase(scope.row)">{{$t('api_test.definition.request.case')}}</el-button>
<el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C">{{$t('commons.delete')}}</el-button>
@ -125,6 +127,7 @@
return {
condition: {},
selectApi: {},
result: {},
moduleId: "",
deletePath: "/test/case/delete",
selectRows: new Set(),
@ -153,10 +156,14 @@
},
props: {
currentProtocol: String,
currentModule: Object,
selectNodeIds: Array,
visible: {
type: Boolean,
default: false,
},
trashEnable: {
type: Boolean,
default: false,
}
},
created: function () {
@ -165,28 +172,28 @@
this.getMaintainerOptions();
},
watch: {
currentModule() {
selectNodeIds() {
this.initApiTable();
},
currentProtocol() {
this.initApiTable();
},
trashEnable() {
if (this.trashEnable) {
this.initApiTable();
}
},
},
methods: {
initApiTable() {
this.selectRows = new Set();
this.condition.filters = ["Prepare", "Underway", "Completed"];
if (this.currentModule != null) {
if (this.currentModule.id == "root") {
this.condition.moduleIds = [];
} else if (this.currentModule.id == "gc") {
this.condition.moduleIds = [];
this.condition.filters = ["Trash"];
}
else {
this.condition.moduleIds = this.currentModule.ids;
}
if (this.trashEnable) {
this.condition.filters = ["Trash"];
this.condition.moduleIds = [];
}
this.condition.moduleIds = this.selectNodeIds;
if (this.projectId != null) {
this.condition.projectId = this.projectId;
}
@ -260,7 +267,7 @@
});
},
handleDeleteBatch() {
if (this.currentModule != undefined && this.currentModule.id == "gc") {
if (this.trashEnable) {
this.$alert(this.$t('api_test.definition.request.delete_confirm') + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
@ -319,7 +326,7 @@
this.$refs.caseList.open(this.selectApi);
},
handleDelete(api) {
if (this.currentModule != undefined && this.currentModule.id == "gc") {
if (this.trashEnable) {
this.$get('/api/definition/delete/' + api.id, () => {
this.$success(this.$t('commons.delete_success'));
this.initApiTable();

View File

@ -1,502 +0,0 @@
<template>
<div v-loading="result.loading">
<el-select class="protocol-select" size="small" v-model="protocol" @change="changeProtocol">
<el-option
v-for="item in options"
:key="item.value"
:name="item.name"
:value="item.value"
:disabled="item.disabled">
</el-option>
</el-select>
<el-input class="filter-input" :placeholder="$t('test_track.module.search')" v-model="filterText"
size="small">
<template v-slot:append>
<el-dropdown size="small" split-button type="primary" class="ms-api-button" @click="handleCommand('add-api')"
@command="handleCommand">
<el-button icon="el-icon-folder-add" @click="addApi"></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="add-api">{{$t('api_test.definition.request.title')}}</el-dropdown-item>
<el-dropdown-item command="debug">{{$t('api_test.definition.request.fast_debug')}}</el-dropdown-item>
<el-dropdown-item command="import">{{$t('api_test.api_import.label')}}</el-dropdown-item>
<el-dropdown-item command="export">{{$t('report.export')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-input>
<el-tree :data="data"
class="filter-tree node-tree"
node-key="id"
:default-expanded-keys="expandedNode"
:expand-on-click-node="false"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
@node-click="selectModule"
@node-drag-end="handleDragEnd"
:filter-node-method="filterNode"
:draggable="true"
:allow-drop="allowDrop"
:allow-drag="allowDrag" ref="tree">
<span class="custom-tree-node father" slot-scope="{ node, data }">
<!-- 如果是编辑状态 -->
<template v-if="data.isEdit==1">
<el-input ref="input"
@blur="() => submitEdit(node,data)"
v-model="newLabel"
class="ms-el-input" size="mini"></el-input>
</template>
<!-- 如果不是编辑状态 -->
<i class="el-icon-delete" v-if="data.isEdit!=1 && data.id==='gc'"/>
<i class="el-icon-folder" v-if="data.isEdit!=1 && data.id!='gc'"/>
<span class="node-title" v-if="data.isEdit!=1" v-text="data.name"></span>
<span class="node-operate child">
<el-tooltip
v-if="data.id!='root' && data.id!='gc'"
class="item"
effect="dark"
:open-delay="200"
:content="$t('test_track.module.rename')"
placement="top">
<i @click.stop="() => edit(node,data)" class="el-icon-edit"></i>
</el-tooltip>
<el-tooltip
v-if="data.id!='gc'"
class="item"
effect="dark"
:open-delay="200"
:content="$t('test_track.module.add_submodule')"
placement="top">
<i @click.stop="() => append(node,data)" class="el-icon-circle-plus-outline"></i>
</el-tooltip>
<el-tooltip
v-if="data.id!='root' && data.id!='gc'"
class="item"
effect="dark"
:open-delay="200"
:content="$t('commons.delete')"
placement="top">
<i @click.stop="() => remove(node, data)" class="el-icon-delete"></i>
</el-tooltip>
</span>
</span>
</el-tree>
<ms-add-basis-api :current-protocol="protocol" ref="basisApi"></ms-add-basis-api>
<api-import ref="apiImport" :project-id="projectId" @refresh="refresh"/>
</div>
</template>
<script>
import MsAddBasisApi from "./basis/AddBasisApi";
import SelectMenu from "../../../track/common/SelectMenu";
import {OPTIONS, DEFAULT_DATA} from "../model/JsonData";
import ApiImport from "./import/ApiImport";
import {getCurrentProjectID} from "@/common/js/utils";
export default {
name: 'MsApiModule',
components: {
MsAddBasisApi,
SelectMenu,
ApiImport
},
data() {
return {
result: {},
options: OPTIONS,
protocol: OPTIONS[0].value,
httpVisible: false,
expandedNode: [],
filterText: "",
nextFlag: true,
projectId: "",
data: DEFAULT_DATA,
currentModule: {},
newLabel: ""
}
},
mounted() {
this.projectId = getCurrentProjectID();
this.changeProtocol();
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
}
},
methods: {
getApiModuleTree() {
if (this.expandedNode.length === 0) {
this.expandedNode.push("root");
}
this.nextFlag = true;
this.result = this.$get("/api/module/list/" + this.projectId + "/" + this.protocol, response => {
if (response.data != undefined && response.data != null) {
this.data[1].children = response.data;
let moduleOptions = [];
this.data[1].children.forEach(node => {
this.buildNodePath(node, {path: ''}, moduleOptions);
});
this.$emit('getApiModuleTree', moduleOptions);
}
});
},
handleCommand(e) {
switch (e) {
case "debug":
this.$emit('debug');
break;
case "add-api":
this.addApi();
break;
case "add-module":
break;
case "import":
this.$refs.apiImport.open(this.currentModule);
break;
default:
this.$emit('exportAPI');
break;
}
},
buildNodePath(node, option, moduleOptions) {
//
option.id = node.id;
option.path = option.path + '/' + node.name;
node.path = option.path;
moduleOptions.push(option);
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
this.buildNodePath(node.children[i], {path: option.path}, moduleOptions);
}
}
},
findTreeByNodeId(rootNode, nodeId) {
if (rootNode.id == nodeId) {
return rootNode;
}
if (rootNode.children) {
for (let i = 0; i < rootNode.children.length; i++) {
if (this.findTreeByNodeId(rootNode.children[i], nodeId)) {
return rootNode;
}
}
}
},
buildParam(draggingNode, dropNode, dropType) {
let param = {};
param.id = draggingNode.data.id;
param.name = draggingNode.data.name;
param.projectId = draggingNode.data.projectId;
if (dropType === "inner") {
param.parentId = dropNode.data.id;
param.level = dropNode.data.level;
} else {
if (!dropNode.parent.id || dropNode.parent.id === 0) {
param.parentId = 0;
param.level = 1;
} else {
param.parentId = dropNode.parent.data.id;
param.level = dropNode.parent.data.level;
}
}
let nodeIds = [];
this.getChildNodeId(draggingNode.data, nodeIds);
if (dropNode.level == 1 && dropType != "inner") {
param.nodeTree = draggingNode.data;
} else {
for (let i = 0; i < this.data.length; i++) {
param.nodeTree = this.findTreeByNodeId(this.data[i], dropNode.data.id);
if (param.nodeTree) {
break;
}
}
}
param.nodeIds = nodeIds;
return param;
},
getTreeNode(nodes, id, list) {
if (!nodes) {
return;
}
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].id === id) {
i - 1 >= 0 ? list[0] = nodes[i - 1].id : list[0] = "";
list[1] = nodes[i].id;
i + 1 < nodes.length ? list[2] = nodes[i + 1].id : list[2] = "";
return;
}
if (nodes[i].children) {
this.getTreeNode(nodes[i].children, id, list);
}
}
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
if (dropNode.data.id === "root" || dropType === "none" || dropType === undefined) {
return;
}
let param = this.buildParam(draggingNode, dropNode, dropType);
this.list = [];
if (param.parentId === "root") {
param.parentId = null;
}
this.getTreeNode(this.data, draggingNode.data.id, this.list);
this.$post("/api/module/drag", param, () => {
this.getApiModuleTree();
}, (error) => {
this.getApiModuleTree();
});
},
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.id === "root") {
return false
} else {
return true
}
},
allowDrag(draggingNode) {
//
if (draggingNode.data.id === "root") {
return false
} else {
return true
}
},
append(node, data) {
if (this.nextFlag === true) {
const newChild = {
id: "newId",
isEdit: 0,
name: "",
children: []
}
if (!data.children) {
this.$set(data, 'children', [])
}
this.nextFlag = false;
data.children.push(newChild)
this.edit(node, newChild);
} else {
this.$message.warning(this.$t('commons.please_save'));
}
},
remove(node, data) {
if (data.name === "") {
this.nextFlag = true;
}
let delIds = [];
this.getChildNodeId(data, delIds);
delIds.push(data.id);
this.$post("/api/module/delete", delIds, () => {
this.$success(this.$t('commons.save_success'));
//
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id != undefined && data.id != undefined && d.id === data.id)
children.splice(index, 1);
});
},
edit(node, data) {
this.$set(data, 'isEdit', 1)
this.newLabel = data.name
this.$nextTick(() => {
})
},
submitEdit(node, data) {
//
if (this.newLabel === "") {
this.nextFlag = false;
this.$message.warning(this.$t('commons.input_name'));
return;
}
this.$set(data, 'name', this.newLabel)
let flag = this.editApiModule(node, data);
if (flag === false) {
this.$set(data, 'isEdit', 1)
return;
}
this.$set(data, 'isEdit', 0)
this.newLabel = ""
this.nextFlag = true;
},
cancelEdit(node, data) {
this.newLabel = ""
this.$set(data, 'isEdit', 0)
},
getChildNodeId(rootNode, nodeIds) {
//ID
nodeIds.push(rootNode.id);
this.nodePath += rootNode.name + "/";
if (rootNode.children) {
for (let i = 0; i < rootNode.children.length; i++) {
this.getChildNodeId(rootNode.children[i], nodeIds);
}
}
},
//
editApiModule(node, data) {
if (!this.projectId) {
this.$error("$t('api_test.select_project')");
return;
}
let url = "";
if (data.id === "newId") {
url = '/api/module/add';
data.level = 1;
if (node.parent && node.parent.key != "root") {
data.parentId = node.parent.key;
data.level = node.parent.level;
}
} else {
url = '/api/module/edit';
let ids = [];
this.getChildNodeId(data, ids);
data.nodeIds = ids;
}
data.protocol = this.protocol;
data.projectId = this.projectId;
this.$post(url, data, () => {
this.$success(this.$t('commons.save_success'));
this.getApiModuleTree();
this.nextFlag = true;
return true;
});
return false;
},
selectModule(data) {
if (data.id != "root") {
if (data.path != undefined && !data.path.startsWith("/")) {
data.path = "/" + data.path;
}
if (data.path != undefined && data.path.endsWith("/")) {
data.path = data.path.substr(0, data.path.length - 1);
}
let nodeIds = [];
this.getChildNodeId(data, nodeIds);
data.ids = nodeIds;
this.currentModule = data;
}
this.$emit('selectModule', data);
},
refresh(data) {
this.$emit('refresh', data);
this.getApiModuleTree();
},
saveAsEdit(data) {
this.$emit('saveAsEdit', data);
},
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
addApi() {
this.$refs.basisApi.open(this.currentModule, this.projectId);
},
nodeExpand(data) {
if (data.id) {
this.expandedNode.push(data.id);
}
},
nodeCollapse(data) {
if (data.id) {
this.expandedNode.splice(this.expandedNode.indexOf(data.id), 1);
}
},
changeProtocol() {
this.getApiModuleTree();
this.$emit('changeProtocol', this.protocol);
}
}
}
</script>
<style scoped>
.node-tree {
margin-top: 15px;
margin-bottom: 15px;
}
.ms-el-input {
height: 25px;
line-height: 25px;
}
.custom-tree-node {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
width: 100%;
}
/deep/ .el-tree-node__content {
height: 33px;
}
.ms-api-button {
width: 30px;
}
.protocol-select {
width: 95px;
height: 30px;
}
.filter-input {
width: 175px;
padding-left: 3px;
}
.ms-api-button .el-button {
padding: 10px;
}
.filter-input >>> .el-input-group__append {
padding-right: 10px;
}
.protocol-select >>> .el-input--small {
font-size: 10px;
width: 90px;
}
.father .child {
display: none;
}
.father:hover .child {
display: block;
}
.node-title {
width: 0px;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1 1 auto;
padding: 0px 5px;
overflow: hidden;
}
.node-operate > i {
color: #409eff;
margin: 0px 5px;
}
</style>

View File

@ -59,7 +59,7 @@
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {REQ_METHOD} from "../../model/JsonData";
import {getCurrentUser, getUUID} from "../../../../../../common/js/utils";
import {getCurrentProjectID, getCurrentUser, getUUID} from "../../../../../../common/js/utils";
import {createComponent, Request} from "../jmeter/components";
import HeaderManager from "../jmeter/components/configurations/header-manager";
@ -77,7 +77,6 @@
httpForm: {},
httpVisible: false,
currentModule: {},
projectId: "",
maintainerOptions: [],
rule: {
name: [
@ -103,9 +102,9 @@
this.httpVisible = false;
if (saveAs) {
this.httpForm.request = JSON.stringify(this.httpForm.request);
this.$parent.saveAsEdit(this.httpForm);
this.$emit('saveAsEdit', this.httpForm);
} else {
this.$parent.refresh(this.currentModule);
this.$emit('refresh');
}
});
} else {
@ -129,7 +128,7 @@
break;
}
this.httpForm.bodyUploadIds = [];
this.httpForm.projectId = this.projectId;
this.httpForm.projectId = getCurrentProjectID();
this.httpForm.id = this.httpForm.request.id;
this.httpForm.protocol = this.currentProtocol;
@ -168,10 +167,9 @@
this.maintainerOptions = response.data;
});
},
open(currentModule, projectId) {
open(currentModule) {
this.httpForm = {method: REQ_METHOD[0].id, userId: getCurrentUser().id};
this.currentModule = currentModule;
this.projectId = projectId;
this.getMaintainerOptions();
this.httpVisible = true;
}

View File

@ -65,6 +65,7 @@
<script>
import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {listenGoBack, removeGoBackListener} from "@/common/js/utils";
import {getCurrentProjectID} from "../../../../../../common/js/utils";
export default {
name: "ApiImport",
@ -104,7 +105,6 @@
environments: [],
useEnvironment: false,
formData: {
projectId: '',
file: undefined,
swaggerUrl: ''
},
@ -113,7 +113,6 @@
fileList: []
}
},
props: ['projectId'],
activated() {
this.selectedPlatform = this.platforms[0];
},
@ -184,7 +183,7 @@
param.platform = this.selectedPlatformValue;
param.moduleId = this.currentModule.id;
param.modulePath = this.currentModule.path;
param.projectId = this.projectId;
param.projectId = getCurrentProjectID();
if (!this.swaggerUrlEable) {
param.swaggerUrl = undefined;
}

View File

@ -0,0 +1,164 @@
<template>
<div v-loading="result.loading">
<ms-node-tree
v-loading="result.loading"
:tree-nodes="data"
:type="'edit'"
@add="add"
@edit="edit"
@drag="drag"
@remove="remove"
@nodeSelectEvent="nodeChange"
ref="nodeTree">
<template v-slot:header>
<api-module-header
:condition="condition"
:current-module="currentModule"
@exportAPI="exportAPI"
@saveAsEdit="saveAsEdit"
@refresh="refresh"
@debug="debug"/>
</template>
</ms-node-tree>
</div>
</template>
<script>
import MsAddBasisApi from "../basis/AddBasisApi";
import SelectMenu from "../../../../track/common/SelectMenu";
import {OPTIONS} from "../../model/JsonData";
import ApiImport from "../import/ApiImport";
import {getCurrentProjectID} from "@/common/js/utils";
import MsNodeTree from "../../../../track/common/NodeTree";
import ApiModuleHeader from "./ApiModuleHeader";
import {buildNodePath} from "../../model/NodeTree";
export default {
name: 'MsApiModule',
components: {
ApiModuleHeader,
MsNodeTree,
MsAddBasisApi,
SelectMenu,
ApiImport
},
data() {
return {
result: {},
condition: {
protocol: OPTIONS[0].value,
filterText: "",
trashEnable: false
},
httpVisible: false,
expandedNode: [],
nextFlag: true,
projectId: "",
data: [],
currentModule: {},
newLabel: ""
}
},
mounted() {
this.projectId = getCurrentProjectID();
this.$emit('protocolChange', this.condition.protocol);
this.list();
},
watch: {
'condition.filterText'(val) {
this.$refs.nodeTree.filter(val);
},
'condition.protocol'() {
this.$emit('protocolChange', this.condition.protocol);
this.list();
},
'condition.trashEnable'() {
this.$emit('enableTrash', this.condition.trashEnable);
},
},
methods: {
list() {
if (this.projectId) {
this.result = this.$get("/api/module/list/" + this.projectId + "/" + this.condition.protocol, response => {
if (response.data != undefined && response.data != null) {
this.data = response.data;
let moduleOptions = [];
this.data.forEach(node => {
buildNodePath(node, {path: ''}, moduleOptions);
});
this.$emit('setModuleOptions', moduleOptions);
}
});
}
},
edit(param) {
param.projectId = this.projectId;
param.protocol = this.condition.protocol;
this.$post("/api/module/edit", param, () => {
this.$success(this.$t('commons.save_success'));
this.list();
this.refresh();
}, (error) => {
this.list();
});
},
add(param) {
param.projectId = this.projectId;
param.protocol = this.condition.protocol;
this.$post("/api/module/add", param, () => {
this.$success(this.$t('commons.save_success'));
this.list();
}, (error) => {
this.list();
});
},
remove(nodeIds) {
this.$post("/api/module/delete", nodeIds, () => {
this.list();
this.refresh();
}, (error) => {
this.list();
});
},
drag(param, list) {
this.$post("/api/module/drag", param, () => {
// this.$post("/api/module/pos", list); //todo
this.list();
}, (error) => {
this.list();
});
},
nodeChange(node, nodeIds, pNodes) {
this.currentModule = node;
this.condition.trashEnable = false;
if (node.data.id === 'root') {
this.$emit("nodeSelectEvent", node, [], pNodes);
} else {
this.$emit("nodeSelectEvent", node, nodeIds, pNodes);
}
},
exportAPI() {
this.$emit('exportAPI');
},
debug() {
this.$emit('debug');
},
saveAsEdit(data) {
this.$emit('saveAsEdit', data);
},
refresh() {
this.$emit("refreshTable");
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,131 @@
<template>
<div>
<el-select class="protocol-select" size="small" v-model="condition.protocol">
<el-option
v-for="item in options"
:key="item.value"
:name="item.name"
:value="item.value"
:disabled="item.disabled">
</el-option>
</el-select>
<el-input class="filter-input" :placeholder="$t('test_track.module.search')" v-model="condition.filterText" size="small">
<template v-slot:append>
<el-dropdown size="small" split-button type="primary" class="ms-api-button" @click="handleCommand('add-api')"
@command="handleCommand">
<el-button icon="el-icon-folder-add" @click="addApi"></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="add-api">{{$t('api_test.definition.request.title')}}</el-dropdown-item>
<el-dropdown-item command="debug">{{$t('api_test.definition.request.fast_debug')}}</el-dropdown-item>
<el-dropdown-item command="import">{{$t('api_test.api_import.label')}}</el-dropdown-item>
<el-dropdown-item command="export">{{$t('report.export')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-input>
<div @click="enableTrash" class="recycle" :class="{'is-active': condition.trashEnable}">
<i class="el-icon-delete"> 回收站</i>
</div>
<ms-add-basis-api
:current-protocol="condition.protocol"
@saveAsEdit="saveAsEdit"
@refresh="refresh"
ref="basisApi"/>
<api-import ref="apiImport" @refresh="refresh"/>
</div>
</template>
<script>
import {OPTIONS} from "../../model/JsonData";
import MsAddBasisApi from "../basis/AddBasisApi";
import ApiImport from "../import/ApiImport";
export default {
name: "ApiModuleHeader",
components: {ApiImport, MsAddBasisApi},
data() {
return {
options: OPTIONS,
}
},
props: {
condition: {
type: Object,
default() {
return {}
}
},
currentModule: {
type: Object,
default() {
return {}
}
}
},
methods: {
handleCommand(e) {
switch (e) {
case "debug":
this.$emit('debug');
break;
case "add-api":
this.addApi();
break;
case "add-module":
break;
case "import":
this.$refs.apiImport.open(this.currentModule);
break;
default:
this.$emit('exportAPI');
break;
}
},
addApi() {
this.$refs.basisApi.open(this.currentModule);
},
saveAsEdit(data) {
this.$emit('saveAsEdit', data);
},
refresh() {
this.$emit('refresh');
},
enableTrash() {
this.condition.trashEnable = true;
}
}
}
</script>
<style scoped>
.protocol-select {
width: 95px;
height: 30px;
}
.filter-input {
width: 175px;
padding-left: 3px;
}
.recycle {
padding-left: 25px;
margin-top: 15px;
height: 26px;
line-height: 26px;
margin-bottom: -10px;
}
.recycle:hover {
color: #6d317c;
cursor: pointer;
}
.is-active {
background-color: #f3f6f9;
}
</style>

View File

@ -0,0 +1,12 @@
// 递归构建节点路径下拉框选项
export function buildNodePath(node, option, moduleOptions) {
option.id = node.id;
option.path = option.path + '/' + node.name;
moduleOptions.push(option);
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
buildNodePath(node.children[i], {path: option.path}, moduleOptions);
}
}
}

View File

@ -5,6 +5,7 @@
<test-case-node-tree
@nodeSelectEvent="nodeChange"
@refreshTable="refresh"
@setTreeNodes="setTreeNodes"
:type="'edit'"
ref="nodeTree"/>
</ms-aside-container>
@ -153,6 +154,9 @@ export default {
},
batchMove(selectIds) {
this.$refs.testBatchMove.open(this.treeNodes, selectIds, this.$refs.testCaseEditDialog.moduleOptions);
},
setTreeNodes(data) {
this.treeNodes = data;
}
}
}

View File

@ -263,6 +263,7 @@ import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEve
import {Message} from "element-ui";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import {getCurrentProjectID} from "../../../../../common/js/utils";
import {buildNodePath} from "../../../api/definition/model/NodeTree";
export default {
name: "TestCaseEdit",
@ -547,7 +548,7 @@ export default {
getModuleOptions() {
let moduleOptions = [];
this.treeNodes.forEach(node => {
this.buildNodePath(node, {path: ''}, moduleOptions);
buildNodePath(node, {path: ''}, moduleOptions);
});
this.moduleOptions = moduleOptions;
},
@ -574,17 +575,7 @@ export default {
this.getMaintainerOptions();
this.getTestOptions();
},
buildNodePath(node, option, moduleOptions) {
//
option.id = node.id;
option.path = option.path + '/' + node.name;
moduleOptions.push(option);
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
this.buildNodePath(node.children[i], {path: option.path}, moduleOptions);
}
}
},
resetForm() {
//
if (this.$refs['caseFrom']) {

View File

@ -36,7 +36,11 @@
default: "view"
},
},
watch: {
treeNodes() {
this.$emit('setTreeNodes', this.treeNodes);
}
},
mounted() {
this.projectId = getCurrentProjectID();
this.list();