高级查询

This commit is contained in:
q4speed 2020-07-13 16:05:01 +08:00
parent c98c8bd340
commit c715a96cb7
22 changed files with 431 additions and 111 deletions

View File

@ -18,4 +18,5 @@ public class QueryAPIReportRequest {
private boolean recent = false; private boolean recent = false;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private Map<String, List<String>> filters; private Map<String, List<String>> filters;
private Map<String, Object> combine;
} }

View File

@ -18,5 +18,5 @@ public class QueryAPITestRequest {
private boolean recent = false; private boolean recent = false;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private Map<String, List<String>> filters; private Map<String, List<String>> filters;
private Map<String, Object> combine;
} }

View File

@ -33,11 +33,9 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.*; import java.io.*;
import java.util.List; import java.util.*;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -304,7 +302,8 @@ public class APITestService {
if (name.endsWith(suffix)) { if (name.endsWith(suffix)) {
request.setName(name.substring(0, name.length() - suffix.length())); request.setName(name.substring(0, name.length() - suffix.length()));
} }
}; }
;
if (isNameExist(request)) { if (isNameExist(request)) {
request.setName(request.getName() + "_" + request.getId().substring(0, 5)); request.setName(request.getName() + "_" + request.getId().substring(0, 5));
} }

View File

@ -8,15 +8,109 @@
<result column="user_name" property="userName"/> <result column="user_name" property="userName"/>
</resultMap> </resultMap>
<sql id="condition">
<choose>
<when test='${object}.operator == "like"'>
like CONCAT('%', #{${object}.value},'%')
</when>
<when test='${object}.operator == "not like"'>
not like CONCAT('%', #{${object}.value},'%')
</when>
<when test='${object}.operator == "in"'>
in
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</when>
<when test='${object}.operator == "not in"'>
not in
<foreach collection="${object}.value" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</when>
<when test='${object}.operator == "between"'>
between #{${object}.value[0]} and #{${object}.value[1]}
</when>
<when test='${object}.operator == "gt"'>
&gt; #{${object}.value}
</when>
<when test='${object}.operator == "lt"'>
&lt; #{${object}.value}
</when>
<when test='${object}.operator == "ge"'>
&gt;= #{${object}.value}
</when>
<when test='${object}.operator == "le"'>
&lt;= #{${object}.value}
</when>
<when test='${object}.operator == "current user"'>
= '${@io.metersphere.commons.utils.SessionUtils@getUserId()}'
</when>
<otherwise>
= #{${object}.value}
</otherwise>
</choose>
</sql>
<sql id="combine">
<if test="${condition}.name != null">
and api_test.name
<include refid="condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.updateTime != null">
and api_test.update_time
<include refid="condition">
<property name="object" value="${condition}.updateTime"/>
</include>
</if>
<if test="${condition}.projectName != null">
and project.name
<include refid="condition">
<property name="object" value="${condition}.projectName"/>
</include>
</if>
<if test="${condition}.createTime != null">
and api_test.create_time
<include refid="condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.status != null">
and api_test.status
<include refid="condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test="${condition}.creator != null">
and api_test.user_id
<include refid="condition">
<property name="object" value="${condition}.creator"/>
</include>
</if>
</sql>
<select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.api.dto.APITestResult"> <select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.api.dto.APITestResult">
select api_test.*, project.name as project_name, user.name as user_name select api_test.*, project.name as project_name, user.name as user_name
from api_test from api_test
left join project on api_test.project_id = project.id left join project on api_test.project_id = project.id
left join user on api_test.user_id = user.id left join user on api_test.user_id = user.id
<where> <where>
<choose>
<!--高级-->
<when test="request.combine != null">
<include refid="combine">
<property name="condition" value="request.combine"/>
</include>
</when>
<!--普通-->
<otherwise>
<if test="request.name != null"> <if test="request.name != null">
and api_test.name like CONCAT('%', #{request.name},'%') and api_test.name like CONCAT('%', #{request.name},'%')
</if> </if>
</otherwise>
</choose>
<if test="request.workspaceId != null"> <if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId} AND project.workspace_id = #{request.workspaceId}
</if> </if>

View File

@ -9,6 +9,55 @@
<result column="user_name" property="userName"/> <result column="user_name" property="userName"/>
</resultMap> </resultMap>
<sql id="condition">
<include refid="io.metersphere.base.mapper.ext.ExtApiTestMapper.condition"/>
</sql>
<sql id="combine">
<if test="${condition}.name != null">
and r.name
<include refid="condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.testName != null">
and t.name
<include refid="condition">
<property name="object" value="${condition}.testName"/>
</include>
</if>
<if test="${condition}.projectName != null">
and project.name
<include refid="condition">
<property name="object" value="${condition}.projectName"/>
</include>
</if>
<if test="${condition}.createTime != null">
and r.create_time
<include refid="condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.status != null">
and r.status
<include refid="condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test="${condition}.triggerMode != null">
and r.trigger_mode
<include refid="condition">
<property name="object" value="${condition}.triggerMode"/>
</include>
</if>
<if test="${condition}.creator != null">
and r.user_id
<include refid="condition">
<property name="object" value="${condition}.creator"/>
</include>
</if>
</sql>
<select id="list" resultMap="BaseResultMap"> <select id="list" resultMap="BaseResultMap">
SELECT t.name AS test_name, SELECT t.name AS test_name,
r.name, r.description, r.id, r.test_id, r.create_time, r.update_time, r.status, r.trigger_mode, r.name, r.description, r.id, r.test_id, r.create_time, r.update_time, r.status, r.trigger_mode,
@ -17,9 +66,20 @@
LEFT JOIN project ON project.id = t.project_id LEFT JOIN project ON project.id = t.project_id
LEFT JOIN user ON user.id = r.user_id LEFT JOIN user ON user.id = r.user_id
<where> <where>
<choose>
<!--高级-->
<when test="request.combine != null">
<include refid="combine">
<property name="condition" value="request.combine"/>
</include>
</when>
<!--普通-->
<otherwise>
<if test="request.name != null"> <if test="request.name != null">
AND r.name like CONCAT('%', #{request.name},'%') and r.name like CONCAT('%', #{request.name},'%')
</if> </if>
</otherwise>
</choose>
<if test="request.projectId != null"> <if test="request.projectId != null">
AND project.id = #{request.projectId} AND project.id = #{request.projectId}
</if> </if>

View File

@ -8,15 +8,69 @@
<result column="user_name" property="userName"/> <result column="user_name" property="userName"/>
</resultMap> </resultMap>
<sql id="condition">
<include refid="io.metersphere.base.mapper.ext.ExtApiTestMapper.condition"/>
</sql>
<sql id="combine">
<if test="${condition}.name != null">
and load_test.name
<include refid="condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.updateTime != null">
and load_test.update_time
<include refid="condition">
<property name="object" value="${condition}.updateTime"/>
</include>
</if>
<if test="${condition}.projectName != null">
and project.name
<include refid="condition">
<property name="object" value="${condition}.projectName"/>
</include>
</if>
<if test="${condition}.createTime != null">
and load_test.create_time
<include refid="condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.status != null">
and load_test.status
<include refid="condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test="${condition}.creator != null">
and load_test.user_id
<include refid="condition">
<property name="object" value="${condition}.creator"/>
</include>
</if>
</sql>
<select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.track.request.testplan.QueryTestPlanRequest"> <select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.track.request.testplan.QueryTestPlanRequest">
select load_test.*, project.name as project_name, user.name as user_name select load_test.*, project.name as project_name, user.name as user_name
from load_test from load_test
left join project on load_test.project_id = project.id left join project on load_test.project_id = project.id
left join user on load_test.user_id = user.id left join user on load_test.user_id = user.id
<where> <where>
<choose>
<!--高级-->
<when test="request.combine != null">
<include refid="combine">
<property name="condition" value="request.combine"/>
</include>
</when>
<!--普通-->
<otherwise>
<if test="request.name != null"> <if test="request.name != null">
and load_test.name like CONCAT('%', #{request.name},'%') and load_test.name like CONCAT('%', #{request.name},'%')
</if> </if>
</otherwise>
</choose>
<if test="request.workspaceId != null"> <if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId} AND project.workspace_id = #{request.workspaceId}
</if> </if>

View File

@ -15,6 +15,55 @@
id, test_id, name, create_time, update_time, status id, test_id, name, create_time, update_time, status
</sql> </sql>
<sql id="condition">
<include refid="io.metersphere.base.mapper.ext.ExtApiTestMapper.condition"/>
</sql>
<sql id="combine">
<if test="${condition}.name != null">
and ltr.name
<include refid="condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.testName != null">
and lt.name
<include refid="condition">
<property name="object" value="${condition}.testName"/>
</include>
</if>
<if test="${condition}.projectName != null">
and project.name
<include refid="condition">
<property name="object" value="${condition}.projectName"/>
</include>
</if>
<if test="${condition}.createTime != null">
and ltr.create_time
<include refid="condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.status != null">
and ltr.status
<include refid="condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test="${condition}.triggerMode != null">
and ltr.trigger_mode
<include refid="condition">
<property name="object" value="${condition}.triggerMode"/>
</include>
</if>
<if test="${condition}.creator != null">
and ltr.user_id
<include refid="condition">
<property name="object" value="${condition}.creator"/>
</include>
</if>
</sql>
<select id="getReportList" resultType="io.metersphere.dto.ReportDTO"> <select id="getReportList" resultType="io.metersphere.dto.ReportDTO">
select ltr.id, ltr.name, ltr.test_id as testId, ltr.description, user.name as userName, project.name as select ltr.id, ltr.name, ltr.test_id as testId, ltr.description, user.name as userName, project.name as
projectName, ltr.trigger_mode, projectName, ltr.trigger_mode,
@ -26,9 +75,20 @@
JOIN project on project.id = lt.project_id JOIN project on project.id = lt.project_id
</if> </if>
<where> <where>
<choose>
<!--高级-->
<when test="reportRequest.combine != null">
<include refid="combine">
<property name="condition" value="reportRequest.combine"/>
</include>
</when>
<!--普通-->
<otherwise>
<if test="reportRequest.name != null"> <if test="reportRequest.name != null">
AND ltr.name like CONCAT('%', #{reportRequest.name},'%') AND ltr.name like CONCAT('%', #{reportRequest.name},'%')
</if> </if>
</otherwise>
</choose>
<if test="reportRequest.workspaceId != null"> <if test="reportRequest.workspaceId != null">
AND workspace_id = #{reportRequest.workspaceId,jdbcType=VARCHAR} AND workspace_id = #{reportRequest.workspaceId,jdbcType=VARCHAR}
</if> </if>

View File

@ -5,12 +5,17 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session; import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import static io.metersphere.commons.constants.SessionConstants.ATTR_USER; import static io.metersphere.commons.constants.SessionConstants.ATTR_USER;
public class SessionUtils { public class SessionUtils {
public static String getUserId() {
return Objects.requireNonNull(getUser()).getId();
}
public static SessionUser getUser() { public static SessionUser getUser() {
try { try {
Subject subject = SecurityUtils.getSubject(); Subject subject = SecurityUtils.getSubject();

View File

@ -14,4 +14,5 @@ public class ReportRequest {
private String workspaceId; private String workspaceId;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private Map<String, List<String>> filters; private Map<String, List<String>> filters;
private Map<String, Object> combine;
} }

View File

@ -13,4 +13,5 @@ public class QueryTestPlanRequest extends TestPlanRequest {
private String workspaceId; private String workspaceId;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private Map<String, List<String>> filters; private Map<String, List<String>> filters;
private Map<String, Object> combine;
} }

View File

@ -4,7 +4,7 @@
<el-card class="table-card" v-loading="result.loading"> <el-card class="table-card" v-loading="result.loading">
<template v-slot:header> <template v-slot:header>
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" <ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search"
:title="$t('api_report.title')" :advanced="advanced" :title="$t('api_report.title')"
:show-create="false"/> :show-create="false"/>
</template> </template>
<el-table :data="tableData" class="table-content" @sort-change="sort" <el-table :data="tableData" class="table-content" @sort-change="sort"
@ -57,7 +57,7 @@
import {_filter, _sort} from "../../../../common/js/utils"; import {_filter, _sort} from "../../../../common/js/utils";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import ReportTriggerModeItem from "../../common/tableItem/ReportTriggerModeItem"; import ReportTriggerModeItem from "../../common/tableItem/ReportTriggerModeItem";
import {REPORT_CONFIGS} from "../../common/components/search/search-components"; import {getReportConfigs} from "../../common/components/search/search-components";
export default { export default {
components: { components: {
@ -68,9 +68,8 @@
data() { data() {
return { return {
result: {}, result: {},
condition: {}, condition: {
advanced: { components: getReportConfigs()
components: REPORT_CONFIGS
}, },
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
@ -99,14 +98,15 @@
}, },
methods: { methods: {
search(advanced) { search(combine) {
console.log(advanced) // combine
let condition = combine ? {combine: combine} : this.condition;
if (this.testId !== 'all') { if (this.testId !== 'all') {
this.condition.testId = this.testId; condition.testId = this.testId;
} }
let url = "/api/report/list/" + this.currentPage + "/" + this.pageSize; let url = "/api/report/list/" + this.currentPage + "/" + this.pageSize;
this.result = this.$post(url, this.condition, response => { this.result = this.$post(url, condition, response => {
let data = response.data; let data = response.data;
this.total = data.itemCount; this.total = data.itemCount;
this.tableData = data.listObject; this.tableData = data.listObject;

View File

@ -4,7 +4,7 @@
<el-card class="table-card" v-loading="result.loading"> <el-card class="table-card" v-loading="result.loading">
<template v-slot:header> <template v-slot:header>
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search" <ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search"
:title="$t('commons.test')" :advanced="advanced" :title="$t('commons.test')"
@create="create" :createTip="$t('load_test.create')"/> @create="create" :createTip="$t('load_test.create')"/>
</template> </template>
<el-table :data="tableData" class="table-content" @sort-change="sort" @row-click="handleView" <el-table :data="tableData" class="table-content" @sort-change="sort" @row-click="handleView"
@ -54,7 +54,7 @@
import MsApiTestStatus from "./ApiTestStatus"; import MsApiTestStatus from "./ApiTestStatus";
import MsTableOperators from "../../common/components/MsTableOperators"; import MsTableOperators from "../../common/components/MsTableOperators";
import {_filter, _sort} from "../../../../common/js/utils"; import {_filter, _sort} from "../../../../common/js/utils";
import {TEST_CONFIGS} from "../../common/components/search/search-components"; import {getTestConfigs} from "../../common/components/search/search-components";
export default { export default {
components: { components: {
@ -64,9 +64,8 @@
data() { data() {
return { return {
result: {}, result: {},
condition: {}, condition: {
advanced: { components: getTestConfigs()
components: TEST_CONFIGS
}, },
projectId: null, projectId: null,
tableData: [], tableData: [],
@ -106,14 +105,15 @@
create() { create() {
this.$router.push('/api/test/create'); this.$router.push('/api/test/create');
}, },
search(advanced) { search(combine) {
console.log(advanced) // combine
let condition = combine ? {combine: combine} : this.condition;
if (this.projectId !== 'all') { if (this.projectId !== 'all') {
this.condition.projectId = this.projectId; condition.projectId = this.projectId;
} }
let url = "/api/list/" + this.currentPage + "/" + this.pageSize let url = "/api/list/" + this.currentPage + "/" + this.pageSize;
this.result = this.$post(url, this.condition, response => { this.result = this.$post(url, condition, response => {
let data = response.data; let data = response.data;
this.total = data.itemCount; this.total = data.itemCount;
this.tableData = data.listObject; this.tableData = data.listObject;

View File

@ -14,7 +14,7 @@
</span> </span>
<span> <span>
<ms-table-search-bar :condition.sync="condition" @change="search" class="search-bar"/> <ms-table-search-bar :condition.sync="condition" @change="search" class="search-bar"/>
<ms-table-adv-search-bar :condition="advanced" @search="search" v-if="advanced"/> <ms-table-adv-search-bar :condition="condition" @search="search" v-if="isCombine"/>
</span> </span>
</el-row> </el-row>
</div> </div>
@ -43,7 +43,6 @@
condition: { condition: {
type: Object type: Object
}, },
advanced: Object,
createTip: { createTip: {
type: String, type: String,
default() { default() {
@ -63,6 +62,11 @@
create() { create() {
this.$emit('create'); this.$emit('create');
} }
},
computed: {
isCombine() {
return this.condition.components !== undefined && this.condition.components.length > 0;
}
} }
} }
</script> </script>

View File

@ -3,10 +3,11 @@
<el-link type="primary" @click="open">{{$t('commons.adv_search.title')}}</el-link> <el-link type="primary" @click="open">{{$t('commons.adv_search.title')}}</el-link>
<el-dialog :title="$t('commons.adv_search.combine')" :visible.sync="visible" width="70%"> <el-dialog :title="$t('commons.adv_search.combine')" :visible.sync="visible" width="70%">
<div> <div>
<div class="search-label">{{$t('commons.adv_search.combine')}}: </div> <!-- 如果有需求再加上-->
<el-select v-model="logic" :placeholder="$t('commons.please_select')" size="small" class="search-combine"> <!-- <div class="search-label">{{$t('commons.adv_search.combine')}}: </div>-->
<el-option v-for="o in options" :key="o.value" :label="o.label" :value="o.value"/> <!-- <el-select v-model="logic" :placeholder="$t('commons.please_select')" size="small" class="search-combine">-->
</el-select> <!-- <el-option v-for="o in options" :key="o.value" :label="o.label" :value="o.value"/>-->
<!-- </el-select>-->
<div class="search-items"> <div class="search-items">
<component class="search-item" v-for="(component, index) in condition.components" :key="index" <component class="search-item" v-for="(component, index) in condition.components" :key="index"
:is="component.name" :component="component"/> :is="component.name" :component="component"/>
@ -47,27 +48,30 @@
methods: { methods: {
search() { search() {
let condition = { let condition = {
logic: this.logic // logic: this.logic //
} }
this.condition.components.forEach(component => { this.condition.components.forEach(component => {
let operator = component.operator.value;
let value = component.value;
if (Array.isArray(component.value)) { if (Array.isArray(component.value)) {
if (component.value.length > 0) { if (component.value.length > 0) {
condition[component.key] = { condition[component.key] = {
operator: component.operator, operator: operator,
value: component.value value: value
} }
} }
} else { } else {
if (component.value !== undefined && component.value !== null) { if (component.value !== undefined && component.value !== null && component.value !== "") {
condition[component.key] = { condition[component.key] = {
operator: component.operator, operator: operator,
value: component.value value: value
} }
} }
} }
}); });
this.$emit('search', condition); this.$emit('search', condition);
this.visible = false;
}, },
open() { open() {
this.visible = true; this.visible = true;

View File

@ -3,7 +3,7 @@
<div class="search-label">{{component.label}}:</div> <div class="search-label">{{component.label}}:</div>
<el-select class="search-operator" v-model="operator" :placeholder="$t('commons.please_select')" size="small" <el-select class="search-operator" v-model="operator" :placeholder="$t('commons.please_select')" size="small"
@change="change" @input="input"> @change="change" @input="input" v-bind="component.operator.props">
<el-option v-for="o in operators" :key="o.value" :label="o.label" :value="o.value"/> <el-option v-for="o in operators" :key="o.value" :label="o.label" :value="o.value"/>
</el-select> </el-select>
@ -19,19 +19,22 @@
props: ['component'], props: ['component'],
data() { data() {
return { return {
operators: this.component.operators || [], operators: this.component.operator.options || [],
operator: (() => { operator: (() => {
if (this.component.operator === undefined && this.component.operators.length > 0) { if (this.component.operator.value === undefined && this.component.operator.options.length > 0) {
this.$emit('input', this.component.operators[0].value); this.$emit('input', this.component.operator.options[0].value);
return this.component.operators[0].value; return this.component.operator.options[0].value;
} else { } else {
this.component.operator return this.component.operator.value
} }
})() })()
} }
}, },
methods: { methods: {
change(value) { change(value) {
if (this.component.operator.change) {
this.component.operator.change(this.component, value)
}
this.$emit('change', value); this.$emit('change', value);
}, },
input(value) { input(value) {
@ -41,8 +44,8 @@
computed: { computed: {
showContent() { showContent() {
return operator => { return operator => {
if (this.component.showContent) { if (this.component.isShow) {
return this.component.showContent(operator); return this.component.isShow(operator);
} }
return true; return true;
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<ms-table-search-component v-model="component.operator" :component="component"> <ms-table-search-component v-model="component.operator.value" :component="component">
<template v-slot="scope"> <template v-slot="scope">
<el-date-picker <el-date-picker
v-model="scope.component.value" v-bind="scope.component.props" v-model="scope.component.value" v-bind="scope.component.props"

View File

@ -1,5 +1,5 @@
<template> <template>
<ms-table-search-component v-model="component.operator" :component="component" @change="change"> <ms-table-search-component v-model="component.operator.value" :component="component" @change="change">
<template v-slot="scope"> <template v-slot="scope">
<el-date-picker v-model="scope.component.value" v-bind="scope.component.props" <el-date-picker v-model="scope.component.value" v-bind="scope.component.props"
:placeholder="$t('commons.date.select_date_time')" size="small" :placeholder="$t('commons.date.select_date_time')" size="small"

View File

@ -1,5 +1,5 @@
<template> <template>
<ms-table-search-component v-model="component.operator" :component="component"> <ms-table-search-component v-model="component.operator.value" :component="component">
<template v-slot="scope"> <template v-slot="scope">
<el-input v-model="scope.component.value" v-bind="props" <el-input v-model="scope.component.value" v-bind="props"
:placeholder="$t('commons.input_content')" size="small"/> :placeholder="$t('commons.input_content')" size="small"/>

View File

@ -1,8 +1,8 @@
<template> <template>
<ms-table-search-component v-model="component.operator" :component="component"> <ms-table-search-component v-model="component.operator.value" :component="component">
<template v-slot="scope"> <template v-slot="scope">
<el-select v-model="scope.component.value" :placeholder="$t('commons.please_select')" size="small" filterable <el-select v-model="scope.component.value" :placeholder="$t('commons.please_select')" size="small"
v-bind="scope.component.props" class="search-select"> filterable v-bind="scope.component.props" class="search-select">
<el-option v-for="op in options" :key="op.value" :label="label(op)" :value="op.value"></el-option> <el-option v-for="op in options" :key="op.value" :label="label(op)" :value="op.value"></el-option>
</el-select> </el-select>
</template> </template>
@ -26,7 +26,10 @@
this.$get(this.component.options.url, response => { this.$get(this.component.options.url, response => {
if (response.data) { if (response.data) {
response.data.forEach(item => { response.data.forEach(item => {
this.options.push({label: item[this.component.options.labelKey], value: item[this.component.options.valueKey]}) this.options.push({
label: item[this.component.options.labelKey],
value: item[this.component.options.valueKey]
})
}) })
} }
}) })

View File

@ -3,6 +3,7 @@ import MsTableSearchDateTimePicker from "./MsTableSearchDateTimePicker";
import MsTableSearchDatePicker from "./MsTableSearchDatePicker"; import MsTableSearchDatePicker from "./MsTableSearchDatePicker";
import MsTableSearchSelect from "./MsTableSearchSelect"; import MsTableSearchSelect from "./MsTableSearchSelect";
import i18n from "../../../../../i18n/i18n"; import i18n from "../../../../../i18n/i18n";
import _ from "lodash"
export default { export default {
MsTableSearchInput, MsTableSearchDatePicker, MsTableSearchDateTimePicker, MsTableSearchSelect MsTableSearchInput, MsTableSearchDatePicker, MsTableSearchDateTimePicker, MsTableSearchSelect
@ -27,23 +28,23 @@ export const OPERATORS = {
}, },
GT: { GT: {
label: i18n.t("commons.adv_search.operators.gt"), label: i18n.t("commons.adv_search.operators.gt"),
value: ">" value: "gt"
}, },
GE: { GE: {
label: i18n.t("commons.adv_search.operators.ge"), label: i18n.t("commons.adv_search.operators.ge"),
value: ">=" value: "ge"
}, },
LT: { LT: {
label: i18n.t("commons.adv_search.operators.lt"), label: i18n.t("commons.adv_search.operators.lt"),
value: "<" value: "lt"
}, },
LE: { LE: {
label: i18n.t("commons.adv_search.operators.le"), label: i18n.t("commons.adv_search.operators.le"),
value: "<=" value: "le"
}, },
EQ: { EQ: {
label: i18n.t("commons.adv_search.operators.equals"), label: i18n.t("commons.adv_search.operators.equals"),
value: "==" value: "eq"
}, },
BETWEEN: { BETWEEN: {
label: i18n.t("commons.adv_search.operators.between"), label: i18n.t("commons.adv_search.operators.between"),
@ -56,48 +57,61 @@ export const OPERATORS = {
} }
export const NAME = { export const NAME = {
key: "name", key: "name", // 返回结果Map的key
name: 'MsTableSearchInput', name: 'MsTableSearchInput', // Vue控件名称
label: i18n.t('commons.name'), label: i18n.t('commons.name'), // 显示名称
operators: [OPERATORS.LIKE, OPERATORS.NOT_LIKE], operator: { // 运算符设置
value: OPERATORS.LIKE.value, // 如果未设置value初始值则value初始值为options[0]
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] // 运算符候选项
},
} }
export const UPDATE_TIME = { export const UPDATE_TIME = {
key: "updateTime", key: "updateTime",
name: 'MsTableSearchDateTimePicker', name: 'MsTableSearchDateTimePicker',
label: i18n.t('commons.update_time'), label: i18n.t('commons.update_time'),
operators: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.GE, OPERATORS.LT, OPERATORS.LE, OPERATORS.EQ], operator: {
options: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.GE, OPERATORS.LT, OPERATORS.LE, OPERATORS.EQ]
},
} }
export const PROJECT_NAME = { export const PROJECT_NAME = {
key: "projectName", key: "projectName",
name: 'MsTableSearchInput', name: 'MsTableSearchInput',
label: i18n.t('commons.adv_search.project'), label: i18n.t('commons.adv_search.project'),
operators: [OPERATORS.LIKE, OPERATORS.NOT_LIKE], operator: {
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE]
},
} }
export const TEST_NAME = { export const TEST_NAME = {
key: "testName", key: "testName",
name: 'MsTableSearchInput', name: 'MsTableSearchInput',
label: i18n.t('commons.adv_search.test'), label: i18n.t('commons.adv_search.test'),
operators: [OPERATORS.LIKE, OPERATORS.NOT_LIKE], operator: {
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE]
},
} }
export const CREATE_TIME = { export const CREATE_TIME = {
key: "createTime", key: "createTime",
name: 'MsTableSearchDateTimePicker', name: 'MsTableSearchDateTimePicker',
label: i18n.t('commons.create_time'), label: i18n.t('commons.create_time'),
operators: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.GE, OPERATORS.LT, OPERATORS.LE, OPERATORS.EQ], operator: {
options: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.GE, OPERATORS.LT, OPERATORS.LE, OPERATORS.EQ]
},
} }
export const STATUS = { export const STATUS = {
key: "status", key: "status",
name: 'MsTableSearchSelect', name: 'MsTableSearchSelect',
label: i18n.t('commons.status'), label: i18n.t('commons.status'),
operators: [OPERATORS.IN, OPERATORS.NOT_IN], operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [ options: [
{label: "Saved", value: "Saved"}, {label: "Starting", value: "Starting"}, {label: "Saved", value: "Saved"}, {label: "Starting", value: "Starting"},
{label: "Running", value: "Running"}, {label: "Reporting", value: "Reporting"}, {label: "Running", value: "Running"}, {label: "Reporting", value: "Reporting"},
{label: "Completed", value: "Completed"}, {label: "Error", value: "Error"} {label: "Completed", value: "Completed"}, {label: "Error", value: "Error"}
], ],
props: { props: { // 尾部控件的props一般为element ui控件的props
multiple: true multiple: true
} }
} }
@ -106,8 +120,15 @@ export const CREATOR = {
key: "creator", key: "creator",
name: 'MsTableSearchSelect', name: 'MsTableSearchSelect',
label: i18n.t('api_test.creator'), label: i18n.t('api_test.creator'),
operators: [OPERATORS.IN, OPERATORS.NOT_IN, OPERATORS.CURRENT_USER], operator: {
options: { options: [OPERATORS.IN, OPERATORS.NOT_IN, OPERATORS.CURRENT_USER],
change: function (component, value) { // 运算符change事件
if (value === OPERATORS.CURRENT_USER.value) {
component.value = value;
}
}
},
options: { // 异步获取候选项
url: "/user/list", url: "/user/list",
labelKey: "name", labelKey: "name",
valueKey: "id", valueKey: "id",
@ -118,7 +139,7 @@ export const CREATOR = {
props: { props: {
multiple: true multiple: true
}, },
showContent: operator => { isShow: operator => {
return operator !== OPERATORS.CURRENT_USER.value; return operator !== OPERATORS.CURRENT_USER.value;
} }
} }
@ -127,7 +148,9 @@ export const TRIGGER_MODE = {
key: "triggerMode", key: "triggerMode",
name: 'MsTableSearchSelect', name: 'MsTableSearchSelect',
label: i18n.t('commons.trigger_mode.name'), label: i18n.t('commons.trigger_mode.name'),
operators: [OPERATORS.IN, OPERATORS.NOT_IN], operator: {
options: [OPERATORS.IN, OPERATORS.NOT_IN]
},
options: [ options: [
{label: i18n.t("commons.trigger_mode.manual"), value: "MANUAL"}, {label: i18n.t("commons.trigger_mode.manual"), value: "MANUAL"},
{label: i18n.t("commons.trigger_mode.schedule"), value: "SCHEDULE"}, {label: i18n.t("commons.trigger_mode.schedule"), value: "SCHEDULE"},
@ -138,6 +161,10 @@ export const TRIGGER_MODE = {
} }
} }
export const TEST_CONFIGS = [NAME, UPDATE_TIME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR] export const getTestConfigs = () => {
return _.cloneDeep([NAME, UPDATE_TIME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR]);
}
export const REPORT_CONFIGS = [NAME, TEST_NAME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE] export const getReportConfigs = () => {
return _.cloneDeep([NAME, TEST_NAME, PROJECT_NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE]);
}

View File

@ -3,17 +3,9 @@
<ms-main-container> <ms-main-container>
<el-card class="table-card" v-loading="result.loading"> <el-card class="table-card" v-loading="result.loading">
<template v-slot:header> <template v-slot:header>
<div> <ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="search"
<el-row type="flex" justify="space-between" align="middle"> :title="$t('commons.report')"
<span class="title">{{$t('commons.report')}}</span> :show-create="false"/>
<span class="search">
<el-input type="text" size="small" :placeholder="$t('report.search_by_name')"
prefix-icon="el-icon-search"
maxlength="60"
v-model="condition.name" @change="search" clearable/>
</span>
</el-row>
</div>
</template> </template>
<el-table :data="tableData" class="test-content" <el-table :data="tableData" class="test-content"
@ -91,10 +83,13 @@
import {_filter, _sort} from "../../../../common/js/utils"; import {_filter, _sort} from "../../../../common/js/utils";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton"; import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import ReportTriggerModeItem from "../../common/tableItem/ReportTriggerModeItem"; import ReportTriggerModeItem from "../../common/tableItem/ReportTriggerModeItem";
import {getReportConfigs} from "../../common/components/search/search-components";
import MsTableHeader from "../../common/components/MsTableHeader";
export default { export default {
name: "PerformanceTestReport", name: "PerformanceTestReport",
components: { components: {
MsTableHeader,
ReportTriggerModeItem, ReportTriggerModeItem,
MsTableOperatorButton, MsPerformanceReportStatus, MsTablePagination, MsContainer, MsMainContainer}, MsTableOperatorButton, MsPerformanceReportStatus, MsTablePagination, MsContainer, MsMainContainer},
created: function () { created: function () {
@ -105,7 +100,9 @@
result: {}, result: {},
queryPath: "/performance/report/list/all", queryPath: "/performance/report/list/all",
deletePath: "/performance/report/delete/", deletePath: "/performance/report/delete/",
condition: {}, condition: {
components: getReportConfigs()
},
projectId: null, projectId: null,
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
@ -129,15 +126,19 @@
} }
}, },
methods: { methods: {
initTableData() { initTableData(combine) {
this.result = this.$post(this.buildPagePath(this.queryPath), this.condition, response => { let condition = combine ? {combine: combine} : this.condition;
if (this.testId !== 'all') {
condition.testId = this.testId;
}
this.result = this.$post(this.buildPagePath(this.queryPath), condition, response => {
let data = response.data; let data = response.data;
this.total = data.itemCount; this.total = data.itemCount;
this.tableData = data.listObject; this.tableData = data.listObject;
}); });
}, },
search() { search(combine) {
this.initTableData(); this.initTableData(combine);
}, },
buildPagePath(path) { buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize; return path + "/" + this.currentPage + "/" + this.pageSize;

View File

@ -82,6 +82,7 @@
import MsTableOperators from "../../common/components/MsTableOperators"; import MsTableOperators from "../../common/components/MsTableOperators";
import {_filter, _sort} from "../../../../common/js/utils"; import {_filter, _sort} from "../../../../common/js/utils";
import MsTableHeader from "../../common/components/MsTableHeader"; import MsTableHeader from "../../common/components/MsTableHeader";
import {getTestConfigs} from "../../common/components/search/search-components";
export default { export default {
components: { components: {
@ -98,7 +99,9 @@
result: {}, result: {},
queryPath: "/performance/list", queryPath: "/performance/list",
deletePath: "/performance/delete", deletePath: "/performance/delete",
condition: {}, condition: {
components: getTestConfigs()
},
projectId: null, projectId: null,
tableData: [], tableData: [],
multipleSelection: [], multipleSelection: [],
@ -140,20 +143,20 @@
this.initTableData(); this.initTableData();
}, },
methods: { methods: {
initTableData() { initTableData(combine) {
let condition = combine ? {combine: combine} : this.condition;
if (this.projectId !== 'all') { if (this.projectId !== 'all') {
this.condition.projectId = this.projectId; condition.projectId = this.projectId;
} }
this.result = this.$post(this.buildPagePath(this.queryPath), this.condition, response => { this.result = this.$post(this.buildPagePath(this.queryPath), condition, response => {
let data = response.data; let data = response.data;
this.total = data.itemCount; this.total = data.itemCount;
this.tableData = data.listObject; this.tableData = data.listObject;
}); });
}, },
search() { search(combine) {
this.initTableData(); this.initTableData(combine);
}, },
buildPagePath(path) { buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize; return path + "/" + this.currentPage + "/" + this.pageSize;