ASP.NET MVC5+EF6+EasyUI 后臺管理系統(tǒng)(81)-數(shù)據(jù)篩選(萬能查詢)實例
前言
聽標(biāo)題的名字似乎是一個非常牛X復(fù)雜的功能,但是實際上它確實是非常復(fù)雜的,我們本節(jié)將演示如何實現(xiàn)對數(shù)據(jù),進行組合查詢(數(shù)據(jù)篩選)
我們都知道Excel中是如何篩選數(shù)據(jù)的.就像下面一樣

他是一個并的關(guān)系,我們現(xiàn)在要做的也是這樣的效果,下面我們將利用EasyUI的DataGrid為例來擴展(就算是其他組件也是可以的,同樣的實現(xiàn)方式!)
實現(xiàn)思路
1.前臺通過查詢組合json
2.后臺通過反射拆解json
3.進行組合查詢
雖然短短3點,夠你寫個3天天夜了
優(yōu)點:需要從很多數(shù)據(jù)中得到精準(zhǔn)的數(shù)據(jù),通常查一些商品他們的屬性異常接近的情況下使用
缺點:我實現(xiàn)的方式為偽查詢,大量數(shù)據(jù)請使用存儲過程
簡單了解
從Easyui的官方擴展中了解到一個JS文件,但是實質(zhì)上,這個文件BUG很多,在使用中我曾經(jīng)一度認(rèn)為是使用出現(xiàn)問題,其實他根本就不可用

所以我這里先獻上修改后的整個JS代碼
(function($){
function getPluginName(target){
if ($(target).data('treegrid')){
return 'treegrid';
} else {
return 'datagrid';
}
}
var autoSizeColumn1 = $.fn.datagrid.methods.autoSizeColumn;
var loadDataMethod1 = $.fn.datagrid.methods.loadData;
var appendMethod1 = $.fn.datagrid.methods.appendRow;
var deleteMethod1 = $.fn.datagrid.methods.deleteRow;
$.extend($.fn.datagrid.methods, {
autoSizeColumn: function(jq, field){
return jq.each(function(){
var fc = $(this).datagrid('getPanel').find('.datagrid-header .datagrid-filter-c');
fc.hide();
autoSizeColumn1.call($.fn.datagrid.methods, $(this), field);
fc.show();
resizeFilter(this, field);
});
},
loadData: function(jq, data){
jq.each(function(){
$.data(this, 'datagrid').filterSource = null;
});
return loadDataMethod1.call($.fn.datagrid.methods, jq, data);
},
appendRow: function(jq, row){
var result = appendMethod1.call($.fn.datagrid.methods, jq, row);
jq.each(function(){
var state = $(this).data('datagrid');
if (state.filterSource){
state.filterSource.total++;
if (state.filterSource.rows != state.data.rows){
state.filterSource.rows.push(row);
}
}
});
return result;
},
deleteRow: function(jq, index){
jq.each(function(){
var state = $(this).data('datagrid');
var opts = state.options;
if (state.filterSource && opts.idField){
if (state.filterSource.rows == state.data.rows){
state.filterSource.total--;
} else {
for(var i=0; i<state.filterSource.rows.length; i++){
var row = state.filterSource.rows[i];
if (row[opts.idField] == state.data.rows[index][opts.idField]){
state.filterSource.rows.splice(i,1);
state.filterSource.total--;
break;
}
}
}
}
});
return deleteMethod1.call($.fn.datagrid.methods, jq, index);
}
});
var loadDataMethod2 = $.fn.treegrid.methods.loadData;
var appendMethod2 = $.fn.treegrid.methods.append;
var insertMethod2 = $.fn.treegrid.methods.insert;
var removeMethod2 = $.fn.treegrid.methods.remove;
$.extend($.fn.treegrid.methods, {
loadData: function(jq, data){
jq.each(function(){
$.data(this, 'treegrid').filterSource = null;
});
return loadDataMethod2.call($.fn.treegrid.methods, jq, data);
},
append: function(jq, param){
return jq.each(function(){
var state = $(this).data('treegrid');
var opts = state.options;
if (opts.oldLoadFilter){
var rows = translateTreeData(this, param.data, param.parent);
state.filterSource.total += rows.length;
state.filterSource.rows = state.filterSource.rows.concat(rows);
$(this).treegrid('loadData', state.filterSource)
} else {
appendMethod2($(this), param);
}
});
},
insert: function(jq, param){
return jq.each(function(){
var state = $(this).data('treegrid');
var opts = state.options;
if (opts.oldLoadFilter){
var ref = param.before || param.after;
var index = getNodeIndex(param.before || param.after);
var pid = index>=0 ? state.filterSource.rows[index]._parentId : null;
var rows = translateTreeData(this, [param.data], pid);
var newRows = state.filterSource.rows.splice(0, index>=0 ? (param.before ? index : index+1) : (state.filterSource.rows.length));
newRows = newRows.concat(rows);
newRows = newRows.concat(state.filterSource.rows);
state.filterSource.total += rows.length;
state.filterSource.rows = newRows;
$(this).treegrid('loadData', state.filterSource);
function getNodeIndex(id){
var rows = state.filterSource.rows;
for(var i=0; i<rows.length; i++){
if (rows[i][opts.idField] == id){
return i;
}
}
return -1;
}
} else {
insertMethod2($(this), param);
}
});
},
remove: function(jq, id){
jq.each(function(){
var state = $(this).data('treegrid');
if (state.filterSource){
var opts = state.options;
var rows = state.filterSource.rows;
for(var i=0; i<rows.length; i++){
if (rows[i][opts.idField] == id){
rows.splice(i, 1);
state.filterSource.total--;
break;
}
}
}
});
return removeMethod2(jq, id);
}
});
var extendedOptions = {
filterMenuIconCls: 'icon-ok',
filterBtnIconCls: 'fa fa-filter fa-lg ',
filterBtnPosition: 'right',
filterPosition: 'bottom',
remoteFilter: false,
showFilterBar: true,
filterDelay: 400,
filterRules: [],
// specify whether the filtered records need to match ALL or ANY of the applied filters
filterMatchingType: 'all', // possible values: 'all','any'
// filterCache: {},
filterMatcher: function(data){
var name = getPluginName(this);
var dg = $(this);
var state = $.data(this, name);
var opts = state.options;
if (opts.filterRules.length){
var rows = [];
if (name == 'treegrid'){
var rr = {};
$.map(data.rows, function(row){
if (isMatch(row, row[opts.idField])){
rr[row[opts.idField]] = row;
row = getRow(data.rows, row._parentId);
while(row){
rr[row[opts.idField]] = row;
row = getRow(data.rows, row._parentId);
}
}
});
for(var id in rr){
rows.push(rr[id]);
}
} else {
for(var i=0; i<data.rows.length; i++){
var row = data.rows[i];
if (isMatch(row, i)){
rows.push(row);
}
}
}
data = {
total: data.total - (data.rows.length - rows.length),
rows: rows
};
}
return data;
function isMatch(row, index){
var rules = opts.filterRules;
if (!rules.length){return true;}
for(var i=0; i<rules.length; i++){
var rule = rules[i];
var source = row[rule.field];
var col = dg.datagrid('getColumnOption', rule.field);
if (col && col.formatter){
source = col.formatter(row[rule.field], row, index);
}
if (source == undefined){
source = '';
}
var op = opts.operators[rule.op];
// if (!op.isMatch(source, rule.value)){return false}
var matched = op.isMatch(source, rule.value);
if (opts.filterMatchingType == 'any'){
if (matched){return true;}
} else {
if (!matched){return false;}
}
}
return opts.filterMatchingType == 'all';
}
function getRow(rows, id){
for(var i=0; i<rows.length; i++){
var row = rows[i];
if (row[opts.idField] == id){
return row;
}
}
return null;
}
},
defaultFilterType: 'text',
defaultFilterOperator: 'contains',
defaultFilterOptions: {
onInit: function(target){
var name = getPluginName(target);
var opts = $(target)[name]('options');
var field = $(this).attr('name');
var input = $(this);
if (input.data('textbox')){
input = input.textbox('textbox');
}
input.unbind('.filter').bind('keydown.filter', function (e) {
var t = $(this);
if (this.timer){
clearTimeout(this.timer);
}
if (e.keyCode == 13) {
_doFilter();
}
else {
this.timer = setTimeout(function(){
_modifyFilter();
}, opts.filterDelay);
}
});
function _doFilter() {
var rule = $(target)[name]('getFilterRule', field);
var value = input.val();
if (value != '') {
$(target)[name]('addFilterRule', {
field: field,
op: opts.defaultFilterOperator,
value: value
});
} else {
if (rule) {
$(target)[name]('removeFilterRule', field);
}
}
$(target)[name]('doFilter');
};
function _modifyFilter() {
var rule = $(target)[name]('getFilterRule', field);
var value = input.val();
if (value != '') {
if ((rule && rule.value != value) || !rule) {
$(target)[name]('addFilterRule', {
field: field,
op: opts.defaultFilterOperator,
value: value
});
}
}
else {
if (rule) {
$(target)[name]('removeFilterRule', field);
}
}
};
}
},
filterStringify: function(data){
return JSON.stringify(data);
},
onClickMenu: function(item,button){}
};
$.extend($.fn.datagrid.defaults, extendedOptions);
$.extend($.fn.treegrid.defaults, extendedOptions);
// filter types
$.fn.datagrid.defaults.filters = $.extend({}, $.fn.datagrid.defaults.editors, {
label: {
init: function(container, options){
return $('<span></span>').appendTo(container);
},
getValue: function(target){
return $(target).html();
},
setValue: function(target, value){
$(target).html(value);
},
resize: function(target, width){
$(target)._outerWidth(width)._outerHeight(22);
}
}
});
$.fn.treegrid.defaults.filters = $.fn.datagrid.defaults.filters;
// filter operators
$.fn.datagrid.defaults.operators = {
nofilter: {
text:Lang.Nofilter //'No Filter'
},
contains: {
text:Lang.Contains ,
isMatch: function(source, value){
source = String(source);
value = String(value);
return source.toLowerCase().indexOf(value.toLowerCase()) >= 0;
}
},
equal: {
text:Lang.Equal,
isMatch: function(source, value){
return source == value;
}
},
notequal: {
text: Lang.Notequal,
isMatch: function(source, value){
return source != value;
}
},
beginwith: {
text: Lang.Beginwith,
isMatch: function(source, value){
source = String(source);
value = String(value);
return source.toLowerCase().indexOf(value.toLowerCase()) == 0;
}
},
endwith: {
text:Lang.Endwith,
isMatch: function(source, value){
source = String(source);
value = String(value);
return source.toLowerCase().indexOf(value.toLowerCase(), source.length - value.length) !== -1;
}
},
less: {
text: Lang.Less,
isMatch: function(source, value){
return source < value;
}
},
lessorequal: {
text: Lang.Lessorequal,
isMatch: function(source, value){
return source <= value;
}
},
greater: {
text: Lang.Greater,
isMatch: function(source, value){
return source > value;
}
},
greaterorequal: {
text: Lang.Greaterorequal,
isMatch: function(source, value){
return source >= value;
}
}
};
$.fn.treegrid.defaults.operators = $.fn.datagrid.defaults.operators;
function resizeFilter(target, field){
var toFixColumnSize = false;
var dg = $(target);
var header = dg.datagrid('getPanel').find('div.datagrid-header');
var tr = header.find('.datagrid-header-row:not(.datagrid-filter-row)');
var ff = field ? header.find('.datagrid-filter[name="'+field+'"]') : header.find('.datagrid-filter');
ff.each(function(){
var name = $(this).attr('name');
var col = dg.datagrid('getColumnOption', name);
var cc = $(this).closest('div.datagrid-filter-c');
var btn = cc.find('a.datagrid-filter-btn');
var cell = tr.find('td[field="'+name+'"] .datagrid-cell');
var cellWidth = cell._outerWidth();
if (cellWidth != _getContentWidth(cc)){
this.filter.resize(this, cellWidth - btn._outerWidth());
}
if (cc.width() > col.boxWidth+col.deltaWidth-1){
col.boxWidth = cc.width() - col.deltaWidth + 1;
col.width = col.boxWidth + col.deltaWidth;
toFixColumnSize = true;
}
});
if (toFixColumnSize){
$(target).datagrid('fixColumnSize');
}
function _getContentWidth(cc){
var w = 0;
$(cc).children(':visible').each(function(){
w += $(this)._outerWidth();
});
return w;
}
}
function getFilterComponent(target, field){
var header = $(target).datagrid('getPanel').find('div.datagrid-header');
return header.find('tr.datagrid-filter-row td[field="'+field+'"] .datagrid-filter');
}
/**
* get filter rule index, return -1 if not found.
*/
function getRuleIndex(target, field){
var name = getPluginName(target);
var rules = $(target)[name]('options').filterRules;
for(var i=0; i<rules.length; i++){
if (rules[i].field == field){
return i;
}
}
return -1;
}
function getFilterRule(target, field){
var name = getPluginName(target);
var rules = $(target)[name]('options').filterRules;
var index = getRuleIndex(target, field);
if (index >= 0){
return rules[index];
} else {
return null;
}
}
function addFilterRule(target, param) {
var name = getPluginName(target);
var opts = $(target)[name]('options');
var rules = opts.filterRules;
if (param.op == 'nofilter'){
removeFilterRule(target, param.field);
} else {
var index = getRuleIndex(target, param.field);
if (index >= 0){
$.extend(rules[index], param);
} else {
rules.push(param);
}
}
var input = getFilterComponent(target, param.field);
if (input.length){
if (param.op != 'nofilter'){
input[0].filter.setValue(input, param.value);
}
var menu = input[0].menu;
if (menu){
menu.find('.'+opts.filterMenuIconCls).removeClass(opts.filterMenuIconCls);
var item = menu.menu('findItem', opts.operators[param.op]['text']);
menu.menu('setIcon', {
target: item.target,
iconCls: opts.filterMenuIconCls
});
}
}
}
function removeFilterRule(target, field){
var name = getPluginName(target);
var dg = $(target);
var opts = dg[name]('options');
if (field){
var index = getRuleIndex(target, field);
if (index >= 0){
opts.filterRules.splice(index, 1);
}
_clear([field]);
} else {
opts.filterRules = [];
var fields = dg.datagrid('getColumnFields',true).concat(dg.datagrid('getColumnFields'));
_clear(fields);
}
function _clear(fields){
for(var i=0; i<fields.length; i++){
var input = getFilterComponent(target, fields[i]);
if (input.length){
input[0].filter.setValue(input, '');
var menu = input[0].menu;
if (menu){
menu.find('.'+opts.filterMenuIconCls).removeClass(opts.filterMenuIconCls);
}
}
}
}
}
function doFilter(target){
var name = getPluginName(target);
var state = $.data(target, name);
var opts = state.options;
if (opts.remoteFilter){
$(target)[name]('load');
} else {
if (opts.view.type == 'scrollview' && state.data.firstRows && state.data.firstRows.length){
state.data.rows = state.data.firstRows;
}
$(target)[name]('getPager').pagination('refresh', {pageNumber:1});
$(target)[name]('options').pageNumber = 1;
$(target)[name]('loadData', state.filterSource || state.data);
}
}
function translateTreeData(target, children, pid){
var opts = $(target).treegrid('options');
if (!children || !children.length){return []}
var rows = [];
$.map(children, function(item){
item._parentId = pid;
rows.push(item);
rows = rows.concat(translateTreeData(target, item.children, item[opts.idField]));
});
$.map(rows, function(row){
row.children = undefined;
});
return rows;
}
function myLoadFilter(data, parentId){
var target = this;
var name = getPluginName(target);
var state = $.data(target, name);
var opts = state.options;
if (name == 'datagrid' && $.isArray(data)){
data = {
total: data.length,
rows: data
};
} else if (name == 'treegrid' && $.isArray(data)){
var rows = translateTreeData(target, data, parentId);
data = {
total: rows.length,
rows: rows
}
}
if (!opts.remoteFilter){
if (!state.filterSource){
state.filterSource = data;
} else {
if (!opts.isSorting) {
if (name == 'datagrid'){
state.filterSource = data;
} else {
state.filterSource.total += data.length;
state.filterSource.rows = state.filterSource.rows.concat(data.rows);
if (parentId){
return opts.filterMatcher.call(target, data);
}
}
} else {
opts.isSorting = undefined;
}
}
if (!opts.remoteSort && opts.sortName){
var names = opts.sortName.split(',');
var orders = opts.sortOrder.split(',');
var dg = $(target);
state.filterSource.rows.sort(function(r1,r2){
var r = 0;
for(var i=0; i<names.length; i++){
var sn = names[i];
var so = orders[i];
var col = dg.datagrid('getColumnOption', sn);
var sortFunc = col.sorter || function(a,b){
return a==b ? 0 : (a>b?1:-1);
};
r = sortFunc(r1[sn], r2[sn]) * (so=='asc'?1:-1);
if (r != 0){
return r;
}
}
return r;
});
}
data = opts.filterMatcher.call(target, {
total: state.filterSource.total,
rows: state.filterSource.rows
});
if (opts.pagination){
var dg = $(target);
var pager = dg[name]('getPager');
pager.pagination({
onSelectPage:function(pageNum, pageSize){
opts.pageNumber = pageNum;
opts.pageSize = pageSize;
pager.pagination('refresh',{
pageNumber:pageNum,
pageSize:pageSize
});
//dg.datagrid('loadData', state.filterSource);
dg[name]('loadData', state.filterSource);
},
onBeforeRefresh:function(){
dg[name]('reload');
return false;
}
});
if (name == 'datagrid'){
var start = (opts.pageNumber-1)*parseInt(opts.pageSize);
var end = start + parseInt(opts.pageSize);
data.rows = data.rows.slice(start, end);
} else {
var topRows = [];
var childRows = [];
$.map(data.rows, function(row){
row._parentId ? childRows.push(row) : topRows.push(row);
});
data.total = topRows.length;
var start = (opts.pageNumber-1)*parseInt(opts.pageSize);
var end = start + parseInt(opts.pageSize);
data.rows = topRows.slice(start, end).concat(childRows);
}
}
$.map(data.rows, function(row){
row.children = undefined;
});
}
return data;
}
function init(target, filters){
filters = filters || [];
var name = getPluginName(target);
var state = $.data(target, name);
var opts = state.options;
if (!opts.filterRules.length){
opts.filterRules = [];
}
opts.filterCache = opts.filterCache || {};
var dgOpts = $.data(target, 'datagrid').options;
var onResize = dgOpts.onResize;
dgOpts.onResize = function(width,height){
resizeFilter(target);
onResize.call(this, width, height);
}
var onBeforeSortColumn = dgOpts.onBeforeSortColumn;
dgOpts.onBeforeSortColumn = function(sort, order){
var result = onBeforeSortColumn.call(this, sort, order);
if (result != false){
opts.isSorting = true;
}
return result;
};
var onResizeColumn = opts.onResizeColumn;
opts.onResizeColumn = function(field,width){
var fc = $(this).datagrid('getPanel').find('.datagrid-header .datagrid-filter-c');
fc.hide();
$(target).datagrid('fitColumns');
if (opts.fitColumns){
resizeFilter(target);
} else {
resizeFilter(target, field);
}
fc.show();
onResizeColumn.call(target, field, width);
};
var onBeforeLoad = opts.onBeforeLoad;
opts.onBeforeLoad = function(param1, param2){
if (param1){
param1.filterRules = opts.filterStringify(opts.filterRules);
}
if (param2){
param2.filterRules = opts.filterStringify(opts.filterRules);
}
var result = onBeforeLoad.call(this, param1, param2);
if (result != false && opts.url) {
if (name == 'datagrid'){
state.filterSource = null;
} else if (name == 'treegrid' && state.filterSource){
if (param1){
var id = param1[opts.idField]; // the id of the expanding row
var rows = state.filterSource.rows || [];
for(var i=0; i<rows.length; i++){
if (id == rows[i]._parentId){ // the expanding row has children
return false;
}
}
} else {
state.filterSource = null;
}
}
}
return result;
};
// opts.loadFilter = myLoadFilter;
opts.loadFilter = function(data, parentId){
var d = opts.oldLoadFilter.call(this, data, parentId);
return myLoadFilter.call(this, d, parentId);
};
initCss();
createFilter(true);
createFilter();
if (opts.fitColumns){
setTimeout(function(){
resizeFilter(target);
}, 0);
}
$.map(opts.filterRules, function(rule){
addFilterRule(target, rule);
});
function initCss(){
if (!$('#datagrid-filter-style').length){
$('head').append(
'<style id="datagrid-filter-style">' +
'a.datagrid-filter-btn{display:inline-block;width:16px;height:16px;vertical-align:top;cursor:pointer;opacity:0.6;filter:alpha(opacity=60);}' +
'a:hover.datagrid-filter-btn{opacity:1;filter:alpha(opacity=100);}' +
'.datagrid-filter-row .textbox,.datagrid-filter-row .textbox .textbox-text{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;height:22px;line-height:22px;padding:0px;padding-left:3px;}' +
'.datagrid-filter-row input{margin:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;}' +
'.datagrid-filter-cache{position:absolute;width:10px;height:10px;left:-99999px;}' +
'</style>'
);
}
}
/**
* create filter component
*/
function createFilter(frozen){
var dc = state.dc;
var fields = $(target).datagrid('getColumnFields', frozen);
if (frozen && opts.rownumbers){
fields.unshift('_');
}
var table = (frozen?dc.header1:dc.header2).find('table.datagrid-htable');
// clear the old filter component
table.find('.datagrid-filter').each(function(){
if (this.filter.destroy){
this.filter.destroy(this);
}
if (this.menu){
$(this.menu).menu('destroy');
}
});
table.find('tr.datagrid-filter-row').remove();
var tr = $('<tr class="datagrid-header-row datagrid-filter-row"></tr>');
if (opts.filterPosition == 'bottom'){
tr.appendTo(table.find('tbody'));
} else {
tr.prependTo(table.find('tbody'));
}
if (!opts.showFilterBar){
tr.hide();
}
for(var i=0; i<fields.length; i++){
var field = fields[i];
var col = $(target).datagrid('getColumnOption', field);
var td = $('<td></td>').attr('field', field).appendTo(tr);
if (col && col.hidden){
td.hide();
}
if (field == '_'){
continue;
}
if (col && (col.checkbox || col.expander)){
continue;
}
var fopts = getFilter(field);
if (fopts){
$(target)[name]('destroyFilter', field); // destroy the old filter component
} else {
fopts = $.extend({}, {
field: field,
type: opts.defaultFilterType,
options: opts.defaultFilterOptions
});
}
var div = opts.filterCache[field];
if (!div){
div = $('<div class="datagrid-filter-c"></div>').appendTo(td);
var filter = opts.filters[fopts.type];
var input = filter.init(div, fopts.options||{});
input.addClass('datagrid-filter').attr('name', field);
input[0].filter = filter;
input[0].menu = createFilterButton(div, fopts.op);
if (fopts.options){
if (fopts.options.onInit){
fopts.options.onInit.call(input[0], target);
}
} else {
opts.defaultFilterOptions.onInit.call(input[0], target);
}
opts.filterCache[field] = div;
resizeFilter(target, field);
} else {
div.appendTo(td);
}
}
}
function createFilterButton(container, operators){
if (!operators){return null;}
var btn = $('<a class="datagrid-filter-btn"> </a>').addClass(opts.filterBtnIconCls);
if (opts.filterBtnPosition == 'right'){
btn.appendTo(container);
} else {
btn.prependTo(container);
}
var menu = $('<div></div>').appendTo('body');
$.map(['nofilter'].concat(operators), function(item){
var op = opts.operators[item];
if (op){
$('<div></div>').attr('name', item).html(op.text).appendTo(menu);
}
});
menu.menu({
alignTo:btn,
onClick:function(item){
var btn = $(this).menu('options').alignTo;
var td = btn.closest('td[field]');
var field = td.attr('field');
var input = td.find('.datagrid-filter');
var value = input[0].filter.getValue(input);
if (opts.onClickMenu.call(target, item, btn, field) == false){
return;
}
addFilterRule(target, {
field: field,
op: item.name,
value: value
});
doFilter(target);
}
});
btn[0].menu = menu;
btn.bind('click', {menu:menu}, function(e){
$(this.menu).menu('show');
return false;
});
return menu;
}
function getFilter(field){
for(var i=0; i<filters.length; i++){
var filter = filters[i];
if (filter.field == field){
return filter;
}
}
return null;
}
}
$.extend($.fn.datagrid.methods, {
enableFilter: function(jq, filters){
return jq.each(function(){
var name = getPluginName(this);
var opts = $.data(this, name).options;
if (opts.oldLoadFilter){
if (filters){
$(this)[name]('disableFilter');
} else {
return;
}
}
opts.oldLoadFilter = opts.loadFilter;
init(this, filters);
$(this)[name]('resize');
if (opts.filterRules.length){
if (opts.remoteFilter){
doFilter(this);
} else if (opts.data){
doFilter(this);
}
}
});
},
disableFilter: function(jq){
return jq.each(function(){
var name = getPluginName(this);
var state = $.data(this, name);
var opts = state.options;
var dc = $(this).data('datagrid').dc;
var div = dc.view.children('.datagrid-filter-cache');
if (!div.length){
div = $('<div class="datagrid-filter-cache"></div>').appendTo(dc.view);
}
for(var field in opts.filterCache){
$(opts.filterCache[field]).appendTo(div);
}
var data = state.data;
if (state.filterSource){
data = state.filterSource;
$.map(data.rows, function(row){
row.children = undefined;
});
}
$(this)[name]({
data: data,
loadFilter: (opts.oldLoadFilter||undefined),
oldLoadFilter: null
});
});
},
destroyFilter: function(jq, field){
return jq.each(function(){
var name = getPluginName(this);
var state = $.data(this, name);
var opts = state.options;
if (field){
_destroy(field);
} else {
for(var f in opts.filterCache){
_destroy(f);
}
$(this).datagrid('getPanel').find('.datagrid-header .datagrid-filter-row').remove();
$(this).data('datagrid').dc.view.children('.datagrid-filter-cache').remove();
opts.filterCache = {};
$(this)[name]('resize');
$(this)[name]('disableFilter');
}
function _destroy(field){
var c = $(opts.filterCache[field]);
var input = c.find('.datagrid-filter');
if (input.length){
var filter = input[0].filter;
if (filter.destroy){
filter.destroy(input[0]);
}
}
c.find('.datagrid-filter-btn').each(function(){
$(this.menu).menu('destroy');
});
c.remove();
opts.filterCache[field] = undefined;
}
});
},
getFilterRule: function(jq, field){
return getFilterRule(jq[0], field);
},
addFilterRule: function(jq, param){
return jq.each(function(){
addFilterRule(this, param);
});
},
removeFilterRule: function(jq, field){
return jq.each(function(){
removeFilterRule(this, field);
});
},
doFilter: function(jq){
return jq.each(function(){
doFilter(this);
});
},
getFilterComponent: function(jq, field){
return getFilterComponent(jq[0], field);
},
resizeFilter: function(jq, field){
return jq.each(function(){
resizeFilter(this, field);
});
}
});
})(jQuery);
InitDateFilter = function (dg, field, op) {
var filter = {
field: field,
type: 'datebox',
options: {
editable: false,
onChange: function (newValue, oldValue) {
var curRule = dg.datagrid("getFilterRule", field);
if (curRule != null) {
curRule.value = newValue;
dg.datagrid('addFilterRule', curRule);
}
}
},
op: op
};
return filter;
};
//Combox類型過濾
InitComboFilter = function (dg, field, data, url, valueField, textField, checkFiled, method) {
var comboOption;
if (url != null) {
comboOption = {
panelHeight: 'auto',
url: url,
method: method,
valueField: valueField,
textField: textField,
panelMaxHeight: 200,
onLoadSuccess: function (result) {
data = result;
},
onChange: function (value) {
DoComboFilter(dg, data, field, value, checkFiled);
}
};
}
else {
comboOption = {
panelHeight: 'auto',
data: data,
valueField: valueField,
textField: textField,
panelMaxHeight: 200,
onChange: function (value) {
DoComboFilter(dg, data, field, value, checkFiled);
}
};
}
var filter = {
field: field,
type: 'combobox',
options: comboOption,
}
//$(".datagrid-filter-row td[field='" + field + "']").find("input").height(22);
//console.log($(".datagrid-filter-row").html());
return filter;
};
InitNumberFilter = function (dg, field, op) {
var filter = {
field: field,
type: 'numberbox',
options: { precision: 1 },
op: op
};
return filter;
};
//啟動combo過濾器
function DoComboFilter(dg, data, field, value, checkFiled) {
if (value == "") {
dg.datagrid('removeFilterRule', field);
dg.datagrid('doFilter');
return;
}
// if (Common.CommonHelper.lslnArray(data, value, checkFiled)) {
dg.datagrid('addFilterRule', {
field: field,
op: 'equal',
value: value
});
dg.datagrid('doFilter');
// }
}
修改版datagrid-filter.js
為了實現(xiàn)一個目的:輸入數(shù)據(jù)后按回車查詢數(shù)據(jù)。
這個擴展可以集成:Easyui 90%的Form組件
1.時間
2.數(shù)字
3.下拉Combobox
4.密碼框
等等.......
實際上只用到1,2,3個Combxbox一般為動態(tài)數(shù)據(jù)AJAX從后臺獲取
看到代碼(我已經(jīng)封裝好了,盡情調(diào)用即可,想要了解就進入查看代碼寫法和邏輯)

上面的廢話已經(jīng)說完了!下面來說說如何調(diào)用
前端實現(xiàn)方式
1.引入datagrid-filter.js
<script src="~/Scripts/easyui/datagrid-filter.js"></script>
2.調(diào)用
調(diào)用之前來看看我們以前寫的datagrid。這是一個普通的datagrid
$('#List').datagrid({
url: '@Url.Action("GetList")',
width: SetGridWidthSub(10),
methord: 'post',
height: $(window).height()/2-35,
fitColumns: true,
sortName: 'CreateTime',
sortOrder: 'desc',
idField: 'Id',
pageSize: 15,
pageList: [15, 20, 30, 40, 50],
pagination: true,
striped: true, //奇偶行是否區(qū)分
singleSelect: true,//單選模式
remoteFilter:true,
columns: [[
{ field: 'Id', title: 'Id', width: 80,hidden:true},
{ field: 'Name', title: '產(chǎn)品名稱', width: 80, sortable: true },
{ field: 'Code', title: '產(chǎn)品代碼', width: 80, sortable: true },
{ field: 'Price', title: '產(chǎn)品價格', width: 80, sortable: true },
{ field: 'Color', title: '產(chǎn)品顏色', width: 80, sortable: true },
{ field: 'Number', title: '產(chǎn)品數(shù)量', width: 80, sortable: true },
{
field: 'CategoryId', title: '類別', width: 80, sortable: true, formatter: function (value, row, index) {
return row.ProductCategory;
}
},
{ field: 'ProductCategory', title: '類別', width: 80, sortable: true,hidden:true },
{ field: 'CreateTime', title: 'CreateTime', width: 80, sortable: true },
{ field: 'CreateBy', title: 'CreateBy', width: 80, sortable: true }
]]
});
那么我只想告訴大家我的DataGrid用的id名稱是List而已
var dg = $('#List');
var op = ['equal', 'notequal', 'less', 'greater'];
var comboData=[{ value: '', text: 'All' }, { value: 'P', text: 'P' }, { value: 'N', text: 'N' }]
dg.datagrid('enableFilter', [
InitNumberFilter(dg, 'Price', op),
InitNumberFilter(dg, 'Number', op),
InitDateFilter(dg, 'CreateTime', op),
InitComboFilter(dg, 'CategoryId', comboData, '', 'Id', 'Name', 'Name', "post")
]);
那么前端的效果就出來了!如此簡單都是因為封裝的JS幫我們做了大量的工作,效果如下:
說明一下:InitComboFilter如果是Ajax那么第4個參數(shù)傳URL即可,鍵值分別是Id和Name
其中:var op = ['equal', 'notequal', 'less', 'greater'];是漏斗,說再多也不明白,如要深入了解需要看源碼

3.回車執(zhí)行過濾
回車事件在源碼中的

到此,前端的調(diào)用就結(jié)束了!
后臺實現(xiàn)方式
因為前端會傳過來多一個參數(shù),所以我們后臺需要寫多一個參數(shù)來接受,修改以前的GridPager就補多一個參數(shù)就好了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Apps.Common
{
public class GridPager
{
public int rows { get; set; }//每頁行數(shù)
public int page { get; set; }//當(dāng)前頁是第幾頁
public string order { get; set; }//排序方式
public string sort { get; set; }//排序列
public int totalRows { get; set; }//總行數(shù)
public int totalPages //總頁數(shù)
{
get
{
return (int)Math.Ceiling((float)totalRows / (float)rows);
}
}
public string filterRules { get; set; }
}
public class GridRows<T>
{
public List<T> rows { get; set; }
public int total { get; set; }
}
}
public string filterRules { get; set; }
所以Controller沒有變化。
BLL變化如下:
using Apps.Common;
using Apps.Models;
using Apps.Models.Spl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Apps.Spl.BLL
{
public partial class Spl_ProductBLL
{
public override List<Spl_ProductModel> GetList(ref GridPager pager, string queryStr)
{
IQueryable<Spl_Product> queryData = null;
if (!string.IsNullOrWhiteSpace(queryStr))
{
queryData = m_Rep.GetList(
a=>a.Id.Contains(queryStr)
|| a.Name.Contains(queryStr)
|| a.Code.Contains(queryStr)
|| a.Color.Contains(queryStr)
|| a.CategoryId.Contains(queryStr)
|| a.CreateBy.Contains(queryStr)
);
}
else
{
queryData = m_Rep.GetList();
}
//啟用通用列頭過濾
if (!string.IsNullOrWhiteSpace(pager.filterRules))
{
List<DataFilterModel> dataFilterList = JsonHandler.Deserialize<List<DataFilterModel>>(pager.filterRules).Where(f => !string.IsNullOrWhiteSpace(f.value)).ToList();
queryData = LinqHelper.DataFilter<Spl_Product>(queryData, dataFilterList);
}
pager.totalRows = queryData.Count();
//排序
queryData = LinqHelper.SortingAndPaging(queryData, pager.sort, pager.order, pager.page, pager.rows);
return CreateModelList(ref queryData);
}
public override List<Spl_ProductModel> CreateModelList(ref IQueryable<Spl_Product> queryData)
{
List<Spl_ProductModel> modelList = (from r in queryData
select new Spl_ProductModel
{
Id = r.Id,
Name = r.Name,
Code = r.Code,
Price = r.Price,
Color = r.Color,
Number = r.Number,
CategoryId = r.CategoryId,
CreateTime = r.CreateTime,
CreateBy = r.CreateBy,
CostPrice = r.CostPrice,
ProductCategory = r.Spl_ProductCategory.Name
}).ToList();
return modelList;
}
}
}
//啟用通用列頭過濾
if (!string.IsNullOrWhiteSpace(pager.filterRules))
{
List<DataFilterModel> dataFilterList = JsonHandler.Deserialize<List<DataFilterModel>>(pager.filterRules).Where(f => !string.IsNullOrWhiteSpace(f.value)).ToList();
queryData = LinqHelper.DataFilter<Spl_Product>(queryData, dataFilterList);
}
其他都不變。
后臺也是做了大量大量的工作的,看LinqHelper這個類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Apps.Common
{
public class LinqHelper
{
/// <summary>
/// 排序
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="sortExpression"></param>
/// <param name="sortDirection"></param>
/// <returns></returns>
public static IQueryable<T> DataSorting<T>(IQueryable<T> source, string sortExpression, string sortDirection)
{
//錯誤查詢
if (string.IsNullOrEmpty(sortExpression) || string.IsNullOrEmpty(sortDirection))
{
return source;
}
string sortingDir = string.Empty;
if (sortDirection.ToUpper().Trim() == "ASC")
sortingDir = "OrderBy";
else if (sortDirection.ToUpper().Trim() == "DESC")
sortingDir = "OrderByDescending";
ParameterExpression param = Expression.Parameter(typeof(T), sortExpression);
PropertyInfo pi = typeof(T).GetProperty(sortExpression);
Type[] types = new Type[2];
types[0] = typeof(T);
types[1] = pi.PropertyType;
Expression expr = Expression.Call(typeof(Queryable), sortingDir, types, source.Expression, Expression.Lambda(Expression.Property(param, sortExpression), param));
IQueryable<T> query = source.AsQueryable().Provider.CreateQuery<T>(expr);
return query;
}
/// <summary>
/// 分頁
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public static IQueryable<T> DataPaging<T>(IQueryable<T> source, int pageNumber, int pageSize)
{
if (pageNumber <= 1)
{
return source.Take(pageSize);
}
else
{
return source.Skip((pageNumber - 1) * pageSize).Take(pageSize);
}
}
/// <summary>
/// 排序并分頁
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="sortExpression"></param>
/// <param name="sortDirection"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public static IQueryable<T> SortingAndPaging<T>(IQueryable<T> source, string sortExpression, string sortDirection, int pageNumber, int pageSize)
{
IQueryable<T> query = DataSorting<T>(source, sortExpression, sortDirection);
return DataPaging(query, pageNumber, pageSize);
}
///<summary>
///表達式操作
///</summary>
///<param name="right"></param>
///<param name="left"></param>
///<returns></returns>
public delegate Expression ExpressionOpretaDelegate(Expression left, Expression right);
/*
* if (!string.IsNullOrWhiteSpace(pager.filterRules))
* {
* IEnumerable<DataFilterModel> dataFilterList = JsonHelper.DeserializeJsonToObject<List<DataFilterModel>>(pager.filterRules).Where(f => !string.IsNullOrWhiteSpace(f.value));
* queryData = LinqHelper.DataFilter<SysSample>(queryData.AsQueryable(), dataFilterList);
* }
*/
///<summary>///通用數(shù)據(jù)列表按過濾方法
///</summary>
///<typeparam name="T">過濾的數(shù)據(jù)類型</typeparam>
///<param name="source">過濾的數(shù)據(jù)源</param>
///<paramname="dataFilterList">過濾條件集合(包含,字段名,值,操作符) </param>
///<returns></returns>
public static IQueryable<T> DataFilter<T>(IQueryable<T> source, IEnumerable<DataFilterModel> datas)
{
T obj = System.Activator.CreateInstance<T>();
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (var item in datas)
{
PropertyInfo p = properties.Where(pro => pro.Name == item.field).FirstOrDefault();
//不進行無效過濾
if (p == null || item.value == null)
{
continue;
}
if (p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(DateTime?))
{
//時間過1濾
source = DateDataFilter<T>(source, item, p);
}
else
{
//普通過濾
source = OrdinaryDataFilter<T>(source, item, p);
}
}
return source;
}
///<summary>
///普通數(shù)據(jù)過濾
///</summary>
///<typeparam name="T"></typeparam>
///<param name="source"></param>
///<param name="item"></param>
///<param name="p"></param>
///<retums></retums>
private static IQueryable<T> OrdinaryDataFilter<T>(IQueryable<T> source, DataFilterModel item, PropertyInfo p)
{
//var selectvalue = Convert.
// ChangeType(item.value, p.PropertyType);
var option = (DataFliterOperatorTypeEnum)
Enum.Parse(typeof(DataFliterOperatorTypeEnum), item.op);
switch (option)
{
case DataFliterOperatorTypeEnum.contains:
{
/* 包含, 目前只支持字符串 */
source = ExpressionOperate(StringContains, source, p, item.value);
break;
}
case DataFliterOperatorTypeEnum.equal:
{
/* 等于 */
source = ExpressionOperate(Expression.Equal, source, p, item.value);
break;
}
case DataFliterOperatorTypeEnum.greater:
{
/* 大于 */
source = ExpressionOperate(Expression.GreaterThan, source, p, item.value);
break;
}
case DataFliterOperatorTypeEnum.greaterorequal:
{
/* 大于等于 */
source =
ExpressionOperate(Expression.GreaterThanOrEqual, source, p, item.value);
break;
}
case DataFliterOperatorTypeEnum.less:
{
/* 小于 */
source = ExpressionOperate(Expression.LessThan, source, p, item.value);
break;
}
case DataFliterOperatorTypeEnum.lessorequal:
{
/* 小于等于 */
source = ExpressionOperate(Expression.LessThanOrEqual, source, p, item.value);
break;
}
default: break;
}
return (source);
}
///<summary>
///時間過濾
///</summary>
///<typeparam name="T"></typeparam>
///<param name="source"></param>
///<param name="item"></param>
///<param name="p"></param>
///<returns></returns>
public static IQueryable<T> DateDataFilter<T>(IQueryable<T> source, DataFilterModel item, PropertyInfo p)
{
var selectDate= Convert.ToDateTime(item.value);
var option= (DataFliterOperatorTypeEnum)
Enum.Parse(typeof(DataFliterOperatorTypeEnum), item.op);
switch(option)
{
case DataFliterOperatorTypeEnum.equal:
{
//大于0時
source=ExpressionOperate(Expression.GreaterThanOrEqual, source, p,selectDate);
//小于后一天
var nextDate= selectDate.AddDays(1);
source=ExpressionOperate(Expression.LessThan, source, p, nextDate);
break;
}
case DataFliterOperatorTypeEnum.greater:
{
//大于等于后一天
selectDate= selectDate.AddDays(1);
source=ExpressionOperate(Expression.GreaterThanOrEqual, source, p,selectDate);
break;
}
case DataFliterOperatorTypeEnum.greaterorequal:
{
//大于等于當(dāng)天
source=ExpressionOperate(Expression.GreaterThanOrEqual, source, p,selectDate);
break;
}
case DataFliterOperatorTypeEnum.less:
{
//小于當(dāng)天
source=ExpressionOperate(Expression. LessThan, source, p,selectDate);
break;
}
case DataFliterOperatorTypeEnum.lessorequal:
{
//小于第二天
selectDate= selectDate.AddDays(1);
source=ExpressionOperate(Expression. LessThan, source, p,selectDate);
break;
}
default: break;
}
return source;
}
///<summary>
///過濾操作
///</summary>
///<typeparam name="T"></typeparam>
//<typeparam name="V"></typeparam>
///<paramname="operateExpression"></ param>
///<param name="source"></param>
///<param name="p"></param> ///<param name="value"></param>
///<returns></returns>
private static IQueryable<T> ExpressionOperate<T, V>(ExpressionOpretaDelegate operateExpression, IQueryable<T> source, PropertyInfo p, V value)
{
Expression right = null;
if (p.PropertyType == typeof(Int32))
{
int val = Convert.ToInt32(value);
right = Expression.Constant(val, p.PropertyType);
}
else if (p.PropertyType == typeof(Decimal))
{
Decimal val = Convert.ToDecimal(value);
right = Expression.Constant(val, p.PropertyType);
}
else if (p.PropertyType == typeof(Byte))
{
Byte val = Convert.ToByte(value);
right = Expression.Constant(val, p.PropertyType);
}
else
{
right = Expression.Constant(value, p.PropertyType);
}
ParameterExpression param = Expression.Parameter(typeof(T), "x");
Expression left = Expression.Property(param, p.Name);
Expression filter = operateExpression(left, right);
Expression<Func<T, bool>> pred = Expression.Lambda<Func<T, bool>>(filter, param);
source = source.Where(pred);
return source;
}
///<summary>
///字符串包含操作
///</summary>
///<param name="left"></param>
///<param name="right"></param>
///<returns></returns>
public static Expression StringContains(Expression left, Expression right)
{
Expression filter = Expression.Call(left, typeof(string).GetMethod("Contains"), right);
return filter;
}
}
}
預(yù)覽效果:

總結(jié)
實現(xiàn)一個組合查詢,只需要在原來的基礎(chǔ)上添加幾行代碼
后臺:
//啟用通用列頭過濾
if (!string.IsNullOrWhiteSpace(pager.filterRules))
{
List<DataFilterModel> dataFilterList = JsonHandler.Deserialize<List<DataFilterModel>>(pager.filterRules).Where(f => !string.IsNullOrWhiteSpace(f.value)).ToList();
queryData = LinqHelper.DataFilter<Spl_Product>(queryData, dataFilterList);
}
前端:
var dg = $('#List');
var op = ['equal', 'notequal', 'less', 'greater'];
var comboData={Category:[]}; //[{ value: '', text: 'All' }, { value: 'P', text: 'P' }, { value: 'N', text: 'N' }]
dg.datagrid('enableFilter', [
InitNumberFilter(dg, 'Price', op),
InitNumberFilter(dg, 'Number', op),
InitDateFilter(dg, 'CreateTime', op),
InitComboFilter(dg, 'CategoryId', comboData, '../Spl/ProductCategory/GetComboxData', 'Id', 'Name', 'Name', "post")
]);
完全沒有任何邏輯,誰都能用,示例代碼下載
http://pan.baidu.com/s/1dF409yx
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- .NET?8新預(yù)覽版使用?Blazor?組件進行服務(wù)器端呈現(xiàn)(項目體驗)
- 國產(chǎn)化中的?.NET?Core?操作達夢數(shù)據(jù)庫DM8的兩種方式(操作詳解)
- 解決Win10無法安裝.Net Framework 3.5提示錯誤代碼0x800F081F
- ASP.NET Core異常和錯誤處理(8)
- win8/8.1系統(tǒng)安裝.net framework 3.5出現(xiàn)0x800F0906代碼錯誤的解決方法
- ASP.NET 程序員都非常有用的85個工具
- 無法啟動.NET Framework NGEN v4.0.30319_X86服務(wù)的解決方法
- .NET8 依賴注入
相關(guān)文章
asp.net gridview的Rowcommand命令中獲取行索引的方法總結(jié)
asp.net gridview的Rowcommand命令中獲取行索引的方法總結(jié),需要的朋友可以參考下。2010-05-05
ASP.NET Core設(shè)置URLs的方法匯總(完美解決.NET 6項目局域網(wǎng)IP地址遠程無法訪問的
近期在dotnet項目中遇到這樣的問題.net6 運行以后無法通過局域網(wǎng)IP地址遠程訪問,整理出解決問題的五種方式方法,感興趣的朋友一起看看吧2023-11-11
運行page頁面時的事件執(zhí)行順序及頁面的回發(fā)與否深度了解
page頁面時的事件執(zhí)行順序的了解對于一些.net開發(fā)者起到者尤關(guān)重要的作用;頁面的回發(fā)與否會涉及到某些事件執(zhí)行與不執(zhí)行,在本文中會詳細介紹,感興趣的朋友可以了解下2013-01-01
ASP.NET服務(wù)器控件開發(fā)(1)封裝html
在我們的項目開發(fā)中,由于ASP.NET的服務(wù)器控件功能有限,所以我們經(jīng)常會自己定義特定的服務(wù)器控件,來滿足開發(fā)中特定的業(yè)務(wù)要求??梢娭廊绾伍_發(fā)ASP.NET服務(wù)器控件是非常有必要的2015-12-12
aspx中的mysql操作類sqldatasource使用示例分享
服務(wù)器裝了mysql odbc驅(qū)動,想在那個iis上操作另一個服務(wù)器的mysql,找到個.net的sqldatasource類可以操作mysql,下在把使用方法分享一下2014-01-01

