videoDetailComment.vue 8.05 KB
<template>
  <div class="">
    <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad" :immediate-check="false">
      <template v-for="(item, key) in commentList" :key="key">
        <div class="comment-wrapper">
          <van-row style="font-size: 0.9rem;">
            <van-col span="4">
              <van-image round width="3rem" height="3rem" :src="item.avatar" />
            </van-col>
            <van-col span="14">
              <p>{{ item.name }}</p>
              <p>{{ item.kg_name }}</p>
            </van-col>
            <van-col span="6" style="text-align: right;">
              <p @click="setComment(item, 'reply')" style="color: #333333;">回复</p>
              <p>{{ item.comment_time }}</p>
            </van-col>
          </van-row>
          <van-row>
            <van-col offset="4">
              <span style="color: #222222;">{{ item.note }}</span>
            </van-col>
          </van-row>
          <van-row>
            <van-col offset="4" span="20">
              <div v-if="item.total" class="reply-wrapper">
                  <template v-for="(reply, index) in item.reply_list" :key="index">
                    <p v-if="reply.reply_to"><span>{{ reply.name }}</span>&nbsp;回复&nbsp;<span>@{{ reply.reply_to }}:</span><span class="content">{{ reply.note }}</span></p>
                    <p v-else><span>{{ reply.name }}:</span><span class="content">{{ reply.note }}</span></p>
                  </template>
                  <p v-if="item.total >= reply_limit" @click="getReplyList(item)">共{{ item.total }}条回复 ></p>
                </div>
            </van-col>
          </van-row>
        </div>
      </template>
    </van-list>
    <div style="height: 5rem;"></div>
    <div class="reply-btn" @click="setComment('', 'comment')">
      <div class="text">写下你友善的留言</div>
    </div>
  </div>
  <comment-list :showPopup="showCommentListPopup" :data="commentData" @on-close="closeCommentList"></comment-list>
  <comment-box :showPopup="showCommentBoxPopup" :type="commentType" :replayUser="replayUser" @on-submit="submitCommentBox" @on-close="closeCommentBox"></comment-box>

  <!-- 写评论时,如果没有实名认证提示弹框 -->
  <notice-overlay :show="showNotice" text="前往认证" @on-submit="onSubmit" @on-close="onClose">
    <div style="color: #333333;">
      <p>您还没有实名认证</p>
      <p>请前往个人中心进行实名认证</p>
    </div>
  </notice-overlay>
</template>

<script setup>
import { mainStore } from '@/store'

import CommentList from '@/components/CommentList/index.vue'
import CommentBox from '@/components/CommentBox/index.vue'
import NoticeOverlay from '@/components/NoticeOverlay/index.vue'

import { ref, reactive, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import axios from '@/utils/axios';
import $ from 'jquery'
import _ from 'lodash'
import { Toast } from 'vant';

// 获取是否实名认证
import { idCard } from '@/composables/useValidIdCard.js'
const validIdCard = idCard();

const $route = useRoute();
const $router = useRouter();


/******** 留言列表相关操作 START *******/
const loading = ref(false);
const finished = ref(false);
const limit = ref(5)
const offset = ref(0)
const reply_limit = ref(3)
const commentList = ref([])

const onLoad = () => {
  // 异步更新数据
  axios.get('/srv/?a=comment_list',{
    params: {
      prod_id: $route.query.prod_id,
      limit: limit.value,
      offset: offset.value,
      reply_limit: reply_limit.value
    }
  })
  .then(res => {
    if (res.data.code === 1) {
      commentList.value = _.concat(commentList.value, res.data.data);
      offset.value = commentList.value.length;
      loading.value = false;
      // 数据全部加载完成
      if (!res.data.data.length) {
        // 加载状态结束
        finished.value = true;
      }
    } else {
      console.warn(res);
      Toast({
        icon: 'close',
        message: res.data.msg
      });
    }
  })
  .catch(err => {
    console.error(err); 
  })
};

const onReload = () => {
  commentList.value = [];
  offset.value = 0;
  onLoad();
  const store = mainStore()
  // 刷新主路由上面的留言数量
  axios.get('/srv/?a=prod_info', {
    params: {
      prod_id: $route.query.prod_id
    }
  })
  .then(res => {
    if (res.data.code === 1) {
      store.changeCommentNum(res.data.data.comment_num);
    } else {
      console.warn(res);
      Toast({
        icon: 'close',
        message: res.data.msg
      });
    }
  })
  .catch(err => {
    console.error(err); 
  })
}
/******** 留言框列表相关操作 END *******/

const showNotice = ref(false)
const onClose = () => { // 关闭提示框回调
  showNotice.value = false;
}
// 跳转个人中心
const onSubmit = () => {
  $router.push({
    path: '/me/index'
  });
}


/******** 留言框相关操作 START *******/
// 回复评论控件
const showCommentBoxPopup = ref(false);
const commentType = ref('comment'); // 类型 comment 为评论/类型 reply 为回复

/**
 * 回复/评论 功能
 * @param {*} v 单行评论数据
 * @param {*} type 类型 comment 为评论/类型 reply 为回复
 */
const commentId = ref('')
const replayUser = ref('')
const setComment = (v, type) => {
  if (validIdCard.can_use.value) {
    showCommentBoxPopup.value = true;
    commentType.value = type;
    replayUser.value = v.name;
    commentId.value = v.id;
  } else {
    showNotice.value = true;
  }
}

/**
 * 提交留言回调
 * @param {*} note 留言内容
 */
const submitCommentBox = (note) => {
  let url = '';
  let data = {}
  // 判断是留言还是回复 动态调整接口名称
  if (commentType.value === 'comment') {
    url = 'add_comment';
    data = {
      prod_id: $route.query.prod_id,
      note
    }
  } else {
    url = 'add_reply';
    data = {
      comment_id: commentId.value,
      note
    }
  }
  axios.post(`/srv/?a=${url}`, data)
  .then(res => {
    if (res.data.code === 1) {
      showCommentBoxPopup.value = false;
      Toast.success('发布成功')
      // 刷新列表
      if (commentType.value === 'comment') {
        // 留言可以刷新列表
        onReload();
      } else {
        // 初始化列表数据,会使得列表滚到最上面
        // 处理方法只能是插入相应的一条数据,这样就需要后台新增完成后,返回完整数据
        _.each(commentList.value, comment => {
          if (comment.id === commentId.value) {
            comment.reply_list.push(res.data.data)
            comment.total = comment.total + 1
          }
        })
      }
      // 不能刷新,只能插入
    } else {
      console.warn(res);
      Toast({
        icon: 'close',
        message: res.data.msg
      });
    }
  })
  .catch(err => {
    console.error(err); 
  })
}

const closeCommentBox = (v) => { // 关闭留言框
  showCommentBoxPopup.value = v;
}
/******** 留言框相关操作 START *******/


/******** 查看回复列表操作 START *******/
const showCommentListPopup = ref(false);
const commentData = ref({})
// 查看更多回复
const getReplyList = (v) => {
  showCommentListPopup.value = true;
  commentData.value = v;
}
const closeCommentList = (v) => { // 查看更多回复
  showCommentListPopup.value = v;
}
/******** 查看回复列表操作 END *******/

onMounted(() => {
  onLoad();
})
</script>

<script>
import mixin from 'common/mixin';

export default {
  mixins: [mixin.init],
  data() {
    return {

    }
  },
  mounted() {
  },
  methods: {

  }
}
</script>

<style lang="less" scoped>
.comment-wrapper {
  color: #999999;
  padding: 1rem;
  line-height: 1.75;

  .reply-wrapper {
    background: #F7F7F7;
    border-radius: 10px;
    padding: 0.5rem;
    margin-top: 0.5rem;
    color: #0B3A72;

    .content {
      color: #222222;
    }
  }
}

.reply-btn {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: white;

  .text {
    text-align: center;
    padding: 0.5rem;
    margin: 0.8rem;
    font-size: 0.85rem;
    border-radius: 24px;
    border: 1px solid F7F7F7;
    color: #B7B7B7;
    background-color: #FFFFFF;
    box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.06);
  }
}
</style>