|
|
@@ -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;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|