[ExtJs] gird Store ajax 分頁 過濾 查詢

在處理一些大量數據時,往往用到查詢,但是大量數據不適合全部查出,最好是分頁查出,分頁時還想有些參數過濾下,如下效果

First 定義一個遠端查詢的store

Ext.define('項目包名.路徑.store類名', {
    extend: 'Ext.data.Store',
    alias: 'store.remoteDemo',//指定store的別名
    idProperty: '列名',
    fields: [
    //fields配置參數
    ],
    remoteSort: true,//重要 指定遠端排序
    remoteFilter: true,//!!重要 指定遠端過濾
    pageSize:20,//指定一頁行數 默認是25
     
    proxy: {
        type: 'ajax',//指定代理爲ajax 通過服務端處理
        api: 'url地址'
    }
 
});

Second 前端控件引用store,並寫好過濾處理

例如grid控件:在grid控件上放個可輸入的文本框 用於遠端查詢過濾

{
    xtype:'grid',
    items:[
        {
            xtype:'toolbar',
            itemId:'tbar',
            docked: 'top',
            items:[
                {
                    xtype:'textfield',
                    name:'paramA',//自定義要查詢的參數的key 
                    role: 'filter',//可以設置一個role字段來標識
                    placeholder:'查詢條件1'
                },
                {
                    xtype:'textfield',
                    name:'paramB',
                    role: 'filter',
                    placeholder:'查詢條件2'
                },
                {
                    xtype:'button',
                    text:'查詢',
                    handler:'onSearch'//當點擊查詢時調用store的過濾查詢
                }
            ]
        }
    ],
    plugins: {
     gridpagingtoolbar: true//使用分頁插件 必備
    },
    store:{
      type:'remoteDemo'//指定第一步配置的store
    },
}

設置store查詢方法處理

onSearch() {
    let grid = 通過lookup或其他查詢器找到grid控件,
    store = grid.getStore(),//獲取store
    filters = [];
     
    let vals;
    const bar = grid.down('#tbar'),
    fields = bar.query('field[role=filter]');//通過查詢器獲取用於輸入過濾條件的控件
    vals = {};
    fields.forEach(field => {
        vals[field.getName()] = field.getValue();
    });
     
    for (var k in vals) {
        if (vals.hasOwnProperty(k) && !Ext.isEmpty(vals[k])) {
            filters.push({ //以鍵值對的形式 組成後端所需的 過濾json
                property: k,
                value: vals[k]
            });
        }
    }
     
    store.suppressNextFilter = true;
    store.clearFilter(true);//清除上次的過濾 防止數據錯誤
    store.setFilters(filters);//加載新的過濾條件
    store.suppressNextFilter = false;
     
    store.loadPage(1);//加載第一頁
}

Third 服務端處理過濾條件,組織查詢語句

後端用的C# 自己可以參照改造,反正前端傳回的值都是 json格式的

定義好一個PageQueryXX方法名的方法(爲何要PageQuery打頭? ——容易辨識)

public StoreResult PageQuerySqlLog(StoreParams storeParams)//使用StoreResult 作爲返回類型,StoreParams 類型用於接收store的各種參數
{
    string where = @"";
    List < SqlParameter > parameters = new List<SqlParameter>();
    if (storeParams.filter != null) {
        foreach(StoreFilter filter in storeParams.filter)//讀取store的filter裏的json信息 
        {
            if (string.IsNullOrEmpty(filter.value)) continue;
             
            if (filter.property == "paramA") {
                where += @" and T.表列名 like '%' + @參數名A + '%'";//拼接sql查詢語句
                parameters.Add(new SqlParameter("@參數名A", filter.value));//爲參數賦值
            }
            else if (filter.property == "paramB") {
                where += @" and T.表列名 >= @DateFr";//時間格式的demo
                SqlParameter pa = new SqlParameter("@DateFr", SqlDbType.DateTime);
                pa.Value = DateTime.Parse(filter.value);
                parameters.Add(pa);
            }
     
        }
    }
    //拼裝分頁查詢的子查詢語句
    string innerSql = string.Format(@" select 列名A,列名B from 表名 T where { 0 } ", where);//把動態拼接的where條件塞入
     
    DataTable dt = null;
    //拼接分頁查詢
    //!!注意: 如果想要查出滿足條件的總數 在sqlSERVER中可以用 COUNT(1) OVER() as TotalCount 以在分頁查詢時 也統計到所有總數
    //不理解此句話就接着往下看文章
    string sql = @"
        Select S1.*, TotalCount
        From(
            select ROW_NUMBER() OVER(order by S.DocKey desc) as RowNum, COUNT(1) OVER() as TotalCount, S.*
            from
                (
                    " + innerSql + @"
                ) S
        ) S1
        where S1.RowNum >= @start And S1.RowNum <= @end
        ";
     
    SqlCommand command = new SqlCommand();
    command.CommandText = sql;
    command.Parameters.AddWithValue("@start", storeParams.start + 1);
    command.Parameters.AddWithValue("@end", storeParams.start + storeParams.limit);
    foreach(SqlParameter pa in parameters)
    {
      command.Parameters.Add(pa);
    }
    dt = ConnectionManager.ExecuteDataTable(command);
     
    StoreResult result = new StoreResult();
    result.root = dt;
    if (dt != null && dt.Rows.Count > 0)
    result.total = TypeHelper.GetIntValue(dt.Rows[0]["TotalCount"]);//將實際行數返回 不需要實際行數 就可以用下面 的Int32.MaxValue; 
    else result.total = 0;
    //若是無需知道總數 可以用 result.total = Int32.MaxValue; 
    //一般前端用的list或dataview控件 就不關心實際總數 返回result.total 值 只是用於在前端可以展示 分頁
    return result;
}

自己定義了兩個store的幫助類

一個是返回結果的類

namespace 命名空間
{
    [Serializable]
    public class StoreResult
    {
        public int total;
        public object root;
        public object footer;
    }
}

 另一個是store參數的類

namespace 命名空間
{
    [Serializable]
    public class StoreParams
    {
        public int page;
        public int start;
        public int limit;
        public string query; //自動完成參數
        public List<StoreGrouper> group;
        public List<StoreSorter> sort;
        public List<StoreFilter> filter;
    }
    [Serializable]
    public class StoreGrouper
    {
        public string property;
        public string direction;
    }
    [Serializable]
    public class StoreSorter
    {
        public string property;
        public string direction;
    }
    [Serializable]
    public class StoreFilter
    {
        public string property;

        private string op;
        [JsonProperty("operator")]
        public string Operator
        {
            get
            {
                return op;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    if (value == "!=") op = "<>";
                    else op = value;
                }
                else
                {
                    throw WarningException.Parse("過濾器操作符{0}不合法", value);
                }
            }
        }
        public string value;
    }
}

 

其他情況:

A: 前端控件使用的是list

list使用的分頁加載是不關心store的總數的,僅僅是爲了出現“加載更多”字樣

那後端在做分頁查詢處理時,若是無需查出真實總數,可以用

StoreResult result = new StoreResult();
result.total = Int32.MaxValue;// 直接用個最大常量 即可

B: 前端控件使用的是Grid

如果這時還是直接返回Int32.MaxValue的話,grid的分頁就會出現如下情況:

返回的不是實際總頁數,這樣會翻出很多空白頁

這時,應該在查詢分頁數時,就將總條數一併查出,使用

COUNT(1) OVER () as TotalCount

一種完整的sql分頁查詢,連同分頁行總數一併查出來了

Select S1.*,TotalCount
From (
    select ROW_NUMBER() OVER (order by S.DocKey desc) as RowNum,COUNT(1) OVER () as TotalCount, S.*
    from 
    (
        " + innerSql + @"
    ) S
) S1
where S1.RowNum >= @start And S1.RowNum <= @end

再返回前端總數值時 把查到的TotalCount 返回即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章