添加评论发表操作

This commit is contained in:
柏码の讲师 2023-10-28 00:22:48 +08:00
parent 863a1d4f0f
commit 47b71807e1
13 changed files with 183 additions and 17 deletions

View File

@ -2,6 +2,7 @@ package com.example.controller;
import com.example.entity.RestBean; import com.example.entity.RestBean;
import com.example.entity.dto.Interact; import com.example.entity.dto.Interact;
import com.example.entity.vo.request.AddCommentVO;
import com.example.entity.vo.request.TopicCreateVO; import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO; import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.*; import com.example.entity.vo.response.*;
@ -93,4 +94,10 @@ public class ForumController {
topicService.updateTopic(id, vo); topicService.updateTopic(id, vo);
return RestBean.success(); return RestBean.success();
} }
@PostMapping("/add-comment")
public RestBean<String> addComment(@Valid @RequestBody AddCommentVO vo,
@RequestAttribute(Const.ATTR_USER_ID) int id) {
return utils.messageHandle(() -> topicService.createComment(vo, id));
}
} }

View File

@ -0,0 +1,20 @@
package com.example.entity.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("db_topic_comments")
public class TopicComment {
@TableId(type = IdType.AUTO)
Integer id;
Integer tid;
Integer uid;
String content;
Date time;
Integer quote;
}

View File

@ -0,0 +1,14 @@
package com.example.entity.vo.request;
import com.alibaba.fastjson2.JSONObject;
import jakarta.validation.constraints.Min;
import lombok.Data;
@Data
public class AddCommentVO {
@Min(1)
int tid;
String content;
@Min(-1)
int quote;
}

View File

@ -0,0 +1,9 @@
package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.dto.TopicComment;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TopicCommentMapper extends BaseMapper<TopicComment> {
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.dto.Interact; import com.example.entity.dto.Interact;
import com.example.entity.dto.Topic; import com.example.entity.dto.Topic;
import com.example.entity.dto.TopicType; import com.example.entity.dto.TopicType;
import com.example.entity.vo.request.AddCommentVO;
import com.example.entity.vo.request.TopicCreateVO; import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO; import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.TopicPreviewVO; import com.example.entity.vo.response.TopicPreviewVO;
@ -21,4 +22,5 @@ public interface TopicService extends IService<Topic> {
TopicDetailVO getTopic(int tid, int uid); TopicDetailVO getTopic(int tid, int uid);
void interact(Interact interact, boolean state); void interact(Interact interact, boolean state);
List<TopicPreviewVO> listCollectTopic(int uid); List<TopicPreviewVO> listCollectTopic(int uid);
String createComment(AddCommentVO vo, int uid);
} }

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.*; import com.example.entity.dto.*;
import com.example.entity.vo.request.AddCommentVO;
import com.example.entity.vo.request.TopicCreateVO; import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO; import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.TopicDetailVO; import com.example.entity.vo.response.TopicDetailVO;
@ -41,6 +42,9 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
@Resource @Resource
AccountPrivacyMapper accountPrivacyMapper; AccountPrivacyMapper accountPrivacyMapper;
@Resource
TopicCommentMapper commentMapper;
@Resource @Resource
FlowUtils flowUtils; FlowUtils flowUtils;
@ -152,6 +156,19 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
} }
} }
@Override
public String createComment(AddCommentVO vo, int uid) {
String key = Const.FORUM_TOPIC_COMMENT_COUNTER + uid;
if(!flowUtils.limitPeriodCounterCheck(key, 2, 60))
return "发表评论频繁,请稍后再试!";
TopicComment comment = new TopicComment();
comment.setUid(uid);
BeanUtils.copyProperties(vo, comment);
comment.setTime(new Date());
commentMapper.insert(comment);
return null;
}
private boolean hasInteract(int tid, int uid, String type){ private boolean hasInteract(int tid, int uid, String type){
String key = tid + ":" + uid; String key = tid + ":" + uid;
if(template.opsForHash().hasKey(type, key)) if(template.opsForHash().hasKey(type, key))

View File

@ -26,5 +26,6 @@ public final class Const {
public final static String FORUM_IMAGE_COUNTER = "image:upload:"; public final static String FORUM_IMAGE_COUNTER = "image:upload:";
public final static String FORUM_WEATHER_CACHE = "weather:cache:"; public final static String FORUM_WEATHER_CACHE = "weather:cache:";
public final static String FORUM_TOPIC_CREATE_COUNTER = "topic:create:"; public final static String FORUM_TOPIC_CREATE_COUNTER = "topic:create:";
public final static String FORUM_TOPIC_COMMENT_COUNTER = "topic:comment:";
public final static String FORUM_TOPIC_PREVIEW_CACHE = "topic:preview:"; public final static String FORUM_TOPIC_PREVIEW_CACHE = "topic:preview:";
} }

View File

@ -0,0 +1,15 @@
.ql-toolbar {
border-radius: 5px 5px 0 0;
border-color: var(--el-border-color) !important;
}
.ql-container{
border-radius: 0 0 5px 5px;
border-color: var(--el-border-color) !important;
}
.ql-editor.ql-blank::before{
color: grey !important;
font-style: normal !important;
}
.ql-editor {
font-size: 14px;
}

View File

@ -0,0 +1,61 @@
<script setup>
import {QuillEditor} from "@vueup/vue-quill";
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import {post} from "@/net";
import {reactive, ref} from "vue";
import {ElMessage} from "element-plus";
const props = defineProps({
quote: Number,
show: Boolean,
tid: String
})
const emit = defineEmits(['close'])
const content = ref()
function submitComment() {
post('/api/forum/add-comment', {
tid: props.tid,
content: JSON.stringify(content.value),
quote: props.quote
}, () => {
ElMessage.success('评论成功')
emit('close')
})
}
</script>
<template>
<div>
<el-drawer :model-value="show"
title="发表回复"
:size="270" direction="btt"
@close="emit('close')"
:show-close="false">
<div style="padding: 10px;width: 100%">
<div>
<quill-editor style="height: 100px" v-model:content="content"
placeholder="请发表友善的评论,不要使用脏话骂人,都是大学生素质高一点"/>
</div>
<div style="margin-top: 10px;text-align: right">
<el-button @click="submitComment" type="success" plain>发表评论</el-button>
</div>
</div>
</el-drawer>
</div>
</template>
<style lang="less" scoped>
:deep(.el-drawer) {
width: 800px;
margin: 20px auto;
border-radius: 10px;
}
:deep(.el-drawer__header) {
margin: 0;
}
:deep(.el-drawer__body) {
padding: 10px;
}
</style>

View File

@ -196,19 +196,4 @@ const editorOption = {
:deep(.el-drawer__header) { :deep(.el-drawer__header) {
margin: 0; margin: 0;
} }
:deep(.ql-toolbar) {
border-radius: 5px 5px 0 0;
border-color: var(--el-border-color);
}
:deep(.ql-container){
border-radius: 0 0 5px 5px;
border-color: var(--el-border-color);
}
:deep(.ql-editor.ql-blank::before){
color: grey;
font-style: normal;
}
:deep(.ql-editor) {
font-size: 14px;
}
</style> </style>

View File

@ -5,6 +5,7 @@ import axios from "axios";
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import 'element-plus/theme-chalk/dark/css-vars.css' import 'element-plus/theme-chalk/dark/css-vars.css'
import '@/assets/quill.css'
axios.defaults.baseURL = 'http://localhost:8080' axios.defaults.baseURL = 'http://localhost:8080'

View File

@ -21,6 +21,6 @@ get('/api/forum/types', data => {
</keep-alive> </keep-alive>
</transition> </transition>
</router-view> </router-view>
<el-backtop target=".main-content-page .el-scrollbar__wrap" :right="20" :bottom="20"/> <el-backtop target=".main-content-page .el-scrollbar__wrap" :right="20" :bottom="70"/>
</div> </div>
</template> </template>

View File

@ -3,7 +3,7 @@ import {useRoute} from "vue-router";
import {get, post} from "@/net"; import {get, post} from "@/net";
import {computed, reactive, ref} from "vue"; import {computed, reactive, ref} from "vue";
import axios from "axios"; import axios from "axios";
import {ArrowLeft, CircleCheck, EditPen, Female, Male, Star} from "@element-plus/icons-vue"; import {ArrowLeft, CircleCheck, EditPen, Female, Male, Plus, Star} from "@element-plus/icons-vue";
import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'; import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html';
import {useStore} from "@/store"; import {useStore} from "@/store";
import Card from "@/components/Card.vue"; import Card from "@/components/Card.vue";
@ -12,6 +12,7 @@ import InteractButton from "@/components/InteractButton.vue";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import TopicTag from "@/components/TopicTag.vue"; import TopicTag from "@/components/TopicTag.vue";
import TopicEditor from "@/components/TopicEditor.vue"; import TopicEditor from "@/components/TopicEditor.vue";
import TopicCommentEditor from "@/components/TopicCommentEditor.vue";
const route = useRoute() const route = useRoute()
const store = useStore() const store = useStore()
@ -25,6 +26,11 @@ const topic = reactive({
comments: [] comments: []
}) })
const edit = ref(false) const edit = ref(false)
const comment = reactive({
show: false,
text: '',
quote: -1
})
function init() { function init() {
get(`/api/forum/topic?tid=${tid}`, data => { get(`/api/forum/topic?tid=${tid}`, data => {
@ -124,15 +130,43 @@ function updateTopic(editor) {
</interact-button> </interact-button>
</div> </div>
</div> </div>
</div>
<div class="topic-main">
</div> </div>
<topic-editor :show="edit" @close="edit = false" v-if="topic.data" <topic-editor :show="edit" @close="edit = false" v-if="topic.data"
:default-title="topic.data.title" :default-text="topic.data.content" :default-title="topic.data.title" :default-text="topic.data.content"
:default-type="topic.data.type" submit-button="更新帖子内容" :default-type="topic.data.type" submit-button="更新帖子内容"
:submit="updateTopic"/> :submit="updateTopic"/>
<topic-comment-editor :show="comment.show" @close="comment.show = false"
:quote="comment.quote" :tid="tid"/>
<div class="add-comment" @click="comment.show = true">
<el-icon><Plus /></el-icon>
</div>
</div> </div>
</template> </template>
<style scoped> <style scoped>
.add-comment {
position: fixed;
bottom: 20px;
right: 20px;
width: 40px;
height: 40px;
line-height: 45px;
font-size: 18px;
color: var(--el-color-primary);
text-align: center;
border-radius: 20px;
background: var(--el-bg-color-overlay);
box-shadow: var(--el-box-shadow-lighter);
&:hover {
background: var(--el-border-color-extra-light);
cursor: pointer;
}
}
.topic-page { .topic-page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;