ExtJS多表自定义查询前台源码实现

作者:技术拾光时间:2026-06-12 08:34:02浏览:132

基于ExtJS2.0构建动态查询系统,利用EditGridPanel实现多表自定义查询,RemoteCheckboxGroup动态生成字段,MetaGrid展示结果,Ehcache缓存元数据,jxl.jar导出Excel,核心功能包括条件组合、行操作及结果渲染。

一套动态查询系统是怎么搭起来的?下面把这个项目的技术选型和核心代码拆开聊聊,主要是给有类似需求的朋友做个参考——从框架到缓存、再到Excel导出,每一步都有具体的组件在支撑。

主要使用的技术:
1. ExtJS 2.0——整体框架的基础。
2. RemoteCheckboxGroup.js——动态生成表字段,给查询结果用。
3. Ext.ux.grid.RowActions.js——给Grid行扩展功能,比如上移、下移、删除这些操作。
4. Datetime.js——时间选择组件。
5. MetaGrid.js——动态生成查询结果列表,也就是返回结果的Grid。
6. Ehcache——缓存自定义表数据,比如表名称、字段描述、字段长度等固定信息。
7. jxl.jar——查询结果输出,最终生成Excel文件。
8. Ja va——后端支撑。

ExtJS多表自定义查询前台源码实现

核心的编辑功能,主要通过一个EditGridPanel来实现。下面是它的核心代码片段,展示了如何配置每一列的编辑器、数据源和渲染逻辑:

{header:'括号',dataIndex:'leftbrackets',width:40,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields:['value','text'], data: leftBracketsComboData }), mode: 'local', triggerAction: 'all', editable:false, valueField: 'value', displayField: 'text', readOnly:true })), renderer: function(value, cellmeta, record){ if(value == null || value == ""){ return ""; } return leftBracketsComboData[value][1]; },scope:this} ,{header:'表名称',dataIndex:'tablename',width:80,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields:['value','text'], data: baseTableData }), id:'baseTableNameID', tpl: '
{text}
', mode: 'local', triggerAction: 'all', editable:false, valueField: 'value', displayField: 'text', lazyInit:false, listeners: { 'expand':function(combo){ combo.clearValue(); combo.store.loadData(baseTableData); } ,'select':function(){ } ,'focus' :function(){ this.expand(); } } })), renderer: function(value, cellmeta, record, row, col, store){ if(value == null || value == ""){ return; } return record.get("tablenamestring"); }} ,{header:'查询条件列',dataIndex:'fieldname',width:90,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ id:'fieldnameID' ,store : new Ext.data.Store({ proxy : new Ext.data.HttpProxy({url : '../SearchTableColumns/extlistKV.do'}) ,reader : new Ext.data.JsonReader({}, ['name','chinese']) ,baseParams:{s_tablename:'0'} }) ,tpl: '
{chinese}
' ,valueField :'name' ,displayField :'chinese' ,mode : 'remote' ,forceSelection : true ,triggerAction : 'all' ,typeAhead : false ,selectOnFocus : true ,resizable:true ,width : 120 ,lazyInit:false ,listeners: { 'focus' : function(){ this.expand(); } } })), renderer: function(value, cellmeta, record, row, col, store){ if(value == null || value == ""){ return ""; } return record.get("fieldnamestring"); }} ,{header:'逻辑运算符',dataIndex:'relationsign',width:70,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields:['value','text'], data: relationSignComboData }), mode: 'local', triggerAction: 'all', editable:false, valueField: 'value', displayField: 'text', readOnly:true, lazyInit:false, listeners: { 'focus' : function(){ this.expand(); } } })), renderer: function(value, cellmeta, record, row, col, store){ if(value == null || value == ""){ return; } return relationSignComboData[value][1]; },scope:this} ,{header:'查询条件值',dataIndex:'expressvalue',width:125,editor:new Ext.grid.GridEditor(new Ext.form.TextField({ })) , renderer: function(value, cellmeta, record, row, col, store){ if(value == null || value == ""){ return ""; } return record.get("expressvaluestring"); } } ,{header:'括号',dataIndex:'rightbrackets',width:40,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields:['value','text'], data: rightBracketsComboData }), mode: 'local', triggerAction: 'all', editable:false, valueField: 'value', displayField: 'text', readOnly:true, lazyInit:false, listeners: { 'focus' : function(){ this.expand(); } } })), renderer: function(value, cellmeta, record){ if(value == null || value == ""){ return ""; } return rightBracketsComboData[value][1]; },scope:this} ,{header:'关系运算符',dataIndex:'operatorsign',width:70,editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields:['value','text'], data: operatorSignComboData }), mode: 'local', triggerAction: 'all', editable:false, valueField: 'value', displayField: 'text', readOnly:true, lazyInit:false, listeners: { 'focus' : function(){ this.expand(); } } })), renderer: function(value, cellmeta, record){ if(value == null || value == ""){ return ; } return operatorSignComboData[value][1]; },scope:this} ,this.rowActions ]);

ExtJS多表自定义查询前台源码实现

再来看看查询结果区域如何处理——这里用到了MetaGrid来做动态列展示。它的核心逻辑是通过配置参数动态加载服务器返回的数据,支持自定义渲染函数,比如颜色标记、文本翻译等。下面这个代码展示了如何初始化MetaGrid并绑定事件:

Ext.apply(Ext, { isFirebug: (window.console && window.console.firebug) }); Ext.ns('app'); app.getMetaGrid = function(config){ return new Ext.ux.grid.MetaGrid(Ext.apply({ baseParams: null, url: '../AdvancedSearch/extSearchResultList.do?ssid='+globalQueryString("ssid"), renderChange: function(val){ if (val > 0) { return '' + val + ''; } else if (val < 0) { return '' + val + ''; } return val; }, renderCombo: function(val, metadata, record, rowIndex, colIndex, store){ var data; // ... (注:此处原代码有注释掉的逻辑,用于组合框数据渲染,但未实际使用) return data; }, renderDate: function(date){ return date date.dateFormat('M d, Y') : ''; }, renderDateTime: function(date){ if (!date) { return ''; } var now = new Date(); var d = now.clearTime(true); var notime = date.clearTime(true).getTime(); if (notime == d.getTime()) { return 'Today ' + date.dateFormat('g:i a'); } d = d.add('d', -6); if (d.getTime() <= notime) { return date.dateFormat('D g:i a'); } return date.dateFormat('n/j g:i a'); }, renderItalic: function(data, metadata, record, rowIndex, columnIndex, store){ return '' + data + ''; }, renderPctChange: function(data, metadata, record, rowIndex, columnIndex, store){ var p = (parseFloat(data) * 100.0).toFixed(1); var qtip = '>'; if (data >= 0) { qtip = " qtip='yeah'/>"; return ''; } else if (data < 0) { qtip = " qtip='woops'/>"; return ''; } return data; }, renderPosNeg: function(data, metadata, record, rowIndex, columnIndex, store){ if (data >= 0) { return '' + data + ''; } else if (data < 0) { return '' + data + ''; } return data; }, renderRisk: function(data, metadata, record, rowIndex, columnIndex, store){ switch (data) { case "high": metadata.css = "redcell"; return "high"; case "medium": return "medium"; case "low": return "low"; default: return data; } }, renderStars: function(data, metadata, record, rowIndex, columnIndex, store){ switch (data) { case "1": metadata.css = "stars1"; return 1; case "2": metadata.css = "stars2"; return; case "3": metadata.css = "stars3"; return; case "4": metadata.css = "stars4"; return; case "5": metadata.css = "stars5"; return; default: return data; } }, renderQtip: function(data, metadata, record, rowIndex, columnIndex, store){ metadata.attr = 'ext:qtip="' + data + '"'; return data; } }, config)); }; Ext.onReady(function(){ var vp = new Ext.Viewport({ layout:'fit', items: [app.getMetaGrid({ border: false })] }); });

ExtJS多表自定义查询前台源码实现

最后,表字段的动态加载部分——利用RemoteCheckboxGroup组件,从后端获取数据,然后按表分组展示为Checkbox列表。这个组件可以配合FieldSet进行分组展示,支持远程数据绑定,并且可以动态加载,避免一次性请求所有数据,对用户体验非常友好。看来对于需要动态选择查询字段的复杂查询场景,这一套组合下来基本够用了。