一维模块移动逻辑后端实现

  • 移动的逻辑,前端有专门的框架sortable.js提供了API进行实现,但是有些场景需要后端实现动态拖动排序,所以记录一下实现过程,后面如果有类似需求直接进行复用。

核心逻辑部分

  • 当前模块里面调整顺序:变动区间重新排序
  • 从另一个模块组移动到当前模块组:当前模块组重排序,原有模块组进行重排序
  • 删除某个元素:模块组内进行冲排序
  • 同个模块组中的移动分为两种:上移和下移
  • 移动的本质:是进行修改操作,修改对应数据的排序

移动操作

定义业务操作接口

  • 定义业务需要操作的接口 及 业务数据透传的实体类
  • 这个实体类只做标识作用,具体业务继承这个实体类增加透传字段

public interface OsDesignerMoveOperationService<T extends MoveBusinessDto> {
  /**
   * 批量更新移动
   *
   * @param moveChangedDto
   */
  void batchUpdateMove(List<MoveDto> moveChangedDto);


  /**
   * 获取移动的列表
   * @param t
   * @param parent
   * @return
   */
  List<MoveDto> getMoveList(T t, Long parent);
}

@Data
@Accessors(chain = true)
public class MoveBusinessDto {

}

移动逻辑

  • 进行排序
  • 重排后的顺序进行更新
public interface MoveService<T> {

  public void move(T t, Long id, MoveRequestDto dto, MoveOperationService service);

  public List<MoveDto> moveOldParentModule(T t, Long oldParent, MoveOperationService service);

}


@Service
public class MoveServiceImpl implements MoveService<MoveBusinessDto> {


  public  void move(MoveBusinessDto t, Long id, MoveRequestDto dto, MoveOperationService service) {
    Long oldParent = dto.getOldParent();
    Long parent = dto.getParent();
    Long brother = dto.getBrother();
    List<MoveDto> dtos = service.getMoveList(t, parent);
    List<MoveDto> moveChangedDto = new ArrayList<>();
    //module sort
    // no sub module
    if (CollectionUtils.isEmpty(dtos)) {
      MoveDto moveDto = new MoveDto();
      moveDto.setOrdering(1).setId(id).setParent(parent);
      moveChangedDto.add(moveDto);
    } else {
      moveChangedDto = getMoveChangeModuleDtos(id, oldParent, parent, brother, dtos);
    }
    service.batchUpdateMove(moveChangedDto);
    // old parent sort
    if (!Objects.equals(oldParent, parent)) {
      List<MoveDto> moveOldParentModule = moveOldParentModule(t, oldParent, service);
      service.batchUpdateMove(moveOldParentModule);
    }

  }

  public List<MoveDto> moveOldParentModule(MoveBusinessDto t, Long oldParent, OsDesignerMoveOperationService service) {
    List<MoveDto> oldModuleMoveDto = service.getMoveList(t, oldParent);
    if (!CollectionUtils.isEmpty(oldModuleMoveDto)) {
      oldModuleMoveDto.forEach(v -> v.setOrdering(v.getRowNum()));
    }
    return oldModuleMoveDto;
  }

  public List<MoveDto> getMoveChangeModuleDtos(Long id, Long oldParent, Long parent, Long brother, List<MoveDto> dtos) {
    List<MoveDto> moveChangedDto;
    if (Objects.equals(oldParent, parent)) {//同组
      MoveDto moveDto = dtos.stream().filter(v -> v.getId().equals(id)).findFirst().get();
      Integer oldMoveRowNum = moveDto.getRowNum();
      Integer oldBrotherRowNum = getOldBrotherMoveRowNum(brother, dtos);
      if (oldMoveRowNum < oldBrotherRowNum) {//下移
        moveChangedDto = dtos.subList(oldMoveRowNum, oldBrotherRowNum);
        moveChangedDto.stream().forEach(v -> v.setOrdering(v.getRowNum() - 1));
        moveDto.setOrdering(oldBrotherRowNum);
      } else {//上移
        moveChangedDto = dtos.subList(oldBrotherRowNum, oldMoveRowNum);
        moveChangedDto.stream().forEach(v -> v.setOrdering(v.getRowNum() + 1));
        moveDto.setOrdering(oldBrotherRowNum + 1);
      }
      moveChangedDto.add(moveDto);
    } else {//跨组
      Integer oldBrotherMoveDtoRowNum = getOldBrotherMoveRowNum(brother, dtos);
      //上移
      moveChangedDto = dtos.subList(oldBrotherMoveDtoRowNum, dtos.size());
      moveChangedDto.stream().forEach(v -> v.setOrdering(v.getRowNum() + 1));

      MoveDto moduleMoveDto = new MoveDto();
      moduleMoveDto.setOrdering(oldBrotherMoveDtoRowNum + 1).setId(id).setParent(parent);
      moveChangedDto.add(moduleMoveDto);
    }
    return moveChangedDto;
  }


  public Integer getOldBrotherMoveRowNum(Long brother, List<MoveDto> dtos) {
    Integer oldBrotherMoveDtoRowNum = 0;
    if (Objects.nonNull(brother) && brother > 0) {
      MoveDto brotherMoveDto = dtos.stream().filter(v -> v.getId().equals(brother)).findFirst().orElse(null);
      if (Objects.nonNull(brotherMoveDto)) {
        oldBrotherMoveDtoRowNum = brotherMoveDto.getRowNum();
      }
    }
    return oldBrotherMoveDtoRowNum;
  }


}


需要业务类实现的接口

继承接口,实现业务方法

public class A implements MoveOperationService<MoveBusinessDto>{

}

获取排序

  • 根据row_num确定排序的序号
  • 旧的组获取也是同一个方法
    select
            row_number() over () as row_num,
            id,
            ordering,
            parent,
        from os_module
        where 1 = 1  and parent = #{parent}
        order by ordering;

批量更新

按照move业务类的参数要求进行封装

对实现过程进行记录,方便后面出现直接代码复用

posted @   PerfectLi  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示