广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >VUE+Java实现评论回复功能
  • 404
分享到

VUE+Java实现评论回复功能

2024-04-02 19:04:59 404人浏览 独家记忆
摘要

背景 最近需要做一个多级评论的功能,技术路线:Vue(Element)+Java(SpringBoot) 效果 后台 SQL Java Controller  @GetMapp

背景

最近需要做一个多级评论的功能,技术路线:Vue(Element)+Java(SpringBoot

效果

后台

SQL

Java

Controller


 @GetMapping("findList")
 public ResultSupport<Object> findList(@RequestParam("relationId") String relationId, @RequestParam("type") String type){
     log.debug("接口[findList]的参数:relationId={}, type={}", relationId, type);
     ResultSupport<Object> result = ResultSupport.createMisResp();
     try {
         List<Comment> commentList = commentService.findList(relationId, type);
         ResultSupportUtils.fillResultSupport(result, commentList);
     } catch (Exception e) {
         log.error("[findList]接口执行异常", e);
         ResultSupportUtils.fillError(result,"系统出现异常!");
     }
     log.debug("接口[findList]的结果:result={}", result);
     return result;
 }

 
 @PostMapping("save")
 public ResultSupport<Object> save(@RequestBody Comment comment, httpservletRequest request){
     log.debug("接口[save]的参数:comment={}", comment);
     ResultSupport<Object> result = ResultSupport.createMisResp();
     String token = request.getHeader("authorization");
     if (StrUtil.isEmpty(token)) {
         result.setSuccess(false);
         result.setMessage("token无效!");
         return result;
     }
     if (BeanUtil.isEmpty(comment)){
         result.setSuccess(false);
         result.setMessage("参数无效!");
         return result;
     }
     try {
         commentService.save(comment, token);
     } catch (Exception e) {
         log.error("[save]接口执行异常", e);
         ResultSupportUtils.fillError(result,"系统出现异常!");
     }
     log.debug("接口[save]的结果:result={}", result);
     return result;
 }

Service


 public List<Comment> findList(String relationId, String type) {
     return commentMapper.findList(relationId, type);
 }

 
 @Transactional(rollbackFor = Exception.class)
 public void save(Comment comment, String token) {
     SysUser user = UserUtils.getUser(token);
     comment.preInsert(user.getId());
     comment.setDelFlag("0");
     commentMapper.save(comment);
 }

Mapper


List<Comment> findList(@Param("relationId") String relationId, @Param("type") String type);


List<Comment> selectByParentId(@Param("parentId") String parentId);


void save(Comment comment);

XML

<sql id="commentColumns">
        a.id AS "id",
        a.user_id AS "userId",
        u.name AS "userName",
        a.relation_id AS "relationId",
        a.type AS "type",
        a.reply_user_id AS "replyUserId",
        r.name AS "replyUserName",
        a.parent_id AS "parentId",
        a.content AS "content",
        u.photo AS "photo",
        a.del_flag AS "delFlag",
        a.create_by AS "createBy",
        a.create_date AS "createDate"
    </sql>

    <sql id="commentJoins">
        LEFT JOIN sys_user u ON a.user_id = u.id AND u.del_flag = '0'
        LEFT JOIN sys_user r ON a.reply_user_id = r.id AND r.del_flag = '0'
    </sql>
    <!-- 保存评论 -->
    <insert id="save">
        INSERT INTO comment(
            id,
            user_id,
            relation_id,
            type,
            reply_user_id,
            parent_id,
            content,
            del_flag,
            create_by,
            create_date
        ) VALUES (
            #{id},
            #{userId},
            #{relationId},
            #{type},
            #{replyUserId},
            #{parentId},
            #{content},
            #{delFlag},
            #{createBy},
            #{createDate}
        )
    </insert>

    <resultMap id="commentResultMap" type="com.harvey.entity.Comment">
        <id column="id" property="id" />
        <result column="userId" property="userId" />
        <result column="userName" property="userName" />
        <result column="relationId" property="relationId" />
        <result column="type" property="type" />
        <result column="replyUserId" property="replyUserId" />
        <result column="replyUserName" property="replyUserName" />
        <result column="parentId" property="parentId" />
        <result column="content" property="content" />
        <collection property="children" column="{parentId=id}" select="selectByParentId" ofType="com.harvey.Comment"/>
    </resultMap>

    <!-- 根据关联id获取评论信息 -->
    <select id="findList" resultMap="commentResultMap">
        SELECT
        <include refid="commentColumns"/>
        FROM
            comment a
        <include refid="commentJoins"/>
        WHERE
            a.relation_id = #{relationId}
            AND a.type = #{type}
            AND a.parent_id = '0'
        ORDER BY
            a.create_date DESC
    </select>

    <!-- 根据id获取子评论内容 -->
    <select id="selectByParentId" resultType="com.harvey.entity.Comment">
        SELECT
        <include refid="commentColumns"/>
        FROM
        comment a
        <include refid="commentJoins"/>
        WHERE
        a.parent_id = #{parentId}
        ORDER BY
        a.create_date DESC
    </select>

前端

把评论抽成组件,方便其他模块引用

<!--评论模块-->
<template>
  <el-drawer
    title="评论"
    :visible.sync="drawer"
    direction="rtl"
    :before-close="handleClose"
    :modal="false"
    :withHeader="true"
    @open="getCommentList"
    @close="close"
    size="320px"
  >
    <div class="container">
      <div class="write-reply" @click="showCommentInputMajor()">
        <div style="margin-top: 10px;">
          <el-input
            class="gray-bg-input"
            v-model="majorComment"
            type="textarea"
            :rows="3"
            autofocus
            placeholder="写下你的评论"
          >
          </el-input>
          <div style="text-align: right;margin-top: 10px;">
            <el-button @click="reset" size="small" round>重置</el-button>
            <el-button
              type="primary"
              round
              @click="commitMajorComment"
              size="small"
              >确定</el-button
            >
          </div>
        </div>
      </div>
      <div class="comment" v-for="item in commentList" :key="item.id">
        <div class="info">
          <img
            class="avatar"
            :src="fileUrl + item.photo"
            width="36"
            height="36"
          />
          <div class="right">
            <div class="name">{{ item.userName }}</div>
            <div class="date">{{ fORMatDate(item.createDate) }}</div>
          </div>
        </div>
        <div class="content">{{ item.content }}</div>
        <div class="control">
          <!-- <span
          class="like"
          :class="{ active: item.isLike }"
          @click="likeClick(item)"
        >
          <i class="iconfont icon-like"></i>
          <span class="like-num">{{
            item.likeNum > 0 ? item.likeNum + "人赞" : "赞"
          }}</span>
        </span> -->
          <span
            class="comment-reply"
            @click="showCommentInput(item, item, 'major')"
          >
            <i class="iconfont icon-iconcomment"></i>
            <span>回复</span>
          </span>
        </div>
        <div class="reply">
          <div class="item" v-for="reply in item.children" :key="reply.id">
            <div class="reply-content">
              <span class="from-name">{{ reply.userName }}</span
              ><span>: </span>
              <span class="to-name">@{{ reply.replyUserName }}</span>
              <span>{{ reply.content }}</span>
            </div>
            <div class="reply-bottom">
              <span>{{ formatDate(reply.createDate) }}</span>
              <span
                class="reply-text"
                @click="showCommentInput(item, reply, 'child')"
              >
                <i class="iconfont icon-iconcomment"></i>
                <span>回复</span>
              </span>
            </div>
          </div>
          <transition name="fade">
            <div class="input-wrapper" v-if="showItemId === item.id">
              <el-tag
                type="info"
                effect="dark"
                v-if="inputLabel != undefined && inputLabel"
                >{{ inputLabel }}</el-tag
              >
              <el-input
                class="gray-bg-input"
                v-model="inputComment"
                type="textarea"
                :rows="3"
                autofocus
                placeholder="写下你的评论"
              >
              </el-input>
              <div class="btn-control">
                <el-button @click="cancel" size="small" round>取消</el-button>
                <el-button
                  type="primary"
                  round
                  @click="commitComment"
                  size="small"
                  >确定</el-button
                >
              </div>
            </div>
          </transition>
        </div>
      </div>
    </div>
  </el-drawer>
</template>

<script>
import * as commentapi from "@/api/comment-api";
import { DateUtil } from "@/utils/DateUtils";
import { UserUtil } from "@/utils/UserUtils";
import "@/assets/CSS/iconfont/iconfont.css";

export default {
  props: {
    drawer: {
      type: Boolean,
      required: true,
      default: false
    },
    relationId: {
      type: String,
      required: true,
      default: ""
    },
    commentType: {
      type: String,
      required: true,
      default: ""
    }
  },
  data() {
    return {
      fileUrl: process.env.VUE_APP_FDFST_FILE_URL,
      commentList: [],
      inputComment: "",
      showItemId: "",
      replyUserId: "",
      parentId: "",
      userInfo: UserUtil.getUserByStorage(),
      inputLabel: "",
      majorComment: ""
    };
  },
  methods: {
    formatDate(date) {
      return DateUtil.formatDate(date, "yyyy-MM-dd hh:mm");
    },
    handleClose(done) {
      done();
    },
    
    
    // 获取评论内容
    getCommentList() {
      commentApi.findList(this.relationId, this.commentType).then(res => {
        this.commentList = res.data;
      });
    },
    
    cancel() {
      this.showItemId = "";
    },

    
    commitComment() {
      // 封装参数
      let param = {
        userId: this.userInfo.userId,
        relationId: this.relationId,
        type: this.commentType,
        replyUserId: this.replyUserId,
        parentId: this.parentId,
        content: this.inputComment
      };
      commentApi.saveComment(param).then(res => {
        if (res.success) {
          this.$message({
            message: "评论成功",
            type: "success"
          });
          this.getCommentList();
          this.inputComment = "";
        } else {
          this.$message.error("评论失败");
        }
      });
    },

    
    commitMajorComment() {
      // 封装参数
      let param = {
        userId: this.userInfo.userId,
        relationId: this.relationId,
        type: this.commentType,
        replyUserId: this.replyUserId,
        parentId: this.parentId,
        content: this.majorComment
      };
      commentApi.saveComment(param).then(res => {
        if (res.success) {
          this.$message({
            message: "评论成功",
            type: "success"
          });
          this.getCommentList();
          this.majorComment = "";
        } else {
          this.$message.error("评论失败");
        }
      });
    },

    
    showCommentInput(item, reply, type) {
      if (reply) {
        this.inputLabel = "@" + reply.userName + " ";
        if (type === "major") {
          this.parentId = reply.id;
        }
        if (type === "child") {
          this.parentId = reply.parentId;
        }
        this.replyUserId = reply.userId;
        debugger;
      } else {
        this.inputLabel = "";
        this.parentId = "0";
        this.replyUserId = "";
      }
      this.inputComment = "";
      this.showItemId = item.id;
    },
    showCommentInputMajor() {
      this.inputLabel = "";
      this.parentId = "0";
      this.replyUserId = "";
    },
    reset() {
      this.inputComment = "";
      this.majorComment = "";
    },
    close() {
      this.$emit("commentClose", "0");
    }
  }
};
</script>

<style scoped lang="less">
/deep/.el-drawer__body {
  overflow: auto;
}
/deep/.el-drawer__header span:focus {
  outline: 0 !important;
}
.container {
  padding: 0 10px;
  box-sizing: border-box;
  .comment {
    display: flex;
    flex-direction: column;
    padding: 10px;
    border-bottom: 1px solid #f2f6fc;
    .info {
      display: flex;
      align-items: center;
      .avatar {
        border-radius: 50%;
      }
      .right {
        display: flex;
        flex-direction: column;
        margin-left: 10px;
        .name {
          font-size: 16px;
          color: #303133;
          margin-bottom: 5px;
          font-weight: 500;
        }
        .date {
          font-size: 12px;
          color: #909399;
        }
      }
    }
    .content {
      font-size: 16px;
      color: #303133;
      line-height: 20px;
      padding: 10px 0;
    }
    .control {
      display: flex;
      align-items: center;
      font-size: 14px;
      color: #909399;
      .like {
        display: flex;
        align-items: center;
        margin-right: 20px;
        cursor: pointer;
        &.active,
        &:hover {
          color: #409eff;
        }
        .iconfont {
          font-size: 14px;
          margin-right: 5px;
        }
      }
      .comment-reply {
        display: flex;
        align-items: center;
        cursor: pointer;
        &:hover {
          color: #333;
        }
        .iconfont {
          font-size: 16px;
          margin-right: 5px;
          margin-top: 4px;
        }
      }
    }
    .reply {
      margin: 10px 0;
      border-left: 2px solid #dcdfe6;
      .item {
        margin: 0 10px;
        padding: 10px 0;
        border-bottom: 1px dashed #ebeef5;
        .reply-content {
          display: flex;
          align-items: center;
          font-size: 14px;
          color: #303133;
          .from-name {
            color: #409eff;
          }
          .to-name {
            color: #409eff;
            margin-left: 5px;
            margin-right: 5px;
          }
        }
        .reply-bottom {
          display: flex;
          align-items: center;
          margin-top: 6px;
          font-size: 12px;
          color: #909399;
          .reply-text {
            display: flex;
            align-items: center;
            margin-left: 10px;
            cursor: pointer;
            &:hover {
              color: #333;
            }
            .icon-iconcomment {
              margin-right: 5px;
              margin-top: 4px;
              font-size: 13px;
            }
          }
        }
      }
      .write-reply {
        display: flex;
        align-items: center;
        font-size: 14px;
        color: #909399;
        padding: 10px;
        cursor: pointer;
        &:hover {
          color: #303133;
        }
        .el-icon-edit {
          margin-right: 5px;
        }
      }
      .fade-enter-active,
      fade-leave-active {
        transition: opacity 0.5s;
      }
      .fade-enter,
      .fade-leave-to {
        opacity: 0;
      }
      .input-wrapper {
        padding: 10px;
        .gray-bg-input,
        .el-input__inner {
          
        }
        .btn-control {
          display: flex;
          justify-content: flex-end;
          align-items: center;
          padding-top: 10px;
          .cancel {
            font-size: 16px;
            color: #606266;
            margin-right: 20px;
            cursor: pointer;
            &:hover {
              color: #333;
            }
          }
          .confirm {
            font-size: 16px;
          }
        }
      }
    }
  }
}
</style>

其他模块引用该评论组件

<template>
    <Comment
      :relationId="kpiPerformance.id"
      :commentType="'1'"
      :drawer="isComment"
      @commentClose="commentClick('0')"
    ></Comment>
</template>

<script>
import Comment from "@/components/Comment";

export default {
    components: {
       Comment
    }
}
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: VUE+Java实现评论回复功能

本文链接: https://www.lsjlt.com/news/146005.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • VUE+Java实现评论回复功能
    背景 最近需要做一个多级评论的功能,技术路线:VUE(Element)+Java(SpringBoot) 效果 后台 SQL Java Controller  @GetMapp...
    99+
    2022-11-13
  • Java单表实现评论回复功能
    Java单表实现评论回复功能 1.简介2.功能实现图3.数据库设计4.实体类5.实现思路6.功能实现6.1 Sql入手6.2 业务实现 7.前端实现8.最终成果 1.简介 最近在写...
    99+
    2023-08-31
    java
  • java怎么实现评论和回复功能
    这篇文章主要介绍了java怎么实现评论和回复功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java怎么实现评论和回复功能文章都会有所收获,下面我们一起来看看吧。效果展示总共是两层回复 (回复评论、回复评论下...
    99+
    2023-07-02
  • Java单表怎么实现评论回复功能
    这篇文章主要介绍“Java单表怎么实现评论回复功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java单表怎么实现评论回复功能”文章能帮助大家解决问题。1.简介评论功能有多种实现方式:单层型套娃型...
    99+
    2023-07-05
  • Java递归实现评论多级回复功能
    目录评论实体添加非回复评论递归添加回复评论结果展示:github 源码最近工作需要做一个评论功能,除了展示评论之外,还需要展示评论回复,评论的回复的回复,这里就用到了递归实现评论的多...
    99+
    2022-11-13
  • java评论、回复功能设计与实现方法
    目录效果展示数据库设计数据库设计思路:实现类源码获取帖子下的评论 获取评论下的回复 获取二级回复总结最近实现了评论和回复、点赞、@的功能。在这里分享一下我的设计思...
    99+
    2022-11-13
  • Springboot+ElementUi实现评论、回复、点赞功能
    目录1.概述2.前端代码1.html2.css3.js4.api调用后台接口3.后端代码1.数据库SQL2.实体类3.daoMapper4.daoMapper实现5.service接...
    99+
    2022-11-13
  • Java单表实现评论回复功能(多种实现方式)
    目录1.简介2.功能实现图3.数据库设计4.实体类5.实现思路6.功能实现6.1 Sql入手6.2 业务实现7.前端实现8.最终成果1.简介 最近在写毕业设计的时候发现需要实现一个评...
    99+
    2023-03-06
    Java评论回复 Java单表评论回复
  • vue实现发表评论功能
    本文实例为大家分享了vue实现发表评论的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html>     <head>  ...
    99+
    2022-11-13
  • 怎么使用Java递归实现评论多级回复功能
    这篇文章主要介绍“怎么使用Java递归实现评论多级回复功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用Java递归实现评论多级回复功能”文章能帮助大家解决问题。评论实体数据库存储字段: i...
    99+
    2023-07-02
  • SpringBoot如何实现无限级评论回复功能
    本篇内容介绍了“SpringBoot如何实现无限级评论回复功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 数据库表结构设计表结构:CR...
    99+
    2023-07-05
  • SpringBoot实现评论回复功能(数据库设计)
    前后端分离项目–二手交易平台小程序 SpringBoot----物品点赞功能实现 SpringBoot----物品收藏功能实现 SpringBoot----文件(图片)上传与显示(下...
    99+
    2022-11-12
  • Vue组件实现评论区功能
    本文实例为大家分享了Vue组件实现评论区的具体代码,供大家参考,具体内容如下 实现代码 <!DOCTYPE html> <html lang="en"> &...
    99+
    2022-11-13
  • vue实现文章评论和回复列表
    本文实例为大家分享了vue实现文章评论和回复列表的具体代码,供大家参考,具体内容如下 效果预览: 父组件: <template>   <div class="co...
    99+
    2022-11-13
  • vue组件实现发表评论功能
    本文实例为大家分享了vue组件实现发表评论的具体代码,供大家参考,具体内容如下 今天看了vue相关的视频,所以跟着做一个小demo把知识串联起来,内容很简单但是也算是学习道路上的一点...
    99+
    2022-11-13
  • vue怎么实现发表评论功能
    今天小编给大家分享一下vue怎么实现发表评论功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。具体代码如下:<!DOC...
    99+
    2023-06-30
  • Vue如何实现发表评论功能
    这篇文章主要为大家展示了“Vue如何实现发表评论功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Vue如何实现发表评论功能”这篇文章吧。具体内容如下这是我在学习中的实例,有些的不足的地方,还望...
    99+
    2023-06-25
  • Vue实现简单的发表评论功能
    本文实例为大家分享了Vue实现简单的发表评论功能的具体代码,供大家参考,具体内容如下 1、这是我在学习中的实例,有些的不足的地方,还望各位大佬指点,感谢哦~ 2、发表评论的效果图 ...
    99+
    2022-11-12
  • vue怎么实现文章评论和回复列表
    今天小编给大家分享一下vue怎么实现文章评论和回复列表的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。效果预览:父组件:<...
    99+
    2023-06-30
  • Ajax实现评论提交功能
    本篇内容介绍了“Ajax实现评论提交功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!代码如下: docu...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作