一、问提描述
前几天遇到elementUI table 筛选问题,按照Element UI筛选案例实现后发现,筛选后出现很多页,然而第一页都没满。发现筛选不是服务器端筛选,而是浏览器端单页面筛选。那么如何实现服务器端筛选呢?
二、查询Element UI 官网table组件发现:
1、Afilter-change事件,说明:当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。参数:filters。
2、 prop属性,说明:对应列内容的字段名,也可以使用 property 属性。类型 string
3、filters属性,说明:数据过滤的选项,数组格式,数组中的元素需要有 text 和 value 属性。类型 Array[{test,value}]
4、column-key属性,说明:column 的 key,如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件 类型:string
5、filter-method方法,没找到说明。找到用法:在列中定义 :filter-method="filterHandler" 然后实现 filterHandler方法。 --测试发现只能实现单个页面逐个筛选,无法整体筛选。
三、用法
由于没有案例,理解这段话非常困难, 经过反复调试,发现用法是:
1.在 el-table标签 @filter-change="handleFilterChange" ,
2. 在vue周期函数methods: {}中实现
handleFilterChange 方法:可以监听整个table中过滤条件变化;
setFilter方法:按照服务器api需要的格式组装过滤条件;
getList()方法:发送请求;
3 在 el-table-column 列中,当以过滤条件 :filters="userStatusNameFilters"、column-key="UserStatusName"、prop="UserStatusName" 三者缺一不可。
4 在data(){return{ userStatusNameFilters: [] }} 定义数组
四、实际案例:
1、vue文件
<template> <div class="app-container"> <div style="margin-left:20px"> <el-form ref="queryForm" label-position="left" label-width="70px" inline size="small" > <el-form-item label="用户名:" > <el-input v-model="queryInfo" style="width: 300px;" placeholder="请输入用户名或姓名" /> </el-form-item> <el-form-item label="" > <el-button type="primary" @click="queryClick">查询</el-button> </el-form-item> </el-form> </div> <el-table v-loading="listLoading" :key="tableKey" :data="list" :border="false" :stripe="true" size="small" style="width: 100%;" @filter-change="handleFilterChange" > <el-table-column :filters="regionNameFilters" column-key="RegionName" label="行政区域" prop="RegionName" align="center" width="120px" /> <el-table-column label="用户ID" prop="UserID" align="center" width="57px" /> <el-table-column label="用户名" prop="UserName" align="center" min-width="100px"/> <el-table-column :filters="userRoleTypeFilters" label="用户角色" prop="UserRoleName" column-key="UserRoleName" align="center" width="80px" > <template slot-scope="scope" > <span> {{ scope.row.UserRoleName }}</span> </template> </el-table-column> <el-table-column label="姓名" prop="RealName" align="center" min-width="80px"/> <el-table-column label="所属单位" prop="Department" align="center" min-width="100px"/> <el-table-column label="联系电话" prop="Phone" align="center" width="110px" /> <el-table-column label="备注" prop="Description" align="center" min-width="100px"/> <el-table-column :filters="userStatusNameFilters" column-key="UserStatusName" label="用户状态" prop="UserStatusName" align="center" min-width="80px" /> <el-table-column :render-header="renderHeader" label="操作" align="center" width="100px" class-name="small-padding fixed-width" > <template slot-scope="scope" > <el-button type="text" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <confirm-poptip type="text" size="mini" @on-ok="handleDelete(scope.row)"/> </template> </el-table-column> </el-table> <div class="pagination-container"> <el-pagination :current-page="listQuery.page" :page-sizes="[10,15,20,30, 50]" :disabled="listLoading" :page-size="listQuery.limit" :total="total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"/> </div> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="600px"> <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" size="small" > <el-form-item label="行政区域" prop="AdminCode"> <el-cascader :options="adminRegionTypeOptions" v-model="temp.AdminCode" :show-all-levels="false" change-on-select filterabl expand-trigger="hover" /> </el-form-item> <el-form-item label="用户名" prop="UserName"> <el-input v-if="dialogStatus=='create'" v-model="temp.UserName" :maxlength="20"/> <el-input v-else v-model="temp.UserName" :disabled="true" :maxlength="20"/> </el-form-item> <el-form-item label="密码" prop="Password"> <el-input v-model="temp.Password" :maxlength="20" /> </el-form-item> <el-form-item label="用户角色" prop="UserRole"> <el-select v-model="temp.UserRole" class="filter-item"> <el-option v-for="item in userRoleTypeOptions" :key="item.id" :label="item.name" :value="item.id"/> </el-select> </el-form-item> <el-form-item label="用户状态" prop="UserStatus" > <el-select v-model="temp.UserStatus" class="filter-item" placeholder="Please select"> <el-option v-for="item in userStatusTypeOptions" :key="item.id" :label="item.name" :value="item.id"/> </el-select> </el-form-item> <el-form-item label="真实姓名" prop="RealName"> <el-input v-model="temp.RealName" :maxlength="20"/> </el-form-item> <el-form-item label="联系电话" prop="Phone"> <el-input v-model="temp.Phone" :maxlength="20" /> </el-form-item> <el-form-item label="所属单位" prop="Department"> <el-input v-model="temp.Department" :maxlength="50" /> </el-form-item> <el-form-item label="备注" prop="Description" > <el-input v-model="temp.Description" :maxlength="50" :autosize="{ minRows: 2, maxRows: 4}" type="textarea"/> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">取 消</el-button> <el-button v-if="dialogStatus=='create'" type="primary" @click="createData">确 定</el-button> <el-button v-else type="primary" @click="updateData">确 定</el-button> </div> </el-dialog> </div> </template> <script> import { getUserRoleData, getUserStatusData, getAdminRegionTree, getAdminRegionName, getList, getInfo, add, update, remove } from '@/api/user' import waves from '@/directive/waves' // 水波纹指令 export default { name: 'ComplexTable', directives: { waves }, filters: { // statusFilter(status) { // const statusMap = { // published: 'success', // draft: 'info', // deleted: 'danger' // } // return statusMap[status] // } }, data() { return { tableKey: 0, list: null, total: null, listLoading: true, listQuery: { page: 1, limit: 15, filters: [] }, queryInfo: null, userRoleTypeOptions: [], // taskStatusType: 0, userStatusTypeOptions: [], // collectDataTypeOptions: [], collectUsersTypeOptions: [], adminRegionTypeOptions: [], userRoleTypeFilters: [], userStatusNameFilters: [], regionNameFilters: [], temp: { UserID: undefined, UserName: '', Password: '', RealName: '', UserRole: 0, // 角色默认游客 UserStatus: 0, // 状态默认正常 Phone: '', Department: '', AdminCode: ['630000000000'], // 行政区域默认青海省 Description: '' // CollectDataType: 1, // TaskStatusType: 0 }, filters: [], dialogFormVisible: false, dialogStatus: '', textMap: { update: '编辑', create: '新建' }, rules: { UserName: [{ required: true, message: '不能为空', trigger: 'change' }] // CollectDataType: [{ required: true, message: '不能为空', trigger: 'change' }], // TaskStatusType: [{ required: true, message: '不能为空', trigger: 'change' }] } } }, watch: { // taskStatusType() { // this.getList() // } }, created() { // this.getStatusData() // this.getCollectDataTypeData() // this.getCollectUsers(); this.getAdminRegionName() this.getAdminRegionTree() this.getUserRoleData() this.getUserStatusData() this.getList() }, methods: { // 当talbel中任何一列的过滤条件点击确定和覆盖时,都会触发此事件。 handleFilterChange(filters) { // console.log(filters) // console.log('筛选条件发生变化') let row = null let val = null // 拷贝filters的值。 for (const i in filters) { row = i // 保存 column-key的值,如果事先没有为column-key赋值,系统会自动生成一个唯一且恒定的名称 val = filters[i] } const filter = [{ row: row, op: 'contains', value: val }] // console.log(filter) this.setFilter(filter) }, // filterUserRoleName(value, row) { // return row.UserRoleName === value // }, getList() { this.listLoading = true var filters = [] for (var i in this.filters) { // 去除value数组为空的值 if (this.filters[i].value && this.filters[i].value.length > 0) { filters.push({ 'field': this.filters[i].row, 'op': this.filters[i].op, 'value': this.filters[i].value }) } } if (filters.length > 0) { // 将 JavaScript 值(通常为对象或数组)转换为 JSON 字符串 this.listQuery.filters = JSON.stringify(filters) } else { this.listQuery.filters = null } this.listQuery.query = this.queryInfo console.log(filters) getList(this.listQuery).then(response => { // console.log(response.data.rows); this.list = response.data.rows this.total = response.data.total this.listLoading = false }) }, queryClick() { this.getList() }, // 通过中间变量this.filters数组,保存当前table中所有列过滤条件的变化。 setFilter(filters) { for (var i in filters) { var filter = null for (var j in this.filters) { // 如果filters[i]中存在于this.filter[]相同的值,那么把当前this.filter[i]的引用覆盖filter的引用. if (filters[i]['row'] === this.filters[j]['row']) { filter = this.filters[j] } } // 如果filter为空,即不存在相同的值,则将当前filter[i]添加到this.filter[] if (filter == null) { this.filters.push({ 'row': filters[i].row, 'op': filters[i].op, 'value': filters[i].value }) } else { // 如果filter不为空,即存在相同的值。则将filter[i] 赋值给filter,本质是更新this.filter[i]的值。 filter.value = filters[i].value filter.op = filters[i].op } } // console.log(this.filters) this.listQuery.page = 1 this.getList() }, getUserRoleData() { getUserRoleData().then(response => { this.userRoleTypeOptions = response.data var temp = [] for (var i = 0; i < this.userRoleTypeOptions.length; i++) { var name = this.userRoleTypeOptions[i].name temp.push({ text: name, value: name }) } this.userRoleTypeFilters = temp.slice(0) }) }, getUserStatusData() { getUserStatusData().then(response => { // console.log(response.data); this.userStatusTypeOptions = response.data var temp = [] for (var i = 0; i < this.userStatusTypeOptions.length; i++) { var name = this.userStatusTypeOptions[i].name temp.push({ text: name, value: name }) } this.userStatusNameFilters = temp.slice(0) }) }, getAdminRegionTree() { getAdminRegionTree().then(response => { // console.log(response.data) this.adminRegionTypeOptions = response.data }) }, getAdminRegionName() { getAdminRegionName().then(response => { var temp = [] for (var i = 0; i < response.data.length; i++) { temp.push({ text: response.data[i].name, value: response.data[i].name }) } this.regionNameFilters = temp.slice(0) // console.log(this.regionNameFilters) }) }, // getCollectDataTypeData() { // getCollectDataTypeData().then(response => { // this.collectDataTypeOptions = response.data // }) // }, renderHeader(h, params) { return h('el-button', { props: { type: 'text', size: 'mini' }, on: { click: () => { this.handleCreate() } } }, '添加') }, handleFilter() { this.listQuery.page = 1 this.getList() }, handleSizeChange(val) { this.listQuery.limit = val this.getList() }, handleCurrentChange(val) { this.listQuery.page = val this.getList() }, // handleModifyStatus(row, status) { // this.$message({ // message: '操作成功', // type: 'success' // }) // row.status = status // }, resetTemp() { this.temp = { UserID: undefined, UserName: '', Password: '', RealName: '', UserRole: 0, // 角色默认游客 UserStatus: 0, // 状态默认正常 Phone: '', Department: '', AdminCode: ['630000000000'], // 行政区域默认青海省 Description: '' // CollectDataType: 1, // TaskStatusType: 0 } }, handleCreate() { this.resetTemp() this.dialogStatus = 'create' this.dialogFormVisible = true this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) }, createData() { this.$refs['dataForm'].validate((valid) => { if (valid) { var mytemp = Object.assign({}, this.temp) mytemp.AdminCode = mytemp.AdminCode[mytemp.AdminCode.length - 1] add(mytemp).then((response) => { console.log(response) if (response.data) { var mydata = response.data mydata.AdminCode = [mydata.AdminCode] this.temp = mydata console.log(this.temp) } this.list.unshift(this.temp) this.dialogFormVisible = false this.$notify({ title: '成功', message: '创建成功', type: 'success', duration: 2000 }) }) } }) }, handleUpdate(row) { var mydata = Object.assign({}, row) // 递归检索 检索到后返回 同时返回上一级 mydata.AdminCode = this.findAdminCode(this.adminRegionTypeOptions, mydata.AdminCode) this.temp = mydata // console.log(this.temp.AdminCode) this.dialogStatus = 'update' this.dialogFormVisible = true this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) getInfo(row.UserID).then((response) => { if (response.success) { var mydata = response.data mydata.AdminCode = this.findAdminCode(this.adminRegionTypeOptions, mydata.AdminCode) this.temp = mydata // console.log(this.temp.AdminCode) for (const v of this.list) { if (v.UserID === this.temp.UserID) { const index = this.list.indexOf(v) this.list.splice(index, 1, this.temp) break } } } }) }, findAdminCode(treeData, key) { const arr = [] // 在递归时操作的数组 let returnArr = [] // 存放结果的数组 let depth = 0 // 定义全局层级 // 定义递归函数 function childrenEach(childrenData, depthN) { for (var j = 0; j < childrenData.length; j++) { depth = depthN // 将执行的层级赋值 到 全局层级 arr[depthN] = (childrenData[j].value) if (childrenData[j].value === key) { // returnArr = arr; // 原写法不行, 因 此赋值存在指针关系 returnArr = arr.slice(0, depthN + 1) // 将目前匹配的数组,截断并保存到结果数组, break } else { if (childrenData[j].children) { depth++ childrenEach(childrenData[j].children, depth) } } } return returnArr } return childrenEach(treeData, depth) }, updateData() { this.$refs['dataForm'].validate((valid) => { if (valid) { var mytemp = Object.assign({}, this.temp) mytemp.AdminCode = mytemp.AdminCode[mytemp.AdminCode.length - 1] update(mytemp).then((response) => { if (response.data) { // this.temp = response.data var mydata = response.data mydata.AdminCode = [mydata.AdminCode] this.temp = mydata } for (const v of this.list) { if (v.UserID === this.temp.UserID) { const index = this.list.indexOf(v) this.list.splice(index, 1, this.temp) break } } this.dialogFormVisible = false this.$notify({ title: '成功', message: '更新成功', type: 'success', duration: 2000 }) }) } }) }, handleDelete(row) { remove(row.UserID).then((response) => { if (response.success) { this.$notify({ title: '成功', message: '删除成功', type: 'success', duration: 2000 }) const index = this.list.indexOf(row) this.list.splice(index, 1) } }) } // deepCopy(obj) { // // obj的属性全部为基础类型,不能有引用类型 // if (typeof obj !== 'object') { return } // var str = JSON.stringify(obj) // return JSON.parse(str) // } } } </script>
2、封装的Url: use.js
import request from '@/utils/request' export function getUserRoleData() { return request({ url: '/user/UserRoleData', method: 'get' }) } export function getUserStatusData() { return request({ url: '/user/UserStatusData', method: 'get' }) } export function getAdminRegionName() { return request({ url: '/adminRegion/AdminRegionName', method: 'get' }) } export function getAdminRegionTree() { return request({ url: '/adminRegion/RegionTree', method: 'get' }) } export function getCollectUsers() { return request({ url: '/user/CollectUsers', method: 'get' }) } export function getList(query) { return request({ url: '/user/list', method: 'get', params: query }) } export function getInfo(id) { return request({ url: '/user/' + id, method: 'get' }) } export function add(data) { return request({ url: '/user', method: 'post', data }) } export function update(data) { return request({ url: '/user', method: 'put', data }) } export function remove(id) { return request({ url: '/user/' + id, method: 'delete' }) }
C# 后端webApi
using Microsoft.AspNet.Identity; using PastureSpace.BLL; using PastureSpace.Models; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace PastureSpace.Controllers.Api { [RoutePrefix("Api/User")] public class UserController : ApiController { UserManage manage = new UserManage(); [HttpGet] [Route("UserRoleData")] public ApiResult GetUserRoleData() { ApiResult result = new ApiResult(); result.success = true; result.data = manage.GetUserRoleData().Select(d => new { id = d.EnumID, name = d.EnumName }); return result; } [HttpGet] [Route("UserStatusData")] public ApiResult GetUserStatusData() { ApiResult result = new ApiResult(); result.success = true; result.data = manage.GetUserStatusData().Select(d => new { id = d.EnumID, name = d.EnumName }); return result; } [HttpGet] [Route("CollectUsers")] public ApiResult GetCollectUsers() { ApiResult result = new ApiResult(); result.success = true; result.data = manage.GetQueryable().Where(d=>d.UserRole == 0).Select(d => new { id = d.UserID, name = d.RealName }); return result; } [HttpGet] [Route("List")] public ApiResult GetList(int page, int limit, string sort = null, string order = null, string filters = null, string query = null) { PageModel p = new PageModel(); if (filters != null) { p.filters = Newtonsoft.Json.JsonConvert.DeserializeObject<Filter[]>(filters); } p.page = page; p.rows = limit; p.sort = sort; p.order = order; if (p.page <= 0) { p.page = 1; } if (p.rows <= 0) { p.rows = 10; } var data = manage.GetQueryable().Select(d => d); //过滤 data = data.Where(p.filters); //搜索条件 if (query != null && query.Length > 0) { data = data.Where(new string[] { "UserName", "RealName" }, query); } //排序 if (order != "normal" && sort != null) { bool isAsc = order == "asc"; data = data.OrderBy(new[] { sort }, new[] { isAsc }); } else { //默认排序 data = data.OrderBy(d => d.UserID); } DataModel pageData = new DataModel(); pageData.page = p.page; pageData.total = data.Count(); pageData.rows = data.Skip((p.page - 1) * p.rows).Take(p.rows).ToList(); ApiResult result = new ApiResult(); result.success = true; result.data = pageData; return result; } [HttpGet] public ApiResult GetInfo(int id) { ApiResult result = new ApiResult(); result.success = true; result.data = manage.GetInfo(id); return result; } [HttpPost] public ApiResult Add(UserAccount info) { var result = new ApiResult(); result.data = manage.Add(info); result.success = true; return result; } [HttpPut] public ApiResult Modify(UserAccount info) { var result = new ApiResult(); result.data = manage.Modify(info); result.success = true; return result; } [HttpDelete] public ApiResult Delete(int id) { manage.Delete(id); var result = new ApiResult(); result.success = true; return result; } } }
C#书写 where orderby 重载
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Web; namespace PastureSpace.Models { public static class QueryableExtension { public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string[] propertyName, bool[] ascending) where T : class { Type type = typeof(T); for (int i = 0; i < propertyName.Length; i++) { PropertyInfo property = type.GetProperty(propertyName[i]); if (property == null) throw new ArgumentException("propertyName", "Not Exist"); ParameterExpression param = Expression.Parameter(type, "p"); Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property); LambdaExpression orderByExpression = Expression.Lambda(propertyAccessExpression, param); string methodName = ascending[i] ? "OrderBy" : "OrderByDescending"; if (i != 0) { methodName = ascending[i] ? "ThenBy" : "ThenByDescending"; } MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression)); source = source.Provider.CreateQuery<T>(resultExp); } return source; } public static IQueryable<T> Where<T>(this IQueryable<T> source, FilterRule[] filterRules) where T : class { if (filterRules == null) { return source; } Type type = typeof(T); ParameterExpression param = Expression.Parameter(type, "c"); Expression<Func<T, bool>> op = null; foreach (var rule in filterRules) { PropertyInfo property = type.GetProperty(rule.Field); if (property == null) { continue; } //c.Field==Value //c=>c.Field.Contains(Value) Expression left = Expression.Property(param, property); Expression right = Expression.Constant(rule.Value); Type valueType = property.PropertyType; if (rule.Value == null || rule.Value == "") continue; DateTime inputDateTime = DateTime.Now; try { if (valueType == typeof(int) || valueType == typeof(int?)) { right = Expression.Constant(Convert.ToInt32(rule.Value.Split('.')[0]), valueType); } else if (valueType == typeof(short) || valueType == typeof(short?)) { right = Expression.Constant(Convert.ToInt16(rule.Value.Split('.')[0]), valueType); } else if (valueType == typeof(byte) || valueType == typeof(byte?)) { right = Expression.Constant(Convert.ToByte(rule.Value.Split('.')[0]), valueType); } else if (valueType == typeof(long) || valueType == typeof(long?)) { right = Expression.Constant(Convert.ToInt64(rule.Value), valueType); } else if (valueType == typeof(float) || valueType == typeof(float?)) { right = Expression.Constant(Convert.ToSingle(rule.Value), valueType); } else if (valueType == typeof(double) || valueType == typeof(double?)) { right = Expression.Constant(Convert.ToDouble(rule.Value), valueType); } else if (valueType == typeof(decimal) || valueType == typeof(decimal?)) { right = Expression.Constant(Convert.ToDecimal(rule.Value), valueType); } else if (valueType == typeof(DateTime) || valueType == typeof(DateTime?)) { inputDateTime = Convert.ToDateTime(rule.Value); right = Expression.Constant(Convert.ToDateTime(rule.Value), valueType); } else if (valueType == typeof(Guid) || valueType == typeof(Guid?)) { right = Expression.Constant(Guid.Parse(rule.Value), valueType); } else if (valueType == typeof(bool) || valueType == typeof(bool?)) { right = Expression.Constant(Boolean.Parse(rule.Value), valueType); } } catch (Exception ex) { Console.WriteLine(ex.Message); break; } Expression filter = Expression.Equal(left, right); Expression filter2 = null; MethodInfo method; switch (rule.Op) { case OP.contains: //BinaryExpression if (valueType == typeof(string)) { method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); filter = Expression.Call(left, method, right); } else if (valueType == typeof(DateTime) || valueType == typeof(DateTime?)) { right = Expression.Constant(inputDateTime.Date); filter = Expression.GreaterThanOrEqual(left, right); right = Expression.Constant(inputDateTime.Date.AddDays(1)); filter2 = Expression.LessThan(left, right); } else { filter = Expression.Equal(left, right); } break; case OP.equal: filter = Expression.Equal(left, right); break; case OP.notequal: filter = Expression.NotEqual(left, right); break; case OP.beginwith: method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); filter = Expression.Call(left, method, right); break; case OP.endwith: method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); filter = Expression.Call(left, method, right); break; case OP.less: filter = Expression.LessThan(left, right); break; case OP.lessorequal: filter = Expression.LessThanOrEqual(left, right); break; case OP.greater: filter = Expression.GreaterThan(left, right); break; case OP.greaterorequal: filter = Expression.GreaterThanOrEqual(left, right); break; default: break; } var lambda = Expression.Lambda<Func<T, bool>>(filter, param); if (op == null) { op = lambda; } else { op = Expression.Lambda<Func<T, bool>>(Expression.And(op.Body, lambda.Body), op.Parameters); } if (filter2 != null) { var lambda2 = Expression.Lambda<Func<T, bool>>(filter2, param); op = Expression.Lambda<Func<T, bool>>(Expression.And(op.Body, lambda2.Body), op.Parameters); } } if (op != null) { source = source.Where(op); } return source; } /// <summary> /// 多条件过滤 /// </summary> /// <typeparam name="T">泛型,默认传入类名</typeparam> /// <param name="source">默认传入where前的IQueryable语句</param> /// <param name="filters">存放一或多个过滤条件的数组</param> /// <returns></returns> public static IQueryable<T> Where<T>(this IQueryable<T> source, Filter[] filters) where T : class { //检查过滤条件是否存在,不存在则返回where前的IQueryable语句 if (filters == null) { return source; } //获取类型 Type type = typeof(T); ParameterExpression param = Expression.Parameter(type, "c"); Expression<Func<T, bool>> op = null; foreach (var rule in filters) { PropertyInfo property = type.GetProperty(rule.Field); if (property == null) { continue; } //c.Field==Value //c=>(c.Field.Contains(Value) || c.Field.Contains(Value)) Exception outExc = new Exception(); Expression left = Expression.Property(param, property); Type valueType = property.PropertyType; if (rule.Value == null || rule.Value.Length <= 0) continue; Expression<Func<T, bool>> lambdaOut = null; foreach (var v in rule.Value) { if (v == null || v == "") continue; Expression right = Expression.Constant(v); DateTime inputDateTime = DateTime.Now; try { if (valueType == typeof(int) || valueType == typeof(int?)) { right = Expression.Constant(Convert.ToInt32(v.Split('.')[0]), valueType); } else if (valueType == typeof(short) || valueType == typeof(short?)) { right = Expression.Constant(Convert.ToInt16(v.Split('.')[0]), valueType); } else if (valueType == typeof(byte) || valueType == typeof(byte?)) { right = Expression.Constant(Convert.ToByte(v.Split('.')[0]), valueType); } else if (valueType == typeof(long) || valueType == typeof(long?)) { right = Expression.Constant(Convert.ToInt64(v), valueType); } else if (valueType == typeof(float) || valueType == typeof(float?)) { right = Expression.Constant(Convert.ToSingle(v), valueType); } else if (valueType == typeof(double) || valueType == typeof(double?)) { right = Expression.Constant(Convert.ToDouble(v), valueType); } else if (valueType == typeof(decimal) || valueType == typeof(decimal?)) { right = Expression.Constant(Convert.ToDecimal(v), valueType); } else if (valueType == typeof(DateTime) || valueType == typeof(DateTime?)) { inputDateTime = Convert.ToDateTime(v); right = Expression.Constant(Convert.ToDateTime(v), valueType); } else if (valueType == typeof(Guid) || valueType == typeof(Guid?)) { right = Expression.Constant(Guid.Parse(v), valueType); } else if (valueType == typeof(bool) || valueType == typeof(bool?)) { right = Expression.Constant(Boolean.Parse(v), valueType); } } catch (Exception ex) { Console.WriteLine(ex.Message); break; } Expression filter = Expression.Equal(left, right); Expression filter2 = null; MethodInfo method; switch (rule.Op) { case OP.contains: //BinaryExpression if (valueType == typeof(string)) { method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); filter = Expression.Call(left, method, right); } else if (valueType == typeof(DateTime) || valueType == typeof(DateTime?)) { right = Expression.Constant(inputDateTime.Date); filter = Expression.GreaterThanOrEqual(left, right); right = Expression.Constant(inputDateTime.Date.AddDays(1)); filter2 = Expression.LessThan(left, right); } else { filter = Expression.Equal(left, right); } break; case OP.equal: filter = Expression.Equal(left, right); break; case OP.notequal: filter = Expression.NotEqual(left, right); break; case OP.beginwith: method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); filter = Expression.Call(left, method, right); break; case OP.endwith: method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); filter = Expression.Call(left, method, right); break; case OP.less: filter = Expression.LessThan(left, right); break; case OP.lessorequal: filter = Expression.LessThanOrEqual(left, right); break; case OP.greater: filter = Expression.GreaterThan(left, right); break; case OP.greaterorequal: filter = Expression.GreaterThanOrEqual(left, right); break; default: break; } var lambda = Expression.Lambda<Func<T, bool>>(filter, param); if (lambdaOut == null) { lambdaOut = lambda; } else { lambdaOut = Expression.Lambda<Func<T, bool>>(Expression.Or(lambdaOut.Body, lambda.Body), lambdaOut.Parameters); } if (filter2 != null) { var lambda2 = Expression.Lambda<Func<T, bool>>(filter2, param); lambdaOut = Expression.Lambda<Func<T, bool>>(Expression.And(lambdaOut.Body, lambda2.Body), lambdaOut.Parameters); } } if (rule.Op == OP.range && rule.Value != null && rule.Value.Length == 2) { if (!(rule.Value[0] == null || rule.Value[0] == "") && !(rule.Value[1] == null || rule.Value[1] == "")) { Expression right1 = Expression.Constant(rule.Value[0]); Expression right2 = Expression.Constant(rule.Value[1]); try { if (valueType == typeof(int) || valueType == typeof(int?)) { right1 = Expression.Constant(Convert.ToInt32(rule.Value[0].Split('.')[0]), valueType); right2 = Expression.Constant(Convert.ToInt32(rule.Value[1].Split('.')[0]), valueType); } else if (valueType == typeof(short) || valueType == typeof(short?)) { right1 = Expression.Constant(Convert.ToInt16(rule.Value[0].Split('.')[0]), valueType); right2 = Expression.Constant(Convert.ToInt16(rule.Value[1].Split('.')[0]), valueType); } else if (valueType == typeof(byte) || valueType == typeof(byte?)) { right1 = Expression.Constant(Convert.ToByte(rule.Value[0].Split('.')[0]), valueType); right2 = Expression.Constant(Convert.ToByte(rule.Value[1].Split('.')[0]), valueType); } else if (valueType == typeof(long) || valueType == typeof(long?)) { right1 = Expression.Constant(Convert.ToInt64(rule.Value[0]), valueType); right2 = Expression.Constant(Convert.ToInt64(rule.Value[1]), valueType); } else if (valueType == typeof(float) || valueType == typeof(float?)) { right1 = Expression.Constant(Convert.ToSingle(rule.Value[0]), valueType); right2 = Expression.Constant(Convert.ToSingle(rule.Value[1]), valueType); } else if (valueType == typeof(double) || valueType == typeof(double?)) { right1 = Expression.Constant(Convert.ToDouble(rule.Value[0]), valueType); right2 = Expression.Constant(Convert.ToDouble(rule.Value[1]), valueType); } else if (valueType == typeof(decimal) || valueType == typeof(decimal?)) { right1 = Expression.Constant(Convert.ToDecimal(rule.Value[0]), valueType); right2 = Expression.Constant(Convert.ToDecimal(rule.Value[1]), valueType); } else if (valueType == typeof(DateTime) || valueType == typeof(DateTime?)) { right1 = Expression.Constant(Convert.ToDateTime(rule.Value[0]), valueType); right2 = Expression.Constant(Convert.ToDateTime(rule.Value[1]), valueType); } else if (valueType == typeof(Guid) || valueType == typeof(Guid?)) { right1 = Expression.Constant(Guid.Parse(rule.Value[0]), valueType); right2 = Expression.Constant(Guid.Parse(rule.Value[0]), valueType); } } catch (Exception ex) { Console.WriteLine(ex.Message); break; } Expression filter = Expression.GreaterThanOrEqual(left, right1); Expression filter2 = Expression.LessThanOrEqual(left, right2); var lambda = Expression.Lambda<Func<T, bool>>(filter, param); if (lambdaOut == null) { lambdaOut = lambda; } else { lambdaOut = Expression.Lambda<Func<T, bool>>(Expression.Or(lambdaOut.Body, lambda.Body), lambdaOut.Parameters); } if (filter2 != null) { var lambda2 = Expression.Lambda<Func<T, bool>>(filter2, param); lambdaOut = Expression.Lambda<Func<T, bool>>(Expression.And(lambdaOut.Body, lambda2.Body), lambdaOut.Parameters); } } } if (op == null) { op = lambdaOut; } else { if (lambdaOut != null) { op = Expression.Lambda<Func<T, bool>>(Expression.And(op.Body, lambdaOut.Body), op.Parameters); } } } if (op != null) { source = source.Where(op); } return source; } /// <summary> /// 仅查询string类型数据 /// </summary> /// <typeparam name="T">泛型,默认传入类名</typeparam> /// <param name="source">默认传入where前的IQueryable语句</param> /// <param name="columnNames">存放待查询列名称的数组</param> /// <param name="filterString">查询内容</param> /// <returns></returns> public static IQueryable<T> Where<T>(this IQueryable<T> source, string[] columnNames, string filterString) { //获取覆盖当前泛型的类型 Type type = typeof(T); //构建表达式树的参数c ParameterExpression param = Expression.Parameter(type, "c"); //构建一个表达式树节点,存放查询内容 Expression right = Expression.Constant(filterString); //1!=1 //Expression op = Expression.NotEqual(Expression.Constant(1), Expression.Constant(1)); //构建一个存放lamdba表达式树的空对象 Expression<Func<T, bool>> op = null; //循环遍历存放查询列的数组 foreach (var column in columnNames) { //反射获取该列对应属性的类型 PropertyInfo property = type.GetProperty(column); //如果不存在该属性则结束本次循环,进入下次循环 if (property == null) { continue; } //c.Field==Value //c=>c.Field.Contains(Value) //构建一个表示访问属性的表达式树c=>c.Field Expression left = Expression.Property(param, property); //获取属性类型 Type valueType = property.PropertyType; //若属性类型不为string类型,则结束本次循环 if (valueType != typeof(string)) continue; //若属性值等于null或字符串长度为0,则结束本次循环 if (filterString == null || filterString == "") continue; //通过反射获取string类型的Contains方法 MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); //构建一个表示调用参数的方法 c=>c.Field.Contains(Value) Expression filter = Expression.Call(left, method, right); //将表达式转换为lambda表达式 var lambda = Expression.Lambda<Func<T, bool>>(filter, param); if (op == null) { //将构建好的lambda表达式赋值给op对象 op = lambda; } else { // 若op非空,则以or形式追加本次lambda表达式到op对象 op = Expression.Lambda<Func<T, bool>>(Expression.Or(op.Body, lambda.Body), op.Parameters); } } if (op != null) { //如果op不为空,则输出合并后的语句 source = source.Where(op); } return source; } } }
manage类
1 using PastureSpace.Common; 2 using PastureSpace.Models; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Web; 7 8 namespace PastureSpace.BLL 9 { 10 public class UserManage 11 { 12 Entities db = new Entities(); 13 PastureSpace.Common.Encryption en = new PastureSpace.Common.Encryption(); 14 public View_UserAccount GetInfo(int userid) 15 { 16 return db.View_UserAccount.Where(d => d.UserID == userid).SingleOrDefault(); 17 } 18 19 public List<UserRoleType> GetUserRoleData() 20 { 21 return db.UserRoleType.ToList(); 22 } 23 24 public List<UserStatus> GetUserStatusData() 25 { 26 return db.UserStatus.ToList(); 27 } 28 29 public IQueryable<View_UserAccount> GetQueryable() 30 { 31 return db.View_UserAccount.Select(d => d); 32 } 33 34 35 public View_UserAccount Add(UserAccount info) 36 { 37 info.Password= en.GetSha1(info.Password); 38 db.UserAccount.Add(info); 39 db.SaveChanges(); 40 return GetInfo(info.UserID); 41 } 42 43 public View_UserAccount Modify(UserAccount info) 44 { 45 var item = db.UserAccount.Where(d => d.UserID == info.UserID).SingleOrDefault(); 46 if (item != null) 47 { 48 item.Address = info.Address; 49 item.AdminCode = info.AdminCode; 50 item.Department = info.Department; 51 item.Description = info.Description; 52 item.Email = info.Email; 53 item.IDNum = info.IDNum; 54 item.Phone = info.Phone; 55 item.RealName = info.RealName; 56 item.UserStatus = info.UserStatus; 57 if (info.Password != null && info.Password.Length > 0) 58 { 59 item.Password = en.GetSha1(info.Password); 60 } 61 db.SaveChanges(); 62 return GetInfo(info.UserID); 63 } 64 return null; 65 } 66 67 public void Delete(int id) 68 { 69 70 var item = db.UserAccount.Where(d => d.UserID == id).SingleOrDefault(); 71 if (item != null) 72 { 73 db.UserAccount.Remove(item); 74 db.SaveChanges(); 75 } 76 } 77 78 /// <summary> 79 /// 登录 80 /// </summary> 81 /// <param name="username">用户名</param> 82 /// <param name="password">密码</param> 83 public LoginStatus Login(string username, string password, string ipAddress, string loginType, out string message, out TokenModel token) 84 { 85 message = null; 86 token = null; 87 //var user = db.T_User.Where(d => d.UserName.ToLower() == username.ToLower()&& d.UserStatus== 2).SingleOrDefault(); 88 var user = db.UserAccount.Where(d => d.UserName.ToLower() == username.ToLower()).SingleOrDefault(); 89 if (user == null) 90 { 91 message = "无效的用户名!"; 92 return LoginStatus.InvalidUsername; 93 } 94 else 95 { 96 #region 验证用户 97 T_UserLogin log = db.T_UserLogin.Where(d => d.UserID == user.UserID).SingleOrDefault(); 98 if (log == null) 99 { 100 log = new T_UserLogin(); 101 log.UserID = user.UserID; 102 log.LoginIP = ipAddress; 103 db.T_UserLogin.Add(log); 104 db.SaveChanges(); 105 } 106 107 int seconds = int.MaxValue; 108 if (log.ErrorLoginTime != null) 109 { 110 seconds = (int)(DateTime.Now - ((DateTime)log.ErrorLoginTime)).TotalSeconds; 111 } 112 int lockMinutes = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["LockMinutes"]); 113 int lockErrorTimes = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["LockErrorTimes"]); 114 if (seconds < lockMinutes * 60 && lockErrorTimes <= log.ErrorLoginTimes) 115 { 116 message = string.Format("登录错误次数过多,请{0}分钟之后再尝试", Math.Ceiling(((double)lockMinutes * 60 - seconds) / 60)); 117 return LoginStatus.Locked; 118 } 119 120 log.LoginIP = ipAddress; 121 if (en.GetSha1(password) == user.Password) 122 { 123 log.ErrorLoginTimes = 0; 124 log.LoginTime = DateTime.Now; 125 126 T_UserToken tokenInfo = new T_UserToken(); 127 tokenInfo.ClientID = Guid.NewGuid(); 128 tokenInfo.ExpireTime = DateTime.Now.AddMinutes(60); 129 tokenInfo.LoginType = loginType; 130 if (loginType == "App") 131 { 132 tokenInfo.ExpireTime = DateTime.Now.AddDays(14); 133 } 134 tokenInfo.LoginTime = DateTime.Now; 135 tokenInfo.Token = Guid.NewGuid(); 136 tokenInfo.UserID = user.UserID; 137 db.T_UserToken.RemoveRange(db.T_UserToken.Where(d => d.ExpireTime < DateTime.Now)); 138 db.T_UserToken.Add(tokenInfo); 139 db.SaveChanges(); 140 141 token = new TokenModel(); 142 token.ClientID = tokenInfo.ClientID; 143 token.RealName = user.RealName; 144 token.Token = tokenInfo.Token; 145 token.UserID = user.UserID; 146 token.UserName = user.UserName; 147 148 return LoginStatus.Success; 149 } 150 else 151 { 152 if (log.ErrorLoginTimes == null) 153 { 154 log.ErrorLoginTimes = 0; 155 } 156 if (seconds > lockMinutes * 60) 157 { 158 log.ErrorLoginTimes = 0; 159 } 160 log.ErrorLoginTimes += 1; 161 log.ErrorLoginTime = DateTime.Now; 162 db.SaveChanges(); 163 if (lockErrorTimes > log.ErrorLoginTimes) 164 { 165 message = string.Format("再登录错误{0}次,账户将被锁定{1}分钟", lockErrorTimes - log.ErrorLoginTimes, lockMinutes); 166 return LoginStatus.InvalidPassword; 167 } 168 else 169 { 170 message = string.Format("登录错误次数过多,请{0}分钟之后再尝试", Math.Ceiling(((double)lockMinutes * 60 - seconds) / 60)); 171 return LoginStatus.Locked; 172 } 173 } 174 #endregion 175 } 176 } 177 178 public LoginStatus Login(string username, string password, string ipAddress) 179 { 180 var user = db.UserAccount.Where(d => d.UserName.ToLower() == username.ToLower()).SingleOrDefault(); 181 if (user == null) 182 { 183 return LoginStatus.InvalidUsername; 184 } 185 else 186 { 187 T_UserLogin log = db.T_UserLogin.Where(d => d.UserID == user.UserID).SingleOrDefault(); 188 if (log == null) 189 { 190 log = new T_UserLogin(); 191 log.UserID = user.UserID; 192 log.LoginIP = ipAddress; 193 db.T_UserLogin.Add(log); 194 db.SaveChanges(); 195 } 196 197 int seconds = int.MaxValue; 198 if (log.ErrorLoginTime != null) 199 { 200 seconds = (DateTime.Now - ((DateTime)log.ErrorLoginTime)).Seconds; 201 } 202 int lockMinutes = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["LockMinutes"]); 203 int lockErrorTimes = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["LockErrorTimes"]); 204 if (seconds < lockMinutes * 60 && lockErrorTimes >= log.ErrorLoginTimes) 205 { 206 return LoginStatus.Locked; 207 } 208 209 log.LoginIP = ipAddress; 210 if (en.GetSha1(password) == user.Password) 211 { 212 log.ErrorLoginTimes = 0; 213 log.LoginTime = DateTime.Now; 214 db.SaveChanges(); 215 216 return LoginStatus.Success; 217 } 218 else 219 { 220 if (log.ErrorLoginTimes == null) 221 { 222 log.ErrorLoginTimes = 0; 223 } 224 log.ErrorLoginTimes += 1; 225 log.ErrorLoginTime = DateTime.Now; 226 db.SaveChanges(); 227 return LoginStatus.InvalidPassword; 228 } 229 } 230 } 231 } 232 233 /// <summary> 234 /// 登录状态 235 /// </summary> 236 public enum LoginStatus 237 { 238 /// <summary> 239 /// 验证成功 240 /// </summary> 241 Success = 0, 242 /// <summary> 243 /// 无效用户名 244 /// </summary> 245 InvalidUsername = 1, 246 /// <summary> 247 /// 无效密码 248 /// </summary> 249 InvalidPassword = 2, 250 /// <summary> 251 /// 无效的用户名或者密码 252 /// </summary> 253 InvalidUsernamePassword = 3, 254 /// <summary> 255 /// 没有权限 256 /// </summary> 257 PermissionDenied = 4, 258 /// <summary> 259 /// 没有权限 260 /// </summary> 261 Locked = 5 262 } 263 }
五、element UI tabel 单页面筛选案例,与分页结合使用后出现很多页面。
在列中设置filtersfilter-method属性即可开启该列的筛选,filters 是一个数组,filter-method是一个方法,它用于决定某些数据是否显示,会传入三个参数:value, row 和 column。 <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" sortable width="180" :filters="[{text: '2016-05-01', value: '2016-05-01'}, {text: '2016-05-02', value: '2016-05-02'}, {text: '2016-05-03', value: '2016-05-03'}, {text: '2016-05-04', value: '2016-05-04'}]" :filter-method="filterHandler" > </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址" :formatter="formatter"> </el-table-column> <el-table-column prop="tag" label="标签" width="100" :filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]" :filter-method="filterTag" filter-placement="bottom-end"> <template slot-scope="scope"> <el-tag :type="scope.row.tag === '家' ? 'primary' : 'success'" disable-transitions>{{scope.row.tag}}</el-tag> </template> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄', tag: '家' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄', tag: '公司' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄', tag: '家' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄', tag: '公司' }] } }, methods: { formatter(row, column) { return row.address; }, filterTag(value, row) { return row.tag === value; }, filterHandler(value, row, column) { const property = column['property']; return row[property] === value; } } } </script>