|
@@ -830,16 +830,28 @@ public class ProductRecommendationService {
|
|
|
* @param limit 返回数量
|
|
* @param limit 返回数量
|
|
|
* @return 关联商品列表
|
|
* @return 关联商品列表
|
|
|
*/
|
|
*/
|
|
|
- public List<Map<String, Object>> getArticleRelatedProducts(Long articleId, Long userId, Long familyId, Long memberId, int limit) {
|
|
|
|
|
- if (articleId == null || limit <= 0) return Collections.emptyList();
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取文章关联商品的完整候选列表(含标签匹配结果或首页推荐兜底)。
|
|
|
|
|
+ * 调用方自行切片实现分页(与 {@link #getDimensionRecommendations} 保持一致的分页语义)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param articleId 文章ID
|
|
|
|
|
+ * @param userId 当前用户ID(可为空)
|
|
|
|
|
+ * @param familyId 家庭ID(可为空)
|
|
|
|
|
+ * @param memberId 成员ID(可为空,兜底首页推荐用于健康画像)
|
|
|
|
|
+ * @param limit 候选上限(0 表示不限制,由调用方决定分页窗口)
|
|
|
|
|
+ * @return 关联商品完整列表(标签匹配优先,无匹配则首页推荐兜底;均为空时返回空列表)
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<Map<String, Object>> getArticleRelatedProductsFull(Long articleId, Long userId, Long familyId, Long memberId, int limit) {
|
|
|
|
|
+ if (articleId == null) return Collections.emptyList();
|
|
|
|
|
+ int fetchLimit = limit > 0 ? limit : Integer.MAX_VALUE;
|
|
|
|
|
|
|
|
- // 1. 优先按文章标签匹配商品;若无标签关联商品,兜底返回首页推荐商品
|
|
|
|
|
- List<Map<String, Object>> tagged = getArticleTagMatchedProducts(articleId, userId, familyId, limit);
|
|
|
|
|
|
|
+ // 1. 优先按文章标签匹配商品;若无标签关联商品,兜底返回首页推荐商品(与首页推荐区块同源,含健康画像过滤与个性化排序)
|
|
|
|
|
+ List<Map<String, Object>> tagged = getArticleTagMatchedProducts(articleId, userId, familyId, fetchLimit);
|
|
|
if (tagged != null && !tagged.isEmpty()) {
|
|
if (tagged != null && !tagged.isEmpty()) {
|
|
|
return tagged;
|
|
return tagged;
|
|
|
}
|
|
}
|
|
|
log.info("文章[{}]无标签关联商品,按首页推荐商品兜底返回", articleId);
|
|
log.info("文章[{}]无标签关联商品,按首页推荐商品兜底返回", articleId);
|
|
|
- List<Map<String, Object>> fallback = getDimensionRecommendations(null, familyId, memberId, null, limit, userId);
|
|
|
|
|
|
|
+ List<Map<String, Object>> fallback = getDimensionRecommendations(null, familyId, memberId, null, fetchLimit, userId);
|
|
|
if (fallback == null || fallback.isEmpty()) {
|
|
if (fallback == null || fallback.isEmpty()) {
|
|
|
return Collections.emptyList();
|
|
return Collections.emptyList();
|
|
|
}
|
|
}
|
|
@@ -850,6 +862,13 @@ public class ProductRecommendationService {
|
|
|
return fallback;
|
|
return fallback;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public List<Map<String, Object>> getArticleRelatedProducts(Long articleId, Long userId, Long familyId, Long memberId, int limit) {
|
|
|
|
|
+ if (articleId == null || limit <= 0) return Collections.emptyList();
|
|
|
|
|
+ List<Map<String, Object>> all = getArticleRelatedProductsFull(articleId, userId, familyId, memberId, limit);
|
|
|
|
|
+ if (all.size() <= limit) return all;
|
|
|
|
|
+ return all.subList(0, limit);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 文章标签匹配商品推荐:通过文章标签与商品标签匹配,按 标签匹配数 > 用户权重 > 家庭权重 > 销量 排序
|
|
* 文章标签匹配商品推荐:通过文章标签与商品标签匹配,按 标签匹配数 > 用户权重 > 家庭权重 > 销量 排序
|
|
|
*
|
|
*
|