標題已指出本文要說的三件事,首先是主角jqgrid,將應用在自定義列表中,重點介紹如何實現高級查詢。
使用jqgrid實現自定義列表分爲兩大步驟,首先是要根據業務完成jqgrid的對象定義,即列表的描述配置;再就是服務端加載數據json對象。爲實現更豐富條件的數據展示,jqgrid內置了高級檢索的功能,可以自定義條件、自定義and、or的規則來查詢數據,如圖:
查詢功能很強大,但問題也明顯,後臺如何識別這些條件?以下是我使用的方法:
1、定義高級查詢的對象,通過json轉換爲對象,一來後臺能夠好進行參數處理,二來強制性的規則更安全,有規則成方圓。
2、爲了完成where條件的轉換,對高級查詢對象進行解析,處理成可執行的sql where查詢條件。
3、在實現上面功能之前,應先完成列表數據字段的規則定義,只有有效的字段才能進行查詢。
以下是查詢對象的定義:
1 /// <summary> 2 /// jqgrid高級查詢json反序列化對象 3 /// </summary> 4 [Serializable] 5 public class ComplexFilters 6 { 7 /// <summary> 8 /// 查詢條件AND、OR 9 /// </summary> 10 public string groupOp { get; set; } 11 12 /// <summary> 13 /// 查詢字段 14 /// </summary> 15 public List<FilterItem> rules { get; set; } 16 17 /// <summary> 18 /// 嵌套查詢 19 /// </summary> 20 public List<ComplexFilters> groups { get; set; } 21 } 22 23 /// <summary> 24 /// jqgrid高級查詢字段明細 25 /// </summary> 26 [Serializable] 27 public class FilterItem 28 { 29 /// <summary> 30 /// 字段名稱 31 /// </summary> 32 public string field { get; set; } 33 34 /// <summary> 35 /// 查詢條件 36 /// </summary> 37 public string op { get; set; } 38 39 /// <summary> 40 /// 關鍵字 41 /// </summary> 42 public string data { get; set; } 43 }
以下是查詢規則的解析:
1 /// <summary> 2 /// 高級查詢,通過grid傳入的filter參數進行解析 3 /// </summary> 4 public class GridComplexFilter 5 { 6 #region 初始化查詢對象 7 8 /// <summary> 9 /// 高級查詢對象 10 /// </summary> 11 public Util.WebControl.ComplexFilters _filterObj { get; set; } 12 13 /// <summary> 14 /// 字段定義 15 /// </summary> 16 public Service.Grid.Base_QueryFieldRORL _baseFiles { get; set; } 17 18 /// <summary> 19 /// 原始高級查詢字符串 20 /// </summary> 21 public string _filterStr { get; set; } 22 23 /// <summary> 24 /// 初始化對象 25 /// </summary> 26 /// <param name="f">grid傳入filter參數</param> 27 /// <param name="b">查詢字段對象集</param> 28 public GridComplexFilter(string f, Service.Grid.Base_QueryFieldRORL b) 29 { 30 if (!string.IsNullOrEmpty(f) && b != null) 31 { 32 this._filterObj = Json.ToObject<Util.WebControl.ComplexFilters>(f); 33 _baseFiles = b; 34 } 35 } 36 37 #endregion 38 39 /// <summary> 40 /// 獲取SQL條件 41 /// </summary> 42 /// <returns></returns> 43 public string GetSqlWhere() 44 { 45 return GetSql(_filterObj); 46 } 47 48 /// <summary> 49 /// 處理SQL查詢條件,含子查詢 50 /// </summary> 51 /// <param name="_fObj">查詢對象</param> 52 /// <returns></returns> 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 /// <summary> 103 /// 處理單個字段查詢,匹配數據類型及查詢方式 104 /// </summary> 105 /// <param name="_fil">查詢字段對象</param> 106 /// <returns></returns> 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 /// <summary> 318 /// 獲取字段數據類型 319 /// </summary> 320 /// <param name="field"></param> 321 /// <returns></returns> 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快速開發平臺》)