html
<template>
<el-drawer
title="评论"
:visible.sync="drawer"
:direction="direction"
:before-close="handleClose"
append-to-body
size="420px"
custom-class="conmment_drawer"
>
<div class="conmment_box">
<div class="my-reply">
<div class="reply-info">
<el-input
@focus="focusInput"
type="textarea"
placeholder="请输入内容"
v-model="textarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength }}</span>
个字符
</div>
<el-button size="mini" type="primary" round @click="sendComment">
发表评论
</el-button>
</div>
</div>
<div
v-for="(item, i) in comments"
:key="i"
class="author-title reply-father"
>
<div class="author-info">
<span class="author-name">{{ item.name }}</span>
<span class="author-time">{{ item.time }}</span>
</div>
<div class="icon-btn">
<span
v-if="!item.inputShow"
@click="showReplyInput(i, item.name, item.id)"
>
<i class="iconfont el-icon-s-comment"></i>
回复
</span>
<span v-else @click="closeReplyInput(i, item.name, item.id)">
<i class="iconfont el-icon-s-comment"></i>
收起回复
</span>
</div>
<div class="talk-box">
<p>
<span class="reply">{{ item.comment }}</span>
</p>
</div>
<!-- 一级回复弹窗 -->
<div v-show="_inputShow(i)" class="my-reply">
<div class="reply-info">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="replytextarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength2 }}</span>
个字符
</div>
<el-button
size="mini"
type="primary"
round
@click="sendCommentReply(i)"
>
发表评论
</el-button>
</div>
</div>
<div class="reply-box">
<div v-for="(reply, j) in item.reply" :key="j" class="author-title">
<div class="author-info">
<span class="author-name">{{ reply.from }}</span>
<span class="author-time">{{ reply.time }}</span>
</div>
<div class="icon-btn">
<span
v-if="!reply.inputShow"
@click="showReplyInput2(i, reply.from, reply.id, j)"
>
<i class="iconfont el-icon-s-comment"></i>
回复
</span>
<span
v-else
@click="closeReplyInput2(i, reply.from, reply.id, j)"
>
<i class="iconfont el-icon-s-comment"></i>
收起回复
</span>
</div>
<div class="talk-box">
<p>
<span>回复 {{ reply.to }}:</span>
<span class="reply">{{ reply.comment }}</span>
</p>
</div>
<!-- 二级回复弹窗 -->
<div v-show="_inputShow2(i, j)" class="my-comment-reply">
<div class="reply-info">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="replytextarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength2 }}</span>
个字符
</div>
<el-button
size="mini"
type="primary"
round
@click="sendCommentReply(i)"
>
发表评论
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</el-drawer>
</template>
css
<style lang="scss" scoped>
>>> .conmment_drawer {
.el-drawer__header {
margin-bottom: 0px;
padding: 10px 16px;
border-bottom: 1px solid rgba(178, 186, 194, 0.3);
}
}
.conmment_box {
.my-reply {
padding: 10px;
background-color: rgba(245, 246, 247, 0.8);
margin: 10px 16px;
border-radius: 8px;
.reply-info {
display: inline-block;
width: 100%;
>>> .reply_input {
.el-textarea__inner {
background: rgba(245, 246, 247, 0.8);
border: none;
padding: 0px 6px;
}
}
}
.reply-btn-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 6px;
margin-top: 10px;
.limit {
font-size: 12px;
color: #999aaa;
.num {
color: #222226;
}
}
}
}
.my-comment-reply {
padding: 10px;
background-color: #ffff;
margin-top: 8px;
border-radius: 8px;
.reply-info {
display: inline-block;
width: 100%;
>>> .reply_input {
.el-textarea__inner {
background: #ffff;
border: none;
padding: 0px 6px;
}
}
}
.reply-btn-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 6px;
margin-top: 10px;
.limit {
font-size: 12px;
color: #999aaa;
.num {
color: #222226;
}
}
}
}
.author-title:not(:last-child) {
border-bottom: 1px solid rgba(178, 186, 194, 0.3);
}
.author-title {
padding: 10px 16px;
.author-info {
display: inline-block;
width: 60%;
line-height: 20px;
> span {
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.author-name {
color: #000;
font-size: 16px;
font-weight: bold;
}
.author-time {
margin-left: 6px;
font-size: 12px;
color: #aaa4a4;
}
}
.icon-btn {
width: 30%;
padding: 0 !important ;
float: right;
text-align: right;
font-size: 12px;
color: #999aaa;
> span {
cursor: pointer;
}
.iconfont {
font-size: 14px;
}
}
.talk-box {
margin-top: 8px;
font-size: 14px;
> p {
margin: 0;
color: #222226;
}
.reply {
font-size: 14px;
color: #000;
}
}
.reply-box {
margin: 10px 0 0 30px;
background-color: #efefef;
border-radius: 4px;
}
}
}
</style>
js
<script>
import request from "@/utils/request";
export default {
computed: {
inputLength () {
return this.textarea.length;
},
inputLength2 () {
return this.replytextarea.length;
},
},
props: {
direction: {
type: String,
default: "rtl"
}
},
data () {
return {
textarea: '',
replytextarea: '',
drawer: true,
closeInput: true,
index: '0',
index1: '0',
index2: '0',
replyComment: '',
myName: 'Lana Del Rey',
myId: 19870621,
to: '',
toId: -1,
comments: [
{
name: '小明',
id: 19870621,
comment: '我发布一张新电影我不是小三,大家快来看啊',
time: '2019年9月16日 18:43',
commentNum: 2,
like: 15,
inputShow: false,
reply: [
{
from: '小华',
fromId: 19891221,
to: '小明',
toId: 19870621,
comment: '我很喜欢你的新电影!!',
time: '2019年9月16日 18:43',
commentNum: 1,
like: 15,
inputShow: false
},
{
from: '小红',
fromId: 1123,
to: '小明',
toId: 19870621,
comment: '别忘记宣传我们的新电影啊',
time: '2019年9月16日 18:43',
commentNum: 0,
like: 5,
inputShow: false
}
]
},
{
name: '小张',
id: 19891221,
comment: '我发行了我的新电影Lover',
time: '2019年9月16日 18:43',
commentNum: 1,
like: 5,
inputShow: false,
reply: [
{
from: '小红',
fromId: 19870621,
to: '小张',
toId: 19891221,
comment: '新电影和speak now 一样棒!',
time: '2019年9月16日 18:43',
commentNum: 25,
like: 5,
inputShow: false
}
]
},
{
name: '小丽',
id: 20190830,
comment: 'ckwell on everywhere',
time: '2019年9月16日 18:43',
commentNum: 0,
like: 5,
inputShow: false,
reply: []
},
]
}
},
mounted () {
this.getList()
},
methods: {
/**
* 获取列表
*/
getList () {
let id = '334551';
let _query = {};
request({
url: `/api/plan/Comment/getListById/${id}`,
method: 'post',
data: _query
}).then((res) => {
console.log(res)
})
},
handleClose () {
},
focusInput () {
this.closeInput = false
},
hideReplyBtn () {
replyInput.style.padding = "10px"
replyInput.style.border = "none"
},
showReplyInput (i, name, id) {
this.closeInput = true
this.comments[this.index1].reply[this.index2].inputShow = false
this.comments[this.index].inputShow = false
this.index = i
this.comments[i].inputShow = true
this.to = name
this.toId = id
},
closeReplyInput (i, name, id) {
this.closeInput = false
this.comments[this.index].inputShow = false
},
showReplyInput2 (i, name, id, j) {
this.closeInput = true
this.comments[this.index].inputShow = false
this.comments[this.index1].reply[this.index2].inputShow = false
this.index1 = i
this.index2 = j
this.comments[i].reply[j].inputShow = true
this.to = name
this.toId = id
},
closeReplyInput2 (i, name, id, j) {
this.closeInput = false
this.comments[i].reply[j].inputShow = false
},
_inputShow (i) {
return this.comments[i].inputShow && this.closeInput
},
_inputShow2 (i, j) {
return this.comments[i].reply[j].inputShow && this.closeInput
},
sendComment () {
if (!this.textarea) {
this.$message({
showClose: true,
type: 'warning',
message: '评论不能为空'
})
} else {
let a = {}
let timeNow = new Date().getTime();
let time = this.dateStr(timeNow);
a.name = this.myName
a.comment = this.textarea
a.time = time
a.commentNum = 0
a.like = 0
this.comments.push(a)
this.replyComment = ''
this.textarea = '';
}
},
sendCommentReply (i) {
if (!this.replytextarea) {
this.$message({
showClose: true,
type: 'warning',
message: '评论不能为空'
})
} else {
let a = {}
let timeNow = new Date().getTime();
let time = this.dateStr(timeNow);
a.from = this.myName
a.to = this.to
a.comment = this.replytextarea
a.time = time
a.commentNum = 0
a.like = 0
this.comments[i].reply.push(a)
this.replytextarea = ''
}
},
dateStr (date) {
//获取js 时间戳
var time = new Date().getTime();
//去掉 js 时间戳后三位,与php 时间戳保持一致
time = parseInt((time - date) / 1000);
//存储转换值
var s;
if (time < 60 * 10) {//十分钟内
return '刚刚';
} else if ((time < 60 * 60) && (time >= 60 * 10)) {
//超过十分钟少于1小时
s = Math.floor(time / 60);
return s + "分钟前";
} else if ((time < 60 * 60 * 24) && (time >= 60 * 60)) {
//超过1小时少于24小时
s = Math.floor(time / 60 / 60);
return s + "小时前";
} else if ((time < 60 * 60 * 24 * 30) && (time >= 60 * 60 * 24)) {
//超过1天少于30天内
s = Math.floor(time / 60 / 60 / 24);
return s + "天前";
} else {
//超过30天ddd
var date = new Date(parseInt(date));
return date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
}
}
}
}
</script>
完整代码
<template>
<el-drawer
title="评论"
:visible.sync="drawer"
:direction="direction"
:before-close="handleClose"
append-to-body
size="420px"
custom-class="conmment_drawer"
>
<div class="conmment_box">
<div class="my-reply">
<div class="reply-info">
<el-input
@focus="focusInput"
type="textarea"
placeholder="请输入内容"
v-model="textarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength }}</span>
个字符
</div>
<el-button size="mini" type="primary" round @click="sendComment">
发表评论
</el-button>
</div>
</div>
<div
v-for="(item, i) in comments"
:key="i"
class="author-title reply-father"
>
<div class="author-info">
<span class="author-name">{{ item.name }}</span>
<span class="author-time">{{ item.time }}</span>
</div>
<div class="icon-btn">
<span
v-if="!item.inputShow"
@click="showReplyInput(i, item.name, item.id)"
>
<i class="iconfont el-icon-s-comment"></i>
回复
</span>
<span v-else @click="closeReplyInput(i, item.name, item.id)">
<i class="iconfont el-icon-s-comment"></i>
收起回复
</span>
</div>
<div class="talk-box">
<p>
<span class="reply">{{ item.comment }}</span>
</p>
</div>
<!-- 一级回复弹窗 -->
<div v-show="_inputShow(i)" class="my-reply">
<div class="reply-info">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="replytextarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength2 }}</span>
个字符
</div>
<el-button
size="mini"
type="primary"
round
@click="sendCommentReply(i)"
>
发表评论
</el-button>
</div>
</div>
<div class="reply-box">
<div v-for="(reply, j) in item.reply" :key="j" class="author-title">
<div class="author-info">
<span class="author-name">{{ reply.from }}</span>
<span class="author-time">{{ reply.time }}</span>
</div>
<div class="icon-btn">
<span
v-if="!reply.inputShow"
@click="showReplyInput2(i, reply.from, reply.id, j)"
>
<i class="iconfont el-icon-s-comment"></i>
回复
</span>
<span
v-else
@click="closeReplyInput2(i, reply.from, reply.id, j)"
>
<i class="iconfont el-icon-s-comment"></i>
收起回复
</span>
</div>
<div class="talk-box">
<p>
<span>回复 {{ reply.to }}:</span>
<span class="reply">{{ reply.comment }}</span>
</p>
</div>
<!-- 二级回复弹窗 -->
<div v-show="_inputShow2(i, j)" class="my-comment-reply">
<div class="reply-info">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="replytextarea"
maxlength="1000"
:autosize="{ minRows: 3, maxRows: 3 }"
autofocus
class="reply_input"
>
</el-input>
</div>
<div class="reply-btn-box">
<div class="limit">
还能输入
<span class="num">{{ 1000 - inputLength2 }}</span>
个字符
</div>
<el-button
size="mini"
type="primary"
round
@click="sendCommentReply(i)"
>
发表评论
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</el-drawer>
</template>
<script>
import request from "@/utils/request";
export default {
computed: {
inputLength () {
return this.textarea.length;
},
inputLength2 () {
return this.replytextarea.length;
},
},
props: {
direction: {
type: String,
default: "rtl"
}
},
data () {
return {
textarea: '',
replytextarea: '',
drawer: true,
closeInput: true,
index: '0',
index1: '0',
index2: '0',
replyComment: '',
myName: 'Lana Del Rey',
myId: 19870621,
to: '',
toId: -1,
comments: [
{
name: '小明',
id: 19870621,
comment: '我发布一张新电影我不是小三,大家快来看啊',
time: '2019年9月16日 18:43',
commentNum: 2,
like: 15,
inputShow: false,
reply: [
{
from: '小华',
fromId: 19891221,
to: '小明',
toId: 19870621,
comment: '我很喜欢你的新电影!!',
time: '2019年9月16日 18:43',
commentNum: 1,
like: 15,
inputShow: false
},
{
from: '小红',
fromId: 1123,
to: '小明',
toId: 19870621,
comment: '别忘记宣传我们的新电影啊',
time: '2019年9月16日 18:43',
commentNum: 0,
like: 5,
inputShow: false
}
]
},
{
name: '小张',
id: 19891221,
comment: '我发行了我的新电影Lover',
time: '2019年9月16日 18:43',
commentNum: 1,
like: 5,
inputShow: false,
reply: [
{
from: '小红',
fromId: 19870621,
to: '小张',
toId: 19891221,
comment: '新电影和speak now 一样棒!',
time: '2019年9月16日 18:43',
commentNum: 25,
like: 5,
inputShow: false
}
]
},
{
name: '小丽',
id: 20190830,
comment: 'ckwell on everywhere',
time: '2019年9月16日 18:43',
commentNum: 0,
like: 5,
inputShow: false,
reply: []
},
]
}
},
mounted () {
this.getList()
},
methods: {
/**
* 获取列表
*/
getList () {
let id = '334551';
let _query = {};
request({
url: `/api/plan/Comment/getListById/${id}`,
method: 'post',
data: _query
}).then((res) => {
console.log(res)
})
},
handleClose () {
},
focusInput () {
this.closeInput = false
},
hideReplyBtn () {
replyInput.style.padding = "10px"
replyInput.style.border = "none"
},
showReplyInput (i, name, id) {
this.closeInput = true
this.comments[this.index1].reply[this.index2].inputShow = false
this.comments[this.index].inputShow = false
this.index = i
this.comments[i].inputShow = true
this.to = name
this.toId = id
},
closeReplyInput (i, name, id) {
this.closeInput = false
this.comments[this.index].inputShow = false
},
showReplyInput2 (i, name, id, j) {
this.closeInput = true
this.comments[this.index].inputShow = false
this.comments[this.index1].reply[this.index2].inputShow = false
this.index1 = i
this.index2 = j
this.comments[i].reply[j].inputShow = true
this.to = name
this.toId = id
},
closeReplyInput2 (i, name, id, j) {
this.closeInput = false
this.comments[i].reply[j].inputShow = false
},
_inputShow (i) {
return this.comments[i].inputShow && this.closeInput
},
_inputShow2 (i, j) {
return this.comments[i].reply[j].inputShow && this.closeInput
},
sendComment () {
if (!this.textarea) {
this.$message({
showClose: true,
type: 'warning',
message: '评论不能为空'
})
} else {
let a = {}
let timeNow = new Date().getTime();
let time = this.dateStr(timeNow);
a.name = this.myName
a.comment = this.textarea
a.time = time
a.commentNum = 0
a.like = 0
this.comments.push(a)
this.replyComment = ''
this.textarea = '';
}
},
sendCommentReply (i) {
if (!this.replytextarea) {
this.$message({
showClose: true,
type: 'warning',
message: '评论不能为空'
})
} else {
let a = {}
let timeNow = new Date().getTime();
let time = this.dateStr(timeNow);
a.from = this.myName
a.to = this.to
a.comment = this.replytextarea
a.time = time
a.commentNum = 0
a.like = 0
this.comments[i].reply.push(a)
this.replytextarea = ''
}
},
dateStr (date) {
//获取js 时间戳
var time = new Date().getTime();
//去掉 js 时间戳后三位,与php 时间戳保持一致
time = parseInt((time - date) / 1000);
//存储转换值
var s;
if (time < 60 * 10) {//十分钟内
return '刚刚';
} else if ((time < 60 * 60) && (time >= 60 * 10)) {
//超过十分钟少于1小时
s = Math.floor(time / 60);
return s + "分钟前";
} else if ((time < 60 * 60 * 24) && (time >= 60 * 60)) {
//超过1小时少于24小时
s = Math.floor(time / 60 / 60);
return s + "小时前";
} else if ((time < 60 * 60 * 24 * 30) && (time >= 60 * 60 * 24)) {
//超过1天少于30天内
s = Math.floor(time / 60 / 60 / 24);
return s + "天前";
} else {
//超过30天ddd
var date = new Date(parseInt(date));
return date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
}
}
}
}
</script>
<style lang="scss" scoped>
>>> .conmment_drawer {
.el-drawer__header {
margin-bottom: 0px;
padding: 10px 16px;
border-bottom: 1px solid rgba(178, 186, 194, 0.3);
}
}
.conmment_box {
.my-reply {
padding: 10px;
background-color: rgba(245, 246, 247, 0.8);
margin: 10px 16px;
border-radius: 8px;
.reply-info {
display: inline-block;
width: 100%;
>>> .reply_input {
.el-textarea__inner {
background: rgba(245, 246, 247, 0.8);
border: none;
padding: 0px 6px;
}
}
}
.reply-btn-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 6px;
margin-top: 10px;
.limit {
font-size: 12px;
color: #999aaa;
.num {
color: #222226;
}
}
}
}
.my-comment-reply {
padding: 10px;
background-color: #ffff;
margin-top: 8px;
border-radius: 8px;
.reply-info {
display: inline-block;
width: 100%;
>>> .reply_input {
.el-textarea__inner {
background: #ffff;
border: none;
padding: 0px 6px;
}
}
}
.reply-btn-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 6px;
margin-top: 10px;
.limit {
font-size: 12px;
color: #999aaa;
.num {
color: #222226;
}
}
}
}
.author-title:not(:last-child) {
border-bottom: 1px solid rgba(178, 186, 194, 0.3);
}
.author-title {
padding: 10px 16px;
.author-info {
display: inline-block;
width: 60%;
line-height: 20px;
> span {
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.author-name {
color: #000;
font-size: 16px;
font-weight: bold;
}
.author-time {
margin-left: 6px;
font-size: 12px;
color: #aaa4a4;
}
}
.icon-btn {
width: 30%;
padding: 0 !important ;
float: right;
text-align: right;
font-size: 12px;
color: #999aaa;
> span {
cursor: pointer;
}
.iconfont {
font-size: 14px;
}
}
.talk-box {
margin-top: 8px;
font-size: 14px;
> p {
margin: 0;
color: #222226;
}
.reply {
font-size: 14px;
color: #000;
}
}
.reply-box {
margin: 10px 0 0 30px;
background-color: #efefef;
border-radius: 4px;
}
}
}
</style>