comment-item.vue 6.72 KB
<template>
	<div class="comment-item">
		<ImageFormat :lazy="false" :src="parentComment.headIco" :width="80" :height="80" class="comment-user-avatar"
                 @click.native="toUserPage"></ImageFormat>
		<div class="comment">
			<div class="comment-nav">
				<div class="comment-nav-left">
					<p class="comment-user-name" @click="toUserPage">
            <span class="name">{{parentComment.userName || '&nbsp;'}}</span>
          </p>
					<p v-if="parentComment.createTime" class="comment-time">{{parentComment.createTime | time}}</p>
          <p v-else class="comment-time">刚刚</p>
				</div>
        <div class="comment-nav-right">
          <WidgetFav
            class="comment-fav"
            :comment-id="parentComment.id"
            :num="praiseTotal"
            :share="share"
            :option="favOption"></WidgetFav>
        </div>
			</div>

			<CommentPlaceholderActionSheet
        class="comment-cont"
        :dest-id="parentComment.id"
        :root-id="parentComment.id"
        :pos-id="posId"
        :article-id="articleId"
        :add-type="1"
        :user="parentComment.userName"
        :column-type="columnType"
        :share="share"
        :authorUid="authorUid"
        :commentUid="parentComment.uid"
        commentType="parent"
        @on-comment="onReply"
        @remove-comment="onRemoveComment"
      >
				{{parentComment.content}}
			</CommentPlaceholderActionSheet>
			<div class="reply-main" v-if="replayShowList.length">
				<CommentPlaceholderActionSheet
          tag="p"
          class="reply-item"
          v-for="(reply, replyIndex) in replayShowList"
          :key="replyIndex"
          :dest-id="reply.id"
          :root-id="parentComment.id"
          :add-type="1"
          :user="reply.userName"
          :column-type="columnType"
          :share="share"
          :authorUid="authorUid"
          :commentUid="reply.uid"
          :article-id="articleId"
          commentType="child"
          @on-comment="onReplyChildren"
          @remove-comment="onRemoveComment"
        >
					<span class="reply-user">{{reply.userName}}</span>
					<template v-if="reply.parentUserName">
						<span>回复</span><em class="reply-to-user">@{{reply.parentUserName}}</em>
					</template>:
          <span>{{reply.content}}</span>
				</CommentPlaceholderActionSheet>
				<p class="reply-more" v-if="moreReplyNum > 0" @click="onShowMore">
          {{replyMoreText}}
          <i class="iconfont icon-right" v-if="!isShowAllReply"></i>
        </p>
			</div>
		</div>
	</div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex';
import CommentPlaceholderActionSheet from './comment-placeholder-actionsheet';

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

export default {
  name: 'CommentItem',
  components: { CommentPlaceholderActionSheet },
  props: {
    parentComment: Object,
    childrenComments: Array,
    columnType: {
      type: Number,
      default: 1001
    },
    share: Boolean,
    posId: Number,
    articleId: Number,
    authorUid: Number
  },
  data() {
    return {
      isShowAllReply: false,
      limitNum: 2,
    };
  },
  computed: {
    favOption() {
      return {
        selected: this.parentComment.isPraise === 'Y'
      };
    },
    replayShowList() {
      if (this.childrenComments.length <= this.limitNum) {
        return this.childrenComments;
      }
      if (this.isShowAllReply) {
        return this.childrenComments;
      }
      return this.childrenComments.slice(0, this.limitNum);
    },
    moreReplyNum() {
      return this.childrenComments.length - this.limitNum;
    },
    replyMoreText() {
      return this.isShowAllReply ? '收起' : `查看${this.moreReplyNum}条回复`;
    },
    praiseTotal() {
      let praiseTotal = this.parentComment.praiseTotal || 0;

      if (praiseTotal > 999) {
        return Math.floor(praiseTotal / 1000) + 'k';
      }

      return praiseTotal;
    }
  },
  methods: {
    ...mapActions(['postComment']),
    onShowMore() {
      this.isShowAllReply = !this.isShowAllReply;
    },
    onReplyChildren(info) {
      this.$emit('on-reply', info);
    },
    async onReply(info) {
      this.$emit('on-reply', info);
    },
    toUserPage() {
      this.$emit('on-close');

      setTimeout(() => {
        this.$router.push({
          name: 'author',
          params: {
            type: this.parentComment.userType || 1,
            id: this.parentComment.uid
          }
        });
      }, 300);
    },
    onRemoveComment({ commentId, commentType, articleId }) {
      let subCount = 0;

      if (commentType === 'parent') {
        subCount = this.childrenComments.length + 1;
      } else {
        subCount = 1;
      }
      this.$emit('remove-comment', { commentId, commentType, articleId, subCount});
    }
  }
};
</script>

<style scoped lang="scss">
.comment-item {
  display: flex;
  margin-bottom: 40px;

  &:last-child {
    margin-bottom: 0;
  }

  .comment-user-avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
  }

  .comment {
    width: 600px;
    margin-left: 10px;
  }

  .comment-nav {
    padding-left: 10px;
    box-sizing: border-box;
    display: flex;
    justify-content: space-between;
  }

  .comment-nav-left {
    flex: 1;

    .comment-user-name {
      font-size: 0;
      color: #222;
      width: 100%;
      height: auto;
      margin-top: 6px;

      .name {
        font-size: 28px;
        line-height: 40px;
        max-width: 300px;
        display: inline-block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-weight: bold;
      }
    }

    .comment-time {
      font-size: 26px;
      color: #b0b0b0;
      line-height: 36px;
      transform: scale(0.8);
      transform-origin: left;
    }
  }

  .comment-nav-right {
    width: 90px;
    display: flex;
    align-items: center;

    .comment-fav {
      position: absolute;
    }
  }

  .comment-cont {
    font-size: 28px;
    color: #444;
    line-height: 40px;
    margin: 12px 0 20px;
    padding-left: 10px;
    box-sizing: border-box;
  }

  .reply-main {
    background: #f0f0f0;
    padding: 20px;
    box-sizing: border-box;
    font-size: 28px;
    color: #444;
    line-height: 34px;
    margin-top: 20px;

    .reply-item {
      margin-bottom: 20px;

      &:last-child {
        margin-bottom: 0;
      }

      > * {
        display: inline-block;
        vertical-align: text-top;
      }

      .reply-user,
      .reply-to-user {
        max-width: 230px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .reply-to-user {
        color: #4a90e2;
        font-style: normal;
      }

      .reply-user {
        font-weight: 500;
      }
    }

    .reply-more {
      text-align: right;
      color: #4a90e2;
    }
  }
}
</style>