Bladeren bron

feat(articles): 文章关联商品无匹配时兜底首页推荐

- ProductRecommendationService.getArticleRelatedProducts 签名新增 memberId 参数
- 原标签匹配逻辑抽取为私有方法 getArticleTagMatchedProducts
- 标签无匹配时调用 getDimensionRecommendations(null, ...) 兜底(与首页推荐同源,含健康画像过滤与个性化排序)
- ArticleController.relatedProducts 透传 currentMemberId/body.memberId
- 兜底结果标记 source=home_fallback,reason=暂无标签关联商品,按首页推荐展示
Xiaogang Liao 1 week geleden
bovenliggende
commit
bbcabe5d36

+ 4 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/content/ArticleController.java

@@ -44,7 +44,8 @@ public class ArticleController {
 
     @PostMapping("/related-products")
     public Result<List<Map<String, Object>>> relatedProducts(@RequestBody Map<String, Object> body,
-                                                             @RequestAttribute(value = "userId", required = false) Long userId) {
+                                                             @RequestAttribute(value = "userId", required = false) Long userId,
+                                                             @RequestAttribute(value = "currentMemberId", required = false) Long currentMemberId) {
         Long articleId = ParamUtils.getLong(body.get("articleId"));
         if (articleId == null) {
             return Result.error("articleId不能为空");
@@ -52,6 +53,7 @@ public class ArticleController {
         int size = body.get("size") != null ? Integer.parseInt(body.get("size").toString()) : 6;
 
         Long familyId = null;
+        Long memberId = ParamUtils.getLong(body.get("memberId"), currentMemberId);
         if (userId != null) {
             User user = userMapper.selectById(userId);
             if (user != null) {
@@ -59,7 +61,7 @@ public class ArticleController {
             }
         }
 
-        List<Map<String, Object>> products = productRecommendationService.getArticleRelatedProducts(articleId, userId, familyId, size);
+        List<Map<String, Object>> products = productRecommendationService.getArticleRelatedProducts(articleId, userId, familyId, memberId, size);
         return Result.success(products);
     }
 

+ 28 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/ProductRecommendationService.java

@@ -830,9 +830,36 @@ public class ProductRecommendationService {
      * @param limit     返回数量
      * @return 关联商品列表
      */
-    public List<Map<String, Object>> getArticleRelatedProducts(Long articleId, Long userId, Long familyId, int limit) {
+    public List<Map<String, Object>> getArticleRelatedProducts(Long articleId, Long userId, Long familyId, Long memberId, int limit) {
         if (articleId == null || limit <= 0) return Collections.emptyList();
 
+        // 1. 优先按文章标签匹配商品;若无标签关联商品,兜底返回首页推荐商品
+        List<Map<String, Object>> tagged = getArticleTagMatchedProducts(articleId, userId, familyId, limit);
+        if (tagged != null && !tagged.isEmpty()) {
+            return tagged;
+        }
+        log.info("文章[{}]无标签关联商品,按首页推荐商品兜底返回", articleId);
+        List<Map<String, Object>> fallback = getDimensionRecommendations(null, familyId, memberId, null, limit, userId);
+        if (fallback == null || fallback.isEmpty()) {
+            return Collections.emptyList();
+        }
+        for (Map<String, Object> item : fallback) {
+            item.put("reason", "暂无标签关联商品,按首页推荐展示");
+            item.put("source", "home_fallback");
+        }
+        return fallback;
+    }
+
+    /**
+     * 文章标签匹配商品推荐:通过文章标签与商品标签匹配,按 标签匹配数 > 用户权重 > 家庭权重 > 销量 排序
+     *
+     * @param articleId 文章ID
+     * @param userId    当前用户ID(可为空,用于用户权重)
+     * @param familyId  家庭ID(可为空,用于家庭权重)
+     * @param limit     返回数量
+     * @return 关联商品列表(无匹配时返回空列表,由调用方决定是否兜底)
+     */
+    private List<Map<String, Object>> getArticleTagMatchedProducts(Long articleId, Long userId, Long familyId, int limit) {
         // 1. 获取文章标签
         Article article = articleMapper.selectById(articleId);
         if (article == null || article.getTags() == null || article.getTags().trim().isEmpty()) {