|
|
@@ -130,11 +130,11 @@ public class ArticleService {
|
|
|
return filtered;
|
|
|
}
|
|
|
|
|
|
- public List<Article> getFeatured(int size, Long userId, Long familyId, String vendorType) {
|
|
|
- return getFeatured(size, null, userId, familyId, vendorType);
|
|
|
+ public List<Article> getFeatured(int size, Long userId, Long familyId, String vendorType, Long memberId) {
|
|
|
+ return getFeatured(size, null, userId, familyId, vendorType, memberId);
|
|
|
}
|
|
|
|
|
|
- public List<Article> getFeatured(int size, String dimensionCode, Long userId, Long familyId, String vendorType) {
|
|
|
+ public List<Article> getFeatured(int size, String dimensionCode, Long userId, Long familyId, String vendorType, Long memberId) {
|
|
|
LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<Article>()
|
|
|
.eq(Article::getStatus, "published")
|
|
|
.eq(Article::getIsFeatured, 1)
|
|
|
@@ -154,6 +154,14 @@ public class ArticleService {
|
|
|
List<Article> all = articleMapper.selectList(wrapper);
|
|
|
List<Article> visible = articlePermissionService.filterVisible(all, userId, familyId, vendorType);
|
|
|
|
|
|
+ // 过滤已阅读达标的文章(达到阈值后不再出现在推荐阅读中)
|
|
|
+ if (memberId != null) {
|
|
|
+ List<Long> completedIds = articleReadingRecordMapper.selectCompletedArticleIdsByChild(memberId);
|
|
|
+ if (!completedIds.isEmpty()) {
|
|
|
+ visible.removeIf(a -> completedIds.contains(a.getId()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
enrichTotalDurationSeconds(visible);
|
|
|
|
|
|
return visible.size() > size ? visible.subList(0, size) : visible;
|
|
|
@@ -199,6 +207,8 @@ public class ArticleService {
|
|
|
record.setChildId(memberId);
|
|
|
record.setContent("");
|
|
|
record.setDurationSeconds(durationSeconds);
|
|
|
+ int minSeconds = getArticleReadingMinSeconds();
|
|
|
+ record.setReadingCompleted(memberId != null && durationSeconds >= minSeconds);
|
|
|
record.setReadAt(new Date());
|
|
|
record.setCreatedAt(new Date());
|
|
|
articleReadingRecordMapper.insert(record);
|
|
|
@@ -209,11 +219,7 @@ public class ArticleService {
|
|
|
}
|
|
|
|
|
|
// 4. Check reading duration threshold
|
|
|
- int minSeconds = 60; // default
|
|
|
- String minSecondsStr = sysConfigService.getValue("article_reading_min_seconds");
|
|
|
- if (minSecondsStr != null && !minSecondsStr.isEmpty()) {
|
|
|
- try { minSeconds = Integer.parseInt(minSecondsStr); } catch (NumberFormatException e) { /* use default */ }
|
|
|
- }
|
|
|
+ int minSeconds = getArticleReadingMinSeconds();
|
|
|
|
|
|
if (durationSeconds < minSeconds) {
|
|
|
result.put("belowThreshold", true);
|
|
|
@@ -344,9 +350,18 @@ public class ArticleService {
|
|
|
.last("LIMIT 1");
|
|
|
ArticleReadingRecord existing = articleReadingRecordMapper.selectOne(wrapper);
|
|
|
|
|
|
+ // 获取阅读达标阈值
|
|
|
+ int minSeconds = getArticleReadingMinSeconds();
|
|
|
+ boolean isCompleted = false;
|
|
|
+
|
|
|
if (existing != null) {
|
|
|
// 累加时长
|
|
|
existing.setDurationSeconds(existing.getDurationSeconds() + durationSeconds);
|
|
|
+ // 累计时长达到阈值时标记为已阅读
|
|
|
+ if (existing.getReadingCompleted() == null || !existing.getReadingCompleted()) {
|
|
|
+ existing.setReadingCompleted(existing.getDurationSeconds() >= minSeconds);
|
|
|
+ isCompleted = existing.getReadingCompleted();
|
|
|
+ }
|
|
|
existing.setUpdatedAt(new Date());
|
|
|
articleReadingRecordMapper.updateById(existing);
|
|
|
} else {
|
|
|
@@ -354,14 +369,26 @@ public class ArticleService {
|
|
|
ArticleReadingRecord record = new ArticleReadingRecord();
|
|
|
record.setArticleId(articleId);
|
|
|
record.setUserId(userId);
|
|
|
- record.setChildId(memberId);
|
|
|
+ record.setChildId(memberId);
|
|
|
record.setDurationSeconds(durationSeconds);
|
|
|
+ record.setReadingCompleted(durationSeconds >= minSeconds);
|
|
|
record.setReadAt(new Date());
|
|
|
record.setCreatedAt(new Date());
|
|
|
articleReadingRecordMapper.insert(record);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取文章阅读达标最低秒数,默认 60 秒
|
|
|
+ */
|
|
|
+ private int getArticleReadingMinSeconds() {
|
|
|
+ String val = sysConfigService.getValue("article_reading_min_seconds");
|
|
|
+ if (val != null && !val.isEmpty()) {
|
|
|
+ try { return Integer.parseInt(val); } catch (NumberFormatException e) {}
|
|
|
+ }
|
|
|
+ return 60;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 递增文章浏览数(打开详情页即计数,匿名/登录用户均计)
|
|
|
*/
|