springboot+vue实现评论回复功能-论坛2
分类: springboot vue 专栏: springboot vue 常用功能 标签: springboot+vue实现评论回复功能-论坛2
2025-02-19 22:16:42 285浏览
springboot+vue实现评论回复功能-论坛2
sql
-- ---------------------------- DROP TABLE IF EXISTS `xl_comment`; CREATE TABLE `xl_comment` ( `id` int(0) NOT NULL AUTO_INCREMENT, `uid` int(0) DEFAULT NULL COMMENT '用户id', `context` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '评论', `cts` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '评论时间', `hf_id` int(0) DEFAULT NULL COMMENT '回复评论id', `hf_uid` int(0) DEFAULT NULL COMMENT '回复用户id', `fid` int(0) DEFAULT NULL COMMENT '帖子id', `ctype` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '保留字段', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 238 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
bean
package com.jff.xinli.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.List;
@Data
@TableName("xl_comment")
public class XlComment {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer uid;
private Integer hfId;
private Integer hfUid;
private String cts;
private String context;
private String ctype;//article,forum
private Integer fid;
@TableField(exist = false)
private String userNickname;
@TableField(exist = false)
private String faceimg;
@TableField(exist = false)
private String uhUserNickname;
@TableField(exist = false)
private String uhFaceimg;
@TableField(exist = false)
private List<XlComment> hfli;
@TableField(exist = false)
private String orderby;
@TableField(exist = false)
private String fname;
@TableField(exist = false)
private String keywords;
@TableField(exist = false)
private Integer tid;
}
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jff.xinli.dao.XlCommentMapper">
<sql id="field"> c.*
,u.nickname as userNickname,u.faceimg
,uh.nickname as uhUserNickname,uh.faceimg as uhFaceimg
,f.fname
</sql>
<select id="getlistByJoin" resultType="com.jff.xinli.bean.XlComment" parameterType="com.jff.xinli.bean.XlComment">
select
<include refid="field"></include>
from xl_comment c
left join xl_users u on u.id=c.uid
left join xl_users uh on uh.id=c.hf_uid
left join xl_forum f on f.id=c.fid
left join xl_type t on t.id=f.tid
where 1=1
<if test="fid != null ">
and c.fid =#{fid}
</if>
<if test="uid != null ">
and c.uid =#{uid}
</if>
<if test="tid != null ">
and t.id =#{tid}
</if>
<if test="hfId != null ">
and c.hf_id =#{hfId}
</if>
<if test="ctype != null and ctype != ''">
and c.ctype = #{ctype}
</if>
<if test="keywords != null and keywords != ''">
and (
c.context like concat('%',#{keywords},'%')
or u.nickname like concat('%',#{keywords},'%')
or uh.nickname like concat('%',#{keywords},'%')
or f.fcont like concat('%',#{keywords},'%')
)
</if>
<if test="orderby == 'id_desc' ">
order by c.id desc
</if>
</select>
<select id="getIdByJoin" resultType="com.jff.xinli.bean.XlComment" parameterType="java.lang.Integer">
select
<include refid="field"></include>
from xl_comment c
left join xl_users u on u.id=c.uid
left join xl_users uh on uh.id=c.hf_uid
left join xl_forum f on f.id=c.fid
where
c.id=#{0}
</select>
<delete id="deleteByHfid" parameterType="java.lang.Integer">
delete from xl_comment where hf_id=#{0} and ctype='forum'
</delete>
<delete id="deleteByFid" parameterType="java.lang.Integer">
delete from xl_comment where fid=#{0} and ctype='forum'
</delete>
<select id="getCountByFid" resultType="java.lang.Integer" parameterType="java.lang.Integer">
select
count(id)
from xl_comment
where fid=#{0} and ctype='forum'
</select>
</mapper>
dao
package com.jff.xinli.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jff.xinli.bean.XlComment;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Mapper
public interface XlCommentMapper extends BaseMapper<XlComment> {
List<XlComment> getlistByJoin(XlComment o);
XlComment getIdByJoin(Integer id);
void deleteByHfid(Integer hfId);
void deleteByFid(Integer fid);
Integer getCountByFid(Integer fid);
}
service
package com.jff.xinli.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jff.xinli.bean.XlComment;
import com.jff.xinli.dao.XlCommentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class XlCommentService extends ServiceImpl<XlCommentMapper, XlComment> {
@Autowired
XlCommentMapper commentMapper;
public List<XlComment> getlistByJoin(XlComment o) {
return commentMapper.getlistByJoin(o);
}
public XlComment getIdByJoin(Integer id){
return commentMapper.getIdByJoin(id);
}
public List<XlComment> getListByFid(Integer fid) {
XlComment o=new XlComment();
o.setFid(fid);
return commentMapper.getlistByJoin(o);
}
public List<XlComment> getListByHfid(Integer hfId) {
if(hfId==null)return null;
XlComment o=new XlComment();
o.setHfId(hfId);
o.setOrderby("id_desc");
return commentMapper.getlistByJoin(o);
}
public void deleteByHfid(Integer hfId){
commentMapper.deleteByHfid( hfId);
}
public void deleteByFid(Integer fid){
commentMapper.deleteByFid( fid);
}
public Integer getCountByFid(Integer fid){
return commentMapper.getCountByFid(fid);
}
}
controller
package com.jff.xinli.control.api;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jff.xinli.bean.XlComment;
import com.jff.xinli.bean.XlForum;
import com.jff.xinli.service.XlCommentService;
import com.jff.xinli.service.XlForumService;
import com.jff.xinli.util.DateUtils;
import com.jff.xinli.util.MessUntil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@CrossOrigin
@RestController
@RequestMapping("/comment")
public class XlCommentController {
@Resource
XlCommentService commentService;
@Resource
XlForumService forumService;
@RequestMapping("/page")
public MessUntil page(@RequestParam(value="pageNo",defaultValue="1")int pageNo , @RequestParam(value="pageSize",defaultValue="10")int pageSize , XlComment o) {
MessUntil mess=new MessUntil();
PageHelper.startPage(pageNo, pageSize, " id desc ");
List<XlComment> li=commentService.getlistByJoin(o);
PageInfo<XlComment> pageInfo = new PageInfo<XlComment>(li, pageSize);
for(XlComment c:li){
if(c.getHfId()==null||c.getHfId()==0){
c.setHfli(commentService.getListByHfid(c.getId()));
}
}
return mess.succ(pageInfo);
}
@RequestMapping("/save")
public MessUntil save( XlComment o ) {
MessUntil mess=new MessUntil();
o.setCts(DateUtils.getNowDateTsString());
commentService.save(o);
if(o.getFid()!=null){
int commentNum=commentService.getCountByFid(o.getFid());
XlForum f=new XlForum();
f.setId(o.getFid());
f.setCommentNum(commentNum);
forumService.updateById(f);
return mess.succ(commentNum );
}
return mess.succ( );
}
@RequestMapping("/del")
public MessUntil del( XlComment o ) {
MessUntil mess=new MessUntil();
o=commentService.getIdByJoin(o.getId());
try {
List<XlComment> hfli=commentService.getListByHfid(o.getId());
if(hfli!=null&&hfli.size()>0){
commentService.deleteByHfid(o.getId());
}
commentService.removeById(o.getId());
} catch (Exception e) {
return mess.error("删除失败,请先删除其关联信息");
}
if(o.getFid()!=null){
int commentNum=commentService.getCountByFid(o.getFid());
XlForum f=new XlForum();
f.setId(o.getFid());
f.setCommentNum(commentNum);
forumService.updateById(f);
return mess.succ(commentNum);
}
return mess.succ();
}
}
vue
admin
<template>
<div class="about">
<v-header/>
<v-sidebar/>
<div class="content-box">
<div class="content">
<div>
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item>
<i class="el-icon-paperclip"></i> 评论管理
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<div class="handle-box">
<el-input v-model="query.keywords" placeholder="评论内容,昵称" style="width: 250px;"></el-input>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
</div>
<el-table size="mini" :data="tableData" border class="table" ref="multipleTable"
header-cell-class-name="table-header" >
<el-table-column fixed="left" prop="id" label="ID" width="60" align="center"></el-table-column>
<el-table-column label="评论内容" prop="cont" align="center" >
<template #default="scope">
<div v-html="scope.row.context"></div>
</template></el-table-column>
<el-table-column label="评论者" prop="userNickname" align="center" width="120"> </el-table-column>
<el-table-column label="头像" width="80" align="center">
<template #default="scope">
<img :src="FILE_URL+ scope.row.faceimg" style="width: 30px;height: 30px;"/>
</template>
</el-table-column>
<el-table-column label="评论时间" prop="cts" align="center" width="180"></el-table-column>
<el-table-column label="操作" width="90" align="center" fixed="right">
<template #default="scope">
<el-dropdown>
<el-button size="mini" type="primary">
操作<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleDelete(scope.$index, scope.row)">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handlePageChange"
:current-page="query.pageNo"
:page-sizes="[10,20,50,100, 200, 300, 400,500]"
:page-size="query.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageTotal">
</el-pagination>
</div>
</div>
</div>
</div>
</div>
<el-dialog :title="'查看 ' +detailObj.title+ ' 详情'" :visible.sync="detailVisible" >
<el-card>
<h4 style="text-align: center;">{{detailObj.title}}</h4>
<div style="margin-top: 30px;"></div>
<div>[简介]{{detailObj.cdesc}}</div>
<div style="margin-top: 30px;"></div>
<div v-html="detailObj.context"></div>
</el-card>
</el-dialog>
</div>
</template>
<script>
import vHeader from "./Header.vue";
import vSidebar from "./Sidebar.vue";
import {
comment_page,
comment_del,
} from '../../api';
export default {
name: "System",
components: {
vHeader,
vSidebar,
},
data() {
return {
detailObj:{},
detailVisible:false,
FILE_URL:'',
lander: {},
FILE_URL: '',
tableData: [],
query: {
keywords: '',
pageNo: 1,
pageSize: 10,
},
pageTotal: 0,
};
},
methods: {
seedetail(row){
this.detailVisible=true;
this.detailObj=row;
},
handleSizeChange(val){
this.query.pageNo = 1;
this.query.pageSize=val;
this.getPage();
},
// 查询操作
handleSearch() {
console.log(this.query)
this.query.pageNo = 1;
this.getPage();
},
// 分页导航
handlePageChange(val) {
this.query.pageNo = val;
this.getPage();
},
//获取列表数据
getPage() {
comment_page(this.query).then((res) => {
this.tableData = res.data.obj.list
this.pageTotal = res.data.obj.total//该页总共多少条记录
})
},
//删除操作
handleDelete(index,row){
// 二次确认删除
this.$confirm("确定要删除吗?", "提示", {
type: "warning",
})
.then(() => {
comment_del({id:row.id}).then((res) => {
if(res.data.status==1){
this.$message.success("删除成功");
this.tableData.splice(index, 1);
this.getPage();
}else{
this.$notify({
title: '提示',
message: res.data.msg,
duration: 0
});
}
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
},
},
mounted() {
this.lander=JSON.parse(localStorage.loginUser)
this.FILE_URL = process.env.VUE_APP_API_ROOT;
if(this.lander.role=='psy')this.query.uid=this.lander.id;
if(this.lander.role=='pt')this.query.uid=this.lander.id;
//去后端查询所有的用户给tableData赋值
this.getPage();
}
}
</script>
<style scoped>
.handle-box {
margin-bottom: 20px;
}
.handle-select {
width: 120px;
}
.handle-input {
width: 300px;
display: inline-block;
}
.table {
width: 100%;
font-size: 14px;
}
.red {
color: #ff0000;
}
.mr10 {
margin-right: 10px;
width: 120px;
}
/*滚动条的宽度*/
/deep/ .el-table__body-wrapper::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/*滚动条滑块*/
/deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
background-color: #409eff;
/*border-radius: 3px;*/
}
.mytip{
padding: 20px; background-color: #fef0f0; color: #F56C6C;border-radius: 5px;font-size: 12px;margin: 10 0;
}
</style>
qt---看文章管理
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
暂无评论,快来写一下吧
展开评论
他的专栏
他感兴趣的技术










java
vue
springboot
Mysql
ssm
小程序
uniapp
js和jquery