feat(cms): 添加虚拟阅读量展示与实际阅读量原子递增功能

- 在CmsArticle实体中新增views字段,表示实际阅读量与虚拟阅读量之和,供展示使用
- 实现views字段的getter方法,动态计算实际阅读量和虚拟阅读量的总和
- 修改CmsArticleServiceImpl中阅读量更新逻辑,采用SQL原子递增实际阅读量,防止并发覆盖
- 更新内存中article的实际阅读量值,保持与数据库同步
This commit is contained in:
2026-08-04 11:13:08 +08:00
parent b007b17e8d
commit 4478f5f23c
2 changed files with 19 additions and 3 deletions

View File

@@ -109,6 +109,16 @@ public class CmsArticle implements Serializable {
@Schema(description = "实际阅读量") @Schema(description = "实际阅读量")
private Integer actualViews; private Integer actualViews;
@Schema(description = "阅读量(实际阅读量 + 虚拟阅读量,仅用于展示)")
@TableField(exist = false)
private Integer views;
public Integer getViews() {
int actual = actualViews == null ? 0 : actualViews;
int virtual = virtualViews == null ? 0 : virtualViews;
return actual + virtual;
}
@Schema(description = "评分") @Schema(description = "评分")
private BigDecimal rate; private BigDecimal rate;

View File

@@ -112,9 +112,15 @@ public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArti
param.setArticleId(articleId); param.setArticleId(articleId);
final CmsArticle article = param.getOne(baseMapper.selectListRel(param)); final CmsArticle article = param.getOne(baseMapper.selectListRel(param));
if (ObjectUtil.isNotEmpty(article)) { if (ObjectUtil.isNotEmpty(article)) {
// 更新阅读数量 // 原子递增实际阅读量COALESCE 兼容历史空值,避免并发覆盖)
article.setActualViews(article.getActualViews() + 1); boolean viewUpdated = lambdaUpdate()
updateById(article); .setSql("actual_views = COALESCE(actual_views, 0) + 1")
.eq(CmsArticle::getArticleId, article.getArticleId())
.update();
if (viewUpdated) {
int current = article.getActualViews() == null ? 0 : article.getActualViews();
article.setActualViews(current + 1);
}
// 读取Banner // 读取Banner
// final CmsModel model = cmsModelService.getOne(new LambdaQueryWrapper<CmsModel>().eq(CmsModel::getModel, article.getModel()).last("limit 1")); // final CmsModel model = cmsModelService.getOne(new LambdaQueryWrapper<CmsModel>().eq(CmsModel::getModel, article.getModel()).last("limit 1"));
// if (ObjectUtil.isNotEmpty(model)) { // if (ObjectUtil.isNotEmpty(model)) {