You've already forked FrameTour-BE
feat(mobile): 实现基于人脸ID的商品列表查询功能
- 修改AppFaceController中list方法,将scenicId转换为Long类型传递 - 在AppGoodsController中注入FaceService,并在goodsList接口中调用faceService获取人脸列表 - 更新FaceMapper中的listByScenicAndUserId方法签名,统一scenicId参数类型为Long - GoodsServiceImpl中新增listGoodsByFaceIdList方法,实现根据人脸ID列表查询相关商品逻辑 - 商品查询支持按成片vlog和源素材分类展示,并去重处理 - 优化GoodsService接口,增加listGoodsByFaceIdList方法定义 - OrderMapper.xml
This commit is contained in:
@@ -59,7 +59,7 @@ public class AppFaceController {
|
||||
public ApiResponse<List<FaceRespVO>> list(@PathVariable("scenicId") String scenicId) {
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
Long userId = worker.getUserId();
|
||||
List<FaceRespVO> list = faceService.listByUser(userId, scenicId);
|
||||
List<FaceRespVO> list = faceService.listByUser(userId, Long.parseLong(scenicId));
|
||||
return ApiResponse.success(list);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<List<GoodsPageVO>> goodsList(@RequestBody GoodsReqQuery query) {
|
||||
return goodsService.goodsList(query);
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
Long userId = worker.getUserId();
|
||||
List<FaceRespVO> faceRespVOS = faceService.listByUser(userId, query.getScenicId());
|
||||
List<Long> faceIds = faceRespVOS.stream().map(FaceRespVO::getId).toList();
|
||||
return goodsService.listGoodsByFaceIdList(faceIds, query.getIsBuy(), query.getScenicId());
|
||||
}
|
||||
|
||||
// 源素材(原片/照片)商品列表
|
||||
|
||||
@@ -35,7 +35,7 @@ public interface FaceMapper {
|
||||
FaceRespVO findLastFaceByUserId(String userId);
|
||||
FaceRespVO findLastFaceByScenicAndUserId(Long scenicId, Long userId);
|
||||
|
||||
List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId);
|
||||
List<FaceRespVO> listByScenicAndUserId(Long scenicId, Long userId);
|
||||
|
||||
List<FaceEntity> listUnpaidEntityBeforeDate(Long scenicId, Date endDate);
|
||||
}
|
||||
|
||||
@@ -57,4 +57,6 @@ public interface GoodsService {
|
||||
* @return 视频更新检查结果
|
||||
*/
|
||||
VideoUpdateCheckVO checkVideoUpdate(Long videoId);
|
||||
|
||||
ApiResponse<List<GoodsPageVO>> listGoodsByFaceIdList(List<Long> faceIds, Integer isBuy, Long scenicId);
|
||||
}
|
||||
|
||||
@@ -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<List<GoodsPageVO>> listGoodsByFaceIdList(List<Long> 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<String, GoodsPageVO> 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<VideoRespVO> 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<SourceRespVO> 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<GoodsPageVO> resultList = new ArrayList<>(goodsMap.values());
|
||||
return ApiResponse.success(resultList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -404,6 +404,11 @@
|
||||
o.scenic_id
|
||||
from `order` AS o
|
||||
left join face f on o.face_id = f.id
|
||||
<where>
|
||||
<if test="memberId != null">
|
||||
and o.member_id = #{memberId}
|
||||
</if>
|
||||
</where>
|
||||
order by o.create_at desc
|
||||
</select>
|
||||
<select id="appDetail" resultMap="AppBaseResultMap">
|
||||
|
||||
Reference in New Issue
Block a user