Files
MER-2.2_2601/mer_uniapp/pages/discover/discover_video/appVideo/comment.nvue
2026-03-08 20:07:52 +08:00

795 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<view class="main_content">
<text class="title">评论 {{noteDetail.replyNum?noteDetail.replyNum:0}}</text>
<image @click="close" class="closeBnt" :src="urlDomain +'crmebimage/presets/close.png'" mode=""></image>
<!-- 评论列表 -->
<view class="main">
<scroll-view class="scroll-view" scroll-y="true" @scroll="followScroll" @scrolltolower="onTouchmove">
<view class="container">
<view v-if="list.length > 0" id="reply">
<view class="common_list" v-for="(item, index) in list" :key="index">
<view class="commen_one">
<image :src="item.avatar || urlDomain+'crmebimage/presets/morenT.png'"
class="image"></image>
</view>
<view class="info_count">
<view class="info">
<view class="message" @click.stop="toReply(item,index)">
<text v-if="item.nickname" class="name">{{item.nickname}}</text>
<view class="desc acea-row row-middle">
<rich-text :nodes="nodes(item)" class="text"></rich-text>
</view>
<view class="timeBox">
<text
class="time">{{item.createTime?getDateDiff(item.createTime):''}}</text>
<text @click.stop="onDel(item, index)" v-if="item.uid == uid"
class="del">删除</text>
</view>
</view>
<view v-if="item.auditStatus!==0" class="like" @click.stop="starComment(item)">
<image v-if="item.isLike" class="dianzan"
:src="`${urlDomain}crmebimage/presets/zan1.png`"></image>
<image v-else class="dianzan"
:src="`${urlDomain}crmebimage/presets/zan.png`"></image>
<text class="like-text">{{item.countStart?item.countStart:0}}</text>
</view>
</view>
<view v-if="item.replyList && item.replyList.length > 0" class="reply_count">
<view v-for="(itemn,indexn) in item.replyList" :key="indexn" class="reply_list">
<view class="item">
<view class="item_count" @click.stop="toReply(itemn,index)">
<image class="image"
:src="itemn.avatar || '/static/images/morenT.png'">
</image>
<text v-if="itemn.nickname" class="name_two">{{itemn.nickname}}
</text>
<view class="desc acea-row row-middle">
<view class="centent">
<rich-text :nodes="nodes(itemn)"
class="reply_text"></rich-text>
</view>
</view>
<view class="timeBox">
<text
class="time_two">{{ getDateDiff(itemn.createTime) }}</text>
<text @click.stop="onDel(itemn, index)" v-if="itemn.uid == uid"
class="del">删除</text>
</view>
</view>
<view v-if="itemn.auditStatus!==0" class="like_two"
@click.stop="starComment(itemn)">
<image v-if="itemn.isLike" class="dianzan"
:src="`${urlDomain}crmebimage/presets/zan1.png`"></image>
<image v-else class="dianzan"
:src="`${urlDomain}crmebimage/presets/zan.png`"></image>
<text class="like-text">{{itemn.countStart ? itemn.countStart : 0}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="end">
<text class="text">到底了~~</text>
</view>
</view>
<view :hidden="!loading" class="acea-row row-center-wrapper loadingicon">
<text class="iconfont icon-jiazai loading"></text>
</view>
<view v-if="list.length == 0 && !loading" class="empty-box">
<image :src="urlDomain+'crmebimage/presets/noEvaluate.png'"></image>
<text class="txt">暂无评论,快去抢沙发吧~</text>
</view>
</view>
</scroll-view>
</view>
<!-- 评论框 -->
<view @click="parentPinglun" class="release_bar">
<image class="image" :src="userInfo.avatar || urlDomain+'crmebimage/presets/morenT.png'"></image>
<text class="lang">{{placeholder}}</text>
</view>
<!-- 真实评论弹窗 -->
<uni-popup type="bottom" ref="comment" @touchmove.stop.prevent="moveHandle">
<view class="release_bar no-border" style="padding: 20rpx 24rpx;">
<image class="image" :src="userInfo.avatar || urlDomain+'crmebimage/presets/morenT.png'"></image>
<textarea :placeholder="placeholder" placeholder-style="color: #999999; font-size: 12px;"
v-model="content" :cursor-spacing="cursorSpacing" confirm-hold
:style="' height: 20px; margin-bottom: 20upx; font-size: 15px; color: #000000; margin-top: 20upx; margin-left: 30upx;'"
:show-confirm-bar="false" class="input_count" :focus="autoFocus"
:adjust-position="adjustPosition" auto-height />
<text class="send" @click.stop="submitComment">发送</text>
</view>
</uni-popup>
</view>
</view>
</template>
<script>
import Cache from '@/utils/cache'
import {
mapGetters
} from "vuex";
import {
discoverNoteLike
} from '@/libs/follow.js';
import {
replyListApi,
noteReplyAddApi,
noteReplyLikeApi,
replyDeleteApi
} from '@/api/discover.js';
import {
toLogin
} from '@/libs/login.js';
import {
Debounce
} from '@/utils/validate.js'
let app = getApp();
export default {
computed: mapGetters(['isLogin', 'userInfo', 'uid']),
watch: {
noteId: {
handler: function(newV, oldV) {
if (newV) {
this.getList();
}
},
deep: true
},
noteDetails: {
handler: function(newV, oldV) {
if (newV) {
this.noteDetail = newV
}
},
deep: true
}
},
props: {
/* 哪里引用detail详情中引用 */
fromTo: {
type: String,
default: ''
},
/* 内容id */
noteId: {
type: Number,
default: 0
},
/* 内容详情 */
noteDetails: {
type: Object,
default: function() {
return {};
},
},
},
data() {
return {
nodes(data) {
return [{
children: [{
type: 'text',
attrs: {
class: 'audit-status',
style: 'color:#FE960F;margin-right: 8rpx;border: 1px solid #FE960F;'
},
text: data.auditStatus === 0 ? '审核中- ' : ''
},
{
type: 'text',
attrs: {
class: 'reply_user',
style: 'color:#4A8AC9'
},
text: data.reviewUserNickname ? `回复@${data.reviewUserNickname}` : ''
}, {
type: 'text',
attrs: {
class: 'reply_text'
},
text: data.content
}
]
}]
},
urlDomain: Cache.get("imgHost"),
cursorSpacing: 20, //键盘距离输入框的距离
adjustPosition: true, //默认
autoFocus: false,
noteDetail: this.noteDetails,
theme: app.globalData.theme,
content: '',
isShowComment: false, //真实评论弹窗显示隐藏
placeholder: "快来说点儿什么吧...",
loadTitle: '加载更多',
where: {
page: 1,
limit: 10,
noteId: ''
},
list: [],
loading: false,
replyId: 0,
focus: false,
index: 0,
isChild: false,
bottomVal: 0
}
},
mounted() {
this.getList();
},
methods: {
getDateDiff(data) {
let datas = data;
// 传进来的data必须是日期格式不能是时间戳
//var str = data;
//将字符串转换成时间格式
var timePublish = new Date(data);
var timeNow = new Date();
var minute = 1000 * 60;
var hour = minute * 60;
var day = hour * 24;
var month = day * 30;
var result = "2";
var diffValue = timeNow - timePublish;
var diffMonth = diffValue / month;
var diffWeek = diffValue / (7 * day);
var diffDay = diffValue / day;
var diffHour = diffValue / hour;
var diffMinute = diffValue / minute;
if (diffValue < 0) {} else if (diffMonth > 3) {
result = timePublish.getFullYear() + "-";
result += timePublish.getMonth() + "-";
result += timePublish.getDate();
} else if (diffMonth > 1) {
result = parseInt(diffMonth) + "月前";
} else if (diffWeek > 1) {
result = parseInt(diffWeek) + "周前";
} else if (diffDay > 1) {
result = parseInt(diffDay) + "天前";
} else if (diffHour > 1) {
result = parseInt(diffHour) + "小时前";
} else if (diffMinute > 1) {
result = parseInt(diffMinute) + "分钟前";
} else {
result = "刚刚";
}
return result;
},
//删除自己的评论
onDel(item, i) {
uni.showModal({
title: '提示',
content: '确认删除评论吗?',
cancelColor: '#f55850',
success: res => {
if (res.confirm) {
this.onSub(item, i);
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
onSub(item, i) {
uni.showLoading({
title: '删除中...'
});
replyDeleteApi(item.id).then(res => {
this.list.splice(i, 1)
uni.showToast({
title: '删除成功',
icon: 'none'
})
this.noteDetail.replyNum--
this.$emit('getReplyNum', this.noteDetail.replyNum)
}).catch(err => {
uni.showToast({
title: err,
icon: 'none'
})
});
},
/*点赞评论*/
starComment: Debounce(function(item) {
let that = this;
noteReplyLikeApi(item.id).then(res => {
this.$set(item, 'isLike', !item.isLike);
if (!item.isLike) {
item.countStart--;
item.countStart = item.countStart == 0 ? 0 : item.countStart
} else {
item.countStart++;
}
}).catch(err => {
uni.showToast({
title: err,
icon: 'none'
})
});
}),
// 模拟触底刷新
onTouchmove(e) {
if (this.loadend || this.loading) return;
this.getList();
},
/**
*
*/
followScroll() {
uni.$emit('scroll');
},
close() {
this.$emit('close');
},
//点赞
likeToggle: Debounce(function(item) {
if (this.isLogin) {
discoverNoteLike(item.id).then(() => {
this.$set(item, 'userIsLike', !item.userIsLike);
if (!item.userIsLike) {
item.likeNum--;
item.likeNum = item.likeNum == 0 ? 0 : item.likeNum
} else {
item.likeNum++;
}
});
} else {
toLogin();
}
}),
//回复
toReply(item, index) {
this.placeholder = '回复:' + item.nickname
this.replyId = item.id
this.isChild = true
this.index = index
this.focus = true
this.content = ""
},
clickTextarea() {
this.isopen = false;
if (uni.getSystemInfoSync().platform == 'ios') {
this.autoFocus = false;
setTimeout(() => {
this.autoFocus = true;
}, 200)
}
},
linechange(event) {
this.lineheight = event.detail.height
},
//真实评论弹窗 关闭
closeComment() {
this.autoFocus = false;
this.placeholder = "快来说点儿什么吧...";
this.content = ""
this.isChild = false
this.focus = false
this.bottomVal = 0
this.isShowComment = false;
},
oninput() {
if (Number(this.noteDetail.replyStatus) > 1) {
return this.$util.Tips({
title: '该内容禁止评论'
});
} else {
this.isShowComment = true
}
},
parentPinglun() {
if (!this.isLogin) {
toLogin();
} else {
if (Number(this.noteDetail.replyStatus) > 1) {
return this.$util.Tips({
title: '该内容禁止评论'
});
} else {
this.$refs.comment.open('bottom')
this.autoFocus = false;
setTimeout(() => {
this.autoFocus = true;
this.isShowComment = true
}, 50)
}
}
},
//评论发送提交
submitComment() {
if (!this.content) return;
noteReplyAddApi({
content: this.content,
noteId: this.noteId,
replyId: this.replyId
}).then(res => {
this.$refs.comment.close();
this.isShowComment = false;
this.autoFocus = false;
if (this.isChild) {
if (this.list[this.index]['replyList']) {
this.list[this.index]['replyList'].push(res.data)
} else {
this.list[this.index]['replyList'] = [res.data]
}
} else {
this.list.unshift(res.data)
}
if (res.data.auditStatus == 1) this.noteDetail.replyNum++
this.$emit('getReplyNum', this.noteDetail.replyNum)
this.closeComment();
this.$util.Tips({
title: res.message
});
}).catch(err => {
this.isShowComment = false
uni.showToast({
title: err,
icon: 'none'
})
});
},
getList() {
let that = this;
if (that.loading || that.loaded) return;
that.loading = true;
that.where.noteId = this.noteId;
replyListApi(that.where).then(res => {
that.loading = false;
that.all = res.data.all;
that.loaded = res.data.list.length < that.where.limit;
that.loadTitle = that.loadend ? '没有了' : '加载更多';
that.list.push.apply(that.list, res.data.list);
that.where.page = that.where.page + 1;
},
error => {
that.loading = false;
that.$util.Tips({
title: error.msg
})
}
);
},
}
}
</script>
<style lang="scss" scoped>
.timeBox {
flex-direction: row;
.time {
color: #BBBBBB;
font-size: 22rpx;
margin-top: 16rpx;
}
.del {
font-size: 24rpx;
color: #4A8AC9;
margin-top: 15rpx;
display: inline-block;
}
}
.audit-status {
font-size: 18rpx !important;
border-radius: 2px;
opacity: 1;
border: 1px solid #FE960F;
color: #FE960F;
height: 32rpx;
padding: 0 4rpx;
line-height: 32rpx;
margin-right: 8rpx;
}
.mt10 {
margin-top: 10rpx;
}
.empty-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-bottom: 60rpx;
image {
width: 414rpx;
height: 305rpx;
}
.txt,
text {
font-size: 26rpx;
color: #999;
}
}
.lang {
width: 616rpx !important;
height: 32px;
line-height: 32px;
margin-left: 30rpx;
padding-left: 30rpx;
background-color: #eee;
border-radius: 50px;
display: flex;
flex-direction: row;
font-size: 13px;
color: #999;
}
.main_content {
padding: 12px 15rpx;
border-bottom: 2px solid #F5F5F5;
position: relative;
bottom: 0;
}
.header {
width: 750rpx;
position: relative;
text-align: center;
}
.title {
text-align: center;
flex-direction: row;
color: #282828;
font-size: 36rpx;
font-weight: bold;
}
.closeBnt {
position: absolute;
right: 30rpx;
top: 30rpx;
width: 15px;
height: 15px;
}
.scroll-view {
height: 600px;
padding-bottom: 240px;
}
.main {
margin-top: 30px;
padding-bottom: 10px;
// position: sticky;
.common_list {
position: relative;
padding-left: 50px;
margin-bottom: 15px;
.commen_one {
position: absolute;
top: 0;
left: 0;
.image {
width: 74rpx;
height: 74rpx;
border-radius: 100%;
}
}
.info {
position: relative;
//padding-right: 90rpx;
width: 630rpx;
}
.name,
.name_two {
color: #999999;
font-size: 26rpx;
}
.text {
color: #282828;
font-size: 28rpx;
}
.desc_two,
.content {
width: 400rpx;
}
.desc {
width: 600rpx;
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
color: #282828;
font-size: 28rpx;
margin-top: 10rpx;
}
.desc_two {
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
color: #282828;
font-size: 28rpx;
margin-top: 10rpx;
}
.reply_text {
font-size: 26rpx;
color: #282828;
}
.desc_two {
.reply_user {
font-size: 24rpx;
color: #4A8AC9;
margin: 0 6rpx;
}
}
.time,
.time_two {
color: #BBBBBB;
font-size: 22rpx;
margin-top: 15rpx;
margin-right: 20rpx;
}
.like,
.like_two {
display: flex;
align-items: center;
text-align: center;
position: absolute;
top: 0;
right: 0;
width: 75rpx;
.like-text {
color: #999999;
font-size: 13px;
margin-top: 2px;
}
.dianzan {
width: 13px;
height: 13px;
}
}
.reply_list {
margin-top: 20rpx;
.item {
//padding-right: 140rpx;
position: relative;
}
.item_count {
position: relative;
padding-left: 56rpx;
.image {
width: 36rpx;
height: 36rpx;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
}
}
}
}
.end {
margin: 50rpx 0;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
.text {
color: #999999;
font-size: 22rpx;
position: relative;
.before,
.after {
display: flex;
width: 22rpx;
height: 1rpx;
background: #999999;
position: absolute;
top: 18rpx;
opacity: .5;
}
.before {
left: -30rpx;
}
.after {
right: -30rpx;
}
}
}
}
.release_bar {
bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
bottom: 0;
position: fixed;
width: 750rpx;
left: 0;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 15rpx 30rpx;
border-top: 1rpx solid #F5F5F5;
flex-direction: row;
.image {
width: 54rpx;
height: 54rpx;
border-radius: 100%;
}
.input_count {
width: 480rpx;
background: #F7F7F7;
border-radius: 31rpx;
padding: 12rpx 30rpx;
line-height: 32px;
}
.send {
font-size: 26rpx;
color: #ffffff;
padding: 12rpx 30rpx;
background: #E93323;
border-radius: 30rpx;
text-align: center;
}
}
.empty {
display: flex;
margin: 130rpx 0 150rpx;
text-align: center;
align-items: center;
// flex-direction: row;
.image {
display: flex;
width: 414rpx;
height: 305rpx;
}
.text {
display: flex;
color: #999999;
font-size: 26rpx;
}
}
</style>