在很多列表展示数据的场合中,大多数都会需要一个排序的处理,以方便快速查找排序所需的数据,本篇随笔介绍如何结合ABP后端和Vue+Element前端结合的分页排序处理过程。

1、Vue+Element前端的排序代码

我们首先参考一下Element界面组件的排序说明。如下效果是Element表格组件的排序效果。

循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理_循序渐进VUE+Element

 

在列中设置sortable属性即可实现以该列为基准的排序,接受一个Boolean,默认为false。可以通过 Table 的default-sort属性设置默认的排序列和排序顺序。可以使用sort-method或者sort-by使用自定义的排序规则。如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-change事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。在本例中,我们还使用了formatter属性,它用于格式化指定列的值,接受一个Function,会传入两个参数:rowcolumn,可以根据自己的需求进行处理。

根据上面说明,我们这里采取的是后端排序,将sortable设置为custom。如下案例代码所示。

    <!--表格列表信息 -->
    <el-table
      v-loading="listLoading"
      :data="list"
      border
      fit
      stripe
      highlight-current-row
      :header-cell-style="{background:'#eef1f6',color:'#606266'}"
      @selection-change="selectionChange"
      @row-dblclick="rowDbclick"
    @sort-change="sortChange"
    >
      <el-table-column type="selection" width="40" />
      <el-table-column align="center" sortable="custom" prop="name" label="姓名">
        <template slot-scope="scope">
          {{ scope.row.name }}
        </template>
      </el-table-column>
      <el-table-column align="center" sortable="custom" prop="age" label="年龄">
        <template slot-scope="scope">
          {{ scope.row.age }} 岁
        </template>
      </el-table-column>
      <!--日期字段信息,显示完整时间格式:formatter="timeFormat",否则使用:formatter="dateFormat" -->
      <el-table-column align="center" label="创建时间" sortable="custom" width="160" prop="creationTime" :formatter="timeFormat" />

以上是界面端的HTML代码,那么前端JS的处理逻辑也需要相应处理下,上面代码中 @sort-change="sortChange" 定义了排序变化的触发事件处理。

  methods: {
    sortChange({ column, prop, order }) {
      var direction = (order === 'ascending') ? ' ASC' : ' DESC'
      this.sorting = !this.isEmpty(prop) ? (prop + direction) : null
      this.getlist()
    },

以上代码主要逻辑是构建一个排序字符串,如:字段 ASC 或 字段 DESC的字符串,以供ABP后端的排序处理即可,这个主要是根据ABP框架排序特点进行提交的。

我们通过getlist的方法提交对应的查询条件和排序字符串,让后端再次获取数据给我们前端处理。

    getlist() { // 列表数据获取
      var param = { // 构造常规的分页查询条件
        // 分页条件
        SkipCount: (this.pageinfo.pageindex - 1) * this.pageinfo.pagesize,
        MaxResultCount: this.pageinfo.pagesize,
        Sorting: this.sorting,

      // 查询过滤条件
        Name: this.searchForm.name,
        AgeStart: this.searchForm.ageStart
      };
      // 使用日期范围选择控件,在查询对象增加开始日期CreationTimeStart、结束日期CreationTimeEnd
      this.addDateRange(param, this.searchForm.creationTime)

      // 获取列表,绑定到模型上,并修改分页数量
      this.listLoading = true
      customer.GetAll(param).then(data => {
        this.list = data.result.items
        this.pageinfo.total = data.result.totalCount
        this.listLoading = false
      })
    },

那么剩下的时候,就是后端如何处理数据的问题了。

 

2、 ABP后端分页排序的处理

我们查看ABP的应用服务层的接口基类可以看到,对应的获取所有记录GetAll方法的定义如下所示。

        public virtual async Task<PagedResultDto<TEntityDto>> GetAllAsync(TGetAllInput input)
        {
            CheckGetAllPermission();                 //检查权限

            var query = CreateFilteredQuery(input);  //构建查询条件

            var totalCount = await AsyncQueryableExecuter.CountAsync(query);  //获取记录总数

            query = ApplySorting(query, input);  //排序
            query = ApplyPaging(query, input);   //分页

            var entities = await AsyncQueryableExecuter.ToListAsync(query);  //返回实体记录

            return new PagedResultDto<TEntityDto>(  //构建分页展示数据
                totalCount,
                entities.Select(MapToEntityDto).ToList()  //实体转换DTO
            );
        }

一般情况下,这些逻辑我们一般不会变化,我们只需要进行一定的重写构建查询条件,以及排序规则即可。

例如重写条件查询获取查询对象的处理如下。

循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理_循序渐进VUE+Element_02

 

 详细代码如下所示:

        /// <summary>
        /// 自定义条件处理
        /// </summary>
        /// <param name="input">查询条件Dto</param>
        /// <returns></returns>
        protected override IQueryable<Customer> CreateFilteredQuery(CustomerPagedDto input)
        {
            return base.CreateFilteredQuery(input)
                .WhereIf(!input.ExcludeId.IsNullOrWhiteSpace(), t=>t.Id != input.ExcludeId) //不包含排除ID
                .WhereIf(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
                 //年龄区间查询
                .WhereIf(input.AgeStart.HasValue, s => s.Age >= input.AgeStart.Value)
                .WhereIf(input.AgeEnd.HasValue, s => s.Age <= input.AgeEnd.Value)
 
                //创建日期区间查询
                .WhereIf(input.CreationTimeStart.HasValue, s => s.CreationTime >= input.CreationTimeStart.Value)
                .WhereIf(input.CreationTimeEnd.HasValue, s => s.CreationTime <= input.CreationTimeEnd.Value)
                ;
        }

排序的处理,我们可以重写下规则如下所示。

        /// <summary>
        /// 自定义排序处理
        /// </summary>
        /// <param name="query">可查询LINQ</param>
        /// <param name="input">查询条件Dto</param>
        /// <returns></returns>
        protected override IQueryable<Customer> ApplySorting(IQueryable<Customer> query, CustomerPagedDto input)
        {
            if (!string.IsNullOrEmpty(input.Sorting))//排序字段是否有值
            {
                query = query.OrderBy(input.Sorting);
            }
            else
            {
                query = query.OrderByDescending(t => t.CreationTime);
            }
            return query;
        }

完成这些,我们就可以测试前端的界面效果了。

循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理_循序渐进VUE+Element_03