From cd8ae491e21e5c3fa696842fa7b3b312d4c67518 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 21 Nov 2025 20:49:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(mobile):=20=E5=AE=9E=E7=8E=B0=E5=9F=BA?= =?UTF-8?q?=E4=BA=8E=E4=BA=BA=E8=84=B8ID=E7=9A=84=E5=95=86=E5=93=81?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改AppFaceController中list方法,将scenicId转换为Long类型传递 - 在AppGoodsController中注入FaceService,并在goodsList接口中调用faceService获取人脸列表 - 更新FaceMapper中的listByScenicAndUserId方法签名,统一scenicId参数类型为Long - GoodsServiceImpl中新增listGoodsByFaceIdList方法,实现根据人脸ID列表查询相关商品逻辑 - 商品查询支持按成片vlog和源素材分类展示,并去重处理 - 优化GoodsService接口,增加listGoodsByFaceIdList方法定义 - OrderMapper.xml --- .../controller/mobile/AppFaceController.java | 2 +- .../controller/mobile/AppGoodsController.java | 10 +- .../com/ycwl/basic/mapper/FaceMapper.java | 2 +- .../basic/service/mobile/GoodsService.java | 2 + .../service/mobile/impl/GoodsServiceImpl.java | 111 +++++++++++++++++- src/main/resources/mapper/OrderMapper.xml | 5 + 6 files changed, 124 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppFaceController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppFaceController.java index 2b899f2b..511432d5 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppFaceController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppFaceController.java @@ -59,7 +59,7 @@ public class AppFaceController { public ApiResponse> list(@PathVariable("scenicId") String scenicId) { JwtInfo worker = JwtTokenUtil.getWorker(); Long userId = worker.getUserId(); - List list = faceService.listByUser(userId, scenicId); + List list = faceService.listByUser(userId, Long.parseLong(scenicId)); return ApiResponse.success(list); } diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java index 8ac7e1b8..d1378a7a 100644 --- a/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java +++ b/src/main/java/com/ycwl/basic/controller/mobile/AppGoodsController.java @@ -4,7 +4,9 @@ import com.ycwl.basic.annotation.IgnoreToken; import com.ycwl.basic.exception.CheckTokenException; import com.ycwl.basic.model.jwt.JwtInfo; import com.ycwl.basic.model.mobile.goods.*; +import com.ycwl.basic.model.pc.face.resp.FaceRespVO; import com.ycwl.basic.service.mobile.GoodsService; +import com.ycwl.basic.service.pc.FaceService; import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.JwtTokenUtil; import org.springframework.beans.factory.annotation.Autowired; @@ -24,11 +26,17 @@ public class AppGoodsController { @Autowired private GoodsService goodsService; + @Autowired + private FaceService faceService; // 商品列表 @PostMapping("/goodsList") public ApiResponse> goodsList(@RequestBody GoodsReqQuery query) { - return goodsService.goodsList(query); + JwtInfo worker = JwtTokenUtil.getWorker(); + Long userId = worker.getUserId(); + List faceRespVOS = faceService.listByUser(userId, query.getScenicId()); + List faceIds = faceRespVOS.stream().map(FaceRespVO::getId).toList(); + return goodsService.listGoodsByFaceIdList(faceIds, query.getIsBuy(), query.getScenicId()); } // 源素材(原片/照片)商品列表 diff --git a/src/main/java/com/ycwl/basic/mapper/FaceMapper.java b/src/main/java/com/ycwl/basic/mapper/FaceMapper.java index 9d713723..7093d030 100644 --- a/src/main/java/com/ycwl/basic/mapper/FaceMapper.java +++ b/src/main/java/com/ycwl/basic/mapper/FaceMapper.java @@ -35,7 +35,7 @@ public interface FaceMapper { FaceRespVO findLastFaceByUserId(String userId); FaceRespVO findLastFaceByScenicAndUserId(Long scenicId, Long userId); - List listByScenicAndUserId(String scenicId, Long userId); + List listByScenicAndUserId(Long scenicId, Long userId); List listUnpaidEntityBeforeDate(Long scenicId, Date endDate); } diff --git a/src/main/java/com/ycwl/basic/service/mobile/GoodsService.java b/src/main/java/com/ycwl/basic/service/mobile/GoodsService.java index 5b243a5f..9e5b762a 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/GoodsService.java +++ b/src/main/java/com/ycwl/basic/service/mobile/GoodsService.java @@ -57,4 +57,6 @@ public interface GoodsService { * @return 视频更新检查结果 */ VideoUpdateCheckVO checkVideoUpdate(Long videoId); + + ApiResponse> listGoodsByFaceIdList(List faceIds, Integer isBuy, Long scenicId); } diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java index 9598d7d2..b1709441 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java @@ -66,6 +66,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.LinkedHashMap; import java.util.stream.Collectors; /** @@ -102,10 +103,6 @@ public class GoodsServiceImpl implements GoodsService { @Autowired private CouponBiz couponBiz; @Autowired - private SourceRepository sourceRepository; - @Autowired - private TemplateBiz templateBiz; - @Autowired private VideoUpdateConfig videoUpdateConfig; @Autowired private MemberRelationRepository memberRelationRepository; @@ -834,5 +831,109 @@ public class GoodsServiceImpl implements GoodsService { return result; } - + + @Override + public ApiResponse> listGoodsByFaceIdList(List faceIds, Integer isBuy, Long scenicId) { + // 参数校验 + if (faceIds == null || faceIds.isEmpty()) { + return ApiResponse.success(Collections.emptyList()); + } + if (scenicId == null) { + return ApiResponse.success(Collections.emptyList()); + } + + // 使用 LinkedHashMap 按 goodsType-goodsId 去重 + Map goodsMap = new LinkedHashMap<>(); + + // 循环查询每个 faceId 的商品 + for (Long faceId : faceIds) { + // 构造查询参数 + GoodsReqQuery query = new GoodsReqQuery(); + query.setFaceId(faceId); + query.setIsBuy(isBuy); + query.setScenicId(scenicId); + + // 查询成片 vlog (goodsType = 0) + VideoReqQuery videoReqQuery = new VideoReqQuery(); + videoReqQuery.setScenicId(scenicId); + videoReqQuery.setIsBuy(isBuy); + videoReqQuery.setFaceId(faceId); + + List videoList = videoMapper.queryByRelation(videoReqQuery); + for (VideoRespVO videoRespVO : videoList) { + String key = "0-" + videoRespVO.getId(); // goodsType=0, goodsId=videoId + if (!goodsMap.containsKey(key)) { + GoodsPageVO goodsPageVO = new GoodsPageVO(); + goodsPageVO.setGoodsName(videoRespVO.getTemplateName()); + goodsPageVO.setScenicId(videoRespVO.getScenicId()); + try { + ScenicV2DTO scenic = scenicRepository.getScenicBasic(videoRespVO.getScenicId()); + goodsPageVO.setScenicName(scenic.getName()); + } catch (Exception e) { + goodsPageVO.setScenicName(""); + } + goodsPageVO.setGoodsType(0); + goodsPageVO.setFaceId(videoRespVO.getFaceId()); + goodsPageVO.setGoodsId(videoRespVO.getId()); + goodsPageVO.setTemplateName(videoRespVO.getTemplateName()); + goodsPageVO.setTemplateCoverUrl(videoRespVO.getTemplateCoverUrl()); + goodsMap.put(key, goodsPageVO); + } + } + + // 查询源素材 (goodsType = 1/2) + SourceReqQuery sourceReqQuery = new SourceReqQuery(); + sourceReqQuery.setScenicId(scenicId); + sourceReqQuery.setIsBuy(isBuy); + sourceReqQuery.setFaceId(faceId); + + List sourceList = sourceMapper.queryByRelation(sourceReqQuery); + ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId); + + // 按 faceId 和 type 分组处理 + sourceList.stream() + .collect(Collectors.groupingBy(SourceRespVO::getFaceId)) + .forEach((sourceFaceId, goods) -> { + goods.stream() + .collect(Collectors.groupingBy(SourceRespVO::getType)) + .forEach((type, sourcesByType) -> { + // 根据景区配置过滤禁用的素材类型 + boolean isDisabled = false; + if (Integer.valueOf(1).equals(type)) { + isDisabled = Boolean.TRUE.equals(scenicConfig.getBoolean("disable_source_video")); + } else if (Integer.valueOf(2).equals(type)) { + isDisabled = Boolean.TRUE.equals(scenicConfig.getBoolean("disable_source_image")); + } + + if (!isDisabled) { + String key = type + "-" + sourceFaceId; // goodsType=type, goodsId=faceId(源素材用faceId作为ID) + if (!goodsMap.containsKey(key)) { + GoodsPageVO goodsPageVO = new GoodsPageVO(); + goodsPageVO.setFaceId(sourceFaceId); + goodsPageVO.setGoodsType(type); + if (type == 1) { + goodsPageVO.setGoodsName("录像集"); + goodsPageVO.setTemplateCoverUrl(scenicConfig.getString("video_cover_url")); + } else if (type == 2) { + goodsPageVO.setGoodsName("照片集"); + goodsPageVO.setTemplateCoverUrl(scenicConfig.getString("photo_cover_url")); + } else { + goodsPageVO.setGoodsName("未知商品"); + } + if (StringUtils.isBlank(goodsPageVO.getTemplateCoverUrl())) { + goodsPageVO.setTemplateCoverUrl(sourcesByType.getFirst().getUrl()); + } + goodsPageVO.setScenicId(scenicId); + goodsMap.put(key, goodsPageVO); + } + } + }); + }); + } + + // 返回去重后的商品列表 + List resultList = new ArrayList<>(goodsMap.values()); + return ApiResponse.success(resultList); + } + } diff --git a/src/main/resources/mapper/OrderMapper.xml b/src/main/resources/mapper/OrderMapper.xml index 966db692..3735703b 100644 --- a/src/main/resources/mapper/OrderMapper.xml +++ b/src/main/resources/mapper/OrderMapper.xml @@ -404,6 +404,11 @@ o.scenic_id from `order` AS o left join face f on o.face_id = f.id + + + and o.member_id = #{memberId} + + order by o.create_at desc