0
点赞
收藏
分享

微信扫一扫

一种列表全字段排序功能方案


概述

网站开发中,很常见的一个需求:要对列表页的全部(或大多数)字段进行排序。

实现

先给出实现好的效果:

一种列表全字段排序功能方案_下划线


一种列表全字段排序功能方案_下划线_02


一种列表全字段排序功能方案_mybatis_03

前端

注:主要技术栈为antd,TypeScript。

const columns = [
{
title: '名称',
dataIndex: 'name',
sorter: true,
render: (text: string, record: any) => (
<div style={{maxWidth: 200, lineHeight: 1.2}} > {record?.name}</div>
),
},
]

​sorter​​​指定该字段是否需要排序功能,两种情况下可以设置为​​sorter: false​​:

  1. 对于跨表Join的字段,有些是无法排序;
  2. 无需排序的列(其实也不叫字段),如操作列。

另外,有些列会有​​render​​​的特殊需求,在加排序功能之前,并没有配置​​dataIndex: 'name'​​​。但是在引入排序功能后,必须指定该字段,下面代码里面的​​sorter.field​​​即依赖于此字段,否则​​sorter.field​​​为​​undefined​​。

列表组件:

<Vi_Table
loading={dataLoading}
rowKey={(record: any) => record.id}
columns={columns}
dataSource={autoJobListData.list}
pagination={{
...pagination,
position: ['bottomCenter'],
total: autoJobListData.total,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total: any) => (`共 ${total} 条`),
}}
onChange={handleTableChange}
/>

列表​​onChange​​方法:

const handleTableChange = (pagination: any, filters: any, sorter: any) => {
if (sorter && sorter.field && sorter.order) {
fetchDataWithParams({
...pagination,
sortField: sorter.field,
sortOrder: sorter.order === 'descend' ? 'desc' : 'asc'
});
} else {
fetchDataWithParams({
...pagination,
sortField: undefined,
sortOrder: undefined
});
}
};

后端

Controller接口

@RequestMapping("/list")
public String autoJobList(@RequestBody JSONObject jsonObject) {
return autoWordConfigService.autoJobList(jsonObject);
}

以JSONObject(或Map)来接收若干参数。

Service方法:

public String autoJobList(JSONObject jsonObject) {
PageHelper.startPage(jsonObject.getInteger("pageNo"), jsonObject.getInteger("pageSize"));
if (StringUtils.isNotBlank(jsonObject.getString("sortField"))) {
jsonObject.put("sortField", StringUtil.camelCaseToUnderscore(jsonObject.getString("sortField")));
}
List<AutoWordConfigWithBlobs> list = autoWordConfigMapper.autoJobList(jsonObject);
PageInfo<AutoWordConfigWithBlobs> pageInfo = new PageInfo<>(list);
return JSONObject.toJSONString(ServiceUtil.returnSuccessData(pageInfo));
}

主要就是分页功能,以及将驼峰命名转换为下划线命名,目地是对数据表里面下划线命名的字段进行排序。

Mapper接口:

<select id="autoJobList" resultType="com.xy.cloudiview.common.po.AutoWordConfigWithBlobs"
parameterType="java.util.Map">
select ac.id
FROM auto_word_config ac LEFT JOIN category dc ON ac.category_id = dc.category_id
LEFT JOIN `user` duo on duo.user_id= ac.owner_id
WHERE ac.isactive = 1 AND dc.isactive = 1
<if test="sortOrder == null or sortOrder == ''">
ORDER BY ac.update_time DESC
</if>
<if test="sortField != null and sortOrder != null">
ORDER BY
<choose>
<when test="sortField == 'owner_name' ">
duo.user_name
</when>
<when test="sortField == 'category_name'">
dc.${sortField}
</when>
<otherwise>
ac.${sortField}
</otherwise>
</choose>
<if test="sortOrder == 'asc'">
ASC
</if>
<if test="sortOrder == 'desc'">
DESC
</if>
</if>
</select>

逻辑:

  1. 如果没有排序,则默认以更新时间降序获取列表;否则就以前端指定的字段来排序;
  2. 跨表join时,需要通过​​choose...when...otherwise​​来选择哪个表的字段来进行排序;
  3. 不能使用​​#{sortField}​​​,必须使用​​${sortField}​​​。因为前者为了防止SQL注入,会自动加单引号​​''​​,导致拼接的SQL执行异常。

工具类方法:

/**
* 驼峰转下划线
*
* @param camel camelCase
* @return Underscore
*/
public static String camelCaseToUnderscore(String camel) {
StringBuilder underscore;
underscore = new StringBuilder(String.valueOf(Character.toLowerCase(camel.charAt(0))));
for (int i = 1; i < camel.length(); i++) {
underscore.append(Character.isLowerCase(camel.charAt(i)) ? String.valueOf(camel.charAt(i))
: "_" + Character.toLowerCase(camel.charAt(i)));
}
return underscore.toString();
}

拓展

局限

只能指定一个排序字段。

优化

上面的代码,可以进一步优化:
前端传参:​​​sortOrder: sorter.order === 'descend' ? 'DESC' : 'ASC'​​ 后端那一大坨代码:

<if test="sortOrder == 'asc'">
ASC
</if>
<if test="sortOrder == 'desc'">
DESC
</if>

则可以替换为:​​${sortOrder}​

规范

上面这个方案,建立在一个开发规范上,即数据表的定义为下划线命名,后端POJO定义为驼峰命名,返回给前端的是驼峰命名,并且驼峰命名通过工具类方法可以转化为下划线。

如果数据表字段定义为board_id,但是返回给前端的字段确实id,此时如果以id来排序,需要映射为boardId,无论是前端还是后端,都需要加一层繁琐的映射:

if (sorter && sorter.field && sorter.order) {
if (sorter.field === 'id') {
sorter.field = 'boardId'
}
if (sorter.field === 'name') {
sorter.field = 'boardName'
}
fetchDataWithParams({
...pagination,
sortField: sorter.field,
sortOrder: sorter.order === 'descend' ? 'desc' : 'asc'
});
}

所以开发规范很重要!!

参考


举报

相关推荐

0 条评论