瀏覽代碼

feat(second): 新增风控商品管理功能- 新增风控商品信息查询接口,支持通过记录ID和商品ID批量查询
- 新增批量下架商品接口,支持根据风控记录批量处理商品
- 新增风控商品相关DTO类,包括查询参数和批量操作参数
- 实现风控商品服务接口,提供商品信息批量查询功能
- 扩展商品Mapper,增加selectGoodsList方法支持复杂查询
-优化批量下架逻辑,支持不同风控规则类型的处理- 在商品VO中新增imageUrls字段,用于存储商品图片列表

wxd 1 月之前
父節點
當前提交
d1d62bb33c

+ 20 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/BatchUnshelveGoodsDTO.java

@@ -0,0 +1,20 @@
+package shop.alien.entity.second.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * 批量下架商品DTO
+ */
+@Data
+@ApiModel(value = "BatchUnshelveGoodsDTO", description = "批量下架商品参数")
+public class BatchUnshelveGoodsDTO {
+
+    @ApiModelProperty(value = "风控规则类型")
+    private Integer ruleType;
+
+    @ApiModelProperty(value = "业务ID")
+    private String businessId;
+}

+ 18 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/RiskControlGoodsIdsDTO.java

@@ -0,0 +1,18 @@
+package shop.alien.entity.second.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 风控商品ID查询DTO
+ */
+@Data
+@ApiModel(value = "RiskControlGoodsIdsDTO", description = "风控商品ID查询参数")
+public class RiskControlGoodsIdsDTO {
+
+    @ApiModelProperty(value = "商品记录表ID列表")
+    private List<Integer> recordIds;
+}

+ 18 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/RiskControlGoodsQueryDTO.java

@@ -0,0 +1,18 @@
+package shop.alien.entity.second.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 风控商品查询DTO
+ */
+@Data
+@ApiModel(value = "RiskControlGoodsQueryDTO", description = "风控商品查询参数")
+public class RiskControlGoodsQueryDTO {
+
+    @ApiModelProperty(value = "商品表ID列表")
+    private List<Integer> goodsIds;
+}

+ 2 - 0
alien-entity/src/main/java/shop/alien/entity/second/vo/SecondGoodsVo.java

@@ -68,6 +68,8 @@ public class SecondGoodsVo extends SecondGoods {
     @TableField(exist = false)
     private String categoryTwoName;
 
+    @ApiModelProperty(value = "商品图片列表")
+    private List<String> imageUrls;
     /** -------------------- 搜索入参 -------------------- */
 
     @TableField(exist = false)

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/second/SecondGoodsMapper.java

@@ -74,6 +74,23 @@ public interface SecondGoodsMapper extends BaseMapper<SecondGoods> {
     List<SecondGoods> getCollectTop10();
 
     /**
+     * 商品列表
+     * @return 结果列表
+     */
+    @Select("SELECT " +
+            "sg.*, " +
+            "sgc1.category_name as categoryOneName, " +
+            "sgc2.category_name as categoryTwoName "+
+            " FROM second_goods sg " +
+            "left JOIN second_goods_category sgc1 " +
+            "on sg.category_one_id = sgc1.id " +
+            "left JOIN second_goods_category sgc2 " +
+            "on sg.category_two_id = sgc2.id "+
+            "${ew.customSqlSegment}")
+    List<SecondGoodsVo> selectGoodsList(@Param(Constants.WRAPPER) QueryWrapper<SecondGoodsVo> queryWrapper);
+
+
+    /**
      * 搜索结果-商品列表
      * @param page 分页参数
      * @return 搜索结果列表

+ 69 - 0
alien-second/src/main/java/shop/alien/second/controller/RiskControlGoodsController.java

@@ -0,0 +1,69 @@
+package shop.alien.second.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiSort;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.second.vo.*;
+import shop.alien.second.service.RiskControlGoodsService;
+import shop.alien.second.service.SecondGoodsService;
+
+import java.util.List;
+
+/**
+ * 风控商品信息控制器
+ */
+@Slf4j
+@Api(tags = {"二手平台-风控商品信息管理(管理后台)"})
+@ApiSort(2)
+@CrossOrigin
+@RestController
+@RequestMapping("/admin/riskControl")
+@RequiredArgsConstructor
+public class RiskControlGoodsController {
+
+    private final RiskControlGoodsService riskControlGoodsService;
+
+    /**
+     * 二手商品服务
+     */
+    private final SecondGoodsService secondGoodsService;
+    /**
+     * 通过商品记录表ID批量查询商品信息(包含图片)
+     *
+     * @param dto 商品记录表ID列表DTO
+     * @return 商品信息列表
+     */
+    @PostMapping("/goods/recordIds")
+    @ApiOperation("通过商品记录表ID批量查询商品信息")
+    public List<SecondGoodsRecordDetailVo> getGoodsInfoByRecordIds(@RequestBody RiskControlGoodsIdsDTO dto) {
+        return riskControlGoodsService.getGoodsInfoByRecordIds(dto.getRecordIds());
+    }
+
+    /**
+     * 通过商品表ID批量查询商品信息(包含图片)
+     *
+     * @param dto 商品表ID列表DTO
+     * @return 商品信息列表
+     */
+    @PostMapping("/goods/goodsIds")
+    @ApiOperation("通过商品表ID批量查询商品信息")
+    public List<SecondGoodsVo> getGoodsInfoByGoodsIds(@RequestBody RiskControlGoodsQueryDTO dto) {
+        return riskControlGoodsService.getGoodsInfoByGoodsIds(dto.getGoodsIds());
+    }
+
+
+    @PostMapping("/batch/unshelve")
+    @ApiOperation("根据风控记录批量下架商品")
+    public R<Boolean> batchUnshelveGoodsByRiskControl(@ApiParam("批量下架参数") @RequestBody BatchUnshelveGoodsDTO dto) {
+        log.info("AdminSecondGoodsController.batchUnshelveGoodsByRiskControl?dto={}", dto);
+
+        boolean result = secondGoodsService.batchShelveGoodsByRiskControlRecord(dto.getRuleType(), dto.getBusinessId());
+
+        return R.data(result, result ? "批量下架成功" : "批量下架失败");
+    }
+}

+ 26 - 0
alien-second/src/main/java/shop/alien/second/service/RiskControlGoodsService.java

@@ -0,0 +1,26 @@
+package shop.alien.second.service;
+
+import shop.alien.entity.second.vo.SecondGoodsRecordDetailVo;
+import shop.alien.entity.second.vo.SecondGoodsVo;
+
+import java.util.List;
+
+/**
+ * 风控商品服务接口
+ */
+public interface RiskControlGoodsService {
+
+    /**
+     * 通过商品记录表ID批量查询商品信息(包含图片)
+     * @param recordIds 商品记录表ID列表
+     * @return 商品信息列表
+     */
+    List<SecondGoodsRecordDetailVo> getGoodsInfoByRecordIds(List<Integer> recordIds);
+
+    /**
+     * 通过商品表ID批量查询商品信息(包含图片)
+     * @param goodsIds 商品表ID列表
+     * @return 商品信息列表
+     */
+    List<SecondGoodsVo> getGoodsInfoByGoodsIds(List<Integer> goodsIds);
+}

+ 317 - 0
alien-second/src/main/java/shop/alien/second/service/impl/RiskControlGoodsServiceImpl.java

@@ -0,0 +1,317 @@
+package shop.alien.second.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.second.SecondGoodsRecord;
+import shop.alien.entity.second.vo.SecondGoodsRecordDetailVo;
+import shop.alien.entity.second.vo.SecondGoodsVo;
+import shop.alien.entity.store.LifeUser;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.mapper.LifeUserMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.second.SecondGoodsMapper;
+import shop.alien.mapper.second.SecondGoodsRecordMapper;
+import shop.alien.second.service.RiskControlGoodsService;
+import shop.alien.util.common.Constants;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 风控商品服务实现类
+ * 提供风控相关的商品信息查询服务,包括通过记录ID和商品ID批量查询商品详细信息
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class RiskControlGoodsServiceImpl implements RiskControlGoodsService {
+
+    /**
+     * 注入商品记录Mapper
+      */
+    private final SecondGoodsRecordMapper secondGoodsRecordMapper;
+
+    /**
+     * 注入商品Mapper
+     */
+    private final SecondGoodsMapper secondGoodsMapper;
+
+    /**
+     * 注入图片Mapper
+      */
+    private final StoreImgMapper storeImgMapper;
+
+    /**
+     * 注入用户Mapper
+     */
+    private final LifeUserMapper lifeUserMapper;
+
+    /**
+     * 通过商品记录表ID批量查询商品信息(包含图片)
+     * @param recordIds 商品记录表ID列表
+     * @return 商品信息列表
+     */
+    @Override
+    public List<SecondGoodsRecordDetailVo> getGoodsInfoByRecordIds(List<Integer> recordIds) {
+        // 检查传入ID列表是否为空,如果为空则直接返回空列表
+        if (CollectionUtils.isEmpty(recordIds)) {
+            return new ArrayList<>();
+        }
+
+        // 构建查询条件,根据记录ID列表查询商品记录信息
+        QueryWrapper<SecondGoodsRecord> queryWrapper = new QueryWrapper<>();
+        queryWrapper.in("sg.id", recordIds);
+        // 执行查询获取商品记录列表
+        List<SecondGoodsRecord> records = secondGoodsRecordMapper.selectdminGoodsList(queryWrapper);
+        
+        // 检查查询结果是否为空,如果为空则直接返回空列表
+        if (CollectionUtils.isEmpty(records)) {
+            return new ArrayList<>();
+        }
+
+        // 批量获取用户和图片信息
+        BatchQueryResult<SecondGoodsRecord> batchResult = batchQueryUserInfoAndImageInfo(records, 
+            SecondGoodsRecord::getUserId, SecondGoodsRecord::getId);
+
+        // 创建结果列表,用于存储最终的商品记录详情VO对象
+        List<SecondGoodsRecordDetailVo> result = new ArrayList<>();
+        // 遍历所有商品记录,构建对应的VO对象
+        for (SecondGoodsRecord record : records) {
+            // 根据商品记录创建VO对象
+            SecondGoodsRecordDetailVo detailVo = SecondGoodsRecordDetailVo.fromRecord(record);
+
+            // 如果记录中有用户ID且在用户映射表中存在该用户,则设置用户信息
+            if (record.getUserId() != null && batchResult.userMap.containsKey(record.getUserId())) {
+                // 从用户映射表中获取用户信息
+                LifeUser user = batchResult.userMap.get(record.getUserId());
+                // 设置用户名和用户手机号
+                detailVo.setUserName(user.getUserName());
+                detailVo.setUserPhone(user.getUserPhone());
+            }
+
+            // 如果图片映射表中包含该记录的ID,则设置图片信息
+            if (batchResult.imageMap.containsKey(record.getId())) {
+                // 从图片映射表中获取该记录的图片列表
+                List<StoreImg> recordImages = batchResult.imageMap.get(record.getId());
+                // 提取图片URL列表
+                List<String> imageUrls = recordImages.stream()
+                        .map(StoreImg::getImgUrl)
+                        .collect(Collectors.toList());
+                // 处理图片列表(区分图片和视频)
+                List<Map<String, Object>> imgList = processReportImages(recordImages, 2);
+                // 设置图片列表和图片URL列表
+                detailVo.setImgList(imgList);
+                detailVo.setImageUrls(imageUrls);
+            }
+
+            // 将构建好的VO对象添加到结果列表中
+            result.add(detailVo);
+        }
+
+        // 返回最终的结果列表
+        return result;
+    }
+
+    /**
+     * 通过商品表ID批量查询商品信息(包含图片)
+     * @param goodsIds 商品表ID列表
+     * @return 商品信息列表
+     */
+    @Override
+    public List<SecondGoodsVo> getGoodsInfoByGoodsIds(List<Integer> goodsIds) {
+        // 检查传入ID列表是否为空,如果为空则直接返回空列表
+        if (CollectionUtils.isEmpty(goodsIds)) {
+            return new ArrayList<>();
+        }
+
+        // 构建查询条件,根据商品ID列表查询商品信息
+        QueryWrapper<SecondGoodsVo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.in("sg.id", goodsIds);
+        // 执行查询获取商品列表
+        List<SecondGoodsVo> secondGoodsList = secondGoodsMapper.selectGoodsList(queryWrapper);
+
+        // 检查查询结果是否为空,如果为空则直接返回空列表
+        if (CollectionUtils.isEmpty(secondGoodsList)) {
+            return new ArrayList<>();
+        }
+
+        // 批量获取用户和图片信息
+        BatchQueryResult<SecondGoodsVo> batchResult = batchQueryUserInfoAndImageInfo(secondGoodsList,
+            SecondGoods::getUserId, SecondGoods::getId);
+
+        // 创建结果列表,用于存储最终的商品VO对象
+        List<SecondGoodsVo> result = new ArrayList<>();
+        // 遍历所有商品,构建对应的VO对象
+        for (SecondGoods secondGoods : secondGoodsList) {
+            // 创建新的商品VO对象
+            SecondGoodsVo secondGoodsVo = new SecondGoodsVo();
+            // 将商品属性复制到VO对象中
+            BeanUtils.copyProperties(secondGoods, secondGoodsVo);
+
+            // 如果VO对象中有用户ID且在用户映射表中存在该用户,则设置用户信息
+            if (secondGoodsVo.getUserId() != null && batchResult.userMap.containsKey(secondGoodsVo.getUserId())) {
+                // 从用户映射表中获取用户信息
+                LifeUser user = batchResult.userMap.get(secondGoodsVo.getUserId());
+                // 设置用户名和用户手机号
+                secondGoodsVo.setUserName(user.getUserName());
+                secondGoodsVo.setUserPhone(user.getUserPhone());
+            }
+
+            // 如果图片映射表中包含该商品的ID,则设置图片信息
+            if (batchResult.imageMap.containsKey(secondGoodsVo.getId())) {
+                // 从图片映射表中获取该商品的图片列表
+                List<StoreImg> recordImages = batchResult.imageMap.get(secondGoodsVo.getId());
+                // 提取图片URL列表
+                List<String> imageUrls = recordImages.stream()
+                        .map(StoreImg::getImgUrl)
+                        .collect(Collectors.toList());
+                // 处理图片列表(区分图片和视频)
+                List<Map<String, Object>> imgList = processReportImages(recordImages, 2);
+                // 设置图片列表和图片URL列表
+                secondGoodsVo.setImgList(imgList);
+                secondGoodsVo.setImageUrls(imageUrls);
+            }
+
+            // 将构建好的VO对象添加到结果列表中
+            result.add(secondGoodsVo);
+        }
+
+        // 返回最终的结果列表
+        return result;
+    }
+
+    /**
+     * 批量查询用户信息和图片信息的通用方法
+     * @param records 商品记录列表
+     * @param userIdGetter 获取用户ID的函数
+     * @param entityIdGetter 获取实体ID的函数(可能是记录ID或商品ID)
+     * @param <T> 记录类型
+     * @return 批量查询结果
+     */
+    private <T> BatchQueryResult<T> batchQueryUserInfoAndImageInfo(List<T> records, 
+            Function<T, Integer> userIdGetter, Function<T, Integer> entityIdGetter) {
+        
+        // 从商品记录中提取所有非空的用户ID并去重,用于后续批量查询用户信息
+        List<Integer> userIds = records.stream()
+                .map(userIdGetter)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+
+        // 创建用户映射表,用于存储用户ID到用户信息的映射关系
+        Map<Integer, LifeUser> userMap = new HashMap<>();
+        // 如果存在用户ID,则批量查询用户信息
+        if (!CollectionUtils.isEmpty(userIds)) {
+            // 构建用户查询条件,根据用户ID列表和未删除标识查询用户信息
+            QueryWrapper<LifeUser> userQueryWrapper = new QueryWrapper<>();
+            userQueryWrapper.lambda()
+                    .in(LifeUser::getId, userIds)
+                    .eq(LifeUser::getDeleteFlag, Constants.DeleteFlag.NOT_DELETED);
+            // 执行查询获取用户列表
+            List<LifeUser> users = lifeUserMapper.selectList(userQueryWrapper);
+            // 将用户列表转换为以用户ID为键的映射表,使用合并函数处理可能的重复键
+            userMap = users.stream().collect(Collectors.toMap(
+                LifeUser::getId,
+                user -> user,
+                (existing, replacement) -> existing // 处理键冲突,保留第一个值
+            ));
+        }
+
+        // 从商品记录中提取所有实体ID,用于后续查询图片信息
+        List<Integer> entityIdList = records.stream()
+                .map(entityIdGetter)
+                .collect(Collectors.toList());
+
+        // 构建图片查询条件,根据实体ID列表、图片类型和未删除标识查询图片信息
+        QueryWrapper<StoreImg> imageQueryWrapper = new QueryWrapper<>();
+        imageQueryWrapper.lambda()
+                .in(StoreImg::getStoreId, entityIdList)
+                .eq(StoreImg::getDeleteFlag, Constants.DeleteFlag.NOT_DELETED)
+                .orderByAsc(StoreImg::getImgSort);
+        
+        // 根据记录类型设置不同的图片类型
+        if (!records.isEmpty()) {
+            T firstRecord = records.get(0);
+            if (firstRecord instanceof SecondGoodsRecord) {
+                // 如果是商品记录类型,使用SECOND_HAND_RECORD类型
+                imageQueryWrapper.lambda()
+                        .eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_RECORD);
+            } else if (firstRecord instanceof SecondGoodsVo) {
+                // 如果是商品类型,使用SECOND_HAND类型
+                imageQueryWrapper.lambda()
+                        .eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_GOODS);
+            }
+        }
+        
+        // 执行查询获取图片列表
+        List<StoreImg> imageList = storeImgMapper.selectList(imageQueryWrapper);
+
+        // 将图片列表按照实体ID进行分组,方便后续关联到对应记录
+        Map<Integer, List<StoreImg>> imageMap = imageList.stream()
+                .collect(Collectors.groupingBy(StoreImg::getStoreId));
+        
+        // 返回批量查询结果
+        return new BatchQueryResult<>(userMap, imageMap);
+    }
+
+    /**
+     * 批量查询结果类
+     * @param <T> 记录类型
+     */
+    private static class BatchQueryResult<T> {
+        final Map<Integer, LifeUser> userMap;
+        final Map<Integer, List<StoreImg>> imageMap;
+
+        public BatchQueryResult(Map<Integer, LifeUser> userMap, Map<Integer, List<StoreImg>> imageMap) {
+            this.userMap = userMap;
+            this.imageMap = imageMap;
+        }
+    }
+
+    /**
+     * 处理图片列表,区分图片和视频类型
+     * @param imageList 图片URL集合
+     * @param type  类型 1-举报 2-商品
+     * @return 图片列表,每个元素包含类型和URL信息
+     */
+    private List<Map<String, Object>> processReportImages(List<StoreImg> imageList, Integer type) {
+        // 创建结果列表
+        List<Map<String, Object>> list = new ArrayList<>();
+        // 定义视频文件类型扩展名列表
+        List<String> videoFileType = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");
+
+        // 遍历所有图片对象
+        for (StoreImg img : imageList) {
+            // 创建映射对象存储图片信息
+            Map<String, Object> map = new HashMap<>();
+            // 从图片URL中提取文件扩展名
+            String fileType = img.getImgUrl().substring(img.getImgUrl().lastIndexOf(".") + 1);
+            // 判断文件类型是否为视频
+            if (videoFileType.contains(fileType.toLowerCase())) {
+                // 如果是视频,设置类型为video
+                map.put("type", "video");
+            } else {
+                // 如果不是视频,设置类型为image
+                map.put("type", "image");
+            }
+            // 设置图片URL
+            map.put("imgUrl", img.getImgUrl());
+            // 如果类型为1(举报类型),则设置视频URL
+            if (type == 1) {
+                map.put("videoUrl", img.getImgUrl());
+            }
+            // 将映射对象添加到结果列表中
+            list.add(map);
+        }
+
+        // 返回处理后的图片列表
+        return list;
+    }
+
+}

+ 21 - 7
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -1902,7 +1902,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     }
 
     /**
-     * 根据风控记录中的JSON数据批量下架商品( ruleType = 4 异常发布场景)
+     * 根据风控记录中的JSON数据批量下架商品
      * @param ruleType 风控规则类型
      * @param businessId 业务ID
      * @return 是否下架成功
@@ -1910,6 +1910,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
     @Override
     public boolean batchShelveGoodsByRiskControlRecord(Integer ruleType, String businessId) {
         try {
+            List<Integer> goodsIdList = Lists.newArrayList();
             // 获取相同类型的风控数据
             List<SecondRiskControlRecord> riskControlRecordList = riskControlService.getSameTypeRiskControlRecords(ruleType, businessId);
             // 获取风控数据详情
@@ -1918,18 +1919,31 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
                     .collect(Collectors.toList());
 
             // 声明所有被风控的商品ID
-            List<Integer> goodsIdList = Lists.newArrayList();
+            List<Integer> idList = Lists.newArrayList();
 
             // 循环情信息json 转换为集合
             for (String detailInfo : detailInfoList){
                 // 解析JSON获取商品ID列表
-                List<Integer> goodsIds = JSON.parseArray(detailInfo, Integer.class);
-                goodsIdList.addAll(goodsIds);
+                List<Integer> ids = JSON.parseArray(detailInfo, Integer.class);
+                idList.addAll(ids);
             }
-
             // goodsIdList 去重
-            goodsIdList = goodsIdList.stream().distinct().collect(Collectors.toList());
-
+            idList = idList.stream().distinct().collect(Collectors.toList());
+            // 交易欺诈
+            if (ruleType.equals(RiskControlRuleTypeEnum.TRANSACTION_FRAUD.getRuleType())){
+                // 根据商品记录id集合查询商品Id 集合
+                QueryWrapper<SecondGoodsRecord> queryWrapper = new QueryWrapper<>();
+                queryWrapper.in("id", idList);
+                List<SecondGoodsRecord> goodsRecordList = secondGoodsRecordMapper.selectList(queryWrapper);
+                // 获取商品Id集合
+                List<Integer> goodsIds = goodsRecordList.stream().map(SecondGoodsRecord::getGoodsId).collect(Collectors.toList());
+                // 去重
+                goodsIds = goodsIds.stream().distinct().collect(Collectors.toList());
+                goodsIdList.addAll(goodsIds);
+                // 异常发布
+            } else if (RiskControlRuleTypeEnum.ABNORMAL_PUBLISH.getRuleType().equals(ruleType)) {
+                goodsIdList.addAll(idList);
+            }
             // 调用批量下架方法
             return batchShelveGoodsByIds(goodsIdList);
         } catch (Exception e) {