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

398 lines
9.8 KiB

2 years ago
<!--
* @Author: ch
* @Date: 2022-06-24 11:43:04
* @LastEditors: ch
2 years ago
* @LastEditTime: 2022-06-28 21:34:32
2 years ago
* @Description: file content
-->
<template>
<div class="comment-info">
2 years ago
<div class="side-user" v-if="type == '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>
2 years ago
<BsCommentSubmit v-if="!commentDetail.id" :commentDetail="commentDetail" @submit="handleSubmit"/>
<template v-else>
<div class="top">
<el-rate :value="commentDetail.commentScore" disabled/>
<span class="time">{{commentDetail.createTime}}</span>
</div>
<p class="sku">已购买{{commentDetail.skuName}}</p>
<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="handleShowFollowForm">发起追评</UiButton>
<BsCommentSubmit v-if="showFollowForm && !followComment" :type="COMMENT.TYPE.FOLLOW_COMMENT"
:commentDetail="commentDetail" @submit="handleSubmitFollow"/>
<BsCommentFollowInfo v-if="followComment"
:followComment="followComment" :commentTime="commentDetail.commentTime"/>
<!-- 点赞评论Bar -->
<div class="operation">
<div>
<span class="operation--chat" @click="answerVisible = !answerVisible">
<template v-if="answerCommentList.length">{{answerCount}}</template>
</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">全部评论({{answerCount}})</b>
<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>
<span>{{item.createTime}}</span>
</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">
<input v-model="answerContent" class="answer--input"
@keydown="handleClearAnswer" :placeholder="answerPlaceholder"/>
<UiButton :disabled="!answerContent" @click="handleSubmitAnswer"
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';
import {Debounce } from '@/plugins/utils';
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:{
type:{
type : String,
2 years ago
default : 'detail' // comment默认显示评价状态follow默认追评状态 detail 查看状态
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 : false,
2 years ago
usefulCount : 0,
showFollowForm : this.type === 'follow' ? true : false,
followComment : this.commentDetail.followComment || null
2 years ago
}
},
computed:{
showAnswerBox(){
return (this.commentDetail.merchantComment || this.answerVisible) ? true : false
},
answerCount(){
let count = this.answerCommentList.length;
if(this.commentDetail.merchantComment){
count += 1;
}
return count
},
answerPlaceholder (){
return this.answer ? `回复:${this.answer.userName}` : '说点什么吧?'
},
imgs (){
let imgs = this.commentDetail.pictureUrl;
return imgs ? imgs.split(',') : [];
2 years ago
},
/**
* 是否需要显示追评按钮
* 如果是在订单里进来的则只要判断没有追评则显示
* 如果在商品中看则需要这条评论是不是当前登录用户评论的如果是则也可以追评
*/
isCanFollowComment(){
let status = false;
const userId = this.$store.state.userInfo.id;
if(!this.followComment && (this.type !== 'detail' || this.commentDetail.userId === userId)){
status = true;
}
return status;
2 years ago
}
},
watch:{
commentDetail(){
2 years ago
this.followComment = this.commentDetail.followComment;
2 years ago
this.answerCommentList = this.commentDetail.answerCommentList || [];
this.isLike = this.commentDetail.isLike;
this.usefulCount = this.commentDetail.usefulCount;
}
},
mounted(){
this.answerCommentList = this.commentDetail.answerCommentList || [];
},
methods : {
2 years ago
/**
* 评价成功后抛出事件方便父组件做数据处理
*/
handleSubmit(result){
this.$emit('submit', result)
},
/**
* 点击追评
*/
handleShowFollowForm(){
if(this.type !== 'detail'){
this.showFollowForm = true;
}else{
this.$router.push(`/account/comment?commentId=${this.commentDetail.id}`);
}
},
/**
* 追评提交成功抛出事件方便父组件做数据处理
*/
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.push({
...result,
userName : this.$store.state.userInfo.nickname,
parentName: this.answer ? this.answer.userName : ''
});
this.answerContent = '';
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;
}
}
}
</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;
}
.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;
}
&--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;
}
}
</style>