ufutx-love-h5-public/src/components/commentModule.vue
2026-04-02 18:12:53 +08:00

647 lines
18 KiB
Vue
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>
<div class="commentModule">
<!-- <van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
> -->
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="">
<div>
<div class="m_com">
<div class="font16 color3 bold" id="commentTitle" v-if="type != 'videoDetails'">
评论·{{ commentNumModeule }}
</div>
<div class="m_cou_box" :class="type == 'videoDetails' ? 'sel' : ''" v-if="emptyData">
<div class="m_cou" :id="'comment_' + item.id" v-for="(item, index) in list" :key="index">
<div class="m_user">
<van-image fit="cover" round v-if="item.pic" class="u_lstImg" :src="item.pic" alt="" />
<div class="m_user_name">
<div class="u_user_name font13 color6 f-fcc">
<div class="bold">{{ item.nickname }}</div>
<!-- <div v-if="userData.id == item.commented_id" class="u_user_own font10">作者</div> -->
</div>
<div class="u_user_time font11 color9">{{ item.created_at }}</div>
</div>
</div>
<div class="m_txt font15 color3" @click="clickReply(item)">{{ item.comment }}</div>
<div class="m_reply_pa">
<div class="m_reply" v-if="item.reply && item.reply.length > 0">
<template v-for="(replyItem, replyIndex) in item.reply">
<div class="m_reply_lst font13" v-if="replyIndex < 3 || item.wholeShow" :key="replyIndex">
<span class="u_repLst_name colorTheme font13">
<div>{{ replyItem.nickname }}</div>
<!-- <div v-if="userData.id == item.commented_id" class="u_reply_lst_own font10">
作者
</div> -->
<div></div>
</span>
<span class="u_repLst_txt color3">{{ replyItem.comment }}</span>
</div>
</template>
<div
class="m_whole f-fc font13 colorTheme"
v-if="item.reply && item.reply.length > 3 && !item.wholeShow"
@click.stop="wholeComment(index)"
>
<div>共{{ item.reply.length }}条回复</div>
<van-image
fit="cover"
class="u_you_icon"
src="https://image.fulllinkai.com/202111/04/8fb1bde2ef2bd5403ee3756ed1e5910a.png"
alt=""
/>
</div>
</div>
</div>
</div>
</div>
<div class="m_lack f-fcc f-fdc" v-else>
<van-image
class="u_lack_img"
fit="contain"
src="https://image.fulllinkai.com/202111/05/23cbdb149f1eb2bcb423aee104715448.png"
alt=""
/>
<div class="font16 color9">暂无评论</div>
</div>
<div class="m_com_bu">
<div class="u_com_bu f-fbc">
<div class="u_combu_inp font13 color9" @click="inpFocus">说点什么吧</div>
<div>
<a class="f-fcc f-fdc" href="#commentTitle">
<van-image
class="u_combu_icon"
fit="contain"
src="https://image.fulllinkai.com/202111/03/efdd9db7a71e1957f9178884701b15af.png"
alt=""
/>
<div class="fong10 color9">评论{{ commentNumModeule }}</div>
</a>
</div>
<div class="f-fcc f-fdc" @click="likeThrottle">
<van-image
class="u_combu_icon"
fit="contain"
v-if="likeShowModeule"
:show-loading="false"
src="https://image.fulllinkai.com/202111/04/0b74b1f0fce864a2b98b6be9499853a0.png"
alt=""
/>
<van-image
class="u_combu_icon"
fit="contain"
v-else
:show-loading="false"
src="https://image.fulllinkai.com/202111/03/f33908d11fb35037be590da6779c78f1.png"
alt=""
/>
<div class="fong10 color9">赞{{ likerNumModeule }}</div>
</div>
<div class="f-fcc f-fdc" @click="commentShare">
<van-image
class="u_combu_icon"
fit="contain"
src="https://image.fulllinkai.com/202111/03/1fe29f6a456ef4099a3f3c1eab962740.png"
alt=""
/>
<div class="fong10 color9">分享</div>
</div>
</div>
</div>
</div>
</div>
</div>
</van-list>
<!-- </van-pull-refresh> -->
<van-popup v-model="focusShow" position="bottom" :lock-scroll="true" :duration="0">
<div class="m_field">
<div class="f-ffs">
<div class="replyName font14" v-if="replyName != ''">
回复<span class="colorTheme">{{ replyName }}</span>
:
</div>
<van-field
class="u_combu_inp font13 color9"
type="textarea"
:border="false"
v-model="commentValue"
maxlength="300"
placeholder="说点什么吧"
ref="fieldPhone"
/>
</div>
<div class="m_sendOut">
<div
class="u_sendOut font14 bold f-fcc colorff bcTheme"
:class="commentValue != '' ? 'sel' : ''"
@click="sendOutComment"
>
发送
</div>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading, $toastText } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
commentUrl: {
type: String,
default: ''
},
publishCommentUrl: {
type: String,
default: ''
},
commentLikeUrl: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
commentNum: {
type: Number,
default: 0
},
likerNum: {
type: Number,
default: 0
},
likeShow: {
type: Boolean,
default: false
}
// list: {
// type: Array,
// default: () => {
// return []
// }
// }
},
data() {
return {
commentList: [],
focusShow: false,
commentValue: '',
reply_id: null,
replyName: '',
list: [],
commentNumModeule: 0,
likerNumModeule: 0,
likeShowModeule: false,
method: '',
userData: [],
page: 1,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
list(e) {
this.commentList = e
},
commentNum(e) {
console.log(e, '1111111111111111111117987979')
this.commentNumModeule = e
},
likerNum(e) {
console.log(e, '4365436434321321')
this.likerNumModeule = e
},
likeShow(e) {
console.log(e, '4365436434321321')
this.likeShowModeule = e
},
commentUrl(e) {
this.page = 1
this.getList()
}
},
methods: {
// getBusinessUser() {
// const vm = this
// const url = `s/h5/BusinessUser`
// service
// .get(url)
// .then(data => {
// vm.userData = data
// })
// .catch(error => {
// console.log(error)
// })
// },
// 评论点赞
commentLike() {
const vm = this
service
.get(vm.commentLikeUrl)
.then(data => {
if (data.code == 1) {
if (vm.likeShowModeule) {
vm.$emit('update:likerNum', (vm.likerNumModeule -= 1))
} else {
vm.$emit('update:likerNum', (vm.likerNumModeule += 1))
}
vm.$emit('update:likeShow', !vm.likeShowModeule)
vm.$emit('likeShowCallback', vm.likeShowModeule)
}
})
.catch(error => {
console.log(error)
})
},
likeThrottle() {
const vm = this
clearTimeout(this.method)
this.method = setTimeout(function() {
if (vm.likeShowModeule) {
vm.$emit('update:likerNum', (vm.likerNumModeule -= 1))
} else {
vm.$emit('update:likerNum', (vm.likerNumModeule += 1))
}
vm.$emit('update:likeShow', !vm.likeShowModeule)
vm.$emit('likeShowCallback', vm.likeShowModeule)
vm.commentLike()
}, 200)
},
// 评论列表
getList() {
const vm = this
// $toastLoading(vm.$i18n.t('loading_text'))
vm.$nextTick(() => {
service
.get(`${vm.commentUrl}?page=${vm.page}`)
.then(data => {
vm.commentNumModeule = vm.commentNum
vm.likerNumModeule = vm.likerNum
vm.likeShowModeule = vm.likeShow
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = formatDate(item.created_at, 1)
item.wholeShow = false
})
}
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
vm.showLoaded = true
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
// $toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
},
commentShare() {
this.$emit('clickShare')
},
inpFocus() {
this.replyName = ''
this.reply_id = ''
if (!localStorage.getItem('authorize_at')) {
this.authorization()
return
}
this.focusShow = true
this.$nextTick(() => {
console.log('11111')
this.$refs.fieldPhone.focus()
})
},
inpBlur() {
this.focusShow = false
},
// 发表评论
sendOutComment() {
const vm = this
if (this.commentValue == '') {
$toastText('说点什么吧')
return
}
vm.focusShow = false
var postData = {
content: vm.commentValue,
reply_id: vm.reply_id
}
service
.post(vm.publishCommentUrl, postData)
.then(data => {
if (data.code != 1) {
var commentData = data
if (vm.reply_id) {
vm.toComment(`comment_${vm.reply_id}`)
vm.forReply(vm.list, vm.reply_id, commentData)
} else {
vm.$nextTick(() => {
vm.emptyData = true
commentData.nickname = vm.userData.nickname
commentData.pic = vm.userData.avatar
commentData.created_at = formatDate(commentData.created_at, 1)
commentData.reply = []
console.log('commentData', commentData)
vm.list.unshift(commentData)
})
this.toComment('commentTitle')
}
vm.$emit('update:commentNum', (vm.commentNumModeule += 1))
vm.$emit('commentNumCallback', vm.commentNumModeule)
}
vm.commentValue = ''
})
.catch(error => {
console.log(error)
})
},
forReply(data, id, addData) {
const vm = this
data.forEach((item, index) => {
if (item.id == id) {
addData.nickname = vm.userData.nickname
item.reply.unshift(addData)
}
})
},
clickReply(item) {
this.replyName = item.nickname
this.reply_id = item.id
this.focusShow = true
this.$nextTick(() => {
this.$refs.fieldPhone.focus()
})
},
wholeComment(index) {
var listArr = this.list[index]
listArr.wholeShow = true
this.list.splice(index, 1, listArr)
},
toComment(id) {
document.querySelector(`#${id}`).scrollIntoView({
behavior: 'smooth', // 定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"
block: 'start', // 定义垂直方向的对齐, "start", "center", "end", 或 "nearest"之一。默认为 "start"
inline: 'nearest' // 定义水平方向的对齐, "start", "center", "end", 或 "nearest"之一。默认为 "nearest"
})
},
authorization() {
const vm = this
const urlPath = vm.$route.path.substr(1, vm.$route.path.length)
localStorage.removeItem('saas_token')
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, urlPath)
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
// this.getBusinessUser()
}
}
</script>
<style lang="scss" scoped>
.commentModule {
width: 100%;
// height: 100vh;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.m_com {
background: #ffffff;
.m_cou_box.sel {
padding-top: 0;
}
.m_cou_box {
padding-top: 22px;
.m_cou {
margin-bottom: 20px;
box-sizing: border-box;
.m_lstCt {
padding-right: 10px;
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_lstCt_ta {
padding-top: 10px;
}
}
.m_user {
display: flex;
align-items: stretch;
.u_lstImg {
width: 30px;
height: 30px;
}
.m_user_name {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 6px;
.u_user_name {
line-height: 13px;
}
.u_user_time {
line-height: 11px;
}
}
}
.m_txt {
padding: 8px 0 0 36px;
box-sizing: border-box;
}
.m_reply_pa {
padding-left: 36px;
box-sizing: border-box;
margin-top: 10px;
.m_reply {
padding: 10px 10px 4px;
box-sizing: border-box;
background: #fbfbfb;
border-radius: 8px;
.m_reply_lst {
padding-bottom: 6px;
.u_repLst_txt,
.u_repLst_name {
line-height: 18px;
div {
display: inline-block;
vertical-align: bottom;
}
.u_reply_lst_own {
padding: 4px 6px 3px;
background: #f2f3ff;
border-radius: 9px;
color: #707ffa;
line-height: 10px;
margin-left: 2px;
}
}
}
}
}
}
}
.m_com_bu {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 999;
.u_com_bu {
padding: 9px 15px;
box-sizing: border-box;
width: 100%;
background: #ffffff;
border-top: #f5f5f5 solid 1px;
}
.u_com_bu.sel {
border-radius: 16px 16px 0px 0px;
}
.u_combu_inp {
width: 200px;
height: 36px;
background: #f5f5f5;
border-radius: 18px;
padding: 0 15px;
box-sizing: border-box;
line-height: 36px;
}
.u_combu_icon {
width: 20px;
height: 20px;
}
}
}
.u_user_own {
padding: 4px 6px 3px;
background: #f2f3ff;
border-radius: 9px;
color: #707ffa;
line-height: 10px;
margin-left: 2px;
}
.van-popup {
top: auto !important;
border-radius: 16px 16px 0px 0px !important;
overflow: hidden;
}
.m_whole {
line-height: 13px;
padding-bottom: 4px;
box-sizing: border-box;
.u_you_icon {
width: 6px;
height: 8px;
margin-left: 4px;
}
}
.m_field {
.replyName {
padding: 15px 0 15px 15px;
box-sizing: border-box;
word-break: keep-all;
white-space: nowrap;
}
.u_combu_inp {
width: 100%;
height: 60px;
border-radius: 6px;
margin-right: 10px;
line-height: 20px;
padding: 15px;
box-sizing: border-box;
background: #ffffff;
flex: 1;
}
.m_sendOut {
display: flex;
justify-content: flex-end;
padding: 0 15px 10px;
box-sizing: border-box;
.u_sendOut {
margin-top: 6px;
width: 60px;
height: 28px;
border-radius: 16px;
opacity: 0.6;
line-height: 13px;
}
.u_sendOut.sel {
opacity: 1;
}
}
}
.m_lack {
padding: 50px 0;
box-sizing: border-box;
.u_lack_img {
width: 196px;
height: 122px;
}
}
</style>
<style lang="scss">
.van-field--min-height .van-field__control {
min-height: 36px;
}
</style>