如何在SpringBoot后台管理面板中自定义调整分类排序?
SpringBoot实现产品分类自定义排序(上下箭头操作)
一、实体层改造
给产品分类实体(如ProductCategory)新增排序字段,用于存储优先级排序值:
@Entity @Table(name = "product_category") public class ProductCategory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 排序字段,值越小展示越靠前,默认初始化0 private Integer sort = 0; // 其他业务字段、getter/setter省略 }
新创建分类时,可将sort设为当前最大排序值+1,确保默认排在列表末尾。
二、DAO层(Repository)
实现核心数据操作方法,支持排序更新、相邻分类查询:
public interface ProductCategoryRepository extends JpaRepository<ProductCategory, Long> { // 根据ID更新排序值 @Modifying @Query("UPDATE ProductCategory c SET c.sort = :sort WHERE c.id = :id") void updateSortById(@Param("id") Long id, @Param("sort") Integer sort); // 查询当前分类的上一个分类(取sort小于当前值的最大项) Optional<ProductCategory> findTopBySortLessThanOrderBySortDesc(Long currentSort); // 查询当前分类的下一个分类(取sort大于当前值的最小项) Optional<ProductCategory> findTopBySortGreaterThanOrderBySortAsc(Long currentSort); // 按排序值升序查询所有分类 List<ProductCategory> findAllByOrderBySortAsc(); }
三、Service层排序逻辑
编写上下移动的业务逻辑,核心是交换当前分类与相邻分类的排序值:
@Service public class ProductCategoryService { @Autowired private ProductCategoryRepository categoryRepository; // 分类上移 public void moveUp(Long categoryId) { ProductCategory current = categoryRepository.findById(categoryId) .orElseThrow(() -> new RuntimeException("目标分类不存在")); Optional<ProductCategory> prevOpt = categoryRepository.findTopBySortLessThanOrderBySortDesc(current.getSort()); if (prevOpt.isPresent()) { ProductCategory prev = prevOpt.get(); // 交换排序值 Integer temp = current.getSort(); current.setSort(prev.getSort()); prev.setSort(temp); categoryRepository.save(current); categoryRepository.save(prev); } } // 分类下移 public void moveDown(Long categoryId) { ProductCategory current = categoryRepository.findById(categoryId) .orElseThrow(() -> new RuntimeException("目标分类不存在")); Optional<ProductCategory> nextOpt = categoryRepository.findTopBySortGreaterThanOrderBySortAsc(current.getSort()); if (nextOpt.isPresent()) { ProductCategory next = nextOpt.get(); // 交换排序值 Integer temp = current.getSort(); current.setSort(next.getSort()); next.setSort(temp); categoryRepository.save(current); categoryRepository.save(next); } } }
四、Controller层接口
按照你提到的/order-save设计统一接口,接收分类ID和移动方向:
@RestController @RequestMapping("/admin/category") public class ProductCategoryController { @Autowired private ProductCategoryService categoryService; @PostMapping("/order-save") public ResponseEntity<Void> saveOrder(@RequestParam Long categoryId, @RequestParam String direction) { if ("up".equals(direction)) { categoryService.moveUp(categoryId); } else if ("down".equals(direction)) { categoryService.moveDown(categoryId); } else { return ResponseEntity.badRequest().build(); } return ResponseEntity.ok().build(); } }
五、前端上下箭头实现
在后台分类列表页面,给每个分类添加fas fa-arrow-up和fas fa-arrow-down按钮,点击时调用后端接口并刷新列表:
<!-- 以Thymeleaf模板为例渲染分类列表 --> <table class="table"> <thead> <tr> <th>分类名称</th> <th>排序操作</th> </tr> </thead> <tbody> <tr th:each="category : ${categories}"> <td th:text="${category.name}"></td> <td> <button class="btn btn-sm btn-outline-primary" onclick="adjustSort([[${category.id}]], 'up')"> <i class="fas fa-arrow-up"></i> </button> <button class="btn btn-sm btn-outline-primary" onclick="adjustSort([[${category.id}]], 'down')"> <i class="fas fa-arrow-down"></i> </button> </td> </tr> </tbody> </table> <script> function adjustSort(categoryId, direction) { fetch('/admin/category/order-save', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-TOKEN': document.querySelector('meta[name="_csrf"]').content }, body: `categoryId=${categoryId}&direction=${direction}` }).then(response => { if (response.ok) { window.location.reload(); } }).catch(error => { console.error('排序失败:', error); alert('排序操作失败,请重试'); }); } </script>
注意事项
- 权限控制:后台接口需添加管理员权限校验,防止非法访问
- 排序初始化:新分类创建时,可通过查询当前最大排序值+1来设置初始
sort - 异常处理:可根据业务需求自定义异常类型,替换示例中的
RuntimeException
内容的提问来源于stack exchange,提问作者mattar
相关产品推荐
相关产品推荐

