前言:业务上经常会有 对分类/菜单 等列表进行拖拽排序 上移/下移等操作,同时后台也需要对整个列表的sort值进行后台更新和前台保持一致
前端需要传被拖拽的对象的id,开始/结束后的下标索引[下标从0开始],同时要求数据字段中包含(long)id,(Integer)sort基础字段,最终返回sort值需要更新的集合,同步更新数据库
package com.example.bean;
import lombok.Data;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* @author 徐刘
* @version 1.0
* @desc demo
* @date 2021/6/25 13:46
*/
public class Test2 {
@Data
static class Test1 {
private Integer id;
private Integer sort;
private String name;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
List<Test1> list = new ArrayList<>();
// 组装一个 list 集合数据 正序展示 sort值 从小到大[0-->4]
/**
* [
* {id:0,sort:0,name:name0}, 下标索引 0
* {id:1,sort:1,name:name1}, 1
* {id:2,sort:2,name:name2}, 2
* {id:3,sort:3,name:name3}, 3
* {id:4,sort:4,name:name4} 4
* ]
*
*/
for (int i = 0; i < 5; i++) {
Test1 test1 = new Test1();
test1.setId(i);
test1.setSort(i);
test1.setName("name" + i);
list.add(test1);
}
// targetId(拖拽的对象) 即 对应的是 {id:1,sort:1,name:name1} 数据
Integer targetId = 1;
// 对象所属当前的 下标 索引位置 1
Integer startIndex = 1;
// 对象所属 拖拽后所属的 下标 索引的 位置[例:把name1 拖拽到 name3 之后的位置 拖拽后的name1的下标索引 即为3]
Integer endIndex = 3;
//list是按照sort 值升序查询 的还是降序查询的
boolean isAsc = true;
//返回sort 值有变化需要更新的集合
List<Test1> needUpdateSortList = getNeedUpdateSortList(list, targetId, startIndex, endIndex, isAsc);
for (Test1 bean : needUpdateSortList) {
System.out.println(bean);
}
//输出的结果 即 name1 在 在name3 之后 同时 name1 的sort 值从 1-->3 ;name2,name3 的排序值进行了-1
//Test2.Test1(id=2, sort=1, name=name2)
//Test2.Test1(id=3, sort=2, name=name3)
//Test2.Test1(id=1, sort=3, name=name1)
}
/**
* @param allList 排序序 的集合(跟列表顺序保持一致)
* @param targetId 目标对象的Id
* @param startIndex 对象在列表的开始索引值[索引值从0 开始]
* @param endIndex 移动后的目标索引值[索引值从0 开始]
* @param isAsc 集合列表 是否正序 TRUE 正序
* @Description: 构建 需要 排序的 list集合
* @Author: 徐刘
* @Date: 2021/6/29 11:49
* @Return: java.util.List<T> 返回sort值变动的数据集合
*/
public static <T> List<T> getNeedUpdateSortList(List<T> allList, Integer targetId, Integer startIndex, Integer endIndex, boolean isAsc) throws NoSuchFieldException, IllegalAccessException {
List<T> buildList = new ArrayList<>();
if (targetId == null || startIndex == null || endIndex == null) {
throw new IllegalAccessException("targetId/startIndex/endIndex不能为空!");
}
if (CollectionUtils.isEmpty(allList) || startIndex.equals(endIndex)) {
return buildList;
}
//需要 修改排序值得 数据集合 不包含 目标对象 本身
List<T> excludeList = new ArrayList();
//目标 对象
T targetBean = null;
//截取的 开始 索引 和 结束 索引 之间的 list 包含 targetBean(拖拽排序目标自身) 的一个 集合
List<T> subList = null;
//需改排序规则 (只修改 索引区间的值)
//== ================获取 索引区间的 数据集合 begin ==================
boolean flag = endIndex > startIndex;
if (flag) {
//下移
subList = allList.subList(Integer.parseInt(startIndex.toString()), Integer.parseInt(endIndex.toString()) + 1);
} else {
// 上移
subList = allList.subList(Integer.parseInt(endIndex.toString()), Integer.parseInt(startIndex.toString()) + 1);
}
//== ================获取 索引区间的 数据集合 end ==================
if (CollectionUtils.isEmpty(subList)) {
return buildList;
}
//=================== 获取 排序区间 里面的 目标对象 + 排出目标对象之后的集合 begin =============
for (T bean : subList) {
Field idField = bean.getClass().getDeclaredField("id");
idField.setAccessible(true);
Object currentId = idField.get(bean);
if (targetId.equals((Integer) (currentId))) {
targetBean = bean;
} else {
excludeList.add(bean);
}
}
if (targetBean == null) {
throw new IllegalAccessException("目标对象不存在!");
}
//=================== 获取 排序区间 里面的 目标对象 + 排出目标对象之后的集合 end =============
//============获取 拖拽对象 上移/下移 之后的 sort 值 begin========================
//需要修改自己的排序值
//需要 对索引区间的排序值(不包含排序对象自身) 进行 加1 或者 减 1
T tempBean = null;
if (flag) {
//下移
tempBean = excludeList.get(excludeList.size() - 1);
} else {
//上移动
tempBean = excludeList.get(0);
}
Field sortField = tempBean.getClass().getDeclaredField("sort");
sortField.setAccessible(true);
Integer sort = (Integer) sortField.get(tempBean);
//============获取 拖拽对象 上移/下移 之后的 sort 值 end========================
//===================修改 目标对象 排序值 begin ==============
Field targetBeanSortField = targetBean.getClass().getDeclaredField("sort");
targetBeanSortField.setAccessible(true);
targetBeanSortField.set(targetBean, sort);
//===================修改 目标对象 排序值 begin ==============
//================修改 需要排序 区间(排序目标对象自身) 排序值 begin ========
//处理
for (T bean : excludeList) {
sortField = bean.getClass().getDeclaredField("sort");
sortField.setAccessible(true);
sort = (Integer) sortField.get(bean);
//flag true : 下移 非拖动对象 自身 排序索引值 需要 -1; false 反之
if (isAsc) {
//正序
sortField.set(bean, flag ? (sort - 1) : (sort + 1));
} else {
//倒叙
sortField.set(bean, flag ? (sort + 1) : (sort - 1));
}
}
//================修改 需要排序 区间(排序目标对象自身) 排序值 end ========
buildList.addAll(excludeList);
buildList.add(targetBean);
return buildList;
}
}