You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shop-pc/components/BsCommentInfo.vue

408 lines
10 KiB

2 years ago
<!--
* @Author: ch
* @Date: 2022-06-24 11:43:04
* @LastEditors: ch
* @LastEditTime: 2022-07-01 18:13:33
2 years ago
* @Description: file content
-->
<template>
<div class="comment-info">
<div class="side-user" v-if="source == 'detail'">
2 years ago
<el-avatar :size="55" :src="commentDetail.userAvatar" />
<p>{{commentDetail.userName}}</p>
</div>
2 years ago
<div class="side-product" v-else>
<img :src="commentDetail.productPicture"/>
<p>{{commentDetail.productName}}</p>
<span>{{commentDetail.skuName}}</span>
</div>
2 years ago
<main>
<BsCommentSubmit v-if="!commentDetail.id" :commentDetail="commentDetail" @submit="handleSubmit"
@editStatusChange="editStatusChange"/>
2 years ago
<template v-else>
<div class="top">
<el-rate :value="commentDetail.commentScore" disabled/>
2 years ago
<span class="time">{{FormatDate(commentDetail.createTime, 'yyyy-mm-dd hh:ii')}}</span>
2 years ago
</div>
<p class="sku" v-if="commentDetail.skuName">{{commentDetail.skuName}}</p>
2 years ago
<div class="ctx">{{commentDetail.commentContent}}</div>
<!-- 图片预览 -->
<UiImgs v-if="imgs.length" :list="imgs" class="imgs" />
<!-- 追评 -->
<UiButton class="follow-btn" type="yellow_line" radius="4px"
v-if="isCanFollowComment && !showFollowForm" @click="showFollowForm = true">发起追评</UiButton>
2 years ago
<BsCommentSubmit v-if="showFollowForm && !followComment" :type="COMMENT.TYPE.FOLLOW_COMMENT"
:commentDetail="commentDetail" @submit="handleSubmitFollow" @editStatusChange="editStatusChange"/>
2 years ago
<BsCommentFollowInfo v-if="followComment"
:followComment="followComment" :commentTime="commentDetail.commentTime"/>
<!-- 点赞评论Bar -->
<div class="operation">
<div>
<span class="operation--chat" @click="answerVisible = !answerVisible">
<template v-if="replyCount">{{replyCount}}</template>
2 years ago
</span>
<span class="operation--show" v-if="answerCommentList.length" @click="answerVisible = !answerVisible">
{{answerVisible ? '收起' : '展开'}}
</span>
</div>
<span class="operation--thumb" :class="{'operation--thumb__active':isLike}" @click="handleUseful">{{usefulCount || ''}}</span>
2 years ago
</div>
2 years ago
<!-- 评论内容 -->
<div class="answer" v-if="showAnswerBox">
<b class="answer--title">全部评论({{replyCount}})</b>
2 years ago
<ul>
<li class="answer--item" v-if="commentDetail.merchantComment">
<div class="answer--name"><b>{{commentDetail.merchantComment.userName}}</b><span>{{commentDetail.merchantComment.createTime}}</span></div>
<p class="answer--ctx">{{commentDetail.merchantComment.commentContent}}</p>
</li>
2 years ago
<template v-if="answerVisible">
<li class="answer--item" v-for="(item, idx) in answerCommentList" :key="idx">
<div class="answer--name">
<b>{{item.userName}} {{item.parentId !== commentDetail.id ? ` 回复 ${item.parentUserName}` : ''}}</b>
2 years ago
<span>{{FormatDate(item.createTime, 'yyyy-mm-dd hh:ii')}}</span>
2 years ago
</div>
<p class="answer--ctx">{{item.commentContent}}</p>
<span class="answer--answer" @click="handleAnswer(item)"></span>
</li>
</template>
2 years ago
</ul>
<div v-if="answerVisible" class="answer--form">
2 years ago
<input v-model="answerContent" class="answer--input" maxlength="500"
2 years ago
@keydown="handleClearAnswer" :placeholder="answerPlaceholder"/>
<UiButton :disabled="!answerContent.trim()" @click="handleSubmitAnswer"
2 years ago
radius="4px" class="answer--btn" type="red_panel">发表</UiButton>
</div>
2 years ago
</div>
2 years ago
</template>
2 years ago
</main>
</div>
</template>
<script>
import BsCommentFollowInfo from './BsCommentFollowInfo.vue';
import {ApiPostComment, ApiPutCommentUseful} from '@/plugins/api/comment';
2 years ago
import {Debounce, FormatDate } from '@/plugins/utils';
2 years ago
import UiImgs from './UiImgs.vue';
import UiButton from './UiButton.vue';
import BsCommentSubmit from './BsCommentSubmit.vue';
2 years ago
import {COMMENT} from '@/constants'
2 years ago
export default {
components: { BsCommentFollowInfo, UiImgs, UiButton, BsCommentSubmit },
props:{
// 来源 comment从我的订单来是需要操作评价detail游客从商品中来只要显示评价详情
source:{
2 years ago
type : String,
default : 'comment'
},
// 是否默认打开追评,只有在无追评时有用
isFollowForm : {
type : Boolean,
default : false,
require : true
2 years ago
},
commentDetail : {
type : Object,
default : () => ({})
}
},
data(){
return {
2 years ago
COMMENT,
answerCommentList : this.commentDetail.answerCommentList || [],
2 years ago
answerVisible : false,
answerContent : '',
answer : null,
isLike : this.commentDetail.isLike,
usefulCount : this.commentDetail.usefulCount,
replyCount : this.commentDetail.replyCount,
showFollowForm : this.isFollowForm,
2 years ago
followComment : this.commentDetail.followComment || null
2 years ago
}
},
computed:{
showAnswerBox(){
return (this.commentDetail.merchantComment || this.answerVisible) ? true : false
},
answerPlaceholder (){
return this.answer ? `回复:${this.answer.userName}` : '说点什么吧?'
},
imgs (){
let imgs = this.commentDetail.pictureUrl;
return imgs ? imgs.split(',') : [];
2 years ago
},
/**
* 是否需要显示追评按钮
* 如果是在订单里进来的且没有追评则显示
2 years ago
*/
isCanFollowComment(){
let status = (!this.followComment && this.source === 'comment')
2 years ago
return status;
2 years ago
}
},
watch:{
commentDetail:{
handler(){
this.followComment = this.commentDetail.followComment;
this.replyCount = this.commentDetail.replyCount || 0;
this.answerCommentList = this.commentDetail.answerCommentList || [];
this.isLike = this.commentDetail.isLike;
this.usefulCount = this.commentDetail.usefulCount;
},
deep : true
2 years ago
}
},
mounted(){
this.answerCommentList = this.commentDetail.answerCommentList || [];
},
methods : {
2 years ago
FormatDate,
2 years ago
/**
* 评价成功后抛出事件方便父组件做数据处理
*/
handleSubmit(result){
this.$emit('submit', result)
},
/**
* 追评提交成功抛出事件方便父组件做数据处理
*/
handleSubmitFollow(result){
this.followComment = result;
},
2 years ago
handleAnswer (item){
this.answer = item;
},
2 years ago
/**
* 有回复用户时取消回复对象
* 输入框没有内容后再按一次退格删除回复对象直接回复评价
*/
2 years ago
handleClearAnswer(e){
if(e.code === 'Backspace' && !this.answerContent && this.answer){
this.answer = null;
}
},
2 years ago
/**
* 评论回复请求成功往列表添加一条记录
*/
async handleSubmitAnswer(){
2 years ago
let data = {
commentContent : this.answerContent,
commentType : 3,
originId : this.commentDetail.id,
parentId : this.answer ? this.answer.id : this.commentDetail.id
}
const {error, result} = await ApiPostComment(data);
if(error){
this.$message.error(error.message);
return false
}
this.answerCommentList.unshift({
2 years ago
...result,
userName : this.$store.state.userInfo.nickname,
2 years ago
parentUserName: this.answer ? this.answer.userName : ''
2 years ago
});
this.answerContent = '';
this.replyCount++;
2 years ago
this.$message.success('评论成功!');
},
2 years ago
/**
* 点击点赞做防抖处理
*/
2 years ago
handleUseful(){
this.isLike = !this.isLike
if(this.isLike){
this.usefulCount++;
}else{
this.usefulCount--;
}
if(!this.debounce){
this.debounce = Debounce(this.updateUseFul, 500);
}
this.debounce();
},
2 years ago
/**
* 更新点赞请求
*/
2 years ago
async updateUseFul(){
if(this.isLike === this.commentDetail.isLike){
return false
}
const {error, result} = await ApiPutCommentUseful({
commentId : this.commentDetail.id,
isLike : this.isLike
});
this.commentDetail.isLike = this.isLike;
},
/**
* 动态监听是否有输入内容的评价或追评
*/
editStatusChange(val){
this.$emit('editStatusChange', val)
2 years ago
}
}
}
</script>
<style lang="scss" scoped>
.comment-info{
display: flex;
border-top: 1px solid #f2f2f2;
padding: 35px 20px 50px 0;
main{
flex: 1;
}
}
2 years ago
.side-user{
2 years ago
width: 170px;
text-align: center;
2 years ago
p{
margin-top: 10px;
@include ellipses(2)
}
}
.side-product{
width: 230px;
padding: 0 45px;
text-align: left;
img{
width: 140px;
height: 140px;
object-fit: contain;
}
p{
margin-top: 10px;
@include ellipses(2);
}
span{
margin-top: 5px;
display: block;
color: #999;
font-size: 12px;
}
2 years ago
}
.top{
display: flex;
justify-content: space-between;
margin-bottom: 10px;
2 years ago
/deep/.el-rate__icon{
margin-right: 0;
font-size: 24px;
}
2 years ago
}
.time, .sku{
color: #999;
font-size: 12px;
}
.ctx{
word-break: break-all;
line-height: 24px;
margin-top: 8px;
}
.imgs{
margin-top: 10px;
}
2 years ago
.follow-btn{
margin-top:30px
}
2 years ago
.follow{
margin-top: 30px;
&--title{
color: #FF6A19;
font-weight: normal;
}
}
.operation{
color: #999;
display: flex;
justify-content: space-between;
margin-top: 30px;
&--show{
color: #3083FF;
margin-left: 28px;
cursor: pointer;
}
&--chat,&--thumb{
background: url('@/assets/img/comment/chat.png') no-repeat left center;
background-size: 16px;
padding-left: 24px;
cursor: pointer;
&__active,&:hover{
background-image: url('@/assets/img/comment/chat_active.png');
color: #FF6A19;
}
}
&--thumb{
background-image: url('@/assets/img/comment/thumb.png');
&__active,&:hover{
background-image: url('@/assets/img/comment/thumb_active.png');
}
}
}
.answer{
background: #F8F8F8;
margin-top: 14px;
padding: 0 24px 20px;
&--item{
border-top: 1px solid #eee;
padding: 20px 0;
}
&--title{
height: 54px;
line-height: 54px;
font-weight: normal;
color: #666;
}
&--name{
color: #999;
font-size: 12px;
display: flex;
justify-content: space-between;
}
&--ctx{
color: #666;
margin: 15px 0 0;
word-break: break-all;
2 years ago
}
&--answer{
font-size: 12px;
color: #666;
text-align: right;
cursor: pointer;
display: block;
}
&--form{
display: flex;
}
&--input{
flex: 1;
height: 40px;
border: 1px solid #eee;
border-radius: 4px;
margin-right: 15px;
padding: 0 20px;
}
&--btn{
height: 40px;
2 years ago
font-size: 14px;
}
/deep/.ui-button__disabled{
background: #eee;
color: #999;
2 years ago
}
}
</style>