ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)实例

前言

听标题的名字似乎是一个非常牛X复杂的功能,但是实际上它确实是非常复杂的,我们本节将演示如何实现对数据,进行组合查询(数据筛选)

我们都知道Excel中是如何筛选数据的.就像下面一样

他是一个并的关系,我们现在要做的也是这样的效果,下面我们将利用EasyUI的DataGrid为例来扩展(就算是其他组件也是可以的,同样的实现方式!)

实现思路

1.前台通过查询组合json

2.后台通过反射拆解json

3.进行组合查询

虽然短短3点,够你写个3天天夜了

优点:需要从很多数据中得到精准的数据,通常查一些商品他们的属性异常接近的情况下使用

缺点:我实现的方式为伪查询,大量数据请使用存储过程

简单了解

从Easyui的官方扩展中了解到一个JS文件,但是实质上,这个文件BUG很多,在使用中我曾经一度认为是使用出现问题,其实他根本就不可用

所以我这里先献上修改后的整个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

为了实现一个目的:输入数据后按回车查询数据。

这个扩展可以集成:Easyui 90%的Form组件

1.时间

2.数字

3.下拉Combobox

4.密码框

等等.......

实际上只用到1,2,3个Combxbox一般为动态数据AJAX从后台获取

看到代码(我已经封装好了,尽情调用即可,想要了解就进入查看代码写法和逻辑)

上面的废话已经说完了!下面来说说如何调用

前端实现方式

1.引入datagrid-filter.js

<script src="~/Scripts/easyui/datagrid-filter.js"></script>

2.调用

调用之前来看看我们以前写的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, //奇偶行是否区分
   singleSelect: true,//单选模式
   remoteFilter:true,
   columns: [[
    { field: 'Id', title: 'Id', width: 80,hidden:true},
    { field: 'Name', title: '产品名称', width: 80, sortable: true },
    { field: 'Code', title: '产品代码', width: 80, sortable: true },
    { field: 'Price', title: '产品价格', width: 80, sortable: true },
    { field: 'Color', title: '产品颜色', width: 80, sortable: true },
    { field: 'Number', title: '产品数量', 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个参数传URL即可,键值分别是Id和Name

其中:var op = ['equal', 'notequal', 'less', 'greater'];是漏斗,说再多也不明白,如要深入了解需要看源码

3.回车执行过滤

回车事件在源码中的

到此,前端的调用就结束了!

后台实现方式

因为前端会传过来多一个参数,所以我们后台需要写多一个参数来接受,修改以前的GridPager就补多一个参数就好了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Apps.Common
{
  public class GridPager
 {
  public int rows { get; set; }//每页行数
  public int page { get; set; }//当前页是第几页
  public string order { get; set; }//排序方式
  public string sort { get; set; }//排序列
  public int totalRows { get; set; }//总行数
  public int totalPages //总页数
  {
   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>///通用数据列表按过滤方法
  ///</summary>
  ///<typeparam name="T">过滤的数据类型</typeparam>
  ///<param name="source">过滤的数据源</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>
  ///普通数据过滤
  ///</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:
    {
     //大于等于当天
     source=ExpressionOperate(Expression.GreaterThanOrEqual, source, p,selectDate);
     break;
    }

    case DataFliterOperatorTypeEnum.less:
    {
     //小于当天
     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;
  }

 }
}

预览效果:

总结

实现一个组合查询,只需要在原来的基础上添加几行代码

后台:

 //启用通用列头过滤
   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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET MVC5+EF6+EasyUI后台管理系统 微信公众平台开发之资源环境准备

    前言: 本次将学习扩展企业微信公众号功能,微信公众号也是企业流量及品牌推广的主要途径,所谓工欲善其事必先利其器,调试微信必须把程序发布外网环境,导致调试速度太慢,太麻烦! 我们需要准备妥当才能进入开发,为后续快速开发作准备 什么是内网穿透? 意在外部网络通过域名可以访问本地IIS站点! 软件环境: Windows10+IIS10 (把本地站点配置到IIS10做为备用,发布站点不作为教程) 知识点:花生壳(主要)ngrok开始: 首先发布站点到IIS,我这里发布站点到本地IIS,并绑定端口为:80

  • ASP.NET MVC5+EF6+EasyUI后台管理系统 微信公众平台开发之消息管理

    前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较多 思维导图 我这个人比较喜欢用思维导图来分析和表达一些模型: 表结构  根据思维导图,我们可以建立的表可以是3张表:消息表,规则表,类型表 消息表:实际的消息 规则表:文本.图文.语音等 类型表:文本.图文.语音(默认回复,订阅回复) 也可以是两张表:规制表,消息表(+一个类型字段) 我这里只设计一张表:消

  • ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)实例

    前言 听标题的名字似乎是一个非常牛X复杂的功能,但是实际上它确实是非常复杂的,我们本节将演示如何实现对数据,进行组合查询(数据筛选) 我们都知道Excel中是如何筛选数据的.就像下面一样 他是一个并的关系,我们现在要做的也是这样的效果,下面我们将利用EasyUI的DataGrid为例来扩展(就算是其他组件也是可以的,同样的实现方式!) 实现思路 1.前台通过查询组合json 2.后台通过反射拆解json 3.进行组合查询 虽然短短3点,够你写个3天天夜了 优点:需要从很多数据中得到精准的数据,通

  • ASP.NET中MVC从后台控制器传递数据到前台视图的方式

    本文实例讲述了ASP.NET中MVC从后台控制器传递数据到前台视图的方式.分享给大家供大家参考.具体分析如下: 数据存储模型Model: 复制代码 代码如下: public class CalendarEvent { public string id { get; set; } public DateTime start { get; set; } public DateTime end { get; set; } public string backgroundColor { get; set

  • 一个简单MVC5 + EF6示例分享

    本文所使用的软件及环境: Visual Studio Ultimate 2013; MVC5 + EF6 + .NET Framework 4.5 + LocalDB;Windows 7 x64 Professional 说明: 1.在EF (Entity Framework,以下简称EF6)框架下,操作数据的方式有三种:Database First, Model First, 以及 Code First,本文基于Code First创建. 2.本文是基于MVC5创建: 3.LocalDB Lo

  • ASP.NET MVC5网站开发概述(一)

    前段时间一直在用MVC4写个网站开发的demo,由于刚开始学所有的代码都写在一个项目中,越写越混乱,到后来有些代码自己都理不清了.正好看到别人在用MVC5写东西,喜新厌旧的我马上下载了Visual Studio 2013,幸好MVC4到MVC5变化不大,这次准备用MVC5重新写个Demo. 每次看以前写的代码总有把它丢进回收站的冲动,其实没有完美的代码,能解决问题的代码就算是好代码吧,但是我还是决定重新写一个学习的Demo,希望这次能有提高,希望这次能写完吧! 一.开发环境 1.开发环境: Vi

  • ASP.NET MVC5 网站开发框架模型、数据存储、业务逻辑(三)

    前面项目的层次和调用关系都说明了,关系如下图 采用三层架构的时候,研究过BLL层的必要性,觉得业务逻辑完全可以在controller里实现,没有必要单独做一个项目,另一个分层多了会影响性能.后来我还是把业务逻辑独立出来,原因如下: 业务逻辑写进controller里代码看着比较混乱,时间久了代码容易理不清. 在controller里直接写逻辑重复代码会不较多,开发效率低. 分项目有利于代码重用,有时候可以直接拿到其他项目中稍作修改就可以用. 对于性能我觉得分层多了肯定会有影响,但是不会很大.现在

  • ASP.NET MVC5网站开发管理列表、回复及删除(十三)

    一.管理列表 跟上次我的列表相似,直接贴代码了. 首先打开Consultation控制器,添加ManageList方法 /// <summary> /// 咨询管理 /// </summary> /// <returns></returns> public ActionResult ManageList() { return View(); } 添加返回json数据的ManageJsonList public JsonResult ManageJsonLis

  • 详解使用React全家桶搭建一个后台管理系统

    引子 学生时代为了掌握某个知识点会不断地做习题,做总结,步入岗位之后何尝不是一样呢?做业务就如同做习题,如果'课后'适当地进行总结,必然更快地提升自己的水平. 由于公司采用的react+node的技术栈,于是就完成了一个reactSPA小项目,计划日后把平时工作中遇到的业务以及学习中遇到有趣的东西给抽象成demo展示出来.目前该项目只是把雏形搭好,效果如下.在此文的基础上,写了篇新文章使用React全家桶搭建一个后台管理系统,欢迎围观.(附注:因为项目不时更新,文章不一定会即时更新,所以以实际的

  • 使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)

    在上篇文章给大家介绍了使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一) 1. 引入路由工具vue-router,切换视图 # 安装vue-router cnpm install vue-router --save-dev 2. 使用vue-router main.js import Vue from 'vue' import App from './App' import VueRouter from 'vue-router' import routeConfig f

随机推荐