comment-list.vue 4.43 KB
<template>
  <div v-if="commentCount" class="comment-context">
    <p class="comment-title">共{{commentCount}}条评论</p>
    <div class="comment-list">
      <CommentItem
        v-for="comment in commentList"
        :key="comment.parentComment.id"
        :class="'comment-' + comment.parentComment.id"
        :parent-comment="comment.parentComment"
        :children-comments="comment.childrenComments"
        :column-type="columnType"
        :pos-id="0"
        :article-id="articleId"
        @on-reply="onReply">
      </CommentItem>
    </div>
    <div v-show="showMore" class="more-comment hover-opacity" @click="onFetch">
      <p class="loading-wrap" v-if="onFetching">
        <Loading :size="20"></Loading>
        &nbsp;&nbsp;加载中
      </p>
      <span v-else>展开{{page > 2 ? '更多' : moreCommentNum + '条'}}评论</span>
    </div>
  </div>
</template>

<script>
import {get, forEach, find} from 'lodash';
import {Loading} from 'cube-ui';
import {mapState as mapYohoState, mapActions as mapYohoActions, createNamespacedHelpers} from 'vuex';

const {mapActions} = createNamespacedHelpers('comment');

export default {
  name: 'ArticleDetailCommentList',
  props: {
    commentCount: [Number, String],
    articleId: [Number, String],
    columnType: {
      type: Number,
      default: 1001
    },
    share: Boolean
  },
  data() {
    return {
      commentList: [],
      page: 1,
      onFetching: false,
      showMore: false,
      moreCommentNum: 0
    };
  },
  mounted() {
    if (!this.yoho.context.userHeadIco) {
      this.$sdk.getUser().then(user => {
        if (user && user.uid) {
          this.fetchUserProfile();
        }
      });
    }

    this.init();
  },
  computed: {
    ...mapYohoState(['yoho']),
  },
  methods: {
    ...mapYohoActions(['fetchUserProfile']),
    ...mapActions(['fetchCommentList', 'fetchReplayList', 'postComment']),
    init() {
      this.commentList.length = 0;
      this.page = 1;
      this.showMore = false;

      if (this.commentCount) {
        this.onFetch();
      }
    },
    updateMoreCommentNum(list = []) {
      let moreCommentNum = this.commentCount;

      forEach(list, val => {
        val.childrenComments = val.childrenComments || [];
        moreCommentNum -= (val.childrenComments.length + 1);
      });
      this.moreCommentNum = moreCommentNum;
    },
    async onFetch() {
      if (!this.articleId || this.onFetching || (this.page > 1 && !this.showMore)) {
        return;
      }

      this.onFetching = true;

      const result = await this.fetchCommentList({
        destId: this.articleId,
        columnType: this.columnType,
        page: this.page,
        limit: 10
      });

      setTimeout(() => {
        if (result.code === 200) {
          this.showMore = result.data.totalPage > this.page;
          this.commentList = this.commentList.concat(result.data.commentInfos || []);

          if (this.page === 1) {
            this.updateMoreCommentNum(result.data.commentInfos);
          }

          this.page++;
        }

        this.onFetching = false;
      }, this.page > 1 ? 800 : 0);
    },
    onReply({comment}) {
      forEach(this.commentList, (val) => {
        if (val.parentComment && +val.parentComment.id === +comment.parentId) {
          val.childrenComments.unshift(Object.assign(comment, {
            id: comment.destId,
            destId: this.articleId,
            headIco: this.yoho.context.userHeadIco,
            userName: this.yoho.context.userName,
            parentUserName: get(find(val.childrenComments, {id: comment.parentId}), 'userName', '')
          }));
        }
      });
    },
    addComment(comment) {
      this.commentList.unshift({
        childrenComments: [],
        parentComment: Object.assign(comment, {
          id: comment.destId,
          destId: this.articleId,
          headIco: this.yoho.context.userHeadIco,
          userName: this.yoho.context.userName
        })
      });
    }
  },
  components: {
    Loading
  }
};
</script>

<style :lang="scss" scoped>
.comment-title {
  font-size: 28px;
  margin: 0 30px;
  color: #9b9b9b;
  line-height: 80px;
  border-top: 1px solid #f0f0f0;
}

.comment-list {
  padding: 20px 30px;
}

.more-comment {
  height: 100px;
  line-height: 1;
  font-size: 28px;
  color: #4a90e2;
  border-top: 1px solid #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;

  .loading-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #999;
  }
}
</style>