index.vue 7.42 KB
<template>
  <van-popup v-model:show="show" :close-on-click-overlay="false" round position="bottom" :style="{ height: '70%' }">
    <div style="position: relative;">
      <div class="van-hairline--bottom"
        style="position: fixed; width: 100%; background-color: white; border-radius: 10px; z-index: 999;">
        <van-row>
          <van-col span="4" @click="onReload">
            <div style="padding: 1rem; text-align: center;">
              <!-- <van-icon :name="icon_x" size="1.25rem" /> -->
            </div>
          </van-col>
          <van-col span="16" style="color: #222222; text-align: center; line-height: 3;">
            <span>{{ listTotal }}条回复</span>
          </van-col>
          <van-col span="4" @click="closeBtn">
            <div style="padding: 1rem;">
              <van-icon :name="icon_y" size="1.25rem" />
            </div>
          </van-col>
        </van-row>
      </div>
      <div style="height: 4rem;"></div>
      <van-list v-model:loading="loading" :finished="finished" :finished-text="finishedTextStatus ? '没有更多了' : ''" @load="onLoad"
        :immediate-check="false">
        <template v-for="(item, key) in replyList" :key="key">
          <div class="comment-wrapper">
            <van-row style="font-size: 0.9rem;">
              <van-col span="4">
                <van-image v-if="item.avatar" round width="3rem" height="3rem" :src="item.avatar" />
                <van-image v-else round width="3rem" height="3rem" :src="icon_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>
          </div>
        </template>
      </van-list>
      <van-empty v-if="emptyStatus"
        class="custom-image"
        :image="no_image"
        description="暂无回复"
      />
    </div>
    <comment-box :showPopup="showCommentBoxPopup" :type="commentType" :replayUser="replayUser"
      @on-submit="submitCommentBox" @on-close="closeCommentBox"></comment-box>
  </van-popup>

  <!-- 写评论时,如果没有实名认证提示弹框 -->
  <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 CommentBox from '@/components/CommentBox/index.vue'
import NoticeOverlay from '@/components/NoticeOverlay/index.vue'
import no_image from '@images/que-shuju@2x.png'

import icon_x from '@images/x.png'
import icon_y from '@images/y.png'
import icon_avatar from '@images/que-touxiang@2x.png'

import { useRoute, useRouter } from 'vue-router'

import axios from '@/utils/axios';
import _ from 'lodash'
import { Toast } from 'vant';

import { ref, reactive, onMounted, watch } from 'vue'
// 获取是否实名认证
import { useDefaultPerf } from '@/composables';

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

const { userInfo } = useDefaultPerf($route.query.book_id);

const props = defineProps({
  showPopup: Boolean,
  data: Object
})

const emit = defineEmits(['on-close']);

/******** 留言框相关操作 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 (userInfo.value.can_upload) {
    showCommentBoxPopup.value = true;
    commentType.value = type;
    replayUser.value = v.name;
    commentId.value = props.data.id;
  } else {
    closeBtn();
    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 => {
      showCommentBoxPopup.value = false;
      if (res.data.code === 1) {
        Toast.success('发布成功')
        onReload()
      } else {
        console.warn(res);
        if (!res.data.show) return false;
        Toast({
          icon: 'close',
          message: res.data.msg
        });
      }
    })
    .catch(err => {
      console.error(err);
    })
}

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

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

const show = ref(false);
const listTotal = ref(0)
const replyList = ref([])
const loading = ref(false)
const finished = ref(false)
const limit = ref(10)
const offset = ref(0)

// 因为不能让空图标提前出来的写法
const finishedTextStatus = ref(false);
const emptyStatus = ref(false);

const onLoad = () => {
  // 异步更新数据
  axios.get('/srv/?a=reply_list', {
    params: {
      comment_id: props.data.id,
      limit: limit.value,
      offset: offset.value
    }
  })
    .then(res => {
      if (res.data.code === 1) {
        listTotal.value = res.data.data.total;
        replyList.value = _.concat(replyList.value, res.data.data.replylist);
        replyList.value = _.uniqBy(replyList.value, 'id');
        offset.value = replyList.value.length;
        loading.value = false;
        // 数据全部加载完成
        if (!res.data.data.replylist.length) {
          // 加载状态结束
          finished.value = true;
        }
        if (!replyList.value.length) {
          finishedTextStatus.value = false;
          emptyStatus.value = true;
        }
      } else {
        console.warn(res);
        if (!res.data.show) return false;
        Toast({
          icon: 'close',
          message: res.data.msg
        });
      }
    })
    .catch(err => {
      console.error(err);
    })
}
const onReload = () => {
  replyList.value = [];
  offset.value = 0;
  onLoad();
}
// const onClose = () => {
//   show.value = false;
// }

// 监听弹出框
watch(() => props.showPopup, (v) => {
  show.value = v;
  onReload()
});


const closeBtn = () => {
  emit('on-close', { comment_id: props.data.id, total: listTotal.value })
  show.value = false;
}
</script>

<script>
export default {
  data() {
    return {
    }
  },
  mounted() {
  },
  watch: {
  },
  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;
    }
  }
}
</style>