完善点赞和收藏的实时展示

This commit is contained in:
柏码の讲师 2023-10-23 00:09:07 +08:00
parent e808240a32
commit ebcd6ab4ae
7 changed files with 51 additions and 5 deletions

View File

@ -16,7 +16,7 @@ public class Interact {
public static Interact parseInteract(String key, String type) {
String[] keys = key.split(":");
return new Interact(Integer.parseInt(keys[0]),
Integer.parseInt(keys[0]),
Integer.parseInt(keys[1]),
new Date(), type);
}

View File

@ -1,5 +1,6 @@
package com.example.entity.vo.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
@ -12,6 +13,14 @@ public class TopicDetailVO {
Integer type;
Date time;
User user;
Interact interact;
@Data
@AllArgsConstructor
public static class Interact {
Boolean like;
Boolean collect;
}
@Data
public static class User {

View File

@ -16,4 +16,6 @@ public class TopicPreviewVO {
int uid;
String username;
String avatar;
int like;
int collect;
}

View File

@ -6,6 +6,7 @@ import com.example.entity.dto.Topic;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@ -30,4 +31,14 @@ public interface TopicMapper extends BaseMapper<Topic> {
</script>
""")
int deleteInteract(List<Interact> interacts, String type);
@Select("""
select count(*) from db_topic_interact_${type} where tid = #{tid}
""")
int interactCount(int tid, String type);
@Select("""
select count(*) from db_topic_interact_${type} where tid = #{tid} and uid = #{uid}
""")
int userInteractCount(int tid, int uid, String type);
}

View File

@ -109,6 +109,11 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
TopicDetailVO vo = new TopicDetailVO();
Topic topic = baseMapper.selectById(tid);
BeanUtils.copyProperties(topic, vo);
TopicDetailVO.Interact interact = new TopicDetailVO.Interact(
hasInteract(tid, topic.getUid(), "like"),
hasInteract(tid, topic.getUid(), "collect")
);
vo.setInteract(interact);
TopicDetailVO.User user = new TopicDetailVO.User();
BeanUtils.copyProperties(topic, user);
vo.setUser(this.fillUserDetailsByPrivacy(user, topic.getUid()));
@ -124,6 +129,13 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
}
}
private boolean hasInteract(int tid, int uid, String type){
String key = tid + ":" + uid;
if(template.opsForHash().hasKey(type, key))
return Boolean.parseBoolean(template.opsForHash().entries(type).get(key).toString());
return baseMapper.userInteractCount(tid, uid, type) > 0;
}
/**
* 由于论坛交互数据如点赞收藏等更新可能会非常频繁
* 更新信息实时到MySQL不太现实所以需要用Redis做缓冲并在合适的时机一次性入库一段时间内的全部数据
@ -134,7 +146,6 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
private final Map<String, Boolean> state = new HashMap<>();
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
private void saveInteractData(String type) {
System.out.println(state);
if(!state.getOrDefault(type, false)) {
state.put(type, true);
service.schedule(() -> {
@ -146,7 +157,6 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
private void saveInteract(String type) {
synchronized (type.intern()) {
System.out.println(type);
List<Interact> check = new LinkedList<>();
List<Interact> uncheck = new LinkedList<>();
template.opsForHash().entries(type).forEach((k, v) -> {
@ -177,6 +187,8 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
TopicPreviewVO vo = new TopicPreviewVO();
BeanUtils.copyProperties(accountMapper.selectById(topic.getUid()), vo);
BeanUtils.copyProperties(topic, vo);
vo.setLike(baseMapper.interactCount(topic.getId(), "like"));
vo.setCollect(baseMapper.interactCount(topic.getId(), "collect"));
List<String> images = new ArrayList<>();
StringBuilder previewText = new StringBuilder();
JSONArray ops = JSONObject.parseObject(topic.getContent()).getJSONArray("ops");

View File

@ -23,7 +23,11 @@ const topic = reactive({
comments: []
})
get(`/api/forum/topic?tid=${tid}`, data => topic.data = data)
get(`/api/forum/topic?tid=${tid}`, data => {
topic.data = data
topic.like = data.interact.like
topic.collect = data.interact.collect
})
const content = computed(() => {
const ops = JSON.parse(topic.data.content).ops

View File

@ -10,7 +10,7 @@ import {
Edit,
EditPen,
Link,
Microphone
Microphone, CircleCheck, Star
} from "@element-plus/icons-vue";
import {computed, reactive, ref, watch} from "vue"
import Weather from "@/components/Weather.vue";
@ -156,6 +156,14 @@ navigator.geolocation.getCurrentPosition(position => {
<div style="display: grid;grid-template-columns: repeat(3, 1fr);grid-gap: 10px">
<el-image v-for="img in item.images" fit="cover" :src="img" class="topic-image"></el-image>
</div>
<div style="display: flex;gap: 20px;font-size: 13px;margin-top: 10px">
<div>
<el-icon style="vertical-align: middle"><CircleCheck /></el-icon> {{item.like}} 点赞
</div>
<div>
<el-icon style="vertical-align: middle"><Star /></el-icon> {{item.collect}} 收藏
</div>
</div>
</light-card>
</div>
</div>