整理个需求的实现思路。
列表展示了一系列产品,现要支持通过拖动来给产品排序,也要支持单个产品的置顶、删除。类似CSDN的专栏文章管理。
现要支持对列表的产品进行拖动排序,考虑新增个hot_sort字段,代表产品的先后顺序(或者热门程度)。关于表设计,可在原来的 t_product表中直接新加个hot_sort字段。如果有其他业务字段,也可新建个中间表,核心字段:t_product表的product_id
、热门排序字段hot_sort
、其余业务字段。
//示例
ALTER TABLE t_product ADD hot_sort INT;
//值越小越靠前
关于接口实现,考虑让前端传两个productId,一个是被移动的产品的ID(productId
),一个则是移动目标点的产品的ID(afterProductId
)。如此,通过比较这两个ID对应产品的hot_sort字段值的大小关系,就可一个接口实现前移、后移、置顶:
以下为示意代码:
//Dto类
@Data
@ToString
public class SortDto {
private String afterProductId;
private String productId;
}
Controller:
@Resource
private Service service;
/**
* 拖动排序:前移、后移、置顶
*/
@PostMapping("/update/sort")
public Result updateSort(@RequestBody SortDto dto) {
return Result.success(service.updateProductSort(dto));
}
/**
* 删除产品
*/
@GetMapping("/delete")
public Result updateSort(String productId) {
return Result.success(service.deleteProduct(productId));
}
Service层,直接写实现类:
@Resource
private ProductMapper mapper;
public class ServiceImpl implements Service {
@Override
public int updateProductSort(SortDto dto) {
//必要的参数和权限校验,略...
//被移动的产品
ProductPo targetPo = mapper.selectById(dto.getProductId);
Assert.notNull(targetPo);
//用于更新的产品对象
ProductPo updatePo = new ProductPo();
updatePo.setId(targetPo.getProductId); //其他属性略,可直接BeanUtils.copyProperties()
//afterProductId为空,代表置顶操作
//非置顶
if (StringUtils.isNotEmpty(dto.getAfterProductId)){
//移动目标点的产品ID
ProductPo afterPo = mapper.selectById(dto.getAfterProductId);
Assert.notNull(afterPo);
//前移
if (afterPo.getHotSort() < targetPo.getHotSort() && targetPo.getHotSort() - afterPo.getHotSort() > 1) {
//产品前移,受影响的产品要后移
mapper.moveBack(afterPo.getHotSort(), targetPo.getHotSort());
//被移动的产品放到目标位置的产品之后
updatePo.setHotSort(afterPo.getHotSort() + 1 );
return mapper.updateById(updatePo);
//后移
} else if (afterPo.getHotSort() > targetPo.getHotSort() && afterPo.getHotSort() - targetPo.getHotSort() > 1) {
//产品后移,受影响的产品要前移
mapper.moveBefore(afterPo.getHotSort(), targetPo.getHotSort());
//被移动的产品放到目标位置的产品之后,但此时目标位置的产品已经前进一步,这里不再需要+1
updatePo.setHotSort(afterPo.getHotSort());
return mapper.updateById(updatePo);
}
} else {
//置顶
mapper.moveTop(targetPo.getHotSort); //处理因置顶产品而受影响的其他产品的sort值
updatePo.setHotSort(0); //赋0,置顶
return mapper.updateById(updatePo);
}
return 1; //如果两个Id都一样,也不用处理,直接返回个操作成功也无所谓
}
@Override
public int deleteProduct(String productId) {
//必要的业务和权限校验,略
ProductPo po = mapper.selectById(productId);
Assert.notNull(po);
int size = mapper.selectCount(new QueryWrapper<>());
//让被删产品后面的产品全部前进一格
mapper.moveBefore(size,po.getHotSort());
return mapper.deleteById(productId);
}
}
Mapper接口略,相关SQL:
<update id="moveBack" parameterType="int">
update t_product
set hot_sort = hot_sort + 1
where hot_sort > #{beforeSort}
and hot_sort < #{moveSort}
update>
<update id="moveBefore" parameterType="int">
update t_product
set hot_sort = hot_sort - 1
where hot_sort > #{moveSort}
and hot_sort <= #{beforeSort}
update>
<update id="moveTop" parameterType="int">
update t_product
set hot_sort = hot_sort + 1
where hot_sort < #{moveSort}
update>