评论的组件封装


主评论的人在数组第一层级,回复的评论都在children里面

【{
name:"张三"
idGenerator: 475403892531269
info_Conmment":"今天天气晴朗😀"
children:[
{
mainIdGenerator:475388950118469
name:"张三"
name1:"李四"
idGenerator:475403933356101
info_Conmment:"哈哈哈哈"
}
]
}】

<template>
  <div
    style="margin: 20px; margin-top: 40px"
    v-if="route.query.isComment == 'true' || props.isComment"
  >
    <p style="font-size: 18px; color: #1d2129">
      <el-divider
        style="width: 3px; height: 18px; background: #2c68ff; margin-left: 0px"
        direction="vertical"
      />{{$t('view.course.comment')}}:
    </p>
    <el-form :model="commentForm">
      <!-- maxlength="1000"
          show-word-limit -->
      <el-form-item>
        <el-input
          v-model="commentForm.commentText"
          :rows="3"
          type="textarea"
          maxlength="150"
          @input="handleInput(commentForm.commentText)"
          :placeholder="$t('view.course.add_comment')"
        >
        </el-input>
        <div class="commentOperate">
          <div class="numberLimit">
           还能输入<span class="remainingCount">{{ remainingCount }}</span
            >个字符
          </div>
          <div class="comment-operate-item">
            <VueEmoji @chooseEmoji="chooseEmoji" />
            <el-button class="commentBtn" type="primary" @click="userCommont"
              >评论
            </el-button>
          </div>
        </div>
      </el-form-item>
    </el-form>
    <!-- 评论列表 -->
    <div v-if="comments.length > 0">
      <div
        v-for="(comment, index) in comments"
        :key="comment.idGenerator"
        style="
          margin-top: 12px;
          border-bottom: 1px #f4f3f3;
          display: flex;
          align-items: flex-start;
        "
      >
        <el-avatar
          :size="40"
          style="margin-right: 12px; margin-left: 10px"
          :src="comment.avatarUrl || profile"
        ></el-avatar>
        <div style="flex: 1">
          <span style="font-size: 16px">{{ comment.name }}</span>
          <p>
            {{ comment.info_Conmment }}
          </p>
          <p style="font-size: 12px; color: #86909c; margin-top: 5px">
            {{ comment.createdTime }}
            <el-button
              link
              style="font-size: 12px; color: #86909c"
              @click="
                toggleLikeComment(comment.idGenerator, comment.isThumbsUp)
              "
            >
              <!-- <svg-icon
                  :icon-class="getCommentIconClass(comment.idGenerator)"
                  :src="getCommentIconSrc(comment.idGenerator)"
                  class="svg-icon"
                  style="
                    margin-left: 20px;
                    margin-right: 3px;
                    transform: translateY(-1px);
                  "
                  :class="{ liked: isCommentLiked(comment.idGenerator) }"
                /> -->
              <svg-icon
                :icon-class="getCommentzanIconClass(comment.isThumbsUp)"
                :src="getCommentzanIconSrc(comment.isThumbsUp)"
                class="svg-icon"
                style="
                  margin-left: 20px;
                  margin-right: 3px;
                  transform: translateY(-1px);
                "
              />
              <span v-if="comment.thumbsUpCount > 0">{{
                comment.thumbsUpCount
              }}</span
              >{{ $t('view.course.like') }}
            </el-button>
            <el-button
              link
              style="font-size: 12px; color: #86909c"
              @click="toggleReply(comment.idGenerator)"
            >
              <el-icon style="margin-right: 3px; font-size: 16px">
                <ChatLineSquare />
              </el-icon>
              {{ $t('view.course.reply') }}
            </el-button>
            <el-dropdown trigger="click">
              <template #default>
                <span>
                  <el-button link>
                    <el-icon
                      style="
                        margin-left: 12px;
                        color: #4e5969;
                        font-size: 12px;
                        transform: translateY(4px);
                      "
                    >
                      <MoreFilled />
                    </el-icon>
                  </el-button>
                </span>
              </template>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="deleteComment(comment.idGenerator)"
                    >删除评论</el-dropdown-item
                  >
                  <el-dropdown-item>
                    <el-dropdown trigger="hover" placement="right-start">
                      <span
                        >禁言<el-icon
                          style="transform: translateY(3px); margin-left: 20px"
                        >
                          <ArrowRight /> </el-icon
                      ></span>
                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item @click="banUserHour(comment.id)"
                            >一个小时</el-dropdown-item
                          >
                          <el-dropdown-item @click="banUserDay(comment.id)"
                            >一天</el-dropdown-item
                          >
                          <el-dropdown-item @click="banUserWeek(comment.id)"
                            >一周</el-dropdown-item
                          >
                          <el-dropdown-item @click="banUserForever(comment.id)"
                            >永久</el-dropdown-item
                          >
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </p>
          <!-- <el-input
              v-if="showReplyInput[comment.id]"
              v-model="replyTexts[comment.id]"
              type="textarea"
              placeholder="说点什么吧"
              rows="4"
              maxlength="150"
              show-word-limit
              style="margin-top: 10px"
            /> -->
          <el-form v-if="showReplyInput[comment.idGenerator]">
            <el-form-item class="childrenForm">
              <el-input
                v-model="replyTexts[comment.idGenerator]"
                :rows="3"
                type="textarea"
                maxlength="150"
                @input="
                  handleInput(
                    replyTexts[comment.idGenerator],
                    comment.idGenerator
                  )
                "
                 :placeholder="$t('view.course.add_comment')"
              >
              </el-input>
              <div class="commentOperate">
                <div class="numberLimit">
                  还能输入<span class="remainingCount">{{
                    remainCount[comment.idGenerator]
                  }}</span
                  >个字符
                </div>
                <div class="comment-operate-item">
                  <VueEmoji
                    @chooseEmoji="chooseEmoji"
                    :replyComment="replyTexts[comment.idGenerator]"
                    :keyId="comment.idGenerator"
                  />
                  <el-button
                    class="commentBtn"
                    type="primary"
                    @click="userChildrenCommont(comment)"
                    >评论
                  </el-button>
                </div>
              </div>
            </el-form-item>
          </el-form>
          <!-- 子评论列表 -->
          <div
            v-for="(reply, replyIndex) in comment.children"
            :key="reply.id"
            style="margin-top: 12px"
          >
            <div
              style="
                margin-top: 12px;
                border-bottom: 1px #f4f3f3;
                display: flex;
                align-items: flex-start;
              "
            >
              <el-avatar
                :size="30"
                :src="reply.avatarUrl || profile"
                style="margin-right: 12px"
              ></el-avatar>
              <div style="flex: 1">
                <span>{{ reply.name || "0713" }}</span>
                <span style="margin-left: 10px; color: #86909c">{{ $t('view.course.reply') }}</span>
                <span style="margin-left: 10px; margin-right: 10px"
                  >{{ reply.name1 }}:{{ reply.info_Conmment }}</span
                >
                <p style="font-size: 12px; color: #86909c; margin-top: 5px">
                  {{ reply.createdTime }}
                  <el-button
                    link
                    style="font-size: 12px; color: #86909c"
                    @click="
                      toggleLikeComment(reply.idGenerator, reply.isThumbsUp)
                    "
                  >
                    <!-- <svg-icon
                        :icon-class="getReplyIconClass(comment.id, reply.id)"
                        :src="getReplyIconSrc(comment.id, reply.id)"
                        class="svg-icon"
                        style="
                          margin-left: 20px;
                          margin-right: 3px;
                          transform: translateY(-1px);
                        "
                        :class="{ liked: isReplyLiked(comment.id, reply.id) }"
                      /> -->
                    <svg-icon
                      :icon-class="getCommentzanIconClass(reply.isThumbsUp)"
                      :src="getCommentzanIconSrc(reply.isThumbsUp)"
                      class="svg-icon"
                      style="
                        margin-left: 20px;
                        margin-right: 3px;
                        transform: translateY(-1px);
                      "
                    />
                    <span v-if="reply.thumbsUpCount > 0">{{
                      reply.thumbsUpCount
                    }}</span
                    >点赞                  </el-button>
                  <el-button
                    link
                    style="font-size: 12px; color: #86909c"
                    @click="toggleReply(reply.idGenerator)"
                  >
                    <el-icon style="margin-right: 3px; font-size: 16px">
                      <ChatLineSquare />
                    </el-icon>
                回复
                  </el-button>
                  <el-dropdown trigger="click">
                    <template #default>
                      <span>
                        <el-button link>
                          <el-icon
                            style="
                              margin-left: 12px;
                              color: #4e5969;
                              font-size: 12px;
                              transform: translateY(4px);
                            "
                          >
                            <MoreFilled />
                          </el-icon>
                        </el-button>
                      </span>
                    </template>
                    <template #dropdown>
                      <el-dropdown-menu>
                        <el-dropdown-item
                          @click="deleteComment(reply.idGenerator)"
                          >删除评论</el-dropdown-item
                        >
                        <el-dropdown-item>
                          <el-dropdown trigger="hover" placement="right-start">
                            <span
                              >禁言<el-icon
                                style="
                                  transform: translateY(3px);
                                  margin-left: 20px;
                                "
                              >
                                <ArrowRight /> </el-icon
                            ></span>
                            <template #dropdown>
                              <el-dropdown-menu>
                                <el-dropdown-item
                                  @click="banUserHour(comment.id)"
                                  >一个小时</el-dropdown-item
                                >
                                <el-dropdown-item
                                  @click="banUserDay(comment.id)"
                                  >一天</el-dropdown-item
                                >
                                <el-dropdown-item
                                  @click="banUserWeek(comment.id)"
                                  >一周</el-dropdown-item
                                >
                                <el-dropdown-item
                                  @click="banUserForever(comment.id)"
                                  >永久</el-dropdown-item
                                >
                              </el-dropdown-menu>
                            </template>
                          </el-dropdown>
                        </el-dropdown-item>
                      </el-dropdown-menu>
                    </template>
                  </el-dropdown>
                </p>
                <!-- <el-input
                    v-if="showReplyInput[reply.id]"
                    v-model="replyTexts[reply.id]"
                    type="textarea"
                     :placeholder="$t('view.course.add_comment')"
                    rows="3"
                    maxlength="150"
                    show-word-limit
                    style="margin-top: 10px"
                  /> -->
                <el-form>
                  <el-form-item
                    class="childrenForm"
                    v-if="showReplyInput[reply.idGenerator]"
                  >
                    <el-input
                      v-model="replyTexts[reply.idGenerator]"
                      :rows="3"
                      type="textarea"
                      maxlength="150"
                      @input="
                        handleInput(
                          replyTexts[reply.idGenerator],
                          reply.idGenerator
                        )
                      "
                      :placeholder="$t('view.course.add_comment')"
                    >
                    </el-input>
                    <div class="commentOperate">
                      <div class="numberLimit">
                        还能输入<span class="remainingCount">{{
                          remainCount[reply.idGenerator]
                        }}</span
                        >个字符
                      </div>
                      <div class="comment-operate-item">
                        <VueEmoji
                          @chooseEmoji="chooseEmoji"
                          :replyComment="replyTexts[reply.idGenerator]"
                          :keyId="reply.idGenerator"
                        />
                        <el-button
                          class="commentBtn"
                          type="primary"
                          @click="userChildrenCommont(reply)"
                          >评论
                        </el-button>
                      </div>
                    </div>
                  </el-form-item>
                </el-form>
              </div>
            </div>
          </div>
          <el-divider
            border-style="double"
            style="height: 1px; border: 1px solid #f4f3f3"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import VueEmoji from "@/views/activity/activityDetail/VueEmoji.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  addComments,
  searchComments,
  commentThumbsUp,
  commentCancelThumbsUp,
  deleteCommentApi,
} from "@/api/common";
import {
  singleCourseCommentThumbsUp,
  singleCourseCommentCancelThumbsUp,
} from "@/api/course";
import { useRoute, useRouter } from "vue-router";
const likeIcon = new URL("@/assets/images/icons/svg/like.svg", import.meta.url)
  .href;
const yellowLikeIcon = new URL(
  "@/assets/images/icons/svg/yellowlike.svg",
  import.meta.url
).href;
import profile from "@/assets/images/profile.jpg";
import { onMounted } from "vue";
const route = useRoute();
const router = useRouter();
const isComment = ref(true);
const detailLoading = ref(false);
// 評論數據
const comments = ref([]);
//回覆評論
const replyTexts = ref({});
const showReplyInput = ref({});
const commentForm = reactive({
  commentText: "",
});
const props = defineProps({
  isComment: {
    type: Boolean,
    default: false,
  },
});

onMounted(()=>{
  searchCommentsFn()
})

const getCommentzanIconSrc = (isThumbsUp) => {
  return isThumbsUp ? yellowLikeIcon : likeIcon;
};

const getCommentzanIconClass = (isThumbsUp) => {
  return isThumbsUp ? "yellowlike" : "like";
};
const toggleReply = (commentId) => {
  remainCount.value[commentId] = 150;
  if (!showReplyInput.value[commentId]) {
    showReplyInput.value[commentId] = false;
  }
  showReplyInput.value[commentId] = !showReplyInput.value[commentId];
};

// 評論點讚狀態
const commentLikes = ref({});

const toggleLikeComment = (commentId, isThumbsUp) => {
  // if (!commentLikes.value[commentId]) {
  //   commentLikes.value[commentId] = false;
  // }
  // commentLikes.value[commentId] = !commentLikes.value[commentId];
  // console.log(commentLikes.value[commentId], "commentLikes.value[commentId]");
  if (!isThumbsUp) {
    singleCourseCommentThumbsUp({
      mainId: route.query.id,
      commentId: commentId,
    }).then((res) => {
      if (res.code == 200) {
        ElMessage.success("点赞成功");
        searchCommentsFn();
      }
    });
  } else {
    singleCourseCommentCancelThumbsUp({
      mainId: route.query.id,
      commentId: commentId,
    }).then((res) => {
      if (res.code == 200) {
        ElMessage.success("取消点赞");
        searchCommentsFn();
      }
    });
  }
};
const searchCommentsFn = () => {
  comments.value = []
  detailLoading.value = true;
  let params = {
    mainId: route.query.id,
    funType: 1,
    pageNum: 1,
    pageSize: 10,
  };
  searchComments(params).then((res) => {
    if (res.code == 200) {
      comments.value = res.data.items;
      detailLoading.value = false;
    } else {
      ElMessage.error(res.message);
      detailLoading.value = false;
    }
  });
};
const remainingCount = ref(150);
const remainCount = ref({});
const handleInput = (value, id) => {
  if (id) {
    remainCount.value[id] = 150 - value.length;
  } else {
    remainingCount.value = 150 - value.length;
  }

  // if (remainingCount.value < 0) {
  //   this.message = this.message.slice(0, this.maxLength);
  //   event.target.scrollTop = event.target.scrollHeight;
  // }
};

const chooseEmoji = (item, replyComment, keyId) => {
  if (keyId) {
    replyComment += item;
    replyTexts.value[keyId] = replyComment;
    remainCount.value[keyId]--;
  } else {
    commentForm.commentText += item;
    remainingCount.value--;
  }
};
const addCommont = (params) => {
  addComments(params).then((res) => {
    if (res.code == 200) {
      ElMessage.success("评论成功");
      showReplyInput.value[params.parentIdGenerator] = false;
      replyTexts.value[params.parentIdGenerator] = "";
      remainCount[params.parentIdGenerator] = 150;
      commentForm.commentText = "";
      remainingCount.value = 150;
      searchCommentsFn();
      detailLoading.value = false;
    } else {
      detailLoading.value = false;
      ElMessage.error(res.message);
    }
  });
};
const userChildrenCommont = (comment) => {
  detailLoading.value = true;
  let params = {
    info_Conmment: replyTexts.value[comment.idGenerator],
    mainIdGenerator: comment.mainIdGenerator,
    parentIdGenerator: comment.idGenerator,
    moduleTypeEnums: 1,
  };
  addCommont(params);
};
const userCommont = () => {
  detailLoading.value = true;
  let params = {
    info_Conmment: commentForm.commentText,
    mainIdGenerator: route.query.id,
    parentIdGenerator: 0,
    moduleTypeEnums: 1,
  };
  addCommont(params);
};
// 刪除評論(按鈕)
const deleteComment = (idValue) => {
  const data = {
    id: idValue,
  };
  ElMessageBox.confirm(`確定刪除评论?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      deleteCommentApi(data).then((res) => {
        if (res.code == 200) {
          ElMessage({
            type: "success",
            message: "刪除评论成功",
          });
          searchCommentsFn();
        } else {
          ElMessage({
            type: "error",
            message: res.message,
          });
        }
      });
    })
    .catch(() => {
      info;
      ElMessage.info("评论成功");
    });
};
watch(
  () => route.query,
  (newValue, oldValue) => {
    if (route.query.typeFlag == "courseindexEnter") {
      commentForm.commentText = "";
      showReplyInput.value = {};
      replyTexts.value = {};
      remainCount.value = {};
      remainingCount.value = 150;
    }
  },
  { immediate: true }
);
defineExpose({ searchCommentsFn });
</script>
<style scoped lang="scss">
:deep(.el-form-item__content) {
  position: relative;
  //   margin-left: 20px;
  margin-top: 10px;
  padding-bottom: 10px;
  border: 1px solid #e7e7e7;
  border-radius: 6px;
  .el-textarea.el-input--default {
    .el-textarea__inner {
      box-shadow: 0 0 0 1px transparent !important;
      padding: 5px 16px !important;
    }
  }
  .commentOperate {
    height: 20px;
    border: 1px solid transparent;
    .numberLimit {
      position: absolute;
      // bottom: 5px;
      left: 16px;
      color: #999aaa;
      .remainingCount {
        color: #1d2129;
        padding: 0 2px;
      }
    }
    .comment-operate-img {
      width: 20px;
      height: 20px;
    }
    .comment-operate-item {
      position: absolute;
      // bottom: 0px;
      right: 21px;
      display: flex;
      align-items: center;
      .comment-operate-img {
        width: 20px;
        height: 20px;
        margin-right: 16px;
        cursor: pointer;
      }
      .commentBtn {
        padding-right: 10px;
        border-radius: 16px;
        width: 60px;
        height: 24px;
        font-size: 14px;
      }
    }
  }
}
</style>

emoji.json

{
  "data": "😀,😁,😂,😃,😄,😅,😆,😉,😊,😋,😎,😍,😘,😗,😙,😚,😇,😐,😑,😶,😏,😣,😥,😮,😯,😪,😫,😴,😌,😛,😜,😝,😒,😓,😔,😕,😲,😷,😖,😞,😟,😤,😢,😭,😦,😧,😨,😬,😰,😱,😳,😵,😡,😠,💘,❤,💓,💔,💕,💖,💗,💙,💚,💛,💜,💝,💞,💟,❣,💪,👈,👉,☝,👆,👇,✌,✋,👌,👍,👎,✊,👊,👋,👏,👐,✍,🍇,🍈,🍉,🍊,🍋,🍌,🍍,🍎,🍏,🍐,🍑,🍒,🍓,🍅,🍆,🌽,🍄,🌰,🍞,🍖,🍗,🍔,🍟,🍕,🍳,🍲,🍱,🍘,🍙,🍚,🍛,🍜,🍝,🍠,🍢,🍣,🍤,🍥,🍡,🍦,🍧,🍨,🍩,🍪,🎂,🍰,🍫,🍬,🍭,🍮,🍯,🍼,☕,🍵,🍶,🍷,🍸,🍹,🍺,🍻,🍴,🌹,🍀,🍎,💰,📱,🌙,🍁,🍂,🍃,🌷,💎,🔪,🔫,🏀,⚽,⚡,👄,👍,🔥,🙈,🙉,🙊,🐵,🐒,🐶,🐕,🐩,🐺,🐱,😺,😸,😹,😻,😼,😽,🙀,😿,😾,🐈,🐯,🐅,🐆,🐴,🐎,🐮,🐂,🐃,🐄,🐷,🐖,🐗,🐽,🐏,🐑,🐐,🐪,🐫,🐘,🐭,🐁,🐀,🐹,🐰,🐇,🐻,🐨,🐼,🐾,🐔,🐓,🐣,🐤,🐥,🐦,🐧,🐸,🐊,🐢,🐍,🐲,🐉,🐳,🐋,🐬,🐟,🐠,🐡,🐙,🐚,🐌,🐛,🐜,🐝,🐞,🦋,😈,👿,👹,👺,💀,☠,👻,👽,👾,💣"
}
相关推荐
大数据编程之光2 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
初九之潜龙勿用3 分钟前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net
风尚云网20 分钟前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
Dola_Pan20 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs20 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj12345678921 分钟前
JDK1.8新增特性
java·开发语言
木子020422 分钟前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing24 分钟前
React核心功能详解(一)
前端·react.js·前端框架
捂月27 分钟前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
IT古董29 分钟前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习