两层评论组件

<template>
  <div class="comment">
    <div
      class="comment-body"
      v-for="(item, index) in comments"
      :key="item.id + '' + index"
    >
      <!-- 一级评论 -->
      <div class="first-comment">
        <el-avatar :size="40" :src="item.avatar"></el-avatar>
        <div class="content">
          <!-- 一级评论用户昵称 -->
          <h3>{{ item.nickname }}</h3>
          <!-- 一级评论发布时间 -->
          <span>{{ item.date }}</span>
          <!-- 一级评论评论内容 -->
          <p>{{ item.content }}</p>
          <!-- 一级评论评论点赞 -->
          <div class="comment-right" @click="isShowSecReply(item.id)">
            <i class="el-icon-chat-dot-round"></i>
            <span>回复</span>
          </div>
          <!-- 回复一级评论 -->
          <div class="reply-comment" v-show="isShowSec === item.id">
            <el-input
              :placeholder="placeholderText"
              class="input"
              v-model.trim="replyContext"
              :maxlength="contentLength"
            ></el-input>
            <el-button
              type="info"
              size="mini"
              class="reply-button"
              @click="addComment(item.id, item.nickname)"
              >回复</el-button
            >
          </div>
          <!-- 次级评论 -->
          <div
            class="second-comment"
            v-for="(reply, index) in item.replyInfo"
            :key="reply.id + '' + index"
          >
            <!-- 次级评论头像,该用户没有头像则显示默认头像 -->
            <el-avatar :size="40" :src="reply.avatar"></el-avatar>
            <div class="content">
              <!-- 次级评论用户昵称 -->
              <h3>{{ reply.nickname }}</h3>
              <!-- 次级评论评论时间 -->
              <span>{{ reply.date }}</span>
              <span class="to_reply">{{ reply.nickname }}</span>
              回复
              <span class="to_reply">{{ reply.replyName }}</span
              >:
              <p>{{ reply.content }}</p>
              <!-- 次级评论评论点赞 -->
              <div class="comment-right" @click="isShowSecReply(reply.id)">
                <i class="el-icon-chat-dot-round"></i>
                <span>回复</span>
              </div>
              <div class="reply-comment" v-show="isShowSec === reply.id">
                <el-input
                  :placeholder="placeholderText"
                  class="input"
                  v-model.trim="replyContext"
                  :maxlength="contentLength"
                ></el-input>
                <el-button
                  type="info"
                  size="mini"
                  class="reply-button"
                  @click="addComment(item.id, reply.nickname)"
                  >回复</el-button
                >
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 暂无评论的空状态 -->
    <el-empty
      :description="emptyText"
      v-show="comments.length === 0"
    ></el-empty>
  </div>
</template>
<script>
import { mapState } from "vuex";
export default {
  props: {
    articleId: {
      //评论所属文章 id
      type: String,
    },
    emptyText: {
      // 评论为空的时候显示的文字
      type: String,
      default: "期待你的评论!",
    },
    buttonText: {
      // 按钮文字
      type: String,
      default: "评论",
    },
    contentLength: {
      // 评论长度
      type: Number,
      default: 150,
    },
    placeholderText: {
      // 默认显示文字
      type: String,
      default: "请输入最多150字的评论...",
    },
  },
  inject: ["refresh"],
  data() {
    return {
      nowTime: "", // 当前时间
      comment: {},
      replyContext: "", //一级评论回复
      isShowSec: "", //是否显示次级回复框
      isClickId: "", //记录点击回复的评论id
      firstIdx: 1,
      secIdx: 1,
      avatar:
        "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
    };
  },
  mounted() {
    this.$store.dispatch("topicById", this.articleId);
    this.$store.dispatch("getUserInfo");
  },
  computed: {
    sum() {
      let s = 0;
      let a = this.$store.state.topic.topicmain.comments.length;
      for (let i = 0; i < a; i++) {
        s += this.$store.state.topic.topicmain.comments[i].replyInfo.length;
      }
      s = s + a;
      return s;
    },
    artmain() {
      return this.$store.state.topic.topicmain;
    },
    comments() {
      return this.$store.state.topic.topicmain.comments;
    },
    ...mapState({
      userInfo: ({ home }) => home.userInfo,
    }),
  },
  methods: {
    //获取时间
    formatDateTime(date) {
      var y = date.getFullYear();
      var m = date.getMonth() + 1;
      m = m < 10 ? "0" + m : m;
      var d = date.getDate();
      d = d < 10 ? "0" + d : d;
      var h = date.getHours();
      h = h < 10 ? "0" + h : h;
      var minute = date.getMinutes();
      minute = minute < 10 ? "0" + minute : minute;
      var second = date.getSeconds();
      second = second < 10 ? "0" + second : second;
      return y + "-" + m + "-" + d + " " + h + ":" + minute + ":" + second;
    },
    isShowSecReply(id) {
      if (id) {
        this.isShowSec = id;
        if (this.isClickId === this.isShowSec) {
          this.isShowSec = "";
        } else {
          this.isShowSec = id;
        }
        this.isClickId = this.isShowSec;
      } else {
        this.isShowSec = this.isClickId = "";
      }
    },
    async addComment(id, replyName) {
      //本地更新评论列表
      if (replyName) {
        // 添加二级评论
        if (!this.replyContext) {
          this.$message.warning("评论或留言不能为空哦!");
          return;
        }
        this.nowTime = new Date();
        this.comment.date = this.formatDateTime(this.nowTime);
        this.comment.id = "sec" + `${this.sum}`;
        this.comment.replyid = id;
        this.comment.artid = this.artmain._id;
        this.comment.content = this.replyContext;
        this.comment.replyName = replyName;
        this.comment.username = this.userInfo.username;
        this.comment.nickname = this.userInfo.nickname;
        this.comment.avatar = this.userInfo.avatar;
        const { comment } = this;
        await this.$store.dispatch("PostFirTopicComment", comment);
        this.comment.date = "";
        this.replyContext = "";
        this.$store.dispatch("topicById", this.articleId);
      }
    },
  },
};
</script>

<style lang="less" scoped>
.comment {
  min-height: 26vh;
  border-radius: 5px;
  margin-top: 2px;
  overflow: hidden;
  .active {
    color: rgb(202, 4, 4);
  }
  .comment-header {
    position: relative;
    height: 50px;
    padding: 10px 5px;
    display: flex;
    align-items: center;

    .input {
      margin-left: 10px;
      margin-right: 20px;
      flex: 1;
      /deep/.el-input__inner:focus {
        border-color: #dcdfe6;
      }
    }
  }

  .comment-body {
    min-height: 70px;
    padding: 10px 20px;
    font-size: 14px;
    .first-comment {
      display: flex;
      .input {
        /deep/.el-input__inner:focus {
          border-color: #dcdfe6;
        }
      }
      i {
        margin-right: 5px;
        margin-left: 1vw;
        cursor: pointer;

        &:nth-child(3) {
          color: rgb(202, 4, 4);
        }
      }

      .content {
        margin-left: 10px;
        position: relative;
        flex: 1;

        & > span {
          font-size: 12px;
          color: rgb(130, 129, 129);
        }

        .comment-right {
          position: absolute;
          right: 0;
          top: 0;
        }

        .reply-comment {
          height: 60px;
          display: flex;
          align-items: center;

          .reply-button {
            margin-left: 20px;
            height: 35px;
          }
        }

        .second-comment {
          display: flex;
          padding: 10px 0 10px 5px;
          border-radius: 20px;
          background: #ffffff;
          .to_reply {
            color: rgb(126, 127, 128);
          }
        }
      }
    }
  }
}
</style>

一层的评论为了方便写方法放到了调用的组件当中去写

主要是展示二级评论的逻辑思路~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值