标题已指出本文要说的三件事,首先是主角jqgrid,将应用在自定义列表中,重点介绍如何实现高级查询。
使用jqgrid实现自定义列表分为两大步骤,首先是要根据业务完成jqgrid的对象定义,即列表的描述配置;再就是服务端加载数据json对象。为实现更丰富条件的数据展示,jqgrid内置了高级检索的功能,可以自定义条件、自定义and、or的规则来查询数据,如图:
查询功能很强大,但问题也明显,后台如何识别这些条件?以下是我使用的方法:
1、定义高级查询的对象,通过json转换为对象,一来后台能够好进行参数处理,二来强制性的规则更安全,有规则成方圆。
2、为了完成where条件的转换,对高级查询对象进行解析,处理成可执行的sql where查询条件。
3、在实现上面功能之前,应先完成列表数据字段的规则定义,只有有效的字段才能进行查询。
以下是查询对象的定义:
1 ///2 /// jqgrid高级查询json反序列化对象 3 /// 4 [Serializable] 5 public class ComplexFilters 6 { 7 /// 8 /// 查询条件AND、OR 9 /// 10 public string groupOp { get; set; } 11 12 /// 13 /// 查询字段 14 /// 15 public List rules { get; set; } 16 17 /// 18 /// 嵌套查询 19 /// 20 public List groups { get; set; } 21 } 22 23 /// 24 /// jqgrid高级查询字段明细 25 /// 26 [Serializable] 27 public class FilterItem 28 { 29 /// 30 /// 字段名称 31 /// 32 public string field { get; set; } 33 34 /// 35 /// 查询条件 36 /// 37 public string op { get; set; } 38 39 /// 40 /// 关键字 41 /// 42 public string data { get; set; } 43 }
以下是查询规则的解析:
1 ///2 /// 高级查询,通过grid传入的filter参数进行解析 3 /// 4 public class GridComplexFilter 5 { 6 #region 初始化查询对象 7 8 /// 9 /// 高级查询对象 10 /// 11 public Util.WebControl.ComplexFilters _filterObj { get; set; } 12 13 /// 14 /// 字段定义 15 /// 16 public Service.Grid.Base_QueryFieldRORL _baseFiles { get; set; } 17 18 /// 19 /// 原始高级查询字符串 20 /// 21 public string _filterStr { get; set; } 22 23 /// 24 /// 初始化对象 25 /// 26 /// grid传入filter参数 27 /// 查询字段对象集 28 public GridComplexFilter(string f, Service.Grid.Base_QueryFieldRORL b) 29 { 30 if (!string.IsNullOrEmpty(f) && b != null) 31 { 32 this._filterObj = Json.ToObject (f); 33 _baseFiles = b; 34 } 35 } 36 37 #endregion 38 39 /// 40 /// 获取SQL条件 41 /// 42 /// 43 public string GetSqlWhere() 44 { 45 return GetSql(_filterObj); 46 } 47 48 /// 49 /// 处理SQL查询条件,含子查询 50 /// 51 /// 查询对象 52 /// 53 private string GetSql(Util.WebControl.ComplexFilters _fObj) 54 { 55 if (_fObj == null) 56 { 57 return ""; 58 } 59 60 bool _isFirst = true;//标识是否为首次加载有效字段条件,作为添加AND或OR关键字 61 StringBuilder _sqlWhere = new StringBuilder(""); 62 //处理字段查询明细 63 if (_fObj.rules != null && _fObj.rules.Count > 0) 64 { 65 foreach (var item in _fObj.rules) 66 { 67 if (!string.IsNullOrEmpty(item.field) && !string.IsNullOrEmpty(item.op)) 68 { 69 if (_isFirst != true) 70 { 71 //非首个条件添加AND或者OR 72 _sqlWhere.AppendFormat(" {0} ", _fObj.groupOp); 73 } 74 _sqlWhere.Append(getFieldFilter(item)); 75 _isFirst = false; 76 } 77 } 78 } 79 //处理嵌套查询 80 if (_fObj.groups != null && _fObj.groups.Count > 0) 81 { 82 foreach (var item in _fObj.groups) 83 { 84 string _child = GetSql(item); 85 if (!string.IsNullOrEmpty(_child)) 86 { 87 _sqlWhere.AppendFormat(" {0} {1}", _fObj.groupOp, _child); 88 } 89 } 90 } 91 92 if (_sqlWhere.Length > 0) 93 { 94 return string.Format(" ({0}) ", _sqlWhere.ToString()); 95 } 96 else 97 { 98 return ""; 99 } 100 } 101 102 /// 103 /// 处理单个字段查询,匹配数据类型及查询方式 104 /// 105 /// 查询字段对象 106 /// 107 private string getFieldFilter(FilterItem _fil) 108 { 109 if (string.IsNullOrEmpty(_fil.op) || string.IsNullOrEmpty(_fil.field)) 110 { 111 return ""; 112 } 113 var _dataType = getDataType(_fil.field);//字段对象 114 string _reValue = ""; 115 if (_dataType.MQF_DataType == "string") 116 {//字段为字符串时的查询 117 #region 字符串查询 118 119 if (_fil.op == "eq" && !string.IsNullOrEmpty(_fil.data)) 120 {//等于 121 _reValue = string.Format(" {0}='{1}' ", _fil.field, _fil.data); 122 } 123 else if (_fil.op == "ne" && !string.IsNullOrEmpty(_fil.data)) 124 {//不等于 125 _reValue = string.Format(" {0}<>'{1}'", _fil.field, _fil.data); 126 } 127 else if (_fil.op == "bw" && !string.IsNullOrEmpty(_fil.data)) 128 {//开头是 129 _reValue = string.Format(" {0} Like '{1}%' ", _fil.field, _fil.data); 130 } 131 else if (_fil.op == "bn" && !string.IsNullOrEmpty(_fil.data)) 132 {//开头不是 133 _reValue = string.Format(" {0} not Like '{1}%' ", _fil.field, _fil.data); 134 } 135 else if ((_fil.op == "in" || _fil.op == "ni") && !string.IsNullOrEmpty(_fil.data)) 136 {//属于、不属于 137 //处理数据项 138 string[] _split = _fil.data.Replace("'", "").Split(' '); 139 string _strSplit = ""; 140 foreach (var item in _split) 141 { 142 if (!string.IsNullOrEmpty(item)) 143 { 144 _strSplit += "'" + item + "',"; 145 } 146 } 147 _strSplit = _strSplit.TrimEnd(','); 148 if (!string.IsNullOrEmpty(_strSplit)) 149 { 150 if (_fil.op == "in") 151 {//属于项 152 _reValue = string.Format(" ({0} in ({1})) ", _fil.field, _fil.data); 153 } 154 else if (_fil.op == "ni") 155 {//不属于项 156 _reValue = string.Format(" ({0} not in ({1})) ", _fil.field, _fil.data); 157 } 158 } 159 } 160 else if (_fil.op == "ew" && !string.IsNullOrEmpty(_fil.data)) 161 {//结尾是 162 _reValue = string.Format(" {0} Like '%{1}' ", _fil.field, _fil.data); 163 } 164 else if (_fil.op == "en" && !string.IsNullOrEmpty(_fil.data)) 165 {//结尾不是 166 _reValue = string.Format(" {0} not Like '%{1}' ", _fil.field, _fil.data); 167 } 168 else if (_fil.op == "cn" && !string.IsNullOrEmpty(_fil.data)) 169 {//包含 170 _reValue = string.Format(" {0} Like '%{1}%' ", _fil.field, _fil.data); 171 } 172 else if (_fil.op == "nc" && !string.IsNullOrEmpty(_fil.data)) 173 {//不包含 174 _reValue = string.Format(" {0} not Like '%{1}%' ", _fil.field, _fil.data); 175 } 176 else if (_fil.op == "nu") 177 {//为空 178 _reValue = string.Format(" ({0} is Null or {0}='')", _fil.field); 179 } 180 else if (_fil.op == "nn") 181 {//不为空 182 _reValue = string.Format(" ({0} is not Null and {0}<>'')", _fil.field); 183 } 184 185 #endregion 186 } 187 else if (_dataType.MQF_DataType == "int" || _dataType.MQF_DataType == "float") 188 {//字段类型为数字 189 #region 数字类型查询 190 191 if (_fil.op == "eq" && !string.IsNullOrEmpty(_fil.data)) 192 {//等于 193 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 194 { 195 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 196 } 197 _reValue = string.Format(" {0} = {1} ", _fil.field, _fil.data); 198 } 199 else if (_fil.op == "ne" && !string.IsNullOrEmpty(_fil.data)) 200 {//不等于 201 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 202 { 203 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 204 } 205 _reValue = string.Format(" {0} <> {1} ", _fil.field, _fil.data); 206 } 207 else if (_fil.op == "lt" && !string.IsNullOrEmpty(_fil.data)) 208 {//小于 209 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 210 { 211 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 212 } 213 _reValue = string.Format(" {0} < {1} ", _fil.field, _fil.data); 214 } 215 else if (_fil.op == "le" && !string.IsNullOrEmpty(_fil.data)) 216 {//小于等于 217 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 218 { 219 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 220 } 221 _reValue = string.Format(" {0} <= {1} ", _fil.field, _fil.data); 222 } 223 else if (_fil.op == "gt" && !string.IsNullOrEmpty(_fil.data)) 224 {//大于 225 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 226 { 227 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 228 } 229 _reValue = string.Format(" {0} > {1} ", _fil.field, _fil.data); 230 } 231 else if (_fil.op == "ge" && !string.IsNullOrEmpty(_fil.data)) 232 {//大于等于 233 if (!Util.ValidateUtil.IsNumberSign(_fil.data) && !Util.ValidateUtil.IsDecimalSign(_fil.data)) 234 { 235 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为数据,查询名称:" + _dataType.MQF_ChineseName); 236 } 237 _reValue = string.Format(" {0} >= {1} ", _fil.field, _fil.data); 238 } 239 else if (_fil.op == "nu") 240 {//为空 241 _reValue = string.Format(" ({0} is Null) ", _fil.field); 242 } 243 else if (_fil.op == "nn") 244 {//不为空 245 _reValue = string.Format(" ({0} is not Null) ", _fil.field); 246 } 247 248 #endregion 249 } 250 else if (_dataType.MQF_DataType == "datetime") 251 {//字段类型为时间 252 #region 日期类型查询 253 254 if (_fil.op == "eq" && !string.IsNullOrEmpty(_fil.data)) 255 {//等于 256 if (!Util.ValidateUtil.IsDate(_fil.data)) 257 { 258 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 259 } 260 _reValue = string.Format(" {0} = '{1}' ", _fil.field, _fil.data); 261 } 262 else if (_fil.op == "ne" && !string.IsNullOrEmpty(_fil.data)) 263 {//不等于 264 if (!Util.ValidateUtil.IsDate(_fil.data)) 265 { 266 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 267 } 268 _reValue = string.Format(" {0} <> '{1}' ", _fil.field, _fil.data); 269 } 270 else if (_fil.op == "lt" && !string.IsNullOrEmpty(_fil.data)) 271 {//小于 272 if (!Util.ValidateUtil.IsDate(_fil.data)) 273 { 274 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 275 } 276 _reValue = string.Format(" {0} < '{1}' ", _fil.field, _fil.data); 277 } 278 else if (_fil.op == "le" && !string.IsNullOrEmpty(_fil.data)) 279 {//小于等于 280 if (!Util.ValidateUtil.IsDate(_fil.data)) 281 { 282 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 283 } 284 _reValue = string.Format(" {0} <= '{1}' ", _fil.field, _fil.data); 285 } 286 else if (_fil.op == "gt" && !string.IsNullOrEmpty(_fil.data)) 287 {//大于 288 if (!Util.ValidateUtil.IsDate(_fil.data)) 289 { 290 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 291 } 292 _reValue = string.Format(" {0} > '{1}' ", _fil.field, _fil.data); 293 } 294 else if (_fil.op == "ge" && !string.IsNullOrEmpty(_fil.data)) 295 {//大于等于 296 if (!Util.ValidateUtil.IsDate(_fil.data)) 297 { 298 throw new Util.SysException.HfQueryPlatException("查询字符串数据类型转换失败,应为日期格式,查询名称:" + _dataType.MQF_ChineseName); 299 } 300 _reValue = string.Format(" {0} >= '{1}' ", _fil.field, _fil.data); 301 } 302 else if (_fil.op == "nu") 303 {//为空 304 _reValue = string.Format(" ({0} is Null) ", _fil.field); 305 } 306 else if (_fil.op == "nn") 307 {//不为空 308 _reValue = string.Format(" ({0} is not Null) ", _fil.field); 309 } 310 311 #endregion 312 } 313 314 return _reValue; 315 } 316 317 /// 318 /// 获取字段数据类型 319 /// 320 /// 321 /// 322 private Service.Grid.Base_QueryFieldROC getDataType(string field) 323 { 324 var _field = this._baseFiles.First(p => p.MQF_Name == field); 325 if (_field != null) 326 { 327 return _field; 328 } 329 else 330 { 331 throw new HFun.Util.SysException.HfQueryPlatException("查询字段数据类型匹配失败,字段:" + field); 332 } 333 } 334 }
以上代码还在完善中。
系统现已将服务层改为webapi,通过csla框架作为配置对象基础,使用redis进行中间数据缓存,通过webapi作为核心服务层向asp.net mvc前端提供对象及数据。
(转载请带标记《HFun.net快速开发平台》)