peng
2 天以前 fa27fd4a21e04352a97988c153b7709ebecc4e89
framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java
@@ -15,10 +15,7 @@
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.modules.goods.entity.dos.*;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.dto.GoodsParamsDTO;
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsSortDTO;
import cn.lili.modules.goods.entity.dto.*;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.entity.vos.GoodsSkuVO;
@@ -50,6 +47,10 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,6 +58,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
@@ -314,9 +318,91 @@
        return this.page(PageUtil.initPage(goodsSearchParams), goodsSearchParams.queryWrapper());
    }
    @Override
    public void queryExportGoods(HttpServletResponse response, GoodsSearchParams searchParams) {
        List<Goods> list = this.list(searchParams.queryWrapper());
        XSSFWorkbook workbook = initGoodsExportData(list);
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("商品清单", "UTF-8");
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            ServletOutputStream out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                workbook.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private XSSFWorkbook initGoodsExportData(List<Goods> list) {
        List<GoodsExportDTO> goodsExportDTOs = new ArrayList<>();
        for (Goods goods : list) {
            GoodsExportDTO goodsExportDTO = new GoodsExportDTO();
            BeanUtils.copyProperties(goods, goodsExportDTO);
            goodsExportDTOs.add(goodsExportDTO);
        }
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("商品清单");
        Row header = sheet.createRow(0);
        String[] headers = {"商品名称", "商品编号", "价格", "销售模式", "商品类型", "状态", "审核状态", "店铺名称"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = header.createCell(i);
            cell.setCellValue(headers[i]);
        }
        for (int i = 0; i < goodsExportDTOs.size(); i++) {
            GoodsExportDTO goodsExportDTO = goodsExportDTOs.get(i);
            Row row = sheet.createRow(i + 1);
            row.createCell(0).setCellValue(goodsExportDTO.getGoodsName());
            row.createCell(1).setCellValue(goodsExportDTO.getId());
            row.createCell(2).setCellValue(goodsExportDTO.getPrice());
            if ("RETAIL".equals(goodsExportDTO.getSalesModel())) {
                row.createCell(3).setCellValue("零售");
            } else if ("WHOLESALE".equals(goodsExportDTO.getSalesModel())) {
                row.createCell(3).setCellValue("批发");
            } else if ("PRESALE".equals(goodsExportDTO.getSalesModel())) {
                row.createCell(3).setCellValue("预售");
            } else {
                row.createCell(3).setCellValue("其他类型");
            }
            if ("PHYSICAL_GOODS".equals(goodsExportDTO.getGoodsType())) {
                row.createCell(4).setCellValue("实物商品");
            } else if ("VIRTUAL_GOODS".equals(goodsExportDTO.getGoodsType())) {
                row.createCell(4).setCellValue("虚拟商品");
            } else {
                row.createCell(4).setCellValue("电子卡券");
            }
            if ("DOWN".equals(goodsExportDTO.getMarketEnable())) {
                row.createCell(5).setCellValue("下架");
            } else if ("UPPER".equals(goodsExportDTO.getMarketEnable())) {
                row.createCell(5).setCellValue("上架");
            }
            if ("TOBEAUDITED".equals(goodsExportDTO.getAuthFlag())) {
                row.createCell(6).setCellValue("待审核");
            } else if ("PASS".equals(goodsExportDTO.getAuthFlag())) {
                row.createCell(6).setCellValue("通过");
            } else if ("REFUSE".equals(goodsExportDTO.getAuthFlag())) {
                row.createCell(6).setCellValue("拒绝");
            }
            row.createCell(7).setCellValue(goodsExportDTO.getStoreName());
        }
        return workbook;
    }
    /**
     * 商品查询
     *
     *g
     * @param goodsSearchParams 查询参数
     * @return 商品信息
     */
@@ -431,28 +517,251 @@
        boolean result;
        //检测管理员权限
        this.checkManagerAuthority();
        LambdaUpdateWrapper<Goods> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Goods::getGoodsSort,req.getSort());
        updateWrapper.eq(Goods::getId, req.getGoodsId());
        //查询出比当前排序大的商品
        LambdaQueryWrapper<Goods> query = Wrappers.<Goods>lambdaQuery();
        query.gt(Goods::getGoodsSort,req.getSort());
        List<Goods> goods = goodsService.list(query);
        List<String> goodsIds = new ArrayList<>();
        if (goods != null && !goods.isEmpty()) {
         //适配没有排序的商品排序字段为null
            goods.forEach(item -> {
                if (item.getGoodsSort() != null) {
                    item.setGoodsSort(item.getGoodsSort() + 1);
                    goodsIds.add(item.getId());
                }
            });
            goodsService.updateBatchById(goods);
        // 获取当前商品的原始排序值
        Goods currentGoods = this.getById(req.getGoodsId());
        Integer oldSort = currentGoods != null ? currentGoods.getGoodsSort() : null;
        Integer newSort = req.getSort();
        // 收集需要更新ES的商品ID
        List<String> goodsIdsToUpdateEs = new ArrayList<>();
        goodsIdsToUpdateEs.add(req.getGoodsId());
        // 处理数据库中的重复排序值,确保唯一性
        List<String> duplicateResolvedGoodsIds = resolveDuplicateSorts();
        goodsIdsToUpdateEs.addAll(duplicateResolvedGoodsIds);
        // 重新获取当前商品的排序值(可能已被resolveDuplicateSorts修改)
        currentGoods = this.getById(req.getGoodsId());
        oldSort = currentGoods != null ? currentGoods.getGoodsSort() : null;
        // 根据操作类型执行不同的排序逻辑
        if (oldSort == null) {
            // 新增排序
            List<String> affectedGoodsIds = adjustForInsert(newSort);
            goodsIdsToUpdateEs.addAll(affectedGoodsIds);
            // 处理可能产生的重复排序值
            List<String> afterInsertResolvedGoodsIds = resolveDuplicateSorts();
            goodsIdsToUpdateEs.addAll(afterInsertResolvedGoodsIds);
        } else if (!oldSort.equals(newSort)) {
            // 修改排序
            if (newSort > oldSort) {
                // 排序值增大:将大于等于新排序值的商品+1,直到遇到断层
                List<String> affectedGoodsIds = adjustForIncrease(newSort);
                goodsIdsToUpdateEs.addAll(affectedGoodsIds);
                // 处理可能产生的重复排序值
                List<String> afterIncreaseResolvedGoodsIds = resolveDuplicateSorts();
                goodsIdsToUpdateEs.addAll(afterIncreaseResolvedGoodsIds);
            } else {
                // 排序值减小:将大于等于新排序值且小于原排序值的商品+1,直到遇到断层
                List<String> affectedGoodsIds = adjustForDecrease(oldSort, newSort);
                goodsIdsToUpdateEs.addAll(affectedGoodsIds);
                // 处理可能产生的重复排序值
                List<String> afterDecreaseResolvedGoodsIds = resolveDuplicateSorts();
                goodsIdsToUpdateEs.addAll(afterDecreaseResolvedGoodsIds);
            }
        }
        // 更新当前商品的排序值
        LambdaUpdateWrapper<Goods> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Goods::getGoodsSort, newSort);
        updateWrapper.eq(Goods::getId, req.getGoodsId());
        result = this.update(updateWrapper);
        goodsIds.add(req.getGoodsId());
        this.updateEsGoods(goodsIds);
        // 更新ES索引
        this.updateEsGoods(goodsIdsToUpdateEs);
        return result;
    }
    /**
     * 处理数据库中的重复排序值,确保唯一性
     * @return 受影响的商品ID列表
     */
    @Transactional(rollbackFor = Exception.class)
    public List<String> resolveDuplicateSorts() {
        // 查询所有有排序值的商品
        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.isNotNull(Goods::getGoodsSort);
        queryWrapper.orderByAsc(Goods::getGoodsSort);
        List<Goods> allGoods = this.list(queryWrapper);
        // 按排序值分组
        Map<Integer, List<Goods>> sortMap = allGoods.stream()
                .collect(Collectors.groupingBy(Goods::getGoodsSort));
        // 处理重复的排序值,只保留第一个,其余重新分配
        List<Goods> toUpdate = new ArrayList<>();
        int nextSort = getMaxSortValue(allGoods) + 1; // 从当前最大值+1开始分配
        for (Map.Entry<Integer, List<Goods>> entry : sortMap.entrySet()) {
            List<Goods> goodsList = entry.getValue();
            if (goodsList.size() > 1) {
                // 有重复值,只保留第一个,其余重新分配
                for (int i = 1; i < goodsList.size(); i++) {
                    Goods goods = goodsList.get(i);
                    goods.setGoodsSort(nextSort++);
                    toUpdate.add(goods);
                }
            }
        }
        // 收集受影响的商品ID
        List<String> affectedGoodsIds = toUpdate.stream()
                .map(Goods::getId)
                .collect(Collectors.toList());
        // 批量更新
        if (!toUpdate.isEmpty()) {
            this.updateBatchById(toUpdate);
        }
        return affectedGoodsIds;
    }
    /**
     * 获取当前最大的排序值
     * @param goodsList 商品列表
     * @return 最大排序值
     */
    private int getMaxSortValue(List<Goods> goodsList) {
        return goodsList.stream()
                .mapToInt(Goods::getGoodsSort)
                .max()
                .orElse(0);
    }
    /**
     * 插入新排序值的处理逻辑
     * 将所有大于等于新排序值的商品排序值+1,直到遇到断层
     * @param newSort 新的排序值
     * @return 受影响的商品ID列表
     */
    @Transactional(rollbackFor = Exception.class)
    public List<String> adjustForInsert(Integer newSort) {
        if (newSort == null) return Collections.emptyList();
        // 查询所有大于等于新排序值的商品,按排序值升序排列
        LambdaQueryWrapper<Goods> query = Wrappers.<Goods>lambdaQuery();
        query.ge(Goods::getGoodsSort, newSort);
        query.isNotNull(Goods::getGoodsSort);
        query.orderByAsc(Goods::getGoodsSort);
        List<Goods> goodsList = this.list(query);
        // 检查连续性,遇到断层则停止
        List<Goods> toUpdate = new ArrayList<>();
        int expectedSort = newSort;
        for (Goods goods : goodsList) {
            if (goods.getGoodsSort().equals(expectedSort)) {
                goods.setGoodsSort(goods.getGoodsSort() + 1);
                toUpdate.add(goods);
                expectedSort++;
            } else {
                // 遇到断层,停止调整
                break;
            }
        }
        // 收集受影响的商品ID
        List<String> affectedGoodsIds = toUpdate.stream()
                .map(Goods::getId)
                .collect(Collectors.toList());
        // 批量更新
        if (!toUpdate.isEmpty()) {
            this.updateBatchById(toUpdate);
        }
        return affectedGoodsIds;
    }
    /**
     * 排序值增大的处理逻辑
     * 将所有大于等于新排序值的商品排序值+1,直到遇到断层
     * @param newSort 新排序值
     * @return 受影响的商品ID列表
     */
    @Transactional(rollbackFor = Exception.class)
    public List<String> adjustForIncrease(Integer newSort) {
        if (newSort == null) return Collections.emptyList();
        // 查询所有大于等于新排序值的商品,按排序值升序排列
        LambdaQueryWrapper<Goods> query = Wrappers.<Goods>lambdaQuery();
        query.ge(Goods::getGoodsSort, newSort);
        query.isNotNull(Goods::getGoodsSort);
        query.orderByAsc(Goods::getGoodsSort);
        List<Goods> goodsList = this.list(query);
        // 检查连续性,遇到断层则停止
        List<Goods> toUpdate = new ArrayList<>();
        int expectedSort = newSort;
        for (Goods goods : goodsList) {
            if (goods.getGoodsSort().equals(expectedSort)) {
                goods.setGoodsSort(goods.getGoodsSort() + 1);
                toUpdate.add(goods);
                expectedSort++;
            } else {
                // 遇到断层,停止调整
                break;
            }
        }
        // 收集受影响的商品ID
        List<String> affectedGoodsIds = toUpdate.stream()
                .map(Goods::getId)
                .collect(Collectors.toList());
        // 批量更新
        if (!toUpdate.isEmpty()) {
            this.updateBatchById(toUpdate);
        }
        return affectedGoodsIds;
    }
    /**
     * 排序值减小的处理逻辑
     * 将大于等于新排序值且小于原排序值的商品排序值+1,直到遇到断层
     * @param oldSort 原排序值
     * @param newSort 新排序值
     * @return 受影响的商品ID列表
     */
    @Transactional(rollbackFor = Exception.class)
    public List<String> adjustForDecrease(Integer oldSort, Integer newSort) {
        if (oldSort == null || newSort == null || oldSort.equals(newSort)) return Collections.emptyList();
        // 查询大于等于新排序值且小于原排序值的商品,按排序值升序排列
        LambdaQueryWrapper<Goods> query = Wrappers.<Goods>lambdaQuery();
        query.ge(Goods::getGoodsSort, newSort);
        query.lt(Goods::getGoodsSort, oldSort);
        query.isNotNull(Goods::getGoodsSort);
        query.orderByAsc(Goods::getGoodsSort);
        List<Goods> goodsList = this.list(query);
        // 检查连续性,遇到断层则停止
        List<Goods> toUpdate = new ArrayList<>();
        int expectedSort = newSort;
        for (Goods goods : goodsList) {
            if (goods.getGoodsSort().equals(expectedSort)) {
                goods.setGoodsSort(goods.getGoodsSort() + 1);
                toUpdate.add(goods);
                expectedSort++;
            } else {
                // 遇到断层,停止调整
                break;
            }
        }
        // 收集受影响的商品ID
        List<String> affectedGoodsIds = toUpdate.stream()
                .map(Goods::getId)
                .collect(Collectors.toList());
        // 批量更新
        if (!toUpdate.isEmpty()) {
            this.updateBatchById(toUpdate);
        }
        return affectedGoodsIds;
    }
    @Override
@@ -604,6 +913,7 @@
        this.baseMapper.addGoodsCommentNum(commentNum, goodsId);
    }
    /**
     * 更新商品状态
     *