Commit 0ea260dc authored by 万成波's avatar 万成波

动态投票

parent 00683b1d
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.tangguo</groupId> <groupId>com.tangguo</groupId>
<artifactId>safe-campus-system</artifactId> <artifactId>safe-campus-quartz</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
......
package com.tangguo.constant;
/**
* 主题常量
*
* @author 谈笑
* @createTime 2025-09-04 21:19:10 星期四
*/
public interface TopicConstant {
/**
* 热搜主题
*/
String HOT_SCORE_CACHE_KEY = "topic.hot";
}
...@@ -11,14 +11,18 @@ import com.tangguo.domain.bo.LikeMomentBO; ...@@ -11,14 +11,18 @@ import com.tangguo.domain.bo.LikeMomentBO;
import com.tangguo.domain.bo.VoteMomentBO; import com.tangguo.domain.bo.VoteMomentBO;
import com.tangguo.domain.vo.BbsCommentDetailVO; import com.tangguo.domain.vo.BbsCommentDetailVO;
import com.tangguo.domain.vo.BbsMomentListVO; import com.tangguo.domain.vo.BbsMomentListVO;
import com.tangguo.domain.vo.BbsVoteOptionVO;
import com.tangguo.domain.vo.BbsVoteVO; import com.tangguo.domain.vo.BbsVoteVO;
import com.tangguo.service.IBbsMomentCommentService; import com.tangguo.service.IBbsMomentCommentService;
import com.tangguo.service.IBbsMomentService; import com.tangguo.service.IBbsMomentService;
import com.tangguo.service.IBbsMomentVoteOptionService;
import com.tangguo.service.IBbsMomentVoteService; import com.tangguo.service.IBbsMomentVoteService;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 移动端动态控制器 * 移动端动态控制器
...@@ -39,6 +43,9 @@ public class MBbsMomentController { ...@@ -39,6 +43,9 @@ public class MBbsMomentController {
@Resource @Resource
private IBbsMomentVoteService momentVoteService; private IBbsMomentVoteService momentVoteService;
@Resource
private IBbsMomentVoteOptionService momentVoteOptionService;
/** /**
* 查询动态列表 * 查询动态列表
...@@ -131,6 +138,24 @@ public class MBbsMomentController { ...@@ -131,6 +138,24 @@ public class MBbsMomentController {
} }
/**
* 投票动态统计
*
* @param momentId 动态Id
* @return 投票结果
*/
@MobileAuth
@GetMapping("/vote/count")
public AjaxResult getMomentVoteCount(@RequestParam Long momentId) {
List<BbsVoteOptionVO> dbOptionCount = this.momentVoteOptionService.getVoteOptionCount(momentId);
int voteCount = dbOptionCount.stream().mapToInt(BbsVoteOptionVO::getVoteCount).sum();
Map<String, Object> voteOptionMap = new LinkedHashMap<>(2);
voteOptionMap.put("voteOptionCount", dbOptionCount);
voteOptionMap.put("voteCount", voteCount);
return AjaxResult.success(voteOptionMap);
}
/** /**
* 动态投票记录 * 动态投票记录
* *
......
...@@ -72,6 +72,6 @@ public class BbsTopic extends BaseEntity { ...@@ -72,6 +72,6 @@ public class BbsTopic extends BaseEntity {
/** 话题热度 */ /** 话题热度 */
@Excel(name = "话题热度") @Excel(name = "话题热度")
@ApiModelProperty("话题热度") @ApiModelProperty("话题热度")
private Integer heat; private Double hotScore;
} }
package com.tangguo.jobs;
import com.tangguo.service.IBbsTopicService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 刷新话题排名定时任务
*
* @author 谈笑
* @createTime 2025-09-04 21:26:18 星期四
*/
@Slf4j
@Component
public class RefreshTopicRankingJob {
@Resource
private IBbsTopicService topicService;
public void run() {
log.info("=> 开始执行刷新话题排名定时任务");
this.topicService.refreshRankingTopic();
log.info("=> 执行刷新话题排名定时任务完毕");
}
}
...@@ -18,6 +18,9 @@ public interface BbsTopicMapper extends BaseMapper<BbsTopic> { ...@@ -18,6 +18,9 @@ public interface BbsTopicMapper extends BaseMapper<BbsTopic> {
List<BbsTopicListVO> selectSelectTopics(@Param("name") String name); List<BbsTopicListVO> selectSelectTopics(@Param("name") String name);
void refreshRankingTopic();
List<BbsTopicListVO> selectRankingTopic(); List<BbsTopicListVO> selectRankingTopic();
} }
...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; ...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.tangguo.domain.BbsMoment; import com.tangguo.domain.BbsMoment;
import com.tangguo.domain.BbsMomentVoteOption; import com.tangguo.domain.BbsMomentVoteOption;
import com.tangguo.domain.bo.CreateMomentBO; import com.tangguo.domain.bo.CreateMomentBO;
import com.tangguo.domain.vo.BbsVoteOptionVO;
import java.util.List; import java.util.List;
...@@ -59,4 +60,13 @@ public interface IBbsMomentVoteOptionService extends IService<BbsMomentVoteOptio ...@@ -59,4 +60,13 @@ public interface IBbsMomentVoteOptionService extends IService<BbsMomentVoteOptio
*/ */
BbsMomentVoteOption getVoteOption(Long momentId, String optionCode); BbsMomentVoteOption getVoteOption(Long momentId, String optionCode);
/**
* 查询动态投票选项统计
*
* @param momentId 动态Id
* @return 投票选项统计
*/
List<BbsVoteOptionVO> getVoteOptionCount(Long momentId);
} }
...@@ -2,6 +2,7 @@ package com.tangguo.service; ...@@ -2,6 +2,7 @@ package com.tangguo.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.tangguo.domain.BbsMomentVote; import com.tangguo.domain.BbsMomentVote;
import com.tangguo.domain.vo.BbsVoteOptionVO;
import com.tangguo.domain.vo.BbsVoteVO; import com.tangguo.domain.vo.BbsVoteVO;
import java.util.List; import java.util.List;
......
...@@ -66,6 +66,12 @@ public interface IBbsTopicService extends IService<BbsTopic> { ...@@ -66,6 +66,12 @@ public interface IBbsTopicService extends IService<BbsTopic> {
List<BbsTopicListVO> getSelectTopics(String name); List<BbsTopicListVO> getSelectTopics(String name);
/**
* 刷新热搜话题
*/
void refreshRankingTopic();
/** /**
* 查询热搜话题 * 查询热搜话题
* *
......
...@@ -268,7 +268,7 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment ...@@ -268,7 +268,7 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment
// 更新动态投票人数 // 更新动态投票人数
BbsMoment updMoment = new BbsMoment(); BbsMoment updMoment = new BbsMoment();
updMoment.setId(dbMoment.getId()); updMoment.setId(dbMoment.getId());
updMoment.setVoteCount(updOption.getVoteCount()); updMoment.setVoteCount(dbMoment.getVoteCount() + 1);
this.updateById(updMoment); this.updateById(updMoment);
} }
...@@ -318,6 +318,12 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment ...@@ -318,6 +318,12 @@ public class BbsMomentServiceImpl extends ServiceImpl<BbsMomentMapper, BbsMoment
updComment.setAncestorPath(String.valueOf(newComment.getId())); updComment.setAncestorPath(String.valueOf(newComment.getId()));
} }
this.commentService.updateById(updComment); this.commentService.updateById(updComment);
// 更新动态评论人数
BbsMoment updMoment = new BbsMoment();
updMoment.setId(dbMoment.getId());
updMoment.setCommentCount(dbMoment.getCommentCount() + 1);
this.updateById(updMoment);
} }
......
...@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; ...@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.domain.BbsMoment; import com.tangguo.domain.BbsMoment;
import com.tangguo.domain.BbsMomentVoteOption; import com.tangguo.domain.BbsMomentVoteOption;
import com.tangguo.domain.bo.CreateMomentBO; import com.tangguo.domain.bo.CreateMomentBO;
import com.tangguo.domain.vo.BbsVoteOptionVO;
import com.tangguo.enums.VoteOptionType; import com.tangguo.enums.VoteOptionType;
import com.tangguo.mapper.BbsMomentVoteOptionMapper; import com.tangguo.mapper.BbsMomentVoteOptionMapper;
import com.tangguo.service.IBbsMomentVoteOptionService; import com.tangguo.service.IBbsMomentVoteOptionService;
...@@ -14,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -14,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
...@@ -122,4 +124,29 @@ public class BbsMomentVoteOptionServiceImpl extends ServiceImpl<BbsMomentVoteOpt ...@@ -122,4 +124,29 @@ public class BbsMomentVoteOptionServiceImpl extends ServiceImpl<BbsMomentVoteOpt
); );
} }
/**
* 查询动态投票选项统计
*
* @param momentId 动态Id
* @return 投票选项统计
*/
@Override
public List<BbsVoteOptionVO> getVoteOptionCount(Long momentId) {
List<BbsMomentVoteOption> options = this.getVoteOptions(momentId);
List<BbsVoteOptionVO> ovs = new ArrayList<>(options.size());
for (BbsMomentVoteOption option : options) {
BbsVoteOptionVO ov = new BbsVoteOptionVO();
ov.setId(option.getId());
ov.setType(option.getType());
ov.setName(option.getName());
ov.setCode(option.getCode());
ov.setImageUrl(option.getImageUrl());
ov.setSort(option.getSort());
ov.setVoteCount(option.getVoteCount());
ovs.add(ov);
}
return ovs;
}
} }
package com.tangguo.service.impl; package com.tangguo.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.core.redis.RedisCache;
import com.tangguo.common.exception.ServiceException; import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.mauth.MobileTokenHelper; import com.tangguo.common.mauth.MobileTokenHelper;
import com.tangguo.common.utils.StringUtils; import com.tangguo.common.utils.StringUtils;
import com.tangguo.constant.TopicConstant;
import com.tangguo.domain.BbsTopic; import com.tangguo.domain.BbsTopic;
import com.tangguo.domain.bo.CreateTopicBO; import com.tangguo.domain.bo.CreateTopicBO;
import com.tangguo.domain.vo.BbsMomentListVO; import com.tangguo.domain.vo.BbsMomentListVO;
...@@ -21,6 +24,7 @@ import java.util.Collections; ...@@ -21,6 +24,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* 话题Service业务层处理 * 话题Service业务层处理
...@@ -34,6 +38,9 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i ...@@ -34,6 +38,9 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i
@Resource @Resource
private BbsTopicMapper bbsTopicMapper; private BbsTopicMapper bbsTopicMapper;
@Resource
private RedisCache redisCache;
/** /**
* 查询话题列表 * 查询话题列表
...@@ -155,6 +162,16 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i ...@@ -155,6 +162,16 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i
} }
/**
* 刷新热搜话题
*/
@Override
public void refreshRankingTopic() {
this.baseMapper.refreshRankingTopic();
this.redisCache.deleteObject(TopicConstant.HOT_SCORE_CACHE_KEY);
}
/** /**
* 查询热搜话题 * 查询热搜话题
* *
...@@ -162,7 +179,12 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i ...@@ -162,7 +179,12 @@ public class BbsTopicServiceImpl extends ServiceImpl<BbsTopicMapper, BbsTopic> i
*/ */
@Override @Override
public List<BbsTopicListVO> getRankingTopic() { public List<BbsTopicListVO> getRankingTopic() {
return this.baseMapper.selectRankingTopic(); List<BbsTopicListVO> topics = this.redisCache.getCacheObject(TopicConstant.HOT_SCORE_CACHE_KEY);
if (CollUtil.isEmpty(topics)) {
topics = this.baseMapper.selectRankingTopic();
this.redisCache.setCacheObject(TopicConstant.HOT_SCORE_CACHE_KEY, topics, 1, TimeUnit.HOURS);
}
return topics;
} }
......
...@@ -72,7 +72,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -72,7 +72,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
FROM FROM
bbs_moment_comment c bbs_moment_comment c
WHERE WHERE
c.moment_id = 1 AND c.`status` = 1 c.moment_id = #{momentId}
ORDER BY ORDER BY
c.create_time c.create_time
</select> </select>
......
...@@ -15,10 +15,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -15,10 +15,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if> </if>
</where> </where>
ORDER BY ORDER BY
is_top DESC, CASE WHEN is_top = 1 THEN top_time END DESC, heat DESC, sort ASC, create_time DESC is_top DESC, CASE WHEN is_top = 1 THEN top_time END DESC, hot_score DESC, sort ASC, create_time DESC
</select> </select>
<update id="refreshRankingTopic">
UPDATE
bbs_topic t
LEFT JOIN
(
SELECT
t.id,
t.`name`,
IFNULL(SUM(m.like_count), 0) AS like_count,
IFNULL(SUM(m.comment_count), 0) AS comment_count,
ROUND(IFNULL(SUM(m.hot_score), 0), 3) AS hot_score
FROM
bbs_topic t
LEFT JOIN (
SELECT
topic_ids,
like_count,
comment_count,
(1 / (1 + 0.1 * TIMESTAMPDIFF(HOUR, create_time, NOW()))) AS time_score,
(LN(1 + like_count) * 1 + LN(1 + comment_count) * 4
+ (1 / (1 + 0.1 * TIMESTAMPDIFF(HOUR, create_time, NOW()))) * 15) * 100 AS hot_score
FROM
bbs_moment
) m ON FIND_IN_SET(t.id, m.topic_ids)
GROUP BY
t.id, t.`name`
) h ON h.id = t.id
SET
t.like_count = h.like_count, t.comment_count = h.comment_count, t.hot_score = h.hot_score
</update>
<select id="selectRankingTopic" resultType="com.tangguo.domain.vo.BbsTopicListVO"> <select id="selectRankingTopic" resultType="com.tangguo.domain.vo.BbsTopicListVO">
SELECT SELECT
t.id, t.name, COUNT(m.id) AS moment_count t.id, t.name, COUNT(m.id) AS moment_count
...@@ -27,7 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -27,7 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN LEFT JOIN
bbs_moment m ON FIND_IN_SET(t.id, m.topic_ids) bbs_moment m ON FIND_IN_SET(t.id, m.topic_ids)
ORDER BY ORDER BY
t.is_top DESC, CASE WHEN t.is_top = 1 THEN t.top_time END DESC, t.heat DESC, t.sort ASC, t.create_time DESC t.is_top DESC, CASE WHEN t.is_top = 1 THEN t.top_time END DESC, t.hot_score DESC, t.create_time DESC
LIMIT 10 LIMIT 10
</select> </select>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment