This commit is contained in:
parent
0a57f08fc2
commit
31a1c69319
|
@ -7,7 +7,6 @@
|
|||
|
||||
[class*="sc-icon-"] {
|
||||
font-family: "scicon" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
|
|
@ -1,251 +1,284 @@
|
|||
<!--
|
||||
* @Descripttion: 过滤器V2
|
||||
* @version: 2.0
|
||||
* @Author: sakuya
|
||||
* @Date: 2021年7月30日14:48:41
|
||||
* @LastEditors:
|
||||
* @LastEditTime:
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="sc-filterBar">
|
||||
<div class="sc-filterBar-scrollbar" ref="scFilterBarScrollbar">
|
||||
<div class="sc-filterBar-tags">
|
||||
<div class="filter-tag" v-for="item in filter" :key="item.keyLabel"><span class="field">{{item.keyLabel}}</span><span class="value">{{item.valueLabel}}<i @click="handleClose(item)" class="el-icon-close"></i></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<el-popover title="新建过滤器" :width="550" trigger="manual" v-model:visible="isadd">
|
||||
<template #reference>
|
||||
<el-button class="button-new-tag" size="small" type="primary" @click="openAdd" icon="el-icon-zoom-in"></el-button>
|
||||
<el-badge :value="filterObjLength" type="danger" :hidden="filterObjLength<=0">
|
||||
<el-button size="small" icon="sc-icon-filter-fill" @click="openFilter"></el-button>
|
||||
</el-badge>
|
||||
<el-drawer title="过滤器" v-model="drawer" :size="650" append-to-body>
|
||||
<el-container v-loading="saveLoading">
|
||||
<el-main style="padding:0">
|
||||
<el-tabs class="root">
|
||||
<el-tab-pane lazy>
|
||||
<template #label>
|
||||
<div class="tabs-label">过滤项</div>
|
||||
</template>
|
||||
<el-form ref="ruleForm" :model="addFilterForm" :rules="addFilterRules" label-width="80px" style="padding-top:10px;">
|
||||
<el-form-item label="字段" prop="field">
|
||||
<el-select v-model="addFilterForm.field" placeholder="请选择" value-key="value" @change="fieldChange" filterable clearable>
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item" :disabled="item.disabled">
|
||||
</el-option>
|
||||
<el-scrollbar>
|
||||
<div class="sc-filter-main">
|
||||
<h2>设置过滤条件</h2>
|
||||
<div v-if="filter.length<=0" class="nodata">
|
||||
没有默认过滤条件,请点击增加过滤项
|
||||
</div>
|
||||
<table v-else>
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col width="140">
|
||||
<col width="120">
|
||||
<col>
|
||||
<col width="40">
|
||||
</colgroup>
|
||||
<tr v-for="(item,index) in filter" :key="index">
|
||||
<td>
|
||||
<el-tag size="medium">{{index+1}}</el-tag>
|
||||
</td>
|
||||
<td>
|
||||
<el-select v-model="item.field" placeholder="过滤字段" filterable @change="fieldChange(item)">
|
||||
<el-option v-for="field in fields" :key="field.value" :label="field.label" :value="field"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="值" prop="value">
|
||||
|
||||
<el-input v-if="!addFilterForm.field.type" v-model="addFilterForm.value" placeholder="请先选择过滤字段" disabled style="width: 400px;"></el-input>
|
||||
|
||||
<el-input v-if="addFilterForm.field.type=='text'" v-model="addFilterForm.value" placeholder="请输入内容" clearable style="width: 400px;"></el-input>
|
||||
|
||||
<el-select v-if="addFilterForm.field.type=='select'" v-model="addFilterForm.value" :loading="selectLoading" :multiple="addFilterForm.field.extend?addFilterForm.field.extend.multiple:false" :remote="addFilterForm.field.extend?addFilterForm.field.extend.remote:false" @visible-change="visibleChange($event)" :remote-method="remoteMethod" filterable clearable placeholder="请选择/输入关键词" style="width: 400px;">
|
||||
<el-option v-for="item in addFilterForm.field.extend.data" :key="item.value" value-key="value" :label="item.label" :value="item"></el-option>
|
||||
</td>
|
||||
<td>
|
||||
<el-select v-model="item.operator" placeholder="运算符">
|
||||
<el-option v-for="ope in operator" :key="ope.value" :label="ope.label" :value="ope.value"></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-date-picker v-if="addFilterForm.field.type=='date'" v-model="addFilterForm.value" type="date" placeholder="请选择日期" style="width: 400px;"></el-date-picker>
|
||||
<el-date-picker v-if="addFilterForm.field.type=='daterange'" v-model="addFilterForm.value" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" placeholder="请选择日期" style="width: 400px;"></el-date-picker>
|
||||
<el-date-picker v-if="addFilterForm.field.type=='datetime'" v-model="addFilterForm.value" type="datetime" placeholder="请选择日期" style="width: 400px;"></el-date-picker>
|
||||
<el-date-picker v-if="addFilterForm.field.type=='datetimerange'" v-model="addFilterForm.value" type="datetimerange" :default-time="defaultTime" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" placeholder="请选择日期" style="width: 400px;"></el-date-picker>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item >
|
||||
<el-button class="button-new-tag" type="primary" @click="ok" icon="el-icon-search">立即过滤</el-button>
|
||||
<el-button class="button-new-tag" @click="cancel">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-popover>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<el-input v-if="!item.field.type" v-model="item.value" placeholder="请选择过滤字段" disabled></el-input>
|
||||
<!-- 输入框 -->
|
||||
<el-input v-if="item.field.type=='text'" v-model="item.value" :placeholder="item.field.placeholder||'请输入'"></el-input>
|
||||
<!-- 下拉框 -->
|
||||
<el-select v-if="item.field.type=='select'" v-model="item.value" :placeholder="item.field.placeholder||'请选择'" filterable :multiple="item.field.extend.multiple" :loading="item.selectLoading" @visible-change="visibleChange($event, item)" :remote="item.field.extend.remote" :remote-method="(query)=>{remoteMethod(query, item)}">
|
||||
<el-option v-for="field in item.field.extend.data" :key="field.value" :label="field.label" :value="field.value"></el-option>
|
||||
</el-select>
|
||||
<!-- 日期 -->
|
||||
<el-date-picker v-if="item.field.type=='date'" v-model="item.value" type="date" value-format="YYYY-MM-DD" :placeholder="item.field.placeholder||'请选择日期'" style="width: 100%;"></el-date-picker>
|
||||
<!-- 日期范围 -->
|
||||
<el-date-picker v-if="item.field.type=='daterange'" v-model="item.value" type="daterange" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 100%;"></el-date-picker>
|
||||
<!-- 日期时间 -->
|
||||
<el-date-picker v-if="item.field.type=='datetime'" v-model="item.value" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" :placeholder="item.field.placeholder||'请选择日期'" style="width: 100%;"></el-date-picker>
|
||||
<!-- 日期时间范围 -->
|
||||
<el-date-picker v-if="item.field.type=='datetimerange'" v-model="item.value" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 100%;"></el-date-picker>
|
||||
<!-- 开关 -->
|
||||
<el-switch v-if="item.field.type=='switch'" v-model="item.value"></el-switch>
|
||||
</td>
|
||||
<td>
|
||||
<i class="el-icon-delete del" @click="delFilter(index)"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<el-button type="text" icon="el-icon-plus" @click="addFilter">增加过滤项</el-button>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane lazy>
|
||||
<template #label>
|
||||
<div class="tabs-label">常用</div>
|
||||
</template>
|
||||
<el-scrollbar>
|
||||
<my ref="my" :data="myFilter" :filterName="filterName" @selectMyfilter="selectMyfilter"></my>
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<el-button type="primary" @click="ok" :disabled="filter.length<=0">立即过滤</el-button>
|
||||
<el-button type="primary" plain @click="saveMy" :disabled="filter.length<=0">另存为常用</el-button>
|
||||
<el-button @click="clear">清空过滤</el-button>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/config/filterBar";
|
||||
import my from './my'
|
||||
|
||||
export default {
|
||||
name: 'filterBar',
|
||||
components: {
|
||||
my
|
||||
},
|
||||
props: {
|
||||
options: { type: Object, default: () => {} },
|
||||
defaultFilter: { type: Object, default: () => {} }
|
||||
filterName: { type: String, default: "" },
|
||||
options: { type: Object, default: () => {} }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultTime: [
|
||||
new Date(2000, 1, 1, 0, 0, 0),
|
||||
new Date(2000, 2, 1, 23, 59, 59)
|
||||
],
|
||||
isadd: false,
|
||||
selectLoading: false,
|
||||
addFilterForm: {
|
||||
field: '',
|
||||
value: ''
|
||||
drawer: false,
|
||||
operator: config.operator,
|
||||
fields: this.options,
|
||||
filter: [],
|
||||
myFilter: [],
|
||||
filterObjLength: 0,
|
||||
saveLoading: false
|
||||
}
|
||||
},
|
||||
addFilterRules: {
|
||||
field: [{required: true, message: '请选择过滤字段', trigger: 'change'}],
|
||||
value: [{required: true, message: '过滤值不能为空', trigger: 'change'}]
|
||||
},
|
||||
filter: []
|
||||
computed: {
|
||||
filterObj(){
|
||||
const obj = {}
|
||||
this.filter.forEach((item) => {
|
||||
obj[item.field.value] = `${item.value}${config.separator}${item.operator}`
|
||||
})
|
||||
return obj
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.filter = this.defaultFilter || [];
|
||||
this.scrollInit()
|
||||
//默认显示的过滤项
|
||||
this.fields.forEach((item) => {
|
||||
if(item.selected){
|
||||
this.filter.push({
|
||||
field: item,
|
||||
operator: item.operator || 'include',
|
||||
value: ''
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
openAdd(){
|
||||
if(this.isadd){
|
||||
this.isadd = false;
|
||||
}else{
|
||||
this.isadd = true;
|
||||
//打开过滤器
|
||||
openFilter(){
|
||||
this.drawer = true
|
||||
},
|
||||
//增加过滤项
|
||||
addFilter(){
|
||||
if(this.fields.length<=0){
|
||||
this.$message.warning('无过滤项');
|
||||
return false
|
||||
}
|
||||
|
||||
//判断已有数据,禁用处理
|
||||
for(let f of this.options){
|
||||
const _f = this.filter.find((item)=>{return item.key === f.value});
|
||||
if(_f){
|
||||
f.disabled = true
|
||||
}else{
|
||||
f.disabled = false
|
||||
const filterNum = this.fields[this.filter.length] || this.fields[0]
|
||||
this.filter.push({
|
||||
field: filterNum,
|
||||
operator: filterNum.operator || 'include',
|
||||
value: ''
|
||||
})
|
||||
},
|
||||
//删除过滤项
|
||||
delFilter(index){
|
||||
this.filter.splice(index, 1)
|
||||
},
|
||||
//过滤项字段变更事件
|
||||
fieldChange(tr){
|
||||
let oldType = tr.field.type
|
||||
tr.field.type = ''
|
||||
this.$nextTick(() => {
|
||||
tr.field.type = oldType
|
||||
})
|
||||
tr.operator = tr.field.operator || 'include'
|
||||
tr.value = ''
|
||||
},
|
||||
//下拉框显示事件处理异步
|
||||
async visibleChange(isopen, item){
|
||||
if(isopen && item.field.extend.request && !item.field.extend.remote){
|
||||
item.selectLoading = true;
|
||||
try {
|
||||
var data = await item.field.extend.request()
|
||||
}catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
item.field.extend.data = data;
|
||||
item.selectLoading = false;
|
||||
}
|
||||
},
|
||||
async remoteMethod(query){
|
||||
//下拉框显示事件处理异步搜索
|
||||
async remoteMethod(query, item){
|
||||
if(query !== ''){
|
||||
this.selectLoading = true;
|
||||
item.selectLoading = true;
|
||||
try {
|
||||
var data = await this.addFilterForm.field.extend.request(query);
|
||||
var data = await item.field.extend.request(query);
|
||||
}catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this.addFilterForm.field.extend.data = data;
|
||||
this.selectLoading = false;
|
||||
item.field.extend.data = data;
|
||||
item.selectLoading = false;
|
||||
}else{
|
||||
this.addFilterForm.field.extend.data = [];
|
||||
item.field.extend.data = [];
|
||||
}
|
||||
},
|
||||
async visibleChange(isopen){
|
||||
if(isopen && this.addFilterForm.field.extend && this.addFilterForm.field.extend.request && !this.addFilterForm.field.extend.remote){
|
||||
//如果字段类型为异步获取数据就在这里处理
|
||||
this.selectLoading = true;
|
||||
try {
|
||||
var data = await this.addFilterForm.field.extend.request();
|
||||
}catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this.addFilterForm.field.extend.data = data;
|
||||
this.selectLoading = false;
|
||||
}
|
||||
},
|
||||
fieldChange(){
|
||||
this.addFilterForm.value = '';
|
||||
if(this.addFilterForm.field.type=='select'){
|
||||
this.addFilterForm.field.type=''
|
||||
this.$nextTick(() => {
|
||||
this.addFilterForm.field.type='select'
|
||||
})
|
||||
}
|
||||
if(this.addFilterForm.field.type=='date'){
|
||||
this.addFilterForm.field.type=''
|
||||
this.$nextTick(() => {
|
||||
this.addFilterForm.field.type='date'
|
||||
})
|
||||
}
|
||||
//选择常用过滤
|
||||
selectMyfilter(item){
|
||||
this.filterObjLength = Object.keys(item.filterObj).length
|
||||
this.$emit('filterChange',item.filterObj)
|
||||
this.drawer = false
|
||||
},
|
||||
//立即过滤
|
||||
ok(){
|
||||
this.$refs.ruleForm.validate((valid) => {
|
||||
if (valid) {
|
||||
var item = {
|
||||
keyLabel: this.addFilterForm.field.label,
|
||||
valueLabel: this.addFilterForm.value,
|
||||
key: this.addFilterForm.field.value,
|
||||
value: this.addFilterForm.value
|
||||
}
|
||||
if(this.addFilterForm.field.type=='select'){
|
||||
if(this.addFilterForm.field.extend && this.addFilterForm.field.extend.multiple){
|
||||
item.valueLabel = this.addFilterForm.value.map(v => v.label).join(",");
|
||||
item.value = this.addFilterForm.value.map(v => v.value).join(",");
|
||||
}else{
|
||||
item.valueLabel = this.addFilterForm.value.label;
|
||||
item.value = this.addFilterForm.value.value;
|
||||
}
|
||||
}
|
||||
if(this.addFilterForm.field.type=='date'){
|
||||
item.valueLabel = this.dateFormat(this.addFilterForm.value, 'yyyy-MM-dd');
|
||||
item.value = this.dateFormat(this.addFilterForm.value, 'yyyy-MM-dd');
|
||||
}
|
||||
if(this.addFilterForm.field.type=='datetime'){
|
||||
item.valueLabel = this.dateFormat(this.addFilterForm.value, 'yyyy-MM-dd hh:mm:ss');
|
||||
item.value = this.dateFormat(this.addFilterForm.value, 'yyyy-MM-dd hh:mm:ss');
|
||||
}
|
||||
if(this.addFilterForm.field.type=='daterange'){
|
||||
item.valueLabel = this.addFilterForm.value.map(item => this.dateFormat(item, 'yyyy-MM-dd')).join(" - ")
|
||||
item.value = this.addFilterForm.value.map(item => this.dateFormat(item, 'yyyy-MM-dd')).join(" - ")
|
||||
}
|
||||
if(this.addFilterForm.field.type=='datetimerange'){
|
||||
item.valueLabel = this.addFilterForm.value.map(item => this.dateFormat(item, 'yyyy-MM-dd hh:mm:ss')).join(" - ")
|
||||
item.value = this.addFilterForm.value.map(item => this.dateFormat(item, 'yyyy-MM-dd hh:mm:ss')).join(" - ")
|
||||
}
|
||||
this.filter.push(item);
|
||||
this.cancel();
|
||||
this.change();
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
this.filterObjLength = this.filter.length
|
||||
this.$emit('filterChange',this.filterObj)
|
||||
this.drawer = false
|
||||
},
|
||||
//保存常用
|
||||
saveMy(){
|
||||
this.$prompt('常用过滤名称', '另存为常用', {
|
||||
inputPlaceholder: '请输入识别度较高的常用过滤名称',
|
||||
inputPattern: /\S/,
|
||||
inputErrorMessage: '名称不能为空'
|
||||
})
|
||||
.then(async ({ value }) => {
|
||||
this.saveLoading = true
|
||||
const saveObj = {
|
||||
title: value,
|
||||
filterObj: this.filterObj
|
||||
}
|
||||
try {
|
||||
var save = await config.saveMy(this.filterName, saveObj)
|
||||
}catch (error) {
|
||||
this.saveLoading = false
|
||||
console.log(error);
|
||||
return false
|
||||
}
|
||||
if(!save){
|
||||
return false
|
||||
}
|
||||
|
||||
this.myFilter.push(saveObj)
|
||||
this.$message.success(`${this.filterName} 保存常用成功`)
|
||||
this.saveLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
//
|
||||
})
|
||||
},
|
||||
cancel(){
|
||||
this.isadd = false;
|
||||
this.addFilterForm.value = '';
|
||||
this.$refs.ruleForm.resetFields();
|
||||
},
|
||||
handleClose(item) {
|
||||
this.filter = this.filter.filter(obj => obj.key !== item.key);
|
||||
this.cancel();
|
||||
this.change();
|
||||
},
|
||||
getFilter(){
|
||||
var _filter = this.filter;
|
||||
var formatData = {};
|
||||
_filter.map(item => {
|
||||
formatData.[item.key]=item.value
|
||||
});
|
||||
return formatData;
|
||||
},
|
||||
change(){
|
||||
this.$emit('change', this.getFilter())
|
||||
},
|
||||
scrollInit(){
|
||||
const scrollDiv = this.$refs.scFilterBarScrollbar;
|
||||
scrollDiv.addEventListener('mousewheel', handler, false)
|
||||
function handler(event) {
|
||||
const detail = event.wheelDelta || event.detail;
|
||||
const moveForwardStep = 1;
|
||||
const moveBackStep = -1;
|
||||
let step = 0;
|
||||
if (detail < 0) {
|
||||
step = moveForwardStep * 50;
|
||||
}else{
|
||||
step = moveBackStep * 50;
|
||||
}
|
||||
scrollDiv.scrollLeft += step;
|
||||
}
|
||||
},
|
||||
dateFormat(date, fmt='yyyy-MM-dd'){
|
||||
date = new Date(date)
|
||||
var o = {
|
||||
"M+" : date.getMonth()+1, //月份
|
||||
"d+" : date.getDate(), //日
|
||||
"h+" : date.getHours(), //小时
|
||||
"m+" : date.getMinutes(), //分
|
||||
"s+" : date.getSeconds(), //秒
|
||||
"q+" : Math.floor((date.getMonth()+3)/3), //季度
|
||||
"S" : date.getMilliseconds() //毫秒
|
||||
};
|
||||
if(/(y+)/.test(fmt)) {
|
||||
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
|
||||
}
|
||||
for(var k in o) {
|
||||
if(new RegExp("("+ k +")").test(fmt)){
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
//清空过滤
|
||||
clear(){
|
||||
this.filter = []
|
||||
this.filterObjLength = 0
|
||||
this.$emit('filterChange',this.filterObj)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sc-filterBar {height: 32px;display: flex;align-items:center;}
|
||||
.sc-filterBar-scrollbar {overflow: auto;}
|
||||
.sc-filterBar-scrollbar::-webkit-scrollbar {display: none;}
|
||||
.sc-filterBar-tags {display: flex;}
|
||||
.filter-tag {display: flex;flex-shrink: 0;padding-right:10px;}
|
||||
.filter-tag .field {display: inline-block;background-color: #d9ecff;color: #409eff;height: 32px;line-height: 30px;padding: 0 10px;border-radius: 4px 0 0 4px;border: 1px solid #d9ecff;border-right: 0;}
|
||||
.filter-tag .value {display: inline-block;background-color: #ecf5ff;color: #409eff;height: 32px;line-height: 30px;padding: 0 10px;border-radius: 0 4px 4px 0;border: 1px solid #d9ecff;border-left: 0;}
|
||||
.filter-tag i {height: 16px;width: 16px;line-height: 16px;cursor: pointer;text-align: center;vertical-align: middle;position: relative;top: -1px;right: -5px;border-radius: 50%;}
|
||||
.filter-tag i:hover {background-color: #409eff;color: #FFF;}
|
||||
.tabs-label {padding:0 20px;}
|
||||
|
||||
.nodata {height:46px;line-height: 46px;margin:15px 0;border: 1px dashed #e6e6e6;color: #999;text-align: center;border-radius: 3px;}
|
||||
|
||||
.sc-filter-main {padding:20px;border-bottom: 1px solid #e6e6e6;background: #fff;}
|
||||
.sc-filter-main h2 {font-size: 12px;color: #999;font-weight: normal;}
|
||||
.sc-filter-main table {width: 100%;margin: 15px 0;}
|
||||
.sc-filter-main table tr {}
|
||||
.sc-filter-main table td {padding:5px 10px 5px 0;}
|
||||
.sc-filter-main table td:deep(.el-input .el-input__inner) {vertical-align: top;}
|
||||
.sc-filter-main table td .el-select {display: block;}
|
||||
.sc-filter-main table td .el-date-editor.el-input {display: block;width: 100%;}
|
||||
.sc-filter-main table td .del {background: #fff;color: #999;width: 32px;height: 32px;line-height: 32px;text-align: center;border-radius:50%;font-size: 12px;cursor: pointer;}
|
||||
.sc-filter-main table td .del:hover {background: #F56C6C;color: #fff;}
|
||||
|
||||
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column
|
||||
}
|
||||
.root:deep(.el-tabs__header) {margin: 0;}
|
||||
.root:deep(.el-tabs__content) {flex: 1;background: #f6f8f9;}
|
||||
.root:deep(.el-tabs__content) .el-tab-pane{overflow: auto;height:100%;}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
<!--
|
||||
* @Descripttion: 过滤器V2 常用组件
|
||||
* @version: 2.0
|
||||
* @Author: sakuya
|
||||
* @Date: 2021年7月31日16:49:56
|
||||
* @LastEditors:
|
||||
* @LastEditTime:
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="sc-filter-my">
|
||||
<el-skeleton v-if="loading" :rows="2" animated />
|
||||
<template v-else>
|
||||
<el-empty v-if="myFilter.length<=0" :image-size="100">
|
||||
<template #description>
|
||||
<h2>没有常用的过滤</h2>
|
||||
<p style="margin-top: 10px;max-width: 300px;">常用过滤可以将多个过滤条件保存为一个集合,方便下次进行相同条件的过滤</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
<ul v-else class="sc-filter-my-list">
|
||||
<li v-for="(item, index) in myFilter" :key="index"><el-tag closable size="medium" effect="dark" type="info" @click="selectMyfilter(item)" @close="closeMyfilter(item, index)">{{item.title}}</el-tag></li>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/config/filterBar";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
filterName: { type: String, default: "" },
|
||||
data: { type: Object, default: () => {} }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
myFilter: []
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
data: {
|
||||
handler(){
|
||||
this.myFilter = this.data
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.myFilter = this.data
|
||||
this.getMyfilter()
|
||||
},
|
||||
methods: {
|
||||
//选择常用过滤
|
||||
selectMyfilter(item){
|
||||
this.$emit('selectMyfilter', item)
|
||||
},
|
||||
//删除常用过滤
|
||||
closeMyfilter(item, index){
|
||||
this.$confirm('此操作将永久删除该常用, 是否继续?', '提示', {
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
try {
|
||||
var del = await config.delMy(this.filterName)
|
||||
}catch (error) {
|
||||
return false
|
||||
}
|
||||
if(!del){
|
||||
return false
|
||||
}
|
||||
this.myFilter.splice(index, 1)
|
||||
this.$message.success('删除常用成功')
|
||||
}).catch(() => {
|
||||
//
|
||||
})
|
||||
},
|
||||
//远程获取我的常用
|
||||
async getMyfilter(){
|
||||
this.loading = true
|
||||
try {
|
||||
this.myFilter = await config.getMy(this.filterName)
|
||||
}catch (error) {
|
||||
return false
|
||||
}
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sc-filter-my {padding:15px;}
|
||||
.sc-filter-my-list {list-style-type: none;}
|
||||
.sc-filter-my-list li {margin-bottom: 15px;}
|
||||
.sc-filter-my-list li .el-tag {cursor: pointer;}
|
||||
</style>
|
|
@ -0,0 +1,74 @@
|
|||
export default {
|
||||
//运算符
|
||||
operator: [
|
||||
{
|
||||
label: '等于',
|
||||
value: '=',
|
||||
},
|
||||
{
|
||||
label: '不等于',
|
||||
value: '!=',
|
||||
},
|
||||
{
|
||||
label: '大于',
|
||||
value: '>',
|
||||
},
|
||||
{
|
||||
label: '大于等于',
|
||||
value: '>=',
|
||||
},
|
||||
{
|
||||
label: '小于',
|
||||
value: '<',
|
||||
},
|
||||
{
|
||||
label: '小于等于',
|
||||
value: '<=',
|
||||
},
|
||||
{
|
||||
label: '包含',
|
||||
value: 'include',
|
||||
},
|
||||
{
|
||||
label: '不包含',
|
||||
value: 'notinclude',
|
||||
}
|
||||
],
|
||||
//过滤结果运算符的分隔符
|
||||
separator: '|',
|
||||
//获取我的常用
|
||||
getMy: function (name) {
|
||||
return new Promise((resolve) => {
|
||||
console.log(`这里可以根据${name}参数请求接口`)
|
||||
var list = []
|
||||
setTimeout(()=>{
|
||||
resolve(list)
|
||||
},500)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 常用保存处理 返回resolve后继续操作
|
||||
* @name scFilterBar组件的props->filterName
|
||||
* @obj 过滤项整理好的对象
|
||||
*/
|
||||
saveMy: function (name, obj) {
|
||||
return new Promise((resolve) => {
|
||||
console.log(name, obj)
|
||||
setTimeout(()=>{
|
||||
resolve(true)
|
||||
},500)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 常用删除处理 返回resolve后继续操作
|
||||
* @name scFilterBar组件的props->filterName
|
||||
*/
|
||||
delMy: function (name) {
|
||||
return new Promise((resolve) => {
|
||||
console.log(name)
|
||||
setTimeout(()=>{
|
||||
resolve(true)
|
||||
},500)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -41,15 +41,6 @@ const routes = [{
|
|||
icon: "el-icon-orange",
|
||||
},
|
||||
component: () => import(/* webpackChunkName: "usercenter" */ '@/views/vab/iconselect'),
|
||||
},
|
||||
{
|
||||
name: "filterbar2",
|
||||
path: "/vab/filterbar2",
|
||||
meta: {
|
||||
title: "过滤器v2",
|
||||
icon: "el-icon-set-up",
|
||||
},
|
||||
component: () => import(/* webpackChunkName: "usercenter" */ '@/views/vab/filterbar2'),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<el-main>
|
||||
<el-card shadow="never">
|
||||
<scFilterBar :options="options" :defaultFilter="defaultFilter" @change="change"></scFilterBar>
|
||||
<scFilterBar filterName="filterName" :options="options" @filterChange="change"></scFilterBar>
|
||||
</el-card>
|
||||
<el-alert title="SCUI 独创的过滤条Filterbar,可配置不同类型的过滤字段,以及异步获取数据,操作上方过滤条查看下方change事件的回调,在表格查询的场景下非常合适" type="success" style="margin:20px 0;"></el-alert>
|
||||
<el-alert title="SCUI 独创的过滤条Filterbar,可配置不同类型的过滤字段,以及异步获取数据,在@/config/filterBar.js中可以更改运算符以及其他配置,操作上方过滤条查看下方change事件的回调,在表格查询的场景下非常合适" type="success" style="margin:20px 0;"></el-alert>
|
||||
<el-card shadow="never">
|
||||
<pre>{{ filterData }}</pre>
|
||||
</el-card>
|
||||
|
@ -24,14 +24,19 @@
|
|||
defaultFilter : [],
|
||||
options: [
|
||||
{
|
||||
label: '输入框',
|
||||
value: 'name',
|
||||
type: 'text'
|
||||
label: '订单号',
|
||||
value: 'id',
|
||||
type: 'text',
|
||||
selected: true,
|
||||
placeholder: '请输入订单号'
|
||||
},
|
||||
{
|
||||
label: '固定下拉框',
|
||||
label: '类型',
|
||||
value: 'type',
|
||||
type: 'select',
|
||||
operator: '=',
|
||||
selected: true,
|
||||
placeholder: '请选择类型',
|
||||
extend: {
|
||||
data:[
|
||||
{
|
||||
|
@ -46,9 +51,11 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
label: '固定下拉框(多选)',
|
||||
label: '类型(多选)',
|
||||
value: 'type2',
|
||||
type: 'select',
|
||||
operator: '=',
|
||||
placeholder: '请选择类型',
|
||||
extend: {
|
||||
multiple: true,
|
||||
data:[
|
||||
|
@ -64,28 +71,42 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
label: '异步下拉框',
|
||||
value: 'type3',
|
||||
label: '通知(异步)',
|
||||
value: 'noticeType',
|
||||
type: 'select',
|
||||
operator: '=',
|
||||
placeholder: '请选择通知类型',
|
||||
extend: {
|
||||
request: async () => {
|
||||
var list = await this.$API.demo.select.get();
|
||||
return list.data;
|
||||
var list = await this.$API.dic.info.get()
|
||||
return list.data.map(item => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.key
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '远程搜索下拉框',
|
||||
value: 'type4',
|
||||
label: '通知(远程搜索)',
|
||||
value: 'noticeType2',
|
||||
type: 'select',
|
||||
operator: '=',
|
||||
placeholder: '请输入关键词后检索',
|
||||
extend: {
|
||||
remote: true,
|
||||
request: async (query) => {
|
||||
var data = {
|
||||
keyword: query,
|
||||
}
|
||||
var list = await this.$API.demo.select.get(data);
|
||||
return list.data;
|
||||
var list = await this.$API.dic.info.get(data)
|
||||
return list.data.map(item => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.key
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
<!--
|
||||
* @Descripttion: 过滤器V2
|
||||
* @version: 2.0
|
||||
* @Author: sakuya
|
||||
* @Date: 2021年7月30日14:48:41
|
||||
* @LastEditors:
|
||||
* @LastEditTime:
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-main>
|
||||
<el-card shadow="never">
|
||||
<el-badge :value="2" type="danger">
|
||||
<el-button size="small" icon="sc-icon-filter-line" @click="openFilter"></el-button>
|
||||
</el-badge>
|
||||
|
||||
<el-drawer title="过滤器" v-model="drawer" :size="650">
|
||||
<el-container>
|
||||
<el-main style="padding:0">
|
||||
|
||||
<el-tabs class="root">
|
||||
<el-tab-pane>
|
||||
<template #label>
|
||||
<div class="tabs-label">
|
||||
过滤项
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar>
|
||||
|
||||
<div class="sc-filter-main">
|
||||
<h2>设置过滤条件</h2>
|
||||
|
||||
<el-alert v-if="filter.length<=0" title="没有默认过滤条件,请点击增加过滤项" type="warning" :closable="false" center style="margin:15px 0;"></el-alert>
|
||||
|
||||
|
||||
<table v-else>
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col width="140">
|
||||
<col>
|
||||
<col width="40">
|
||||
</colgroup>
|
||||
<tr v-for="(item,index) in filter" :key="index">
|
||||
<td>
|
||||
<el-tag size="medium">{{index+1}}</el-tag>
|
||||
</td>
|
||||
<td>
|
||||
<el-select v-model="item.field" placeholder="过滤字段" filterable @change="fieldChange(item)">
|
||||
<el-option v-for="field in fields" :key="field.value" :label="field.label" :value="field"></el-option>
|
||||
</el-select>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<el-input v-if="item.field.type=='text'" v-model="item.value" :placeholder="item.field.placeholder"></el-input>
|
||||
|
||||
<el-select v-if="item.field.type=='select'" v-model="item.value" :placeholder="item.field.placeholder" filterable :multiple="item.field.extend.multiple">
|
||||
<el-option v-for="field in item.field.extend.data" :key="field.value" :label="field.label" :value="field.value"></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-date-picker v-if="item.field.type=='datetime'" v-model="item.value" type="datetime" :placeholder="item.field.placeholder" style="width: 100%;"></el-date-picker>
|
||||
|
||||
<el-date-picker v-if="item.field.type=='datetimerange'" v-model="item.value" type="datetimerange" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 100%;"></el-date-picker>
|
||||
|
||||
<el-switch v-if="item.field.type=='switch'" v-model="item.value"></el-switch>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<i class="el-icon-delete del" @click="delFilter(index)"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<el-button type="text" icon="el-icon-plus" @click="addFilter">增加过滤项</el-button>
|
||||
</div>
|
||||
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane>
|
||||
<template #label>
|
||||
<div class="tabs-label">
|
||||
常用
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar>
|
||||
<ul class="sc-filter-my">
|
||||
<li><label>已过期的用户</label></li>
|
||||
<li><label>类型为正常且已缴费的用户</label></li>
|
||||
</ul>
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
</el-main>
|
||||
<el-footer>
|
||||
<el-button type="primary" @click="ok">立即过滤</el-button>
|
||||
<el-button type="primary" plain @click="savemy">保存常用</el-button>
|
||||
<el-button>重置</el-button>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</el-drawer>
|
||||
|
||||
</el-card>
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'filterBar2',
|
||||
data() {
|
||||
return {
|
||||
drawer: false,
|
||||
form: {
|
||||
checkboxGroup1: ['1'],
|
||||
radio1: ''
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
label: 'ID',
|
||||
value: 'id',
|
||||
type: 'text',
|
||||
selected: true,
|
||||
placeholder: '请输入ID'
|
||||
},
|
||||
{
|
||||
label: '姓名',
|
||||
value: 'name',
|
||||
type: 'text',
|
||||
placeholder: '请输入姓名'
|
||||
},
|
||||
{
|
||||
label: '类型',
|
||||
value: 'type',
|
||||
type: 'select',
|
||||
selected: true,
|
||||
placeholder: '请选择类型',
|
||||
extend: {
|
||||
//multiple: true,
|
||||
data: [
|
||||
{
|
||||
label: "选项1",
|
||||
value: "1"
|
||||
},
|
||||
{
|
||||
label: "选项2",
|
||||
value: "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '注册日期',
|
||||
value: 'date',
|
||||
type: 'datetime',
|
||||
placeholder: '请选择日期时间'
|
||||
},
|
||||
{
|
||||
label: '有效期',
|
||||
value: 'date2',
|
||||
type: 'datetimerange',
|
||||
placeholder: '请选择日期时间'
|
||||
},
|
||||
{
|
||||
label: '是否警用',
|
||||
value: 'switch',
|
||||
type: 'switch'
|
||||
}
|
||||
],
|
||||
filter: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
//默认显示
|
||||
this.fields.forEach((item) => {
|
||||
if(item.selected){
|
||||
this.filter.push({
|
||||
field: item,
|
||||
value: ''
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
openFilter(){
|
||||
this.drawer = true
|
||||
},
|
||||
addFilter(){
|
||||
this.filter.push({
|
||||
field: this.fields[0],
|
||||
value: ''
|
||||
})
|
||||
},
|
||||
delFilter(index){
|
||||
console.log(index)
|
||||
this.filter.splice(index, 1)
|
||||
},
|
||||
ok(){
|
||||
console.log(this.filter);
|
||||
},
|
||||
fieldChange(tr){
|
||||
tr.value = ''
|
||||
},
|
||||
savemy(){
|
||||
this.$prompt('请输入常用过滤名称', '提示', {
|
||||
inputPlaceholder: '请输入常用过滤名称'
|
||||
})
|
||||
.then(({ value }) => {
|
||||
console.log(value);
|
||||
})
|
||||
.catch(() => {
|
||||
//
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tabs-label {padding:0 20px;}
|
||||
|
||||
.sc-filter-main {padding:20px;border-bottom: 1px solid #e6e6e6;background: #fff;}
|
||||
.sc-filter-main h2 {font-size: 12px;color: #999;font-weight: normal;}
|
||||
.sc-filter-main table {width: 100%;margin: 15px 0;}
|
||||
.sc-filter-main table tr {}
|
||||
.sc-filter-main table td {padding:5px 10px 5px 0;}
|
||||
.sc-filter-main table td .el-select {display: block;}
|
||||
.sc-filter-main table td .el-date-editor.el-input {display: block;width: 100%;}
|
||||
.sc-filter-main table td .del {background: #fff;color: #999;width: 32px;height: 32px;line-height: 32px;text-align: center;border-radius:50%;font-size: 12px;cursor: pointer;}
|
||||
.sc-filter-main table td .del:hover {background: #F56C6C;color: #fff;}
|
||||
|
||||
.sc-filter-my {list-style-type: none;padding:15px;}
|
||||
.sc-filter-my li {font-size: 12px;margin-bottom: 15px;}
|
||||
.sc-filter-my li label {background: #222b45;color: #fff;padding:5px 10px;border-radius:4px;}
|
||||
.sc-filter-my li:hover {box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);position: relative;}
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column
|
||||
}
|
||||
.root:deep(.el-tabs__header) {margin: 0;}
|
||||
.root:deep(.el-tabs__content) {flex: 1;background: #f6f8f9;}
|
||||
.root:deep(.el-tabs__content) .el-tab-pane{overflow: auto;height:100%;}
|
||||
</style>
|
Loading…
Reference in New Issue