Controller
/**
* 根据关联id获取评论信息
* @param relationId 关联id
* @param type 类型
* @return: com.harvey.result.ResultSupport
* @date: 2020/12/10 14:37
*/
@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;
}
/**
* 保存评论
* @param comment 参数
* @return: com.tortoise.common.result.ResultSupport
* @date: 2020/12/10 14:37
*/
@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
/**
* 根据关联id获取绩效信息
*/
public List<Comment> findList(String relationId, String type) {
return commentMapper.findList(relationId, type);
}
/**
* 保存评论
* @param comment 参数
* @param token 用户token
* @return:
* @date: 2020/12/10 14:37
*/
@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
/**
* 根据关联id获取绩效信息
*/
List<Comment> findList(@Param("relationId") String relationId, @Param("type") String type);
/**
* 根据id获取子评论内容
*/
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>
<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>
<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="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();
},
/**
* 点赞
*/
/* likeClick(item) {
if (item.isLike === null) {
item.likeNum++;
} else {
if (item.isLike) {
item.likeNum--;
} else {
item.likeNum++;
}
item.isLike = !item.isLike;
}
}, */
// 获取评论内容
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("评论失败");
}
});
},
/**
* 点击评论按钮显示输入框
* item: 当前大评论
* reply: 当前回复的评论
*/
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 {
/*background-color: #67C23A;*/
}
.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>