feat: 增加博客评论模块
This commit is contained in:
41
src/components/Blog/Comment/BlogComment.vue
Normal file
41
src/components/Blog/Comment/BlogComment.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="blog-comment">
|
||||
<div class="comment-total">
|
||||
<span>共 {{ blogStore.blogNestedCommentList.length }} 条评论</span>
|
||||
</div>
|
||||
|
||||
<div class="comment-list">
|
||||
<blog-comment-item v-for="(item, index) in blogStore.blogNestedCommentList" :key="index"
|
||||
:comment="item.comment" :replyList="item.replies"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlogCommentItem from '@/components/Blog/Comment/BlogCommentItem.vue'
|
||||
import { onMounted } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog'
|
||||
import { flattenToTwoLevel } from '@/utils/blog/blogUtil'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
onMounted(() => {
|
||||
blogStore.queryBlogComment(blogStore.currentBlogId)
|
||||
blogStore.blogNestedCommentList = flattenToTwoLevel(blogStore.blogCommentList)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.blog-comment {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #EEEEEE;
|
||||
border-radius: 10px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
87
src/components/Blog/Comment/BlogCommentEdit.vue
Normal file
87
src/components/Blog/Comment/BlogCommentEdit.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="blog-comment-edit">
|
||||
<div class="comment-title">
|
||||
<el-input v-model="blogComment.name"
|
||||
placeholder="请输入Github用户名"/>
|
||||
<el-input v-model="blogComment.website"
|
||||
placeholder="请输入个人博客网站"/>
|
||||
</div>
|
||||
|
||||
<el-input v-model="blogComment.content"
|
||||
placeholder="有什么想和我说的呢" maxlength="500"
|
||||
:rows="7" show-word-limit type="textarea"
|
||||
/>
|
||||
|
||||
<div class="comment-button">
|
||||
<el-popover ref="emojiPopoverRef" placement="top" :width="300" trigger="hover">
|
||||
<template #default>
|
||||
<div class="emoji-panel">
|
||||
<EmojiPicker :native="true" @select="onSelectEmoji" />
|
||||
</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<el-button circle>
|
||||
<i class="fa-regular fa-face-smile"></i>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
<el-button type="primary"
|
||||
:disabled="blogComment.content.length === 0"
|
||||
class="send-button">发送</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import EmojiPicker from 'vue3-emoji-picker'
|
||||
import 'vue3-emoji-picker/css'
|
||||
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const emojiPopoverRef = ref()
|
||||
|
||||
const blogComment = reactive({
|
||||
name: '',
|
||||
website: '',
|
||||
content: ''
|
||||
})
|
||||
|
||||
const onSelectEmoji = (emoji) => {
|
||||
if (blogComment.content.length <= 498) {
|
||||
blogComment.content += emoji.i
|
||||
}
|
||||
|
||||
emojiPopoverRef.value.hide()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.blog-comment-edit {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #EEEEEE;
|
||||
border-radius: 10px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
.comment-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.comment-button {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.send-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
107
src/components/Blog/Comment/BlogCommentItem.vue
Normal file
107
src/components/Blog/Comment/BlogCommentItem.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<div class="blog-comment-card">
|
||||
<el-avatar :size="50" :src="`https://github.com/${props.comment.name}.png`" alt="未加载"/>
|
||||
|
||||
<div class="blog-comment-content">
|
||||
<div class="basic-info">
|
||||
<span>{{ props.comment.name }}</span>
|
||||
<span class="content">Chrome 137.0.0.0</span>
|
||||
<span class="content">macOS 10.15.7</span>
|
||||
</div>
|
||||
|
||||
<div class="sub-info">
|
||||
<span class="content">{{ props.comment.createTime }}</span>
|
||||
<el-button v-if="!blogComment.isShowEdit"
|
||||
type="primary" text @click="replyClick">回复</el-button>
|
||||
<el-button v-else type="primary"
|
||||
text @click="cancelClick">取消</el-button>
|
||||
</div>
|
||||
|
||||
<p>{{ props.comment.content }}</p>
|
||||
|
||||
<blog-comment-edit v-if="blogComment.isShowEdit"/>
|
||||
|
||||
<div class="reply-list">
|
||||
<div class="blog-comment-card" v-for="(item, index) in props.replyList" :key="index">
|
||||
<el-avatar :size="50" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'" />
|
||||
|
||||
<div class="blog-comment-content">
|
||||
<div class="basic-info">
|
||||
<span>{{ item.name }}</span>
|
||||
<span class="content">Chrome 137.0.0.0</span>
|
||||
<span class="content">macOS 10.15.7</span>
|
||||
</div>
|
||||
|
||||
<div class="sub-info">
|
||||
<span class="content">{{ item.createTime }}</span>
|
||||
</div>
|
||||
<p>{{ item.content }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlogCommentEdit from '@/components/Blog/Comment/BlogCommentEdit.vue'
|
||||
import 'vue3-emoji-picker/css'
|
||||
import { defineProps, PropType, reactive } from 'vue'
|
||||
import { IBlogComment } from '@/types/blog'
|
||||
|
||||
const props = defineProps({
|
||||
comment: {
|
||||
type: Object as PropType<IBlogComment>
|
||||
},
|
||||
replyList: {
|
||||
type: Object as PropType<IBlogComment[]>
|
||||
}
|
||||
})
|
||||
|
||||
const blogComment = reactive({
|
||||
isShowEdit: false
|
||||
})
|
||||
|
||||
const replyClick = () => {
|
||||
blogComment.isShowEdit = true
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
blogComment.isShowEdit = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.blog-comment-card {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 60px 1fr;
|
||||
gap: 5px;
|
||||
|
||||
.blog-comment-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.sub-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: small;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -28,11 +28,17 @@
|
||||
<div class="blog-ending">
|
||||
<span>-------------本文结束♥感谢您的阅读♥给个五星好评吧~~-------------</span>
|
||||
</div>
|
||||
|
||||
<blog-comment-edit />
|
||||
|
||||
<blog-comment />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlogLabel from '@/components/Blog/Content/BlogLabel.vue'
|
||||
import BlogCommentEdit from '@/components/Blog/Comment/BlogCommentEdit.vue'
|
||||
import BlogComment from '@/components/Blog/Comment/BlogComment.vue'
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
import 'md-editor-v3/lib/style.css'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
|
||||
Reference in New Issue
Block a user