|
|
@@ -104,11 +104,21 @@ public class ArticleService {
|
|
|
|
|
|
public Page<Article> getPublicList(Long categoryId, String keyword, String dimensionCode, int page, int size,
|
|
|
Long userId, Long familyId, String vendorType) {
|
|
|
- return getPublicList(categoryId, keyword, dimensionCode, page, size, userId, familyId, vendorType, null);
|
|
|
+ return getPublicList(categoryId, keyword, dimensionCode, null, page, size, userId, familyId, vendorType, null);
|
|
|
}
|
|
|
|
|
|
public Page<Article> getPublicList(Long categoryId, String keyword, String dimensionCode, int page, int size,
|
|
|
Long userId, Long familyId, String vendorType, Long memberId) {
|
|
|
+ return getPublicList(categoryId, keyword, dimensionCode, null, page, size, userId, familyId, vendorType, memberId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 知识中心文章列表:支持按文章标签筛选(知识中心 Tab 从「五维」改为「文章标签」)。
|
|
|
+ * tag 为空时行为与旧版一致;tag 非空时仅返回 tags 字段包含该标签的文章。
|
|
|
+ * tags 字段为 JSON 数组字符串(如 ["减脂","睡眠"])或逗号分隔,统一由 parseCommaOrJsonTags 解析后内存过滤。
|
|
|
+ */
|
|
|
+ public Page<Article> getPublicList(Long categoryId, String keyword, String dimensionCode, String tag,
|
|
|
+ int page, int size, Long userId, Long familyId, String vendorType, Long memberId) {
|
|
|
LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<Article>()
|
|
|
.eq(Article::getStatus, "published")
|
|
|
.orderByDesc(Article::getIsFeatured)
|
|
|
@@ -137,6 +147,14 @@ public class ArticleService {
|
|
|
// 前端 noMore = 已加载数 >= total 恒为真,导致只显示一页、无法加载更多。
|
|
|
List<Article> all = articleMapper.selectList(wrapper);
|
|
|
|
|
|
+ // 按文章标签筛选(与 parseCommaOrJsonTags 解析语义对齐,兼容 JSON 数组 / 逗号分隔两种存储格式)
|
|
|
+ if (tag != null && !tag.trim().isEmpty()) {
|
|
|
+ String targetTag = tag.trim();
|
|
|
+ all = all.stream()
|
|
|
+ .filter(a -> parseCommaOrJsonTags(a.getTags()).contains(targetTag))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
List<Article> visible = articlePermissionService.filterVisible(all, userId, familyId, vendorType);
|
|
|
|
|
|
// 过滤已完成阅读且获得CF值的文章(达到阈值且答题得CF后不再出现在文章列表中)
|
|
|
@@ -179,6 +197,32 @@ public class ArticleService {
|
|
|
DimensionThresholdFilter.filterVisible(visible, Article::getId, "ARTICLE", familyAvg, byId);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 聚合已发布文章的标签,按出现频次降序返回 Top N(知识中心 Tab 动态标签列表数据源)。
|
|
|
+ * 标签格式兼容 JSON 数组 / 逗号分隔,统一由 parseCommaOrJsonTags 解析拆分去重。
|
|
|
+ */
|
|
|
+ public List<String> listTopTags(int limit) {
|
|
|
+ int n = limit > 0 ? limit : 20;
|
|
|
+ LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<Article>()
|
|
|
+ .eq(Article::getStatus, "published")
|
|
|
+ .and(w -> w.isNotNull(Article::getTags).or().apply("TRIM(tags) <> ''"));
|
|
|
+ List<Article> articles = articleMapper.selectList(wrapper);
|
|
|
+ Map<String, Integer> freq = new HashMap<>();
|
|
|
+ for (Article a : articles) {
|
|
|
+ for (String t : parseCommaOrJsonTags(a.getTags())) {
|
|
|
+ if (!t.isEmpty()) {
|
|
|
+ freq.merge(t, 1, Integer::sum);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return freq.entrySet().stream()
|
|
|
+ .sorted(Map.Entry.<String, Integer>comparingByValue().reversed()
|
|
|
+ .thenComparing(Map.Entry.comparingByKey()))
|
|
|
+ .limit(n)
|
|
|
+ .map(Map.Entry::getKey)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
public List<Article> getFeatured(int size, Long userId, Long familyId, String vendorType, Long memberId) {
|
|
|
return getFeatured(size, null, userId, familyId, vendorType, memberId);
|
|
|
}
|