完善点赞和收藏的实时展示
This commit is contained in:
parent
e808240a32
commit
ebcd6ab4ae
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -16,4 +16,6 @@ public class TopicPreviewVO {
|
||||
int uid;
|
||||
String username;
|
||||
String avatar;
|
||||
int like;
|
||||
int collect;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user