소스 검색

feat(collect): 新增收藏商品列表分页查询功能

- 添加 collectSecondGoodsByPage 接口支持分页查询收藏的商品
- 集成地理位置距离计算功能,显示商品距离信息
- 实现商品屏蔽列表过滤,避免展示用户屏蔽的商品
- 添加价格格式化处理,保留两位小数显示
- 集成 JWT 用户身份验证和权限校验
- 优化 SQL 查询性能,使用内连接获取收藏商品数据
- 添加异常处理和日志记录机制
fcw 2 일 전
부모
커밋
cf2f2d35c5

+ 46 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeCollectMapper.java

@@ -1,12 +1,58 @@
 package shop.alien.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import shop.alien.entity.second.vo.SecondGoodsRecommendVo;
 import shop.alien.entity.store.LifeCollect;
 
+import java.util.List;
+
 /**
  * 收藏
  */
 @Mapper
 public interface LifeCollectMapper extends BaseMapper<LifeCollect> {
+
+    /**
+     * 获取收藏的二级商品
+     * @param page
+     * @param userId
+     * @param s
+     * @param s1
+     * @return
+     */
+    @Select("<script>" +
+            "SELECT " +
+            "  sg.id, " +
+            "  sg.user_id, " +
+            "  sg.title, " +
+            "  sg.price, " +
+            "  sg.price AS amount, " +
+            "  sg.home_image, " +
+            "  sg.video_first_frame, " +
+            "  sg.collect_count, " +
+            "  lc.created_time, " +
+            // 距离计算字段(你原有的逻辑)
+            "  ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(sg.position, ',', ' '), ')' ))) / 1000, 2) AS dist " +
+            "FROM second_goods sg " +
+            // 内连接:只查询【当前用户】收藏的商品
+            "INNER JOIN life_collect lc " +
+            "  ON lc.business_id = sg.id " +
+            "  AND lc.business_type = 1 " +
+            "  AND lc.delete_flag = 0 " +
+            "  AND lc.user_id = #{s} " +
+            "WHERE sg.delete_flag = 0 " +
+            // 动态排除屏蔽商品(空集合不拼接,避免SQL报错)
+            "<if test=\"shieldedGoodsIds != null and !shieldedGoodsIds.isEmpty()\">" +
+            "  AND sg.id NOT IN " +
+            "  <foreach collection='shieldedGoodsIds' item='id' open='(' separator=',' close=')'>" +
+            "    #{id}" +
+            "  </foreach>" +
+            "</if>" +
+            // 按收藏时间倒序排序
+            "ORDER BY lc.created_time DESC" +
+            "</script>")
+    IPage<SecondGoodsRecommendVo> collectSecondGoodsByPage(IPage<SecondGoodsRecommendVo> page, Integer userId, String s, String position, List<Integer> shieldedGoodsIds);
 }

+ 98 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeCollectController.java

@@ -1,26 +1,38 @@
 package shop.alien.store.controller;
 
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoods;
+import shop.alien.entity.second.vo.SecondCommentVo;
+import shop.alien.entity.second.vo.SecondGoodsRecommendVo;
+import shop.alien.entity.second.vo.SecondGoodsVo;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.vo.StoreInfoVo;
 import shop.alien.mapper.*;
 import shop.alien.mapper.second.SecondGoodsMapper;
+import shop.alien.mapper.second.SecondRecommendMapper;
 import shop.alien.store.annotation.TrackEvent;
 import shop.alien.store.config.GaoDeMapUtil;
+import shop.alien.store.service.LifeDiscountCouponService;
+import shop.alien.util.common.Constants;
+import shop.alien.util.common.JwtUtil;
 import shop.alien.util.common.ListToPage;
 
+import java.math.BigDecimal;
 import java.text.DecimalFormat;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -38,6 +50,11 @@ public class LifeCollectController {
 
     private final LifeCollectMapper lifeCollectMapper;
 
+
+    private SecondRecommendMapper secondRecommendMapper;
+
+    private final LifeUserMapper lifeUserMapper;
+
     private final SecondGoodsMapper secondGoodsMapper;
 
     private final StoreInfoMapper storeInfoMapper;
@@ -290,4 +307,85 @@ public class LifeCollectController {
         return R.success("取消收藏成功");
     }
 
+
+    @ApiOperation("收藏商品列表")
+    @PostMapping("/collectSecondGoodsByPage")
+    public R<IPage<SecondGoodsRecommendVo>> collectSecondGoodsByPage(
+            @RequestParam(value = "pageNum", required = false) Integer pageNum,
+            @RequestParam(value = "pageSize", required = false) Integer pageSize,
+            @RequestParam(value = "longitude", required = false) String longitude,
+            @RequestParam(value = "latitude", required = false) String latitude) throws Exception {
+        log.info("LifeCollectController.cancelCollect?pageNum={},pageSize={},longitude={},latitude={}", pageNum, pageSize, longitude, latitude);
+        try {
+            IPage<SecondGoodsRecommendVo> page = new Page<>(pageNum, pageSize);
+            JSONObject data = JwtUtil.getCurrentUserInfo();
+            String phoneId = null;
+            Integer userId = null;
+            if (data != null) {
+                phoneId = data.getString("phone");
+                userId = data.getInteger("userId");
+            }
+            if (StringUtil.isBlank(phoneId)) {
+                return null;
+            }
+            LifeUser lifeUser = lifeUserMapper.selectById(userId);
+            // 获取商品屏蔽列表
+            List<SecondGoods> shieldedGoodsList = getShieldedGoodsList(userId);
+            // 提取屏蔽商品ID
+            List<Integer> shieldedGoodsIds = shieldedGoodsList.stream()
+                    .map(SecondGoods::getId)
+                    .collect(Collectors.toList());
+
+//            QueryWrapper<SecondGoodsVo> queryWrapper = new QueryWrapper<>();
+//            queryWrapper
+//                    // 可以查看已删除的商品数据
+//                    .eq("sg.delete_flag", Constants.DeleteFlag.NOT_DELETED)
+//                    .eq("lc.delete_flag", Constants.DeleteFlag.NOT_DELETED)
+//                    .notIn(CollectionUtil.isNotEmpty(shieldedGoodsIds), "sg.id", shieldedGoodsIds)
+//                    .eq("lc.user_id", "user_"+lifeUser.getUserPhone())
+//                    .orderByDesc("lc.created_time");
+
+            IPage<SecondGoodsRecommendVo> list = lifeCollectMapper.collectSecondGoodsByPage(page, userId, "user_" + phoneId, longitude + "," + latitude, shieldedGoodsIds);
+            List<Integer> idList = list.getRecords().stream() // 创建流
+                    .map(obj -> obj.getId())   // 提取每个元素的 ID
+                    .collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(idList)) {
+                return R.data(list);
+            }
+//            List<SecondCommentVo> commentList =secondRecommendMapper.querySecondCommentInfo(idList);
+            list.getRecords().forEach(item -> {
+                // 距离拼接
+                if (StringUtil.isNotBlank(item.getDist())) {
+                    item.setPosition("距离" + item.getDist() + "km");
+                }
+                // 价格保留两位小数
+                item.setPrice(item.getAmount() != null ? item.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toString() : null);
+
+                // 评论列表
+//                List<SecondCommentVo> cList = new ArrayList<>();
+//                commentList.forEach(comment -> {
+//                    if (item.getId().equals(comment.getBusinessId())) {
+//                        cList.add(comment);
+//                    }
+//                });
+//                if (cList.size() > 0) {
+//                    item.setCommentList(cList);
+//                }
+            });
+            return R.data(list);
+        } catch (Exception e){
+            log.error("收藏商品列表 Error Mgs={}", e.getMessage());
+            throw new Exception(e);
+        }
+    }
+
+    /**
+     * 获取商品屏蔽列表
+     * @param userId 用户ID
+     * @return 商品屏蔽列表
+     */
+    private List<SecondGoods> getShieldedGoodsList(Integer userId) {
+        // 调用mapper方法
+        return secondGoodsMapper.getShieldedGoodsList(userId);
+    }
 }