利用周末时间,对自己的项目进行了升级,原来使用的是tkmybatis,改为mybatis-plus。但是返回数据的格式变了,导致前端的客户端排序失效了,于是决定在服务端实现排序。
目录
easyui的数据表格datagrid支持多字段排序,可以控制是否通过服务器排序,核心代码如下。
前端代码
role_list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>角色列表</title>
<link rel="stylesheet" href="/css/themes/icon.css"/>
<link rel="stylesheet" href="/css/themes/default/easyui.css" />
</head>
<body>
<table id="role_list"></table>
<script src="/js/public/public.js"></script>
<script src="/js/public/jquery.min.js"></script>
<script src="/js/public/jquery.easyui.min.js"></script>
<script src="/js/public/easyui-lang-zh_CN.js"></script>
<script src="/js/role_account/role_list.js"></script>
</body>
</html>
role_list.js
在需要开启排序功能的字段后面添加sortable:true的选项
let pageList = [10, 20, 50, 100];
$(document).ready(function() {
// 角色数据表格
$("#role_list").datagrid({
url: '/role_account/selectByPage',
striped: true,
multiSort: true,
fitColumns: true,
remoteSort: true,
singleSelect: true,
height: table_height,
pagination: true,
pageList: pageList,
pageSize: pageList[0],
loadFilter: function(result){
if (result.code === 200){
return result.data;
} else {
return null;
}
},
toolbar: [{
iconCls: 'icon-add',
text: '添加',
handler: function() {
handleAdd();
}
}, '-', {
iconCls: 'icon-edit',
text: '修改',
handler: function() {
handleUpdate();
}
}, '-', {
iconCls: 'icon-set',
text: '加点',
handler: function() {
handleJiadian();
}
}, '-', {
iconCls: 'icon-shield',
text: '属性',
handler: function() {
handleAttribute();
}
}, '-', {
iconCls: 'icon-search',
text: '查看',
handler: function() {
handleView();
}
}, '-', {
iconCls: 'icon-tip',
text: '关于',
handler: function() {
handleTip();
}
}],
columns: [[
{field: 'id', title: '角色ID', align: "center", sortable: true, width:100},
{field: 'name', title: '角色名', align: "center", width: 120},
{field: 'modelingId', title: '角色造型', align: "center", width: 80
, formatter: function(value, rowData, rowIndex) {
get("/role_modeling/selectById", {
id: value
}, function(result) {
$("#modeling_" + rowIndex).attr("src", result.image)
.attr("title", result.name);
}, error);
return "<img width='" + size + "' id='modeling_" + rowIndex + "' />";
}
},
{field: 'grade', title: '等级', align: "center", sortable: true, width: 80
, formatter: function(value) {
let group; // 组别
if(value >= 0 && value <= 69) { // [0, 69]精锐组
group = "精锐组";
} else if(value >= 70 && value <= 89) { // [70, 89]勇武组
group = "勇武组";
} else if(value >= 90) { // [90, 115]神威组
group = "神威组";
} else { // [-∞, 0) ∪ (115, +∞)
group = "等级不合法";
}
return "<span title='" + group + "'>" + value+ "级</span>";
}
},
{field: 'score', title: '人物评分', align: "center", sortable: true, width: 80},
{field: 'schoolId', title: '门派', align: "center", width: 80
, formatter: function(value, rowData, rowIndex) {
get("/school/selectById", {
id: value
}, function(result) {
$("#school_" + rowIndex).attr("src", result.image)
.attr("title", result.name).width(size);
}, error);
return "<img width='" + size + "' id='school_" + rowIndex + "' />";
}
},
{field: 'jinbi', title: '金币', align: "center", sortable: true, width: 80},
{field: 'accountId', title: '账号', align: "center", width: 200
, formatter: function(value, rowData, rowIndex) {
get("/account/selectAccountById", {
id: value
}, function(response) {
$("#account_" + rowIndex).html(response.data);
}, error);
return "<div id='account_" + rowIndex + "'></div>";
}
},
{field: "lastUpdateTime", title: "最后一次修改时间", align: "center", sortable: true, width: 125},
{field: 'right', title: '操作', align: "center"
, formatter: function(value, rowData, rowIndex) {
return '<a href="javascript:;" '
+ 'onclick="handleDelete(' + rowData.id + ')">'
+ '<img title="删除" src="/css/themes/icons/delete.png" /></a>';
}
}
]]
});
});
表格的multiSort选项设置为true表示允许多字段排序,remoteSort表示是否从服务器排序,设置为true,我们接下来在后台接口处理字段排序。
后端代码
controller层
RoleAccountController.java
@RestController
@RequestMapping(path = "/role_account", produces="application/json; charset=utf-8")
public class RoleAccountController {
private final IRoleAccountService service;
@Autowired
public RoleAccountController(IRoleAccountService service) {
this.service = service;
}
@ApiOperation("分页查询角色列表")
@RequestMapping(value = "/selectByPage", method = RequestMethod.POST)
public JsonResult<PageResult<RoleAccount>> selectByPage(RoleAccountPager pager) {
Page<RoleAccount> page = service.selectByPage(pager);
return JsonResult.restPage(page);
}
}
service层
RoleAccountServiceImpl.java
@Service
public class RoleAccountServiceImpl implements RoleAccountService {
@Override
public Page<RoleAccount> selectByPage(RoleAccountPager pager) {
Page<RoleAccount> page = new Page<>(pager.getPage(), pager.getRows());
QueryWrapper<RoleAccount> wrapper = new QueryWrapper<>();
wrapper.eq(
!StringUtils.isEmpty(pager.getId()),
"id", pager.getId());
wrapper.like(
!StringUtils.isEmpty(pager.getName()),
"name", pager.getName()
);
wrapper.eq(
pager.getSchoolId() != null,
"school_id", pager.getSchoolId()
);
wrapper.eq(
pager.getModelingId() != null,
"modeling_id", pager.getModelingId()
);
wrapper.eq(
!StringUtils.isEmpty(pager.getAccountId()),
"account_id", pager.getAccountId()
);
// 得到order by语句
String statement = Pager.getOrderByStatement(pager);
wrapper.last(statement);
return mapper.selectPage(page, wrapper);
}
}
mapper层
RoleAccountMapper.java
@Repository public interface RoleAccountMapper extends BaseMapper<RoleAccount> { }
RoleAccount.java
@Data
public class RoleAccount {
@TableId("id")
private String id;
/**
* 角色名
*/
private String name;
/**
* 等级
*/
private Integer grade;
/**
* 人物评分
*/
private Integer score;
/**
* 金币
*/
private Integer jinbi;
/**
* 账号id
*/
private String accountId;
/**
* 门派id
*/
private Integer schoolId;
/**
* 服务器id
*/
private Integer serverId;
/**
* 角色造型id
*/
private Integer modelingId;
/**
* 账号创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime birthday;
/**
* 最后一次修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime lastUpdateTime;
}
RoleAccountPager.java
接收前端传递的查询参数
@Data
@EqualsAndHashCode(callSuper = true)
public class RoleAccountPager extends Pager {
/**
* 角色id
*/
private String id;
/**
* 角色名
*/
private String name;
/**
* 等级
*/
private Integer grade;
/**
* 账号id
*/
private String accountId;
/**
* 门派id
*/
private Integer schoolId;
/**
* 角色造型id
*/
private Integer modelingId;
}
Pager.java
/**
* 基础分页对象,包含页数和每页的记录数
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class Pager extends Sorter {
/**
* 页数
*/
private Integer page = 1;
/**
* 每页记录数
*/
private Integer rows = 10;
}
Sorter.java
以上是easyui官网的相关截图,当多字段排序时,传递给后台的参数中通过逗号拼接。
【例如】:通过评分score升序和等级grade降序排序时,后台接收到的参数为:
{
"sort": "score,grade"
"order": "asc,desc"
}
于是基于此规则,在Sorter.java中提供一个处理排序字段的方法
/**
* 基础排序对象,包含排序字段和排序方式
*/
@Data
public class Sorter {
/**
* 排序字段
*/
private String sort;
/**
* 排序方式:asc/desc
*/
private String order;
/**
* 根据查询条件拼接得到order by语句
* @param sorter 分页查询条件
* @return String
*/
public static String getStatement(Sorter sorter) {
String sort;
String[] sortArray = {};
String[] orderArray = {};
String order = sorter.getOrder();
String sortColumn = sorter.getSort();
StringBuilder statement = new StringBuilder();
// 多字段排序
if (StringUtils.isNotEmpty(sortColumn)) {
// 驼峰命名转为下划线
sort = StringUtils.toLowerCase(sortColumn);
if (sort.contains(",")) {
sortArray = sort.split(",");
}
} else {
return "";
}
if (StringUtils.isNotEmpty(order)) {
if (order.contains(",")) {
orderArray = order.split(",");
}
} else {
return "";
}
if (sortArray.length > 0 && orderArray.length > 0) {
int length = sortArray.length;
for (int i = 0; i < length; i++) {
statement.append(sortArray[i]);
statement.append(" ");
statement.append(orderArray[i]);
if (i < length - 1 ) {
statement.append(", ");
}
}
} else {
// " #{sort} #{order}“
statement.append(sort);
statement.append(" ");
statement.append(order);
}
return statement.toString();
}
/**
* 根据查询条件拼接得到order by语句
* @param sorter 分页查询条件
* @return String
*/
public static String getOrderByStatement(Sorter sorter) {
String statement = getStatement(sorter);
if (StringUtils.isNotEmpty(statement)) {
return " order by " + statement;
} else {
return statement;
}
}
}
因为排序的字段名是驼峰命名,需要转为小写字母+下划线命名,转换的方法抽象到了StringUtils工具类中,代码如下。
public class StringUtils {
/**
* 功能:驼峰命名转下划线命名
* 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
* @param str 待转换的字符串
* @return String
*/
public static String toLowerCase(String str) {
str = str.replaceAll("([a-z])([A-Z])", "$1_$2");
return str.toLowerCase();
}
}
通过继承关系,我们控制器接口的参数类型继承自Pager<T>即自动获得分页和排序功能,只需要在构造条件查询器QueryWrapper时增加以下两行代码即可在后端开启多字段排序功能:
String statement = Pager.getOrderByStatement(pager);
wrapper.last(statement);
好了,文章就分享到这里了,看完不要忘了点赞+收藏哦~