最近在用jeecg做項目,在使用高級查詢的時候發現它不支持布爾值的查詢以及列表的下拉框的查詢,所以小編修改了底層代碼,完善了高級查詢,現在與大家一起分享。先上一張圖給大家看一下修改前的高級查詢。
它只支持了文本的查詢以及日期格式的查詢,很難滿足在使用過程中的要求。所以小編把他的功能豐富了一下,下面把源碼分享給大家。
首先先簡單介紹一下jeecg高級查詢的原理,一切的秘密都在DataGridTag這個標簽類里面,在打開一個頁面的時候,這個類會對頁面的左右變遷進行初始化,以及對高級查詢的頁面進行構造。當你在jsp頁面中對datagrid設置屬性queryBuilder="true",頁面中就會出現高級查詢的按鈕,點擊高級查詢,就會彈出,DataGridTag這個類在初始化是生成的高級查詢的頁面。先看一下生徹骨頁面的源碼
fieldArray.append(" [ "); for (int i=0;i<columnList.size();i++){ DataGridColumn col =columnList.get(i); if("opt".equals(col.getField()))continue;//忽略操作虛擬字段 if (!col.isHidden()) { fieldArray.append(" {'fieldId':'"+ ((col.getQueryChangeCol() != null && !col.getQueryChangeCol().equals("")) ? col.getQueryChangeCol() : getDBFieldName(col.getField()))+"','fieldName':'"+col.getTitle()+"'"); if(col.getEditor()!=null){ fieldArray.append(",editor:'"+col.getEditor()+"'"); } if(col.getReplace()!=null){ String str = col.getReplace(); fieldArray.append(",replaceid:'"+str+"'"); } fieldArray.append("}"); if(i<columnList.size()-1){ fieldArray.append(","); } } }
datagrid這個表格列支持一個replace屬性,例如:
<t:dgCol title="單據狀態" field="billstate" editor="combobox" hidden="false" queryMode="single" formatter="billstateFormat" width="120" replace="自由態_0,提交_1,審批_2"></t:dgCol>
這是會在主界面根據不同得知,顯示不同的文字,類似於表格的自定義轉換,我們要在高級查詢中支持下拉框和bool值也要利用這個屬性。上面的代碼就是就是獲取到主界面忠表格所有現實的列,構造高級查詢字段這一列供你查詢,注意這一段代碼
if(col.getReplace()!=null){ String str = col.getReplace(); fieldArray.append(",replaceid:'"+str+"'");
}
它的作用就是在構造你可以查詢的的字段中,如果某一個列的replace屬性有值,說明他在展示中進行了值得轉換,同時也說明 他在高級查詢中應該是一個下拉框供人選擇,所以我們在構造字段列的時候不能單單構造到他的fieldId,fieldName,還要記錄一下它設置的replace的值,方便你選到這個進行查詢時,他會在值錄入的那一列自動轉換成一個下拉框,並對下拉框進行賦值。
構造好這一切之后,要做的就是對高級查詢的頁面的treegrid的每一列進行樣式的設置,這里面最重要的就是界面中字段列的下拉框的選擇改變事件,讓我們來看下:
appendLine(sb,"for(var i=0;i<data.length;i++){"); appendLine(sb,"if(value == data[i]['fieldId']){"); appendLine(sb,"return data[i]['fieldName'];"); appendLine(sb,"}"); appendLine(sb,"}"); appendLine(sb,"return value;"); appendLine(sb,"},editor:{"); appendLine(sb,"type:'combobox',"); appendLine(sb," options:{"); appendLine(sb,"valueField:'fieldId',"); appendLine(sb,"textField:'fieldName',"); appendLine(sb,"data: "); sb.append(fieldArray); appendLine(sb," , "); appendLine(sb, "required:true,onSelect : function(record) { debugger;"); appendLine(sb,"var opts = $('#"+name+"tg').treegrid('getColumnOption','value');"); appendLine(sb, " if(record.editor != null && record.editor != ''){"); appendLine(sb, " opts.editor={'type':record.editor};"); appendLine(sb, "var tr = $(this).closest('tr.datagrid-row');"); appendLine(sb, "var index = parseInt(tr.attr('node-id'));"); appendLine(sb, " $($('#"+name+"tg').treegrid('getEditors', index)[3].target).val('');"); appendLine(sb, " $($($('#"+name+"tg').treegrid('getEditors', index)[3].target).next().find('input')[1]).val('');"); appendLine(sb, " $('#"+name+"tg').treegrid('endEdit', index);"); appendLine(sb, " $('#"+name+"tg').treegrid('beginEdit', index);"); appendLine(sb, " var arrayList = []; "); appendLine(sb, " if (record.replaceid != null) {var jsonid = record.replaceid;"); appendLine(sb, " var idList = jsonid.split(',');"); appendLine(sb, " if (opts.editor.type == 'combobox'){ "); appendLine(sb, "$.each(idList,function(i,n){"); appendLine(sb, "var obj={};"); appendLine(sb, "var namelist=n.split('_');"); appendLine(sb, "obj['relationId']=namelist[1];"); appendLine(sb, "obj['relationName']=namelist[0];"); appendLine(sb," if(namelist[2] != null){"); appendLine(sb," obj['ifnull']=namelist[2]}"); appendLine(sb, "arrayList.push(obj);"); appendLine(sb, "}); "); appendLine(sb, "$($('#"+name+"tg').treegrid('getEditors', index)[3].target).combobox({"); appendLine(sb, " valueField:'relationId',"); appendLine(sb, "textField:'relationName' "); appendLine(sb, " })"); appendLine(sb, "$($('#"+name+"tg').treegrid('getEditors', index)[3].target).combobox('loadData',arrayList);$($($('#"+name+"tg').treegrid('getEditors', index)[3].target).next().find('input')[0]).css('width','70px');"); appendLine(sb, "if(arrayMap==null){arrayMap = {};};arrayMap[record.fieldId]=arrayList;}}"); appendLine(sb, "else{"); appendLine(sb, "opts.editor={'type':record.editor,option:{ valueField:'relationId', textField:'relationName' ,required:true }}}"); appendLine(sb, " }else{"); appendLine(sb, " opts.editor='text';"); appendLine(sb, "var tr = $(this).closest('tr.datagrid-row');"); appendLine(sb, "var index = parseInt(tr.attr('node-id'));"); appendLine(sb, " $($($('#"+name+"tg').treegrid('getEditors', index)[3].target).next().find('input')[1]).val('');"); appendLine(sb, " $('#"+name+"tg').treegrid('endEdit', index);"); appendLine(sb, " $('#"+name+"tg').treegrid('beginEdit', index);"); appendLine(sb, " }"); appendLine(sb, "}"); appendLine(sb," }}\">字段</th>");
關鍵的就是上面的代碼中表藍色的部分,他就是字段列下拉框的改變事件,先看一下我調整后的效果
我們來分析一下代碼,
var opts = $('#"+name+"tg').treegrid('getColumnOption','value');//獲取到所選的字段這一行列標題為值得這一列的屬性對象
然后他會去獲取你在主界面列展示中地這個屬性設置的editor的值,然后賦給value這一列,其實也就是把設置好的類型賦值給他,例如:
<t:dgCol title="單據狀態" field="billstate" editor="combobox" hidden="false" queryMode="single" formatter="billstateFormat" width="120" replace="自由態_0,提交_1,審批_2"></t:dgCol>
你設置了editor="combobox"那么你在高級查詢界面選擇了單據轉改進行查詢,相應的它的值那一列就會變成下拉框。
下面就是給值得下拉框賦值的問題了,
if (record.replaceid != null) {
var jsonid = record.replaceid;//之前在構造字段列的時候會記錄每一個字段是否有replace值,如果有,先獲取到它的replace值,例如:replace="自由態_0,提交_1,審批_2" var idList = jsonid.split(','); if (opts.editor.type == 'combobox'){ $.each(idList,function(i,n){//根據逗號分隔的數組,進行對下拉框數據源進行組裝 var obj={}; var namelist=n.split('_'); obj['relationId']=namelist[1];//下拉框隱藏的id obj['relationName']=namelist[0];//下拉框現實的text if(namelist[2] != null){ obj['ifnull']=namelist[2]}//ifnull這個是方便數據哭某些表的integer的類型的字段忘記選中分空,所以會出現一些數據為空的情況,你也可以根據replace屬性的設置,對空值轉換 arrayList.push(obj); }); $($('#"+name+"tg').treegrid('getEditors', index)[3].target).combobox({//制定下拉框的屬性對應數據源的屬性 valueField:'relationId', textField:'relationName' }) $($('#"+name+"tg').treegrid('getEditors', index)[3].target).combobox('loadData',arrayList);$($($('#"+name+"tg').treegrid('getEditors', index)[3].target).next().find('input')[0]).css('width','70px');//對下拉框進行數據源的綁定,注意在獲取下拉框的時候一定要像這樣$($('#"+name+"tg').treegrid('getEditors', index)[3].target)獲取到他下拉框的combobox控件進行時間綁定,否則數據是綁定不了的。 if(arrayMap==null){arrayMap = {};};
arrayMap[record.fieldId]=arrayList;//大家注意這一行代碼是要記錄這一個字段對應的下拉框的數據源,方便下拉框選擇了值之后,將下拉框的valueField轉成textField。以及當你第二次打開高級查詢時,查詢歷史的查詢記錄,同樣也要根據這個將下拉框的值進行轉換,非常重要。
}}
下面就涉及到了高級查詢界面的確定按鈕,先看一下代碼
appendLine(sb, "function queryBuilderSearch() { "); appendLine(sb, " var json = view();"); appendLine(sb, " $('#_sqlbuilder').val(json); "); appendLine(sb, " var isnew=true; "); appendLine(sb, "for(var i=0;i< "+name+"his.length;i++){"); appendLine(sb, " if("+name+"his[i]&&"+name+"his[i].json==json){"); appendLine(sb, " isnew=false;"); appendLine(sb, " }"); appendLine(sb, "}"); appendLine(sb, "if(isnew && json!='[]'){"); appendLine(sb, " "+name+"his.push({name:'Query'+"+name+"his.length,json:json});saveHistory();"); appendLine(sb, "var name= 'Query'+( "+name+"his.length-1);"); appendLine(sb, " var name= 'Query'+("+name+"his.length-1);"); appendLine(sb, "appendTree("+name+"his.length-1,name);"); appendLine(sb, "}"); appendLine(sb, " var t = $('#" + name + "tg');"); appendLine(sb, " var data = t.treegrid('loadData',[]);"); appendLine(sb, " " + name + "search();$('#_sqlbuilder').val('');$('#"+name+"_qbwin').window('close')"); appendLine(sb, " }");
appendLine(sb, "function view(){"); appendLine(sb,"save();"); appendLine(sb,"var t = $('#"+name+"tg');"); appendLine(sb,"var data = t.treegrid('getData');"); //// 增加布爾類型的值. appendLine(sb,"for (var i = 0; i < data.length; i++) {
if(jQuery.isEmptyObject(arrayMap)){arrayMap=storage.get('arrayMap');}");//因為我們下拉框的數據源會進行緩存,所以第二次進入高級查詢時,map會是空的,我們要去緩存中 獲取之前的map數據 appendLine(sb," if (arrayMap != null){var list = arrayMap[data[i].field];if (list != null){"); appendLine(sb," if(data[i].rember == null || data[i].rember==''){$.each(list,function(j,n){"); appendLine(sb," if(n.relationId==data[i].value){"); appendLine(sb," data[i].rember=data[i].value;if(n.ifnull != null){data[i].ifnull = n.ifnull;};data[i].replace = n.relationName;");//在要緩存的記錄數據中增加replace屬性,記錄下拉框值對應的文本顯示 appendLine(sb, " }})} else{data[i].value=data[i].rember;}}} "); appendLine(sb," }"); //// 增加布爾類型的值。 appendLine(sb,"return JSON.stringify(data) ;");
appendLine(sb,"function save(){"); appendLine(sb," var t = $('#"+name+"tg');"); appendLine(sb," var nodes = t.treegrid('getData');"); appendLine(sb," for (var i = 0; i < nodes.length; i++) {"); appendLine(sb," t.treegrid('endEdit',nodes[i].id);} "); appendLine(sb," for (var i = 0; i < nodes.length; i++) {"); appendLine(sb," if(jQuery.isEmptyObject(arrayMap)){arrayMap=storage.get('arrayMap');} if (arrayMap != null) {var list = arrayMap[nodes[i].field];if (list != null){"); appendLine(sb, " $.each(list,function(j,n){t.treegrid('beginEdit',nodes[i].id);"); appendLine(sb," if(n.relationId==nodes[i].value){"); appendLine(sb," nodes[i].replace = n.relationName; nodes[i].rember = n.relationId;if(n.ifnull != null){nodes[i].ifnull = n.ifnull;}; nodes[i].value = nodes[i].replace;}"); appendLine(sb, " t.treegrid('update',{id:nodes[i].id,row:nodes[i]})})}}" ); appendLine(sb," } "); appendLine(sb,"saveHistory();storage.set('arrayMap',JSON.stringify(arrayMap));");//緩存字段的下拉框的數據源 appendLine(sb," }");
重要的就是對這三個js方法進行修改,下面一次為大家講解這三個方法:
view()方法主要是對查詢界面的treegrid的數據進行一下加工,因為查詢的記錄會被緩存,而傳到服務端的只會是下拉框的value,以方便再次查看,所以我們要在緩存的數據中增加一些屬性,例如要記錄下拉框選中的值對應的text文本,方便再次查看時進行轉換。
save()方法和view方法構造數據的方式相差不多,s它的主要作用就是構造好數據,然后保存這次查詢到記錄中。
好了,修改過后的js,他會記錄你所需要的數據,方便你之后的使用和查詢時的數據轉換。
開源的平台的好處就是我們可以隨意的改造,添加自己的想法,如果對高級查詢這塊有什么想法要和我交流討論或者想要完整源碼的可以加這個QQ:2672773684,寫明備注就可以了。