xiangpei
2025-05-27 f2cc79e9e83aafacc1af0e2c86e3c8df384fc895
视频评论功能代码
1个文件已修改
10个文件已添加
711 ■■■■■ 已修改文件
buyer-api/src/main/java/cn/lili/controller/lmk/VideoCommentController.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/common/sensitive/SensitiveWordsFilter.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoComment.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoCommentForm.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoCommentQuery.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoCommentVO.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoCommentStatusEnum.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/mapper/VideoCommentMapper.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/VideoCommentService.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/resources/mapper/lmk/VideoCommentMapper.xml 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
buyer-api/src/main/java/cn/lili/controller/lmk/VideoCommentController.java
New file
@@ -0,0 +1,77 @@
package cn.lili.controller.lmk;
import cn.lili.group.Update;
import cn.lili.group.Add;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import lombok.RequiredArgsConstructor;
import java.util.List;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import cn.lili.modules.lmk.service.VideoCommentService;
import cn.lili.base.Result;
import cn.lili.modules.lmk.domain.form.VideoCommentForm;
import cn.lili.modules.lmk.domain.query.VideoCommentQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
 * 视频评论 前端控制器
 *
 * @author xp
 * @since 2025-05-27
 */
@Validated
@RequiredArgsConstructor
@Api(value = "视频评论", tags = "视频评论管理")
@RestController
@RequestMapping("/buyer/lmk/video-comment")
public class VideoCommentController {
    private final VideoCommentService videoCommentService;
    @PostMapping("/comment")
    @ApiOperation(value = "评论", notes = "评论")
    public Result comment(@RequestBody @Validated(Add.class) VideoCommentForm form) {
        return videoCommentService.comment(form);
    }
    @GetMapping("/wx/page")
    @ApiOperation(value = "小程序分页", notes = "评论")
    public Result wxPage(VideoCommentQuery query) {
        return videoCommentService.wxPage(query);
    }
    @DeleteMapping("/{id}")
    @ApiOperation(value = "ID删除", notes = "ID删除")
    public Result removeById(@PathVariable("id") String id) {
        return videoCommentService.removeById(id);
    }
    @DeleteMapping("/batch")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    public Result remove(@RequestBody @NotEmpty(message = "请选择数据") List<String> ids) {
        return videoCommentService.remove(ids);
    }
    @GetMapping("/page")
    @ApiOperation(value = "分页", notes = "分页")
    public Result page(VideoCommentQuery query) {
        return videoCommentService.page(query);
    }
    @GetMapping("/{id}")
    @ApiOperation(value = "详情", notes = "详情")
    public Result detail(@PathVariable("id") String id) {
        return videoCommentService.detail(id);
    }
    @GetMapping("/list")
    @ApiOperation(value = "列表", notes = "列表")
    public Result list() {
        return videoCommentService.all();
    }
}
framework/src/main/java/cn/lili/common/sensitive/SensitiveWordsFilter.java
@@ -53,6 +53,17 @@
    }
    /**
     * 判断内容是否包含敏感词,如果不包含 filter方法会原封不动的返回
     *
     * @param content
     * @return true:包含  false:不包含
     */
    public static Boolean includeSentenceWord(String content) {
        String filter = filter(content, WILDCARD_STAR);
        return !content.equals(filter);
    }
    /**
     * 对句子进行敏感词过滤<br/>
     * 如果无敏感词返回输入的sentence对象,即可以用下面的方式判断是否有敏感词:<br/>
     *
framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoComment.java
New file
@@ -0,0 +1,56 @@
package cn.lili.modules.lmk.domain.entity;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
/**
 * 视频评论
 *
 * @author xp
 * @since 2025-05-27
 */
@Data
@TableName("lmk_video_comment")
public class VideoComment extends BaseEntity {
    private static final long serialVersionUID = 1L;
    @TableField("video_id")
    /** 视频id */
    private String videoId;
    @TableField("comment_content")
    /** 评论内容 */
    private String commentContent;
    @TableField("reply_id")
    /** 回复的评论id */
    private String replyId;
    @TableField("reply_user_id")
    /** 被回复人id */
    private String replyUserId;
    @TableField("reply_user_nickname")
    /** 被回复人昵称 */
    private String replyUserNickname;
    @TableField("master_comment_id")
    /** 主评论id */
    private String masterCommentId;
    @TableField("status")
    /** 评论状态 */
    private String status;
    @TableField("user_nickname")
    /** 评论人昵称 */
    private String userNickname;
    @TableField("user_avatar")
    /** 评论人头像 */
    private String userAvatar;
}
framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoCommentForm.java
New file
@@ -0,0 +1,57 @@
package cn.lili.modules.lmk.domain.form;
import cn.lili.group.Update;
import cn.lili.group.Add;
import cn.lili.base.AbsForm;
import cn.lili.modules.lmk.domain.entity.VideoComment;
import org.springframework.beans.BeanUtils;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.springframework.lang.NonNull;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * 视频评论表单
 *
 * @author xp
 * @since 2025-05-27
 */
@Data
@ApiModel(value = "VideoComment表单", description = "视频评论表单")
public class VideoCommentForm extends AbsForm {
    @NotBlank(message = "视频id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("视频id")
    private String videoId;
    @Max(value = 1000, message = "评论内容过长")
    @NotBlank(message = "评论内容不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("评论内容")
    private String commentContent;
    @ApiModelProperty("回复的评论id")
    private String replyId;
    @ApiModelProperty("回复的人")
    private String replyUserId;
    @ApiModelProperty("回复的人昵称")
    private String replyUserNickname;
    @ApiModelProperty("主评论id,可从reply的评论上获取到")
    private String masterCommentId;
    public static VideoComment getEntityByForm(@NonNull VideoCommentForm form, VideoComment entity) {
        if(entity == null) {
          entity = new VideoComment();
        }
        BeanUtils.copyProperties(form, entity);
        return entity;
    }
}
framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoCommentQuery.java
New file
@@ -0,0 +1,32 @@
package cn.lili.modules.lmk.domain.query;
import cn.lili.base.AbsQuery;
import java.util.List;
import org.springframework.lang.NonNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * 视频评论查询
 *
 * @author xp
 * @since 2025-05-27
 */
@Data
@ApiModel(value = "VideoComment查询参数", description = "视频评论查询参数")
public class VideoCommentQuery extends AbsQuery {
    @ApiModelProperty("视频id")
    private String videoId;
    @ApiModelProperty("是否是加载更多子评论,即查子评论分页")
    private String masterCommentId;
    @ApiModelProperty(hidden = true)
    private String replyId;
}
framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoCommentVO.java
New file
@@ -0,0 +1,63 @@
package cn.lili.modules.lmk.domain.vo;
import cn.lili.base.AbsVo;
import cn.lili.modules.lmk.domain.entity.VideoComment;
import java.util.List;
import com.baomidou.mybatisplus.annotation.TableField;
import org.springframework.lang.NonNull;
import org.springframework.beans.BeanUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * 视频评论展示
 *
 * @author xp
 * @since 2025-05-27
 */
@Data
@ApiModel(value = "视频评论响应数据", description = "视频评论响应数据")
public class VideoCommentVO extends AbsVo {
    /** 视频id */
    @ApiModelProperty("视频id")
    private String videoId;
    /** 评论内容 */
    @ApiModelProperty("评论内容")
    private String commentContent;
    /** 回复的评论id,即parentId */
    @ApiModelProperty("回复的评论id")
    private String replyId;
    private String replyUserId;
    private String replyUserNickname;
    @ApiModelProperty("主评论id")
    private String masterCommentId;
    /** 评论状态 */
    @ApiModelProperty("评论状态")
    private String status;
    @ApiModelProperty("评论人id")
    private String userId;
    @ApiModelProperty("评论人昵称")
    private String userNickname;
    @ApiModelProperty("评论人头像")
    private String userAvatar;
    public static VideoCommentVO getVoByEntity(@NonNull VideoComment entity, VideoCommentVO vo) {
        if(vo == null) {
            vo = new VideoCommentVO();
        }
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoCommentStatusEnum.java
New file
@@ -0,0 +1,47 @@
package cn.lili.modules.lmk.enums.general;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
/**
 * 视频评论状态
 *
 * @author:xp
 * @date:2025/5/14 10:30
 */
@Getter
public enum VideoCommentStatusEnum {
    NORMAL("normal", "正常"),
    AUDITING("auditing", "审核中"),
    INVALID("invalid", "无效的/未通过审核的"),
    ;
    private final String value;
    private final String desc;
    VideoCommentStatusEnum(String value, String desc) {
        this.value = value;
        this.desc = desc;
    }
    /**
     * 获取含义
     *
     * @param value
     * @return
     */
    public static String getDescByValue(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        for (VideoCommentStatusEnum e : VideoCommentStatusEnum.values()){
            if (value.equals(e.getValue())) {
                return e.getDesc();
            }
        }
        return null;
    }
}
framework/src/main/java/cn/lili/modules/lmk/mapper/VideoCommentMapper.java
New file
@@ -0,0 +1,50 @@
package cn.lili.modules.lmk.mapper;
import cn.lili.modules.lmk.domain.entity.VideoComment;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.lili.modules.lmk.domain.vo.VideoCommentVO;
import cn.lili.modules.lmk.domain.form.VideoCommentForm;
import cn.lili.modules.lmk.domain.query.VideoCommentQuery;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * 视频评论 Mapper 接口
 *
 * @author xp
 * @since 2025-05-27
 */
@Mapper
public interface VideoCommentMapper extends BaseMapper<VideoComment> {
    /**
     * id查找视频评论
     * @param id
     * @return
     */
    VideoCommentVO getById(String id);
    /**
    *  分页
    */
    IPage getPage(IPage page, @Param("query") VideoCommentQuery query);
    /**
     * 小程序主评论分页查询
     *
     * @param page
     * @param query
     * @return
     */
    IPage masterCommentPage(IPage page, @Param("query") VideoCommentQuery query);
    /**
     * 小程序回复评论分页查询
     *
     * @param page
     * @param query
     */
    IPage replyCommentPage(IPage page, @Param("query") VideoCommentQuery query);
}
framework/src/main/java/cn/lili/modules/lmk/service/VideoCommentService.java
New file
@@ -0,0 +1,66 @@
package cn.lili.modules.lmk.service;
import cn.lili.modules.lmk.domain.entity.VideoComment;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.lili.base.Result;
import cn.lili.modules.lmk.domain.form.VideoCommentForm;
import cn.lili.modules.lmk.domain.query.VideoCommentQuery;
import java.util.List;
/**
 * 视频评论 服务类
 *
 * @author xp
 * @since 2025-05-27
 */
public interface VideoCommentService extends IService<VideoComment> {
    /**
     * 添加
     * @param form
     * @return
     */
    Result comment(VideoCommentForm form);
    /**
     * 批量删除
     * @param ids
     * @return
     */
    Result remove(List<String> ids);
    /**
     * id删除
     * @param id
     * @return
     */
    Result removeById(String id);
    /**
     * 分页查询
     * @param query
     * @return
     */
    Result page(VideoCommentQuery query);
    /**
     * 根据id查找
     * @param id
     * @return
     */
    Result detail(String id);
    /**
     * 列表
     * @return
     */
    Result all();
    /**
     * 小程序查视频评论
     *
     * @param query
     * @return
     */
    Result wxPage(VideoCommentQuery query);
}
framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoCommentServiceImpl.java
New file
@@ -0,0 +1,147 @@
package cn.lili.modules.lmk.service.impl;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.sensitive.SensitiveWordsFilter;
import cn.lili.modules.lmk.enums.general.VideoCommentStatusEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.lili.modules.lmk.domain.entity.VideoComment;
import cn.lili.modules.lmk.mapper.VideoCommentMapper;
import cn.lili.modules.lmk.service.VideoCommentService;
import cn.lili.base.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.lili.modules.lmk.domain.form.VideoCommentForm;
import cn.lili.modules.lmk.domain.vo.VideoCommentVO;
import cn.lili.modules.lmk.domain.query.VideoCommentQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import cn.lili.utils.PageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * 视频评论 服务实现类
 *
 * @author xp
 * @since 2025-05-27
 */
@Service
@RequiredArgsConstructor
public class VideoCommentServiceImpl extends ServiceImpl<VideoCommentMapper, VideoComment> implements VideoCommentService {
    private final VideoCommentMapper videoCommentMapper;
    /**
     * 添加
     * @param form
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result comment(VideoCommentForm form) {
        // 监测内容是否包含敏感词
        if (SensitiveWordsFilter.includeSentenceWord(form.getCommentContent())) {
            return Result.error("评论含敏感内容");
        }
        if (StringUtils.isNotBlank(form.getReplyId())) {
            VideoComment beReplyComment = baseMapper.selectById(form.getReplyId());
            if (Objects.isNull(beReplyComment)) {
                throw new RuntimeException("您回复的评论已被删除");
            } else if (VideoCommentStatusEnum.INVALID.getValue().equals(beReplyComment.getStatus())) {
                throw new RuntimeException("您回复的评论已失效");
            }
        }
        VideoComment entity = VideoCommentForm.getEntityByForm(form, null);
        entity.setStatus(VideoCommentStatusEnum.AUDITING.getValue());
        AuthUser currentUser = UserContext.getCurrentUser();
        entity.setUserNickname(currentUser.getNickName());
        entity.setUserAvatar(currentUser.getFace());
        baseMapper.insert(entity);
        if (StringUtils.isBlank(entity.getReplyId())) {
            // 不是回复评论,那么就是主评论,主评论的masterId设置为自己的id
            entity.setMasterCommentId(entity.getId());
        }
        baseMapper.updateById(entity);
        return Result.ok("添加成功");
    }
    /**
     * 批量删除
     * @param ids
     * @return
     */
    @Override
    public Result remove(List<String> ids) {
        baseMapper.deleteBatchIds(ids);
        return Result.ok("删除成功");
    }
    /**
     * id删除
     * @param id
     * @return
     */
    @Override
    public Result removeById(String id) {
        baseMapper.deleteById(id);
        return Result.ok("删除成功");
    }
    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public Result page(VideoCommentQuery query) {
        IPage<VideoCommentVO> page = PageUtil.getPage(query, VideoCommentVO.class);
        baseMapper.getPage(page, query);
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public Result detail(String id) {
        VideoCommentVO vo = baseMapper.getById(id);
        Assert.notNull(vo, "记录不存在");
        return Result.ok().data(vo);
    }
    /**
     * 列表
     * @return
     */
    @Override
    public Result all() {
        List<VideoComment> entities = baseMapper.selectList(null);
        List<VideoCommentVO> vos = entities.stream()
                .map(entity -> VideoCommentVO.getVoByEntity(entity, null))
                .collect(Collectors.toList());
        return Result.ok().data(vos);
    }
    @Override
    public Result wxPage(VideoCommentQuery query) {
        IPage<VideoCommentVO> page = PageUtil.getPage(query, VideoCommentVO.class);
        if (StringUtils.isNotBlank(query.getMasterCommentId())) {
            // 加载子评论的情况
            baseMapper.replyCommentPage(page, query);
        } else {
            // 加载主评论的情况。主评论id = masterCommentId
            baseMapper.masterCommentPage(page, query);
        }
        return Result.ok().data(page.getRecords());
    }
}
framework/src/main/resources/mapper/lmk/VideoCommentMapper.xml
New file
@@ -0,0 +1,105 @@
<?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="cn.lili.modules.lmk.mapper.VideoCommentMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.VideoCommentVO">
        <id column="id" property="id"/>
        <result column="video_id" property="videoId" />
        <result column="comment_content" property="commentContent" />
        <result column="reply_id" property="replyId" />
        <result column="reply_user_id" property="replyUserId" />
        <result column="reply_user_nickname" property="replyUserNickname" />
        <result column="master_comment_id" property="masterCommentId" />
        <result column="status" property="status" />
        <result column="create_by" property="userId" />
        <result column="user_nickname" property="userNickname" />
        <result column="user_avatar" property="userAvatar" />
    </resultMap>
    <select id="getById" resultMap="BaseResultMap">
        SELECT
            LVC.video_id,
            LVC.comment_content,
            LVC.reply_id,
            LVC.master_comment_id,
            LVC.status,
            LVC.id
        FROM
            lmk_video_comment LVC
        WHERE
            LVC.id = #{id} AND LVC.delete_flag = 0
    </select>
    <select id="getPage" resultMap="BaseResultMap">
        SELECT
            LVC.video_id,
            LVC.comment_content,
            LVC.reply_id,
            LVC.master_comment_id,
            LVC.status,
            LVC.id
        FROM
            lmk_video_comment LVC
        WHERE
            LVC.delete_flag = 0
    </select>
    <select id="masterCommentPage" resultMap="BaseResultMap">
        SELECT
            LVC.video_id,
            LVC.comment_content,
            LVC.reply_id,
            LVC.reply_user_id,
            LVC.reply_user_nickname,
            LVC.master_comment_id,
            LVC.status,
            LVC.id,
            LVC.create_by,
            LVC.user_nickname,
            LVC.user_avatar
        FROM
             lmk_video_comment LVC
        WHERE
              LVC.id = LVC.master_comment_id
              AND LVC.video_id = #{query.videoId}
              AND LVC.status = 'normal'
              AND LVC.delete_flag = 0
        ORDER BY
            LVC.create_time DESC
    </select>
    <select id="replyCommentPage" resultMap="BaseResultMap">
        SELECT
            LVC.video_id,
            LVC.comment_content,
            LVC.reply_id,
            LVC.reply_user_id,
            LVC.reply_user_nickname,
            LVC.master_comment_id,
            LVC.status,
            LVC.id,
            LVC.create_by,
            LVC.user_nickname,
            LVC.user_avatar
        FROM
            lmk_video_comment LVC
        WHERE
              LVC.id = LVC.master_comment_id
              AND LVC.video_id = #{query.videoId}
              AND LVC.master_comment_id = #{query.masterCommentId}
              AND LVC.status = 'normal'
              AND LVC.delete_flag = 0
        ORDER BY
            LVC.create_time ASC
    </select>
</mapper>