<template>
<div class="comment">
<div
class="comment-body"
v-for="(item, index) in comments"
:key="item.id + '' + index"
>
<!-- 一级评论 -->
<div class="first-comment">
<el-avatar :size="40" :src="item.avatar"></el-avatar>
<div class="content">
<!-- 一级评论用户昵称 -->
<h3>{{ item.nickname }}</h3>
<!-- 一级评论发布时间 -->
<span>{{ item.date }}</span>
<!-- 一级评论评论内容 -->
<p>{{ item.content }}</p>
<!-- 一级评论评论点赞 -->
<div class="comment-right" @click="isShowSecReply(item.id)">
<i class="el-icon-chat-dot-round"></i>
<span>回复</span>
</div>
<!-- 回复一级评论 -->
<div class="reply-comment" v-show="isShowSec === item.id">
<el-input
:placeholder="placeholderText"
class="input"
v-model.trim="replyContext"
:maxlength="contentLength"
></el-input>
<el-button
type="info"
size="mini"
class="reply-button"
@click="addComment(item.id, item.nickname)"
>回复</el-button
>
</div>
<!-- 次级评论 -->
<div
class="second-comment"
v-for="(reply, index) in item.replyInfo"
:key="reply.id + '' + index"
>
<!-- 次级评论头像,该用户没有头像则显示默认头像 -->
<el-avatar :size="40" :src="reply.avatar"></el-avatar>
<div class="content">
<!-- 次级评论用户昵称 -->
<h3>{{ reply.nickname }}</h3>
<!-- 次级评论评论时间 -->
<span>{{ reply.date }}</span>
<span class="to_reply">{{ reply.nickname }}</span>
回复
<span class="to_reply">{{ reply.replyName }}</span
>:
<p>{{ reply.content }}</p>
<!-- 次级评论评论点赞 -->
<div class="comment-right" @click="isShowSecReply(reply.id)">
<i class="el-icon-chat-dot-round"></i>
<span>回复</span>
</div>
<div class="reply-comment" v-show="isShowSec === reply.id">
<el-input
:placeholder="placeholderText"
class="input"
v-model.trim="replyContext"
:maxlength="contentLength"
></el-input>
<el-button
type="info"
size="mini"
class="reply-button"
@click="addComment(item.id, reply.nickname)"
>回复</el-button
>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 暂无评论的空状态 -->
<el-empty
:description="emptyText"
v-show="comments.length === 0"
></el-empty>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
props: {
articleId: {
//评论所属文章 id
type: String,
},
emptyText: {
// 评论为空的时候显示的文字
type: String,
default: "期待你的评论!",
},
buttonText: {
// 按钮文字
type: String,
default: "评论",
},
contentLength: {
// 评论长度
type: Number,
default: 150,
},
placeholderText: {
// 默认显示文字
type: String,
default: "请输入最多150字的评论...",
},
},
inject: ["refresh"],
data() {
return {
nowTime: "", // 当前时间
comment: {},
replyContext: "", //一级评论回复
isShowSec: "", //是否显示次级回复框
isClickId: "", //记录点击回复的评论id
firstIdx: 1,
secIdx: 1,
avatar:
"https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
};
},
mounted() {
this.$store.dispatch("topicById", this.articleId);
this.$store.dispatch("getUserInfo");
},
computed: {
sum() {
let s = 0;
let a = this.$store.state.topic.topicmain.comments.length;
for (let i = 0; i < a; i++) {
s += this.$store.state.topic.topicmain.comments[i].replyInfo.length;
}
s = s + a;
return s;
},
artmain() {
return this.$store.state.topic.topicmain;
},
comments() {
return this.$store.state.topic.topicmain.comments;
},
...mapState({
userInfo: ({ home }) => home.userInfo,
}),
},
methods: {
//获取时间
formatDateTime(date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? "0" + m : m;
var d = date.getDate();
d = d < 10 ? "0" + d : d;
var h = date.getHours();
h = h < 10 ? "0" + h : h;
var minute = date.getMinutes();
minute = minute < 10 ? "0" + minute : minute;
var second = date.getSeconds();
second = second < 10 ? "0" + second : second;
return y + "-" + m + "-" + d + " " + h + ":" + minute + ":" + second;
},
isShowSecReply(id) {
if (id) {
this.isShowSec = id;
if (this.isClickId === this.isShowSec) {
this.isShowSec = "";
} else {
this.isShowSec = id;
}
this.isClickId = this.isShowSec;
} else {
this.isShowSec = this.isClickId = "";
}
},
async addComment(id, replyName) {
//本地更新评论列表
if (replyName) {
// 添加二级评论
if (!this.replyContext) {
this.$message.warning("评论或留言不能为空哦!");
return;
}
this.nowTime = new Date();
this.comment.date = this.formatDateTime(this.nowTime);
this.comment.id = "sec" + `${this.sum}`;
this.comment.replyid = id;
this.comment.artid = this.artmain._id;
this.comment.content = this.replyContext;
this.comment.replyName = replyName;
this.comment.username = this.userInfo.username;
this.comment.nickname = this.userInfo.nickname;
this.comment.avatar = this.userInfo.avatar;
const { comment } = this;
await this.$store.dispatch("PostFirTopicComment", comment);
this.comment.date = "";
this.replyContext = "";
this.$store.dispatch("topicById", this.articleId);
}
},
},
};
</script>
<style lang="less" scoped>
.comment {
min-height: 26vh;
border-radius: 5px;
margin-top: 2px;
overflow: hidden;
.active {
color: rgb(202, 4, 4);
}
.comment-header {
position: relative;
height: 50px;
padding: 10px 5px;
display: flex;
align-items: center;
.input {
margin-left: 10px;
margin-right: 20px;
flex: 1;
/deep/.el-input__inner:focus {
border-color: #dcdfe6;
}
}
}
.comment-body {
min-height: 70px;
padding: 10px 20px;
font-size: 14px;
.first-comment {
display: flex;
.input {
/deep/.el-input__inner:focus {
border-color: #dcdfe6;
}
}
i {
margin-right: 5px;
margin-left: 1vw;
cursor: pointer;
&:nth-child(3) {
color: rgb(202, 4, 4);
}
}
.content {
margin-left: 10px;
position: relative;
flex: 1;
& > span {
font-size: 12px;
color: rgb(130, 129, 129);
}
.comment-right {
position: absolute;
right: 0;
top: 0;
}
.reply-comment {
height: 60px;
display: flex;
align-items: center;
.reply-button {
margin-left: 20px;
height: 35px;
}
}
.second-comment {
display: flex;
padding: 10px 0 10px 5px;
border-radius: 20px;
background: #ffffff;
.to_reply {
color: rgb(126, 127, 128);
}
}
}
}
}
}
</style>
一层的评论为了方便写方法放到了调用的组件当中去写
主要是展示二级评论的逻辑思路~