feat(dealer): 添加经销商拖拽排序功能
- 新增 DealerDragCmd 数据传输对象,用于接收拖拽排序参数 - 在 DealerController 中添加 dragDealer 接口,支持 PATCH 和 PUT 请求 - 在 DealerServiceI 接口及其实现类 DealerServiceImpl 中增加 drag 方法 - 在 DealerGateway 接口及实现类 DealerGatewayImpl 中添加 drag 方法逻辑 - 修改 Dealer 实体类和 DealerDO 数据库映射类,新增 sort 字段用于排序 - 更新 DealerMapper,添加批量重置排序的 SQL 方法 batchResetSort - 在查询接口中默认按 sort 字段升序排列,确保展示顺序正确 - 新增 DealerDragCmdExe 执行器处理拖拽命令,并调用网关层进行业务处理 - 实现拖拽排序核心算法,包括计算新 sort 值、判断是否需要重整排序等逻辑
This commit is contained in:
parent
aa4620b30b
commit
ebfdedc01a
@ -8,6 +8,7 @@ import com.alibaba.cola.dto.SingleResponse;
|
||||
import com.xunhong.erp.turbo.api.biz.api.DealerServiceI;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerCreateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDestroyCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerUpdateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerListQry;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPageQry;
|
||||
@ -82,4 +83,13 @@ public class DealerController {
|
||||
dealerService.destroy(dealerDestroyCmd);
|
||||
return Response.buildSuccess();
|
||||
}
|
||||
|
||||
@SaCheckLogin
|
||||
// @SaCheckPermission(value = {PermissionConstant.MDB_BUSINESS_DEALER_UPDATE})
|
||||
@RequestMapping(value = "dragDealer", method = {RequestMethod.PATCH, RequestMethod.PUT})
|
||||
@Operation(summary = "经销商表拖拽排序", method = "PATCH")
|
||||
public Response dragDealer(@RequestBody @Validated DealerDragCmd dealerDragCmd) {
|
||||
dealerService.drag(dealerDragCmd);
|
||||
return Response.buildSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
package com.xunhong.erp.turbo.biz.app.executor.query;
|
||||
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.biz.domain.gateway.DealerGateway;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author shenyifei
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class DealerDragCmdExe {
|
||||
private final DealerGateway dealerGateway;
|
||||
|
||||
public void execute(DealerDragCmd dealerDragCmd) {
|
||||
dealerGateway.drag(dealerDragCmd);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.xunhong.erp.turbo.biz.app.service;
|
||||
import com.xunhong.erp.turbo.api.biz.api.DealerServiceI;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerCreateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDestroyCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerUpdateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerListQry;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPageQry;
|
||||
@ -12,6 +13,7 @@ import com.xunhong.erp.turbo.base.dto.PageDTO;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.cmd.DealerCreateCmdExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.cmd.DealerDestroyCmdExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.cmd.DealerUpdateCmdExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.query.DealerDragCmdExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.query.DealerListQryExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.query.DealerPageQryExe;
|
||||
import com.xunhong.erp.turbo.biz.app.executor.query.DealerShowQryExe;
|
||||
@ -33,10 +35,11 @@ public class DealerServiceImpl implements DealerServiceI {
|
||||
|
||||
private final DealerCreateCmdExe dealerCreateCmdExe;
|
||||
private final DealerUpdateCmdExe dealerUpdateCmdExe;
|
||||
private final DealerPageQryExe dealerPageQryExe;
|
||||
private final DealerListQryExe dealerListQryExe;
|
||||
private final DealerShowQryExe dealerShowQryExe;
|
||||
private final DealerDestroyCmdExe dealerDestroyCmdExe;
|
||||
private final DealerPageQryExe dealerPageQryExe;
|
||||
private final DealerListQryExe dealerListQryExe;
|
||||
private final DealerDragCmdExe dealerDragCmdExe;
|
||||
|
||||
@Override
|
||||
public DealerVO create(DealerCreateCmd dealerCreateCmd) {
|
||||
@ -67,5 +70,9 @@ public class DealerServiceImpl implements DealerServiceI {
|
||||
public void destroy(DealerDestroyCmd dealerDestroyCmd) {
|
||||
dealerDestroyCmdExe.execute(dealerDestroyCmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drag(DealerDragCmd dealerDragCmd) {
|
||||
dealerDragCmdExe.execute(dealerDragCmd);
|
||||
}
|
||||
}
|
||||
@ -88,6 +88,11 @@ public class Dealer extends DTO {
|
||||
*/
|
||||
private String deliveryTemplate;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private BigDecimal sort;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ -99,4 +104,3 @@ public class Dealer extends DTO {
|
||||
private List<DealerPaymentAccount> dealerPaymentAccountList;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package com.xunhong.erp.turbo.biz.domain.gateway;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerCreateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDestroyCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerUpdateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerListQry;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPageQry;
|
||||
@ -26,5 +27,6 @@ public interface DealerGateway {
|
||||
Dealer show(DealerShowQry dealerShowQry);
|
||||
|
||||
void destroy(DealerDestroyCmd dealerDestroyCmd);
|
||||
}
|
||||
|
||||
void drag(DealerDragCmd dealerDragCmd);
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@ public interface DealerConvert {
|
||||
@Mapping(target = "dealerPaymentAccountList", source = "dealerPaymentAccountDOList")
|
||||
Dealer toDealer(DealerDO dealerDO);
|
||||
|
||||
@Mapping(target = "sort", ignore = true)
|
||||
@Mapping(target = "deliveryTemplate", ignore = true)
|
||||
@Mapping(target = "dealerPaymentAccountDOList", ignore = true)
|
||||
@Mapping(target = "version", ignore = true)
|
||||
@Mapping(target = "updatedAt", ignore = true)
|
||||
@ -25,6 +27,7 @@ public interface DealerConvert {
|
||||
@Mapping(target = "createdAt", ignore = true)
|
||||
DealerDO toDealerDO(DealerCreateCmd dealerCreateCmd);
|
||||
|
||||
@Mapping(target = "sort", ignore = true)
|
||||
@Mapping(target = "dealerPaymentAccountDOList", ignore = true)
|
||||
@Mapping(target = "version", ignore = true)
|
||||
@Mapping(target = "updatedAt", ignore = true)
|
||||
@ -32,4 +35,3 @@ public interface DealerConvert {
|
||||
@Mapping(target = "createdAt", ignore = true)
|
||||
void toDealerDO(@MappingTarget DealerDO dealerDO, DealerUpdateCmd dealerUpdateCmd);
|
||||
}
|
||||
|
||||
|
||||
@ -104,10 +104,15 @@ public class DealerDO extends BaseDO<DealerDO> {
|
||||
@TableField(value = "delivery_template")
|
||||
private String deliveryTemplate;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
@TableField(value = "sort")
|
||||
private BigDecimal sort;
|
||||
|
||||
/**
|
||||
* 付款账户列表
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<DealerPaymentAccountDO> dealerPaymentAccountDOList;
|
||||
}
|
||||
|
||||
|
||||
@ -3,11 +3,13 @@ package com.xunhong.erp.turbo.biz.infrastructure.gateway;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerCreateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDestroyCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerUpdateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerListQry;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPageQry;
|
||||
@ -21,10 +23,12 @@ import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerMapper;
|
||||
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerPaymentAccountMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -55,6 +59,7 @@ public class DealerGatewayImpl implements DealerGateway {
|
||||
queryWrapper.eq(Objects.nonNull(dealerPageQry.getDealerType()), DealerDO::getDealerType, dealerPageQry.getDealerType());
|
||||
queryWrapper.eq(Objects.nonNull(dealerPageQry.getStatus()), DealerDO::getStatus, dealerPageQry.getStatus());
|
||||
|
||||
queryWrapper.orderByAsc(DealerDO::getSort);
|
||||
queryWrapper.orderByDesc(DealerDO::getCreatedAt);
|
||||
|
||||
IPage<DealerDO> page = new Page<>(dealerPageQry.getPageIndex(), dealerPageQry.getPageSize());
|
||||
@ -82,6 +87,7 @@ public class DealerGatewayImpl implements DealerGateway {
|
||||
queryWrapper.eq(Objects.nonNull(dealerListQry.getStatus()), DealerDO::getStatus, dealerListQry.getStatus());
|
||||
queryWrapper.eq(Objects.nonNull(dealerListQry.getDealerType()), DealerDO::getDealerType, dealerListQry.getDealerType());
|
||||
|
||||
queryWrapper.orderByAsc(DealerDO::getSort);
|
||||
queryWrapper.orderByDesc(DealerDO::getCreatedAt);
|
||||
List<DealerDO> dealerDOList = dealerMapper.selectList(queryWrapper);
|
||||
return dealerDOList.stream().map(dealerConvert::toDealer).toList();
|
||||
@ -120,5 +126,50 @@ public class DealerGatewayImpl implements DealerGateway {
|
||||
DealerDO dealerDO = dealerMapper.selectOne(queryWrapper);
|
||||
dealerDO.deleteById();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void drag(DealerDragCmd dealerDragCmd) {
|
||||
reorderTask(dealerDragCmd.getCurrentId(), dealerDragCmd.getPrevId(), dealerDragCmd.getNextId());
|
||||
}
|
||||
|
||||
// 拖拽排序核心方法
|
||||
public void reorderTask(Long currentId, Long prevId, Long nextId) {
|
||||
// 获取相邻元素的sort值
|
||||
Double prevSort = Optional.ofNullable(prevId)
|
||||
.map(id -> dealerMapper.selectById(id).getSort().doubleValue())
|
||||
.orElse(null);
|
||||
Double nextSort = Optional.ofNullable(nextId)
|
||||
.map(id -> dealerMapper.selectById(id).getSort().doubleValue())
|
||||
.orElse(null);
|
||||
// 计算新sort值
|
||||
Double newSort = calculateNewSort(prevSort, nextSort);
|
||||
// 检查是否需要重整排序
|
||||
if (needResetSort(prevSort, nextSort)) {
|
||||
dealerMapper.batchResetSort(dealerMapper.selectById(currentId).getDealerId());
|
||||
} else {
|
||||
// 更新当前任务sort值
|
||||
dealerMapper.update(null, new LambdaUpdateWrapper<DealerDO>()
|
||||
.eq(DealerDO::getDealerId, currentId)
|
||||
.set(DealerDO::getSort, newSort)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Double calculateNewSort(Double prevSort, Double nextSort) {
|
||||
if (prevSort == null && nextSort != null) {
|
||||
return nextSort - 1000; // 插入到开头
|
||||
} else if (nextSort == null && prevSort != null) {
|
||||
return prevSort + 1000; // 插入到末尾
|
||||
} else if (prevSort == null && nextSort == null) {
|
||||
return 0.0;
|
||||
} else {
|
||||
return (prevSort + nextSort) / 2; // 插入中间
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needResetSort(Double prevSort, Double nextSort) {
|
||||
return prevSort != null && nextSort != null
|
||||
&& (nextSort - prevSort) < 1.0; // 判断间隙是否耗尽
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,19 @@ package com.xunhong.erp.turbo.biz.infrastructure.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.xunhong.erp.turbo.biz.infrastructure.entity.DealerDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
/**
|
||||
* @author shenyifei
|
||||
*/
|
||||
@Mapper
|
||||
public interface DealerMapper extends BaseMapper<DealerDO> {
|
||||
// 批量更新排序值(用于间隙重整)
|
||||
@Update("UPDATE dealer t " +
|
||||
"JOIN (SELECT dealer_id, (ROW_NUMBER() OVER (ORDER BY sort) - 1) * 1000 AS new_sort " +
|
||||
"FROM dealer WHERE dealer_id = #{dealerId}) AS sorted_rows " +
|
||||
"ON t.dealer_id = sorted_rows.dealer_id " +
|
||||
"SET t.sort = sorted_rows.new_sort WHERE t.dealer_id = #{dealerId}")
|
||||
void batchResetSort(@Param("dealerId") Long dealerId);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package com.xunhong.erp.turbo.api.biz.api;
|
||||
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerCreateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDestroyCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerDragCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerUpdateCmd;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerListQry;
|
||||
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPageQry;
|
||||
@ -26,5 +27,7 @@ public interface DealerServiceI {
|
||||
DealerVO show(DealerShowQry dealerShowQry);
|
||||
|
||||
void destroy(DealerDestroyCmd dealerDestroyCmd);
|
||||
|
||||
void drag(DealerDragCmd dealerDragCmd);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
package com.xunhong.erp.turbo.api.biz.dto.cmd;
|
||||
|
||||
import com.xunhong.erp.turbo.base.dto.Command;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @author shenyifei
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "经销商拖拽")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DealerDragCmd extends Command {
|
||||
|
||||
/**
|
||||
* 相邻元素
|
||||
*/
|
||||
@Schema(title = "相邻元素前")
|
||||
private Long prevId;
|
||||
|
||||
/**
|
||||
* 相邻元素
|
||||
*/
|
||||
@Schema(title = "相邻元素后")
|
||||
private Long nextId;
|
||||
|
||||
/**
|
||||
* 当前元素
|
||||
*/
|
||||
@Schema(title = "当前元素")
|
||||
private Long currentId;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user