refactor(高级搜索): 优化根据所属模块搜索

This commit is contained in:
shiziyuan9527 2022-07-12 18:36:23 +08:00 committed by shiziyuan9527
parent cabd97b96f
commit 3eea5fbd4c
7 changed files with 273 additions and 5 deletions

View File

@ -208,6 +208,12 @@
<property name="object" value="${condition}.module"/> <property name="object" value="${condition}.module"/>
</include> </include>
</if> </if>
<if test="${condition}.moduleIds != null">
and api_definition.module_id
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
<property name="object" value="${condition}.moduleIds"/>
</include>
</if>
<if test="${condition}.caseCount != null"> <if test="${condition}.caseCount != null">
and api_definition.case_total and api_definition.case_total
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition"> <include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">

View File

@ -162,6 +162,12 @@
<property name="object" value="${condition}.module"/> <property name="object" value="${condition}.module"/>
</include> </include>
</if> </if>
<if test="${condition}.moduleIds != null">
and api_scenario.api_scenario_module_id
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
<property name="object" value="${condition}.moduleIds"/>
</include>
</if>
<if test="${condition}.stepCount != null"> <if test="${condition}.stepCount != null">
and api_scenario.step_total and api_scenario.step_total
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition"> <include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">

View File

@ -34,6 +34,12 @@
<property name="object" value="${condition}.module"/> <property name="object" value="${condition}.module"/>
</include> </include>
</if> </if>
<if test="${condition}.moduleIds != null">
and test_case.node_id
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">
<property name="object" value="${condition}.moduleIds"/>
</include>
</if>
<if test="${condition}.priority != null"> <if test="${condition}.priority != null">
and test_case.priority and test_case.priority
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition"> <include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.condition">

View File

@ -2,6 +2,7 @@
<span> <span>
<span> <span>
<ms-search <ms-search
v-if="visibleSearch"
:condition.sync="condition" :condition.sync="condition"
:base-search-tip="$t('commons.search_by_id_name_tag_path')" :base-search-tip="$t('commons.search_by_id_name_tag_path')"
:base-search-width="260" :base-search-width="260"
@ -431,6 +432,7 @@ export default {
projectName: "", projectName: "",
versionEnable: false, versionEnable: false,
isFirstInitTable: true, isFirstInitTable: true,
visibleSearch: true
}; };
}, },
props: { props: {
@ -517,6 +519,7 @@ export default {
this.editApi(response.data); this.editApi(response.data);
}); });
} }
this.setAdvSearchParam();
}, },
watch: { watch: {
selectNodeIds() { selectNodeIds() {
@ -535,6 +538,9 @@ export default {
initCondition(this.condition, false); initCondition(this.condition, false);
this.closeCaseModel(); this.closeCaseModel();
this.initTable(true); this.initTable(true);
this.visibleSearch = false;
this.$nextTick(() => (this.visibleSearch = true));
this.setAdvSearchParam();
}, },
currentVersion() { currentVersion() {
this.condition.versionId = this.currentVersion; this.condition.versionId = this.currentVersion;
@ -557,6 +563,12 @@ export default {
}, },
}, },
methods: { methods: {
setAdvSearchParam() {
let comp = this.condition.components.find(c => c.key === 'moduleIds');
if (comp) {
comp.options.params = {protocol: this.currentProtocol};
}
},
getProtocolFilter() { getProtocolFilter() {
this.methodFilters = getProtocolFilter(this.currentProtocol); this.methodFilters = getProtocolFilter(this.currentProtocol);
}, },

View File

@ -172,8 +172,15 @@ export default {
if (!this.isInit) { if (!this.isInit) {
this.isInit = true; this.isInit = true;
this.init(); this.init();
} else {
this.refreshComponentOption();
} }
}, },
refreshComponentOption() {
//
let comps = this.optional.components.filter(cp => cp.init && cp.init instanceof Function);
comps.forEach(comp => comp.init());
},
addFilter() { addFilter() {
const index = _findIndexByKey(this.optional.components, this.nullFilterKey); const index = _findIndexByKey(this.optional.components, this.nullFilterKey);
if (index > -1) { if (index > -1) {

View File

@ -0,0 +1,191 @@
<template>
<ms-table-search-component
v-model="component.operator.value"
:component="component"
v-on="$listeners"
v-bind="$attrs">
<template v-slot="scope">
<el-select
v-loading="result.loading"
v-model="scope.component.value"
:placeholder="$t('commons.please_select')"
:popper-append-to-body="false"
@remove-tag="removeTreeTag"
@change="changeTreeTag"
class="search-select"
size="small"
collapse-tags
multiple>
<div class="search-div">
<el-option
v-for="item in treeOptions"
class="search-select-option"
:label="item.name"
:value="item.id"
:key="item.id">
</el-option>
<el-input
size="small"
class="search-input"
:placeholder="$t('api_test.request.parameters_mock_filter_tips')"
v-model="filterText">
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
<el-tree
:data="treeNodes"
:filter-node-method="filterNode"
@check="handleCheckChange"
default-expand-all
show-checkbox
node-key="id"
class="search-tree"
ref="tree">
</el-tree>
</div>
</el-select>
</template>
</ms-table-search-component>
</template>
<script>
import MsTableSearchComponent from "@/business/components/common/components/search/MsTableSearchComponet";
import MsNodeTree from "@/business/components/track/common/NodeTree";
import {cloneDeep} from "lodash";
export default {
name: "MsTableSearchNodeTree",
components: {
MsTableSearchComponent,
MsNodeTree
},
props: ['component'],
data() {
return {
treeOptions: [],
result: {},
treeNodes: [],
filterText: '',
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
}
},
created() {
this.init();
// component.init()
this.component.init = this.reload;
},
methods: {
init() {
this.treeOptions = [];
let options = cloneDeep(this.component.options);
let {url, params, type} = options;
if (!url) return;
if (type === "POST") {
this.result = this.$post(url, params || {}, response => {
this.handleTreeNodes(response.data);
});
return;
}
if (type === "GET") {
this.result = this.$get(this.handleGETUrl(url, params), response => {
this.handleTreeNodes(response.data);
});
}
},
reload() {
//
this.init();
//
this.resetChecked();
},
resetChecked() {
if (this.component.value && this.component.value instanceof Array) {
for (let i = this.component.value.length - 1; i >= 0; i--) {
let node = this.$refs.tree.getNode(this.component.value[i]);
if (!node) {
this.component.value.splice(i, 1);
}
}
}
this.changeTreeTag();
},
handleGETUrl(url, params) {
if (!params) {
return url;
}
for (let p in params) {
if (params.hasOwnProperty(p) && params[p]) {
url = url + "/" + params[p];
}
}
return url;
},
handleTreeNodes(data) {
if (!data) {
return;
}
this.treeNodes = data;
this.treeNodes.forEach(node => {
node.name = node.name === '未规划用例' ? this.$t('api_test.unplanned_case') : node.name;
this.buildTree(node);
});
},
buildTree(node) {
this.treeOptions.push(node);
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
this.buildTree(node.children[i]);
}
}
},
handleCheckChange(data, curData) {
const {checkedKeys} = curData;
this.component.value = checkedKeys;
},
changeTreeTag() {
this.$refs.tree.setCheckedKeys(this.component.value);
},
removeTreeTag(data) {
this.$refs.tree.setChecked(data, false, false);
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
}
}
</script>
<style scoped>
.search-select {
display: inline-block;
width: 100%;
}
.search-div {
max-height: 700px;
}
.search-input {
padding: 0;
margin-top: -5px;
}
.search-tree {
margin-top: 6px;
}
.search-select-option {
display: none;
}
.search-input >>> .el-input__inner {
border-radius: 2px;
border-color: #e1dee5;
}
</style>

View File

@ -5,6 +5,7 @@ import MsTableSearchSelect from "./MsTableSearchSelect";
import MsTableSearchInputNumber from "@/business/components/common/components/search/MsTableSearchInputNumber"; import MsTableSearchInputNumber from "@/business/components/common/components/search/MsTableSearchInputNumber";
import {getCurrentProjectID} from "@/common/js/utils"; import {getCurrentProjectID} from "@/common/js/utils";
import MsTableSearchMix from "@/business/components/common/components/search/MsTableSearchMix"; import MsTableSearchMix from "@/business/components/common/components/search/MsTableSearchMix";
import MsTableSearchNodeTree from "@/business/components/common/components/search/MsTableSearchNodeTree";
export default { export default {
MsTableSearchInput, MsTableSearchInput,
@ -12,7 +13,8 @@ export default {
MsTableSearchDateTimePicker, MsTableSearchDateTimePicker,
MsTableSearchSelect, MsTableSearchSelect,
MsTableSearchInputNumber, MsTableSearchInputNumber,
MsTableSearchMix MsTableSearchMix,
MsTableSearchNodeTree
} }
export const OPERATORS = { export const OPERATORS = {
@ -665,6 +667,44 @@ export const ID = {
} }
} }
function _getModuleTree(options) {
return {
key: "moduleIds",
name: 'MsTableSearchNodeTree',
label: "test_track.case.module",
operator: {
value: OPERATORS.IN.value,
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: options,
init: undefined // 高级搜索框非首次打开时会执行该函数在组件首次created时给其赋值
}
}
export const TEST_CASE_MODULE_TREE = _getModuleTree({
url: "/case/node/list/" + getCurrentProjectID(),
type: "POST",
params: {} // 赋值时注意顺序
})
export const API_MODULE_TREE = _getModuleTree({
url: "/api/module/list/" + getCurrentProjectID(),
type: "GET",
params: {}
})
export const SCENARIO_MODULE_TREE = _getModuleTree({
url: "/api/automation/module/list/" + getCurrentProjectID(),
type: "GET",
params: {}
})
export const UI_MODULE_TREE = _getModuleTree({
url: "/ui/scenario/module/list/" + getCurrentProjectID(),
type: "GET",
params: {}
})
export const TEST_CONFIGS = [ID, NAME, UPDATE_TIME, CREATE_TIME, STATUS, CREATOR, FOLLOW_PEOPLE]; export const TEST_CONFIGS = [ID, NAME, UPDATE_TIME, CREATE_TIME, STATUS, CREATOR, FOLLOW_PEOPLE];
export const PROJECT_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, CREATOR]; export const PROJECT_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, CREATOR];
@ -673,21 +713,21 @@ export const REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, STATUS, CREATOR, TR
export const REPORT_CASE_CONFIGS = [NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE]; export const REPORT_CASE_CONFIGS = [NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE];
export const UI_REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, UI_REPORT_STATUS, CREATOR, TRIGGER_MODE]; export const UI_REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, UI_REPORT_STATUS, CREATOR, TRIGGER_MODE, UI_MODULE_TREE];
// 测试跟踪-测试用例 列表 // 测试跟踪-测试用例 列表
export const TEST_CASE_CONFIGS = [ID, NAME, TAGS, MODULE, CREATE_TIME, UPDATE_TIME, CREATOR, CASE_REVIEW_STATUS, FOLLOW_PEOPLE, CASE_DEMAND]; export const TEST_CASE_CONFIGS = [ID, NAME, TAGS, TEST_CASE_MODULE_TREE, CREATE_TIME, UPDATE_TIME, CREATOR, CASE_REVIEW_STATUS, FOLLOW_PEOPLE, CASE_DEMAND];
export const TEST_PLAN_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, PRINCIPAL, TEST_PLAN_STATUS, STAGE, TAGS, FOLLOW_PEOPLE, ACTUAL_START_TIME, ACTUAL_END_TIME, PLAN_START_TIME, PLAN_END_TIME]; export const TEST_PLAN_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, PRINCIPAL, TEST_PLAN_STATUS, STAGE, TAGS, FOLLOW_PEOPLE, ACTUAL_START_TIME, ACTUAL_END_TIME, PLAN_START_TIME, PLAN_END_TIME];
// 测试跟踪 测试评审列表 // 测试跟踪 测试评审列表
export const TEST_REVIEW = [NAME, CREATOR, TAGS, TEST_PLAN_STATUS, FOLLOW_PEOPLE, CREATE_TIME, UPDATE_TIME, END_TIME]; export const TEST_REVIEW = [NAME, CREATOR, TAGS, TEST_PLAN_STATUS, FOLLOW_PEOPLE, CREATE_TIME, UPDATE_TIME, END_TIME];
export const API_DEFINITION_CONFIGS = [ID, NAME, API_METHOD, API_PATH, API_STATUS, TAGS, UPDATE_TIME, CREATE_TIME, API_PRINCIPAL, ISREFERENCE, MODULE, FOLLOW_PEOPLE, CASE_COUNT]; export const API_DEFINITION_CONFIGS = [ID, NAME, API_METHOD, API_PATH, API_STATUS, TAGS, UPDATE_TIME, CREATE_TIME, API_PRINCIPAL, ISREFERENCE, API_MODULE_TREE, FOLLOW_PEOPLE, CASE_COUNT];
export const API_CASE_CONFIGS = [ID, NAME, PRIORITY, TAGS, API_CASE_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, ISREFERENCE, FOLLOW_PEOPLE, API_PATH]; export const API_CASE_CONFIGS = [ID, NAME, PRIORITY, TAGS, API_CASE_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, ISREFERENCE, FOLLOW_PEOPLE, API_PATH];
export const API_SCENARIO_CONFIGS = [ID, NAME, PRIORITY, TAGS, API_SCENARIO_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, FOLLOW_PEOPLE, STEP_COUNT, MODULE, API_STATUS]; export const API_SCENARIO_CONFIGS = [ID, NAME, PRIORITY, TAGS, API_SCENARIO_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, FOLLOW_PEOPLE, STEP_COUNT, SCENARIO_MODULE_TREE, API_STATUS];
export const TEST_PLAN_REPORT_CONFIGS = [NAME, TEST_PLAN_NAME, CREATOR, CREATE_TIME, TEST_PLAN_TRIGGER_MODE, TEST_PLAN_REPORT_STATUS]; export const TEST_PLAN_REPORT_CONFIGS = [NAME, TEST_PLAN_NAME, CREATOR, CREATE_TIME, TEST_PLAN_TRIGGER_MODE, TEST_PLAN_REPORT_STATUS];