修改vlog视频的点赞评论和粉丝后台管理

This commit is contained in:
cjh 2025-06-07 09:22:31 +08:00
parent 4d0b6cb113
commit d8c32b0d55
23 changed files with 627 additions and 288 deletions

View File

@ -49,9 +49,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://82.156.121.2:23306/wzj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: wzj
password: A085F27A43B0
url: jdbc:mysql://127.0.0.1:3306/sys?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123
# # 从库数据源
# slave:
# lazy: true

View File

@ -132,6 +132,11 @@ tenant:
# 排除表
excludes:
- sys_menu
- t_users
- t_vlog
- t_comment
- t_my_liked_vlog
- t_fans
- sys_tenant
- sys_tenant_package
- sys_role_dept

View File

@ -1,116 +1,116 @@
package com.wzj.soopin.content.controller;
import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.domain.bo.CommentBO;
import com.wzj.soopin.content.domain.po.Comment;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.vo.CommentVO;
import com.wzj.soopin.content.enums.MessageEnum;
import com.wzj.soopin.content.service.CommentService;
import com.wzj.soopin.content.service.MsgService;
import com.wzj.soopin.content.service.VlogService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RequestMapping("comment")
@RestController
public class CommentController extends BaseInfoProperties {
@Autowired
private CommentService commentService;
@Autowired
private MsgService msgService;
@Autowired
private VlogService vlogService;
//package com.wzj.soopin.content.controller;
//
@PostMapping("create")
public R create(@RequestBody @Valid CommentBO commentBO)
throws Exception {
CommentVO commentVO = commentService.createComment(commentBO);
return R.ok(commentVO);
}
//
@GetMapping("counts")
public R counts(@RequestParam String vlogId) {
String countsStr = redis.get(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
if (StringUtils.isBlank(countsStr)) {
countsStr = "0";
}
return R.ok(Integer.valueOf(countsStr));
}
@GetMapping("list")
public R list(@RequestParam String vlogId,
@RequestParam(defaultValue = "") String userId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
return R.ok(
commentService.queryVlogComments(
vlogId,
userId,
page,
pageSize));
}
@DeleteMapping("delete")
public R delete(@RequestParam String commentUserId,
@RequestParam String commentId,
@RequestParam String vlogId) {
commentService.deleteComment(commentUserId,
commentId,
vlogId);
return R.ok();
}
@PostMapping("like")
public R like(@RequestParam String commentId,
@RequestParam String userId) {
// 故意犯错bigkey
redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId, "1");
// redis.hset(REDIS_USER_LIKE_COMMENT, userId, "1");
// 系统消息点赞评论
Comment comment = commentService.getComment(commentId);
Vlog vlog = vlogService.getVlog(comment.getVlogId());
Map msgContent = new HashMap();
msgContent.put("vlogId", vlog.getId());
msgContent.put("vlogCover", vlog.getCover());
msgContent.put("commentId", commentId);
msgService.createMsg(userId,
comment.getCommentUserId(),
MessageEnum.LIKE_COMMENT.type,
msgContent);
return R.ok();
}
@PostMapping("unlike")
public R unlike(@RequestParam String commentId,
@RequestParam String userId) {
redis.decrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
redis.hdel(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
return R.ok();
}
}
//import com.wzj.soopin.content.domain.base.BaseInfoProperties;
//import com.wzj.soopin.content.domain.bo.CommentBO;
//import com.wzj.soopin.content.domain.po.Comment;
//import com.wzj.soopin.content.domain.po.Vlog;
//import com.wzj.soopin.content.domain.vo.CommentVO;
//import com.wzj.soopin.content.enums.MessageEnum;
//import com.wzj.soopin.content.service.CommentService;
//import com.wzj.soopin.content.service.MsgService;
//import com.wzj.soopin.content.service.VlogService;
//import jakarta.validation.Valid;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.dromara.common.core.domain.R;
//import org.dromara.common.web.core.BaseController;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.*;
//
//import java.util.HashMap;
//import java.util.Map;
//
//
//
//@Slf4j
//@RequestMapping("comment")
//@RestController
//public class CommentController extends BaseInfoProperties {
//
// @Autowired
// private CommentService commentService;
// @Autowired
// private MsgService msgService;
// @Autowired
// private VlogService vlogService;
////
// @PostMapping("create")
// public R create(@RequestBody @Valid CommentBO commentBO)
// throws Exception {
//
// CommentVO commentVO = commentService.createComment(commentBO);
// return R.ok(commentVO);
// }
////
// @GetMapping("counts")
// public R counts(@RequestParam String vlogId) {
//
// String countsStr = redis.get(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
// if (StringUtils.isBlank(countsStr)) {
// countsStr = "0";
// }
//
// return R.ok(Integer.valueOf(countsStr));
// }
//
// @GetMapping("list")
// public R list(@RequestParam String vlogId,
// @RequestParam(defaultValue = "") String userId,
// @RequestParam Integer page,
// @RequestParam Integer pageSize) {
//
// return R.ok(
// commentService.queryVlogComments(
// vlogId,
// userId,
// page,
// pageSize));
// }
//
// @DeleteMapping("delete")
// public R delete(@RequestParam String commentUserId,
// @RequestParam String commentId,
// @RequestParam String vlogId) {
// commentService.deleteComment(commentUserId,
// commentId,
// vlogId);
// return R.ok();
// }
//
// @PostMapping("like")
// public R like(@RequestParam String commentId,
// @RequestParam String userId) {
//
// // 故意犯错bigkey
// redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
// redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId, "1");
//// redis.hset(REDIS_USER_LIKE_COMMENT, userId, "1");
//
//
// // 系统消息点赞评论
// Comment comment = commentService.getComment(commentId);
// Vlog vlog = vlogService.getVlog(comment.getVlogId());
// Map msgContent = new HashMap();
// msgContent.put("vlogId", vlog.getId());
// msgContent.put("vlogCover", vlog.getCover());
// msgContent.put("commentId", commentId);
// msgService.createMsg(userId,
// comment.getCommentUserId(),
// MessageEnum.LIKE_COMMENT.type,
// msgContent);
//
//
// return R.ok();
// }
//
// @PostMapping("unlike")
// public R unlike(@RequestParam String commentId,
// @RequestParam String userId) {
//
// redis.decrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
// redis.hdel(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
//
// return R.ok();
// }
//}

View File

@ -0,0 +1,92 @@
package com.wzj.soopin.content.controller.admin;
import com.wzj.soopin.content.domain.po.Comment;
import com.wzj.soopin.content.domain.vo.CommentVO;
import com.wzj.soopin.content.result.GraceJSONResult;
import com.wzj.soopin.content.service.CommentService;
// import com.wzj.soopin.content.utils.PagedGridResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
@Slf4j
@Api(tags = "管理端-评论管理接口")
@RequestMapping("admin/comment")
@RestController
public class CommentController {
@Autowired
private CommentService commentService;
@ApiOperation("获取评论列表")
@GetMapping("/list")
public TableDataInfo<CommentVO> getCommentList(
@ApiParam(value = "视频ID") @RequestParam(required = false) String vlogId,
PageQuery pageQuery) {
try {
return commentService.getCommentList(vlogId, pageQuery);
} catch (Exception e) {
log.error("获取评论列表失败", e);
return null;
}
}
@ApiOperation("查询视频评论列表")
@GetMapping("/vlogComments")
public TableDataInfo<CommentVO> queryVlogComments(
@ApiParam(value = "视频ID") @RequestParam String vlogId,
@ApiParam(value = "用户ID") @RequestParam(required = false) String userId,
PageQuery pageQuery) {
try {
return commentService.queryVlogComments(vlogId, userId, pageQuery);
} catch (Exception e) {
log.error("查询视频评论列表失败", e);
return null;
}
}
@ApiOperation("删除评论")
@PostMapping("/delete")
public GraceJSONResult deleteComment(
@ApiParam(value = "评论ID") @RequestParam String commentId) {
try {
commentService.deleteComment(commentId);
return GraceJSONResult.ok();
} catch (Exception e) {
log.error("删除评论失败", e);
return GraceJSONResult.errorMsg("删除评论失败: " + e.getMessage());
}
}
@ApiOperation("获取评论详情")
@GetMapping("/detail")
public GraceJSONResult getCommentDetail(@ApiParam(value = "评论ID") @RequestParam String commentId) {
try {
Comment comment = commentService.getCommentDetail(commentId);
if (comment == null) {
return GraceJSONResult.errorMsg("评论不存在");
}
// 获取子评论
List<Comment> childComments = commentService.getChildComments(commentId);
Map<String, Object> result = new HashMap<>();
result.put("comment", comment);
result.put("childComments", childComments);
return GraceJSONResult.ok(result);
} catch (Exception e) {
log.error("获取评论详情失败", e);
return GraceJSONResult.errorMsg("获取评论详情失败: " + e.getMessage());
}
}
}

View File

@ -1,8 +1,13 @@
package com.wzj.soopin.content.controller.admin;
import com.tencentcloudapi.vod.v20180717.models.*;
import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.mapper.FansMapper;
import com.wzj.soopin.content.mapper.FansMapperCustom;
import com.wzj.soopin.content.mapper.MyLikedVlogMapper;
import com.wzj.soopin.content.result.GraceJSONResult;
import com.wzj.soopin.content.service.VlogUploadService;
import com.wzj.soopin.content.utils.RedisOperator;
import com.wzj.soopin.content.utils.TencentCloudUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -10,7 +15,7 @@ import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
@ -24,7 +29,7 @@ import com.tencentcloudapi.common.exception.TencentCloudSDKException;
@Api(tags = "管理端-视频上传接口")
@RequestMapping("admin/vlog/upload")
@RestController
public class VlogUploadController {
public class VlogUploadController extends BaseInfoProperties {
@Autowired
private VlogUploadService vlogUploadService;
@ -35,12 +40,27 @@ public class VlogUploadController {
@Autowired
private com.wzj.soopin.content.mapper.VlogMapper vlogMapper;
@Autowired
private com.wzj.soopin.content.mapper.CommentMapper commentMapper;
@Autowired
private RedisOperator redis;
@Autowired
private MyLikedVlogMapper myLikedVlogMapper;
@Autowired
private FansMapper fansMapper;
@Autowired
private FansMapperCustom fansMapperCustom;
@ApiOperation("获取腾讯云点播视频列表")
@GetMapping("/list")
public GraceJSONResult getVodList(
@ApiParam(value = "页码", defaultValue = "1") @RequestParam(required = false, defaultValue = "1") Integer pageNum,
@ApiParam(value = "每页记录数", defaultValue = "10") @RequestParam(required = false, defaultValue = "10") Integer pageSize,
@ApiParam(value = "文件状态可选值Normal正常、SystemForbidden平台封禁、Forbidden主动封禁") @RequestParam(required = false) String[] status,
@ApiParam(value = "文件状态可选值Normal正常、SystemForbidden平台封禁、Forbidden主动") @RequestParam(required = false) String[] status,
@ApiParam(value = "文件类型可选值Video视频、Audio音频、Image图片") @RequestParam(required = false) String[] categories,
@ApiParam(value = "媒体文件来源可选值Upload上传、Record直播录制") @RequestParam(required = false) String[] sourceTypes,
@ApiParam(value = "媒体文件封装格式mp4、mov等") @RequestParam(required = false) String[] mediaTypes,
@ -84,9 +104,6 @@ public class VlogUploadController {
if (sourceTypes != null && sourceTypes.length > 0) {
req.setSourceTypes(sourceTypes);
}
// if (mediaTypes != null && mediaTypes.length > 0) {
// req.setMediaTypes(mediaTypes);
// }
if (names != null && names.length > 0) {
req.setNames(names);
}
@ -105,12 +122,6 @@ public class VlogUploadController {
if (storageRegions != null && storageRegions.length > 0) {
req.setStorageRegions(storageRegions);
}
// if (createTimeAfter != null && !createTimeAfter.isEmpty()) {
// req.setCreateTimeAfter(createTimeAfter);
// }
// if (createTimeBefore != null && !createTimeBefore.isEmpty()) {
// req.setCreateTimeBefore(createTimeBefore);
// }
if (filters != null && filters.length > 0) {
req.setFilters(filters);
}
@ -149,6 +160,40 @@ public class VlogUploadController {
mediaMap.put("category", basicInfo.getCategory());
mediaMap.put("storageClass", basicInfo.getStorageClass());
mediaMap.put("tagSet", basicInfo.getTagSet());
// 先通过fileId查询本地数据库获取视频信息
com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectByFileId(mediaInfo.getFileId());
if (vlog != null) {
mediaMap.put("vlogId", vlog.getId());
// 点赞数通过点赞表统计
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
mediaMap.put("likeCounts", likeCounts);
// 评论数
Integer commentCount = commentMapper.countByVlogId(vlog.getId());
mediaMap.put("commentCounts", commentCount);
// 获取粉丝数量优先 Redis无则 MySQL
String fansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId());
Integer fansCounts = 0;
if (StringUtils.isNotBlank(fansCountsStr)) {
fansCounts = Integer.valueOf(fansCountsStr);
} else {
// Redis 中没有从数据库查询
fansCounts = fansMapper.countFansByVlogerId(vlog.getVlogerId());
// 可以选择在这里将数据库查询结果写入 Redis以便下次使用
if (fansCounts != null) {
redis.set(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId(), String.valueOf(fansCounts));
}
}
mediaMap.put("fansCounts", fansCounts);
} else {
mediaMap.put("vlogId", null);
mediaMap.put("likeCounts", 0);
mediaMap.put("commentCounts", 0);
mediaMap.put("fansCounts", 0);
}
mediaList.add(mediaMap);
}
}
@ -195,17 +240,55 @@ public class VlogUploadController {
* 视频详情接口
*/
@GetMapping("/detail")
public GraceJSONResult vlogDetail(@RequestParam String vlogId) {
public GraceJSONResult vlogDetail(@RequestParam String fileId) {
try {
// 先查询本地数据库获取 fileId
com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectById(vlogId);
if (vlog != null && StringUtils.hasText(vlog.getFileId())) {
// 如果找到 fileId使用 fileId 查询腾讯云
return GraceJSONResult.ok(vlogUploadService.getVlogDetail(vlog.getFileId()));
// 先通过fileId查询本地数据库获取vlog信息
com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectByFileId(fileId);
Map<String, Object> result = new HashMap<>();
if (vlog != null) {
log.info("找到视频信息: vlogId={}, fileId={}", vlog.getId(), fileId);
// 如果找到vlog信息使用fileId查询腾讯云
Object vodDetail = vlogUploadService.getVlogDetail(fileId);
if (vodDetail instanceof Map) {
result.putAll((Map<String, Object>) vodDetail);
} else {
result.put("vodDetail", vodDetail);
}
// 添加评论信息
List<Map<String, Object>> comments = commentMapper.selectCommentsByVlogId(vlog.getId());
result.put("comments", comments);
// 添加点赞数通过点赞表统计
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
result.put("likeCounts", likeCounts);
result.put("vlogId", vlog.getId());
// 查询点赞用户信息
List<Map<String, Object>> likedUsers = myLikedVlogMapper.selectLikedUsersByVlogId(vlog.getId());
result.put("likedUsers", likedUsers);
// 查询粉丝列表
Map<String, Object> fansQueryMap = new HashMap<>();
fansQueryMap.put("myId", vlog.getVlogerId());
List<com.wzj.soopin.content.domain.vo.FansVO> fansList = fansMapperCustom.queryMyFans(fansQueryMap);
result.put("fansList", fansList);
} else {
// 如果没有找到 fileId直接使用 vlogId 查询
return GraceJSONResult.ok(vlogUploadService.getVlogDetail(vlogId));
log.info("未找到视频信息, fileId={}", fileId);
// 如果没有找到vlog信息只返回腾讯云视频信息
Object vodDetail = vlogUploadService.getVlogDetail(fileId);
if (vodDetail instanceof Map) {
result.putAll((Map<String, Object>) vodDetail);
} else {
result.put("vodDetail", vodDetail);
}
// 设置默认值
result.put("comments", Collections.emptyList());
result.put("likeCounts", 0);
result.put("likedUsers", Collections.emptyList());
result.put("fansList", Collections.emptyList());
}
return GraceJSONResult.ok(result);
} catch (Exception e) {
log.error("获取视频详情失败", e);
return GraceJSONResult.errorMsg("获取视频详情失败: " + e.getMessage());

View File

@ -1,57 +1,51 @@
package com.wzj.soopin.content.domain.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.time.LocalDateTime;
import java.util.Date;
@TableName("t_comment")
@Data
@EqualsAndHashCode(callSuper = true)
public class Comment extends TenantEntity {
@TableId
@TableName("t_comment")
public class Comment {
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 评论的视频是哪个作者vloger的关联id
* 评论的视频是哪个作者(vloger)的关联id
*/
@TableField( "vloger_id")
private String vlogerId;
/**
* 如果是回复留言则本条为子留言需要关联查询
* 如果是回复评论则本条为子评论需要关联查询
*/
private String fatherCommentId;
/**
* 回复的那个视频id
*/
@TableField( "vlog_id")
private String vlogId;
/**
* 发布留言的用户id
* 发布评论的用户id
*/
private String commentUserId;
/**
* 留言内容
* 评论内容
*/
private String content;
/**
* 留言的点赞总数
* 评论的点赞总数
*/
private Integer likeCounts;
/**
* 留言时间
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.tenant.core.TenantEntity;
import java.util.Date;
@ -12,7 +13,7 @@ import java.util.Date;
@TableName( "t_fans")
@Data
@EqualsAndHashCode(callSuper = true)
public class Fans extends TenantEntity {
public class Fans extends BaseAudit {
@TableId
private String id;

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.tenant.core.TenantEntity;
import java.util.Date;
@ -12,7 +13,7 @@ import java.util.Date;
@TableName("t_my_liked_vlog")
@Data
@EqualsAndHashCode(callSuper = true)
public class MyLikedVlog extends TenantEntity {
public class MyLikedVlog extends BaseAudit {
@TableId
private String id;

View File

@ -4,13 +4,14 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.tenant.core.TenantEntity;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName( "r_user_member")
public class UserMember extends TenantEntity {
public class UserMember extends BaseAudit {
private String userId;
private String memberId;
}

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.model.BaseAudit;
import org.dromara.common.tenant.core.TenantEntity;
import java.util.Date;
@ -14,7 +15,7 @@ import java.util.Date;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Users extends TenantEntity {
public class Users extends BaseAudit {
@TableId
private String id;

View File

@ -5,19 +5,20 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import org.dromara.common.core.domain.model.BaseAudit;
@TableName("t_vlog")
@TableName(value = "t_vlog", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
public class Vlog extends TenantEntity {
public class Vlog extends BaseAudit {
@TableId
private String id;
/**
* 对应用户表idvlog视频发布者
*/
@TableField( "vloger_id")
@TableField("vloger_id")
private String vlogerId;
/**
@ -60,8 +61,6 @@ public class Vlog extends TenantEntity {
*/
private Integer isPrivate;
/**
* 视频状态
*/
@ -86,6 +85,4 @@ public class Vlog extends TenantEntity {
* 首帧图
*/
private String firstFrameImg;
}

View File

@ -1,11 +1,47 @@
package com.wzj.soopin.content.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wzj.soopin.content.domain.po.Comment;
import com.wzj.soopin.content.domain.vo.CommentVO;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Repository
public interface CommentMapper extends BaseMapperPlus<Comment, CommentVO> {
import java.util.List;
import java.util.Map;
@InterceptorIgnore(tenantLine = "true")
@Mapper
public interface CommentMapper extends BaseMapper<Comment> {
/**
* 根据视频ID查询评论列表
*/
List<Comment> selectByVlogId(@Param("vlogId") String vlogId);
/**
* 根据父评论ID查询子评论列表
*/
List<Comment> selectByFatherCommentId(@Param("fatherCommentId") String fatherCommentId);
/**
* 根据评论ID查询评论信息
*/
Comment selectByCommentId(@Param("commentId") String commentId);
/**
* 根据视频ID统计评论数量
*/
@Select("SELECT COUNT(*) FROM t_comment WHERE vlog_id = #{vlogId}")
Integer countByVlogId(@Param("vlogId") String vlogId);
/**
* 根据视频ID查询评论列表
*/
@Select("SELECT c.*, u.nickname as userNickname, u.face as userFace " +
"FROM t_comment c " +
"LEFT JOIN t_users u ON c.comment_user_id = u.id " +
"WHERE c.vlog_id = #{vlogId} " +
"ORDER BY c.create_time DESC")
List<Map<String, Object>> selectCommentsByVlogId(@Param("vlogId") String vlogId);
}

View File

@ -5,6 +5,7 @@ import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.vo.FansVO;
import com.wzj.soopin.content.domain.vo.VlogerVO;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.springframework.stereotype.Repository;
@ -14,4 +15,9 @@ import java.util.Map;
public interface FansMapper extends BaseMapperPlus<Fans, FansVO> {
public List<Map<String, Object>> getFollowedVlogerIds(@Param("currentUserId")String currentUserId,@Param("vlogerIds")List<String> vlogerIds);
/**
* 根据vlogerId统计粉丝数量
*/
int countFansByVlogerId(@Param("vlogerId") String vlogerId);
}

View File

@ -3,7 +3,21 @@ package com.wzj.soopin.content.mapper;
import com.wzj.soopin.content.domain.po.MyLikedVlog;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
@Repository
@Mapper
public interface MyLikedVlogMapper extends BaseMapperPlus<MyLikedVlog,MyLikedVlog> {
/**
* 统计某视频的点赞数
*/
@Select("SELECT COUNT(*) FROM t_my_liked_vlog WHERE vlog_id = #{vlogId}")
int countLikesByVlogId(@Param("vlogId") String vlogId);
@Select("SELECT u.nickname, u.face, l.created_time FROM t_my_liked_vlog l LEFT JOIN t_users u ON l.user_id = u.id WHERE l.vlog_id = #{vlogId} ORDER BY l.created_time DESC")
List<Map<String, Object>> selectLikedUsersByVlogId(@Param("vlogId") String vlogId);
}

View File

@ -1,18 +1,20 @@
package com.wzj.soopin.content.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
//@Repository
//public interface VlogMapper extends MyMapper<Vlog> {
//}
@InterceptorIgnore(tenantLine = "true")
@Repository
public interface VlogMapper extends BaseMapper<Vlog> {
// public List<IndexVlogVO> updateVlogStatus(@Param("paramMap") Map<String, Object> map);
@ -63,4 +65,11 @@ public interface VlogMapper extends BaseMapper<Vlog> {
* @return 影响的行数
*/
int updateVlogStatus(@Param("params") Map<String, Object> params);
/**
* 根据fileId查询Vlog信息
* @param fileId 云点播视频唯一标识
* @return Vlog对象或null
*/
Vlog selectByFileId(@Param("fileId") String fileId);
}

View File

@ -1,5 +1,6 @@
package com.wzj.soopin.content.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
import com.wzj.soopin.content.domain.vo.VlogerVO;
@ -11,6 +12,7 @@ import java.util.List;
import java.util.Map;
@Repository
@InterceptorIgnore(tenantLine = "true")
public interface VlogMapperCustom extends BaseMapperPlus<Vlog, VlogerVO> {
public List<IndexVlogVO> getIndexVlogList(@Param("paramMap")Map<String, Object> map);

View File

@ -1,35 +1,48 @@
package com.wzj.soopin.content.service;
import com.wzj.soopin.content.domain.bo.CommentBO;
import com.wzj.soopin.content.domain.po.Comment;
import com.wzj.soopin.content.domain.vo.CommentVO;
import com.wzj.soopin.content.utils.PagedGridResult;
// import com.wzj.soopin.content.utils.PagedGridResult;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.List;
public interface CommentService {
/**
* 发表评论
* 获取评论列表
*/
public CommentVO createComment(CommentBO commentBO);
/**
* 查询评论的列表
*/
public PagedGridResult queryVlogComments(String vlogId,
String userId,
Integer page,
Integer pageSize);
TableDataInfo<CommentVO> getCommentList(String vlogId, PageQuery pageQuery);
/**
* 删除评论
*/
public void deleteComment(String commentUserId,
String commentId,
String vlogId);
void deleteComment(String commentId);
/**
* 根据主键查询comment
* 获取评论详情
*/
public Comment getComment(String id);
Comment getCommentDetail(String commentId);
/**
* 获取子评论列表
*/
List<Comment> getChildComments(String fatherCommentId);
/**
* 创建评论
*/
void createComment(CommentBO commentBO);
/**
* 更新评论
*/
void updateComment(Comment comment);
/**
* 查询视频评论列表
*/
TableDataInfo<CommentVO> queryVlogComments(String vlogId, String userId, PageQuery pageQuery);
}

View File

@ -1,6 +1,7 @@
package com.wzj.soopin.content.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.domain.bo.CommentBO;
@ -16,10 +17,15 @@ import com.wzj.soopin.content.service.MsgService;
import com.wzj.soopin.content.service.VlogService;
import com.wzj.soopin.content.utils.PagedGridResult;
import com.wzj.soopin.content.utils.Sid;
import org.apache.commons.lang3.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.core.utils.MapstructUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.HashMap;
@ -27,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
public class CommentServiceImpl extends BaseInfoProperties implements CommentService {
@Autowired
@ -41,7 +48,101 @@ public class CommentServiceImpl extends BaseInfoProperties implements CommentSer
private Sid sid;
@Override
public CommentVO createComment(CommentBO commentBO) {
public TableDataInfo<CommentVO> getCommentList(String vlogId, PageQuery pageQuery) {
LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
// 构建查询条件
if (StringUtils.hasText(vlogId)) {
queryWrapper.eq(Comment::getVlogId, vlogId);
}
// 按创建时间倒序排序
queryWrapper.orderByDesc(Comment::getCreateTime);
// 分页查询
Page<Comment> page = pageQuery.build();
Page<Comment> result = commentMapper.selectPage(page, queryWrapper);
// 转换为CommentVO列表
List<CommentVO> commentVOList = result.getRecords().stream()
.map(comment -> {
CommentVO vo = new CommentVO();
BeanUtils.copyProperties(comment, vo);
// 设置额外的VO属性
vo.setCommentId(comment.getId());
return vo;
})
.collect(Collectors.toList());
// 创建新的Page对象包含转换后的VO列表
Page<CommentVO> voPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
voPage.setRecords(commentVOList);
// 构建并返回TableDataInfo
return TableDataInfo.build(voPage);
}
@Override
public TableDataInfo<CommentVO> queryVlogComments(String vlogId, String userId, PageQuery pageQuery) {
// 创建分页对象
Page<Comment> page = pageQuery.build();
// 构建查询条件
LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Comment::getVlogId, vlogId)
.orderByDesc(Comment::getCreateTime);
// 执行分页查询
Page<Comment> commentPage = commentMapper.selectPage(page, queryWrapper);
// 转换为CommentVO列表
List<CommentVO> commentVOList = commentPage.getRecords().stream()
.map(comment -> {
CommentVO vo = new CommentVO();
BeanUtils.copyProperties(comment, vo);
// 设置额外的VO属性
vo.setCommentId(comment.getId());
return vo;
})
.collect(Collectors.toList());
// 创建新的Page对象包含转换后的VO列表
Page<CommentVO> voPage = new Page<>(commentPage.getCurrent(), commentPage.getSize(), commentPage.getTotal());
voPage.setRecords(commentVOList);
// 构建并返回TableDataInfo
return TableDataInfo.build(voPage);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteComment(String commentId) {
Comment comment = commentMapper.selectByCommentId(commentId);
if (comment == null) {
throw new RuntimeException("评论不存在");
}
// 删除评论及其子评论
commentMapper.deleteById(commentId);
List<Comment> childComments = commentMapper.selectByFatherCommentId(commentId);
for (Comment childComment : childComments) {
commentMapper.deleteById(childComment.getId());
}
}
@Override
public Comment getCommentDetail(String commentId) {
return commentMapper.selectByCommentId(commentId);
}
@Override
public List<Comment> getChildComments(String fatherCommentId) {
return commentMapper.selectByFatherCommentId(fatherCommentId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createComment(CommentBO commentBO) {
String commentId = sid.nextShort();
Comment comment = new Comment();
comment.setId(commentId);
@ -53,72 +154,11 @@ public class CommentServiceImpl extends BaseInfoProperties implements CommentSer
comment.setLikeCounts(0);
comment.setCreateTime(LocalDateTime.now());
commentMapper.insert(comment);
// redis操作放在service中评论总数的累加
redis.increment(REDIS_VLOG_COMMENT_COUNTS + ":" + commentBO.getVlogId(), 1);
// 留言后的最新评论需要返回给前端进行展示
CommentVO commentVO = new CommentVO();
BeanUtils.copyProperties(comment, commentVO);
// 系统消息评论/回复
Vlog vlog = vlogService.getVlog(commentBO.getVlogId());
Map msgContent = new HashMap();
msgContent.put("vlogId", vlog.getId());
msgContent.put("vlogCover", vlog.getCover());
msgContent.put("commentId", commentId);
msgContent.put("commentContent", commentBO.getContent());
Integer type = MessageEnum.COMMENT_VLOG.type;
if (StringUtils.isNotBlank(commentBO.getFatherCommentId()) &&
!commentBO.getFatherCommentId().equalsIgnoreCase("0") ) {
type = MessageEnum.REPLY_YOU.type;
}
msgService.createMsg(commentBO.getCommentUserId(),
commentBO.getVlogerId(),
type,
msgContent);
return commentVO;
}
@Override
public PagedGridResult queryVlogComments(String vlogId, String userId, Integer page, Integer pageSize) {
Map<String, Object> map = new HashMap<>();
map.put("vlogId", vlogId);
Page<Comment> pageParam = new Page<>(page, pageSize);
LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Comment::getVlogId, vlogId);
Page<Comment> commentPage = commentMapper.selectPage(pageParam, queryWrapper);
List<Comment> commentList = commentPage.getRecords();
List<CommentVO> list = commentList.stream().map(comment -> {
CommentVO cv = new CommentVO();
BeanUtils.copyProperties(comment, cv);
String commentId = cv.getCommentId();
// 当前短视频的某个评论的点赞总数
String countsStr = redis.getHashValue(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId);
Integer counts = 0;
if (StringUtils.isNotBlank(countsStr)) {
counts = Integer.valueOf(countsStr);
}
cv.setLikeCounts(counts);
// 判断当前用户是否点赞过该评论
String doILike = redis.hget(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
if (StringUtils.isNotBlank(doILike) && doILike.equalsIgnoreCase("1")) {
cv.setIsLike(YesOrNo.YES.type);
}
return cv;
}).collect(Collectors.toList());
return null;
}
@Override
public void deleteComment(String commentUserId, String commentId, String vlogId) {
LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Comment::getId, commentId)
.eq(Comment::getCommentUserId, commentUserId);
commentMapper.delete(queryWrapper);
// 评论总数的累减
redis.decrement(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId, 1);
}
@Override
public Comment getComment(String id) {
return commentMapper.selectById(id);
@Transactional(rollbackFor = Exception.class)
public void updateComment(Comment comment) {
commentMapper.updateById(comment);
}
}

View File

@ -12,6 +12,8 @@ import com.wzj.soopin.content.domain.vo.CommentVO;
import com.wzj.soopin.content.service.VlogUploadService;
import com.wzj.soopin.content.utils.TencentCloudUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -169,30 +171,30 @@ public class VlogUploadServiceImpl implements VlogUploadService {
// 获取VOD客户端实例
VodClient client = tencentCloudUtil.getVodClient();
// 创建审核请求
com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoRequest req = new com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoRequest();
req.setFileId(vlogId);
// 设置审核内容包括视频和封面
req.setReviewContents(new String[]{"Media", "Cover"});
// 设置审核模板ID10为预置模板
req.setDefinition(10L);
// 设置任务优先级
req.setTasksPriority(0L);
// 设置来源上下文用于透传用户请求信息
req.setSessionContext(String.format("status=%d&reason=%s", status, reason != null ? reason : ""));
// 调用审核API
com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoResponse resp = client.ReviewAudioVideo(req);
// 记录审核结果
log.info("视频审核任务已提交 - vlogId: {}, status: {}, reason: {}, taskId: {}",
log.info("视频审核任务已提交 - vlogId: {}, status: {}, reason: {}, taskId: {}",
vlogId, status, reason, resp.getTaskId());
// TODO: 暂时注释掉数据库操作等待数据库表创建完成后再启用
/*
// 更新本地数据库状态
@ -202,11 +204,11 @@ public class VlogUploadServiceImpl implements VlogUploadService {
updateMap.put("reason", reason);
updateMap.put("auditTime", new Date());
vlogMapper.updateVlogStatus(updateMap);
// 记录审核日志
log.info("视频状态已更新 - vlogId: {}, status: {}, reason: {}", vlogId, status, reason);
*/
} catch (TencentCloudSDKException e) {
log.error("视频审核失败 - vlogId: {}, error: {}", vlogId, e.getMessage(), e);
throw new RuntimeException("视频审核失败: " + e.getMessage());
@ -323,13 +325,10 @@ public class VlogUploadServiceImpl implements VlogUploadService {
// 4. 评论内容只查 MySQL
List<com.wzj.soopin.content.domain.vo.CommentVO> commentList = new ArrayList<>();
try {
com.wzj.soopin.content.utils.PagedGridResult pagedGridResult = commentService.queryVlogComments(vlogId, null, 1, 10);
if (pagedGridResult != null && pagedGridResult.getRows() != null) {
@SuppressWarnings("unchecked")
List<com.wzj.soopin.content.domain.vo.CommentVO> tempList = (List<com.wzj.soopin.content.domain.vo.CommentVO>) pagedGridResult.getRows();
if (tempList != null) {
commentList = tempList;
}
PageQuery pageQuery = new PageQuery(1, 10);
TableDataInfo<CommentVO> tableDataInfo = commentService.queryVlogComments(vlogId, null, pageQuery);
if (tableDataInfo != null && tableDataInfo.getRows() != null) {
commentList = tableDataInfo.getRows();
}
} catch (Exception e) {
log.warn("获取评论列表失败: {}", e.getMessage());

View File

@ -14,4 +14,30 @@
<result column="like_counts" property="likeCounts" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
</resultMap>
<!-- 根据视频ID查询评论列表 -->
<select id="selectByVlogId" resultType="com.wzj.soopin.content.domain.po.Comment">
SELECT * FROM t_comment
WHERE vlog_id = #{vlogId}
ORDER BY create_time DESC
</select>
<!-- 根据父评论ID查询子评论列表 -->
<select id="selectByFatherCommentId" resultType="com.wzj.soopin.content.domain.po.Comment">
SELECT * FROM t_comment
WHERE father_comment_id = #{fatherCommentId}
ORDER BY create_time ASC
</select>
<!-- 根据评论ID查询评论信息 -->
<select id="selectByCommentId" resultType="com.wzj.soopin.content.domain.po.Comment">
SELECT * FROM t_comment
WHERE id = #{commentId}
</select>
<!-- 根据视频ID统计评论数量 -->
<select id="countByVlogId" resultType="java.lang.Integer">
SELECT COUNT(*) FROM t_comment
WHERE vlog_id = #{vlogId}
</select>
</mapper>

View File

@ -16,4 +16,10 @@
</select>
<!-- 根据vlogerId统计粉丝数量 -->
<select id="countFansByVlogerId" resultType="java.lang.Integer">
SELECT COUNT(*) FROM t_fans
WHERE vloger_id = #{vlogerId}
</select>
</mapper>

View File

@ -88,7 +88,8 @@
v.reason as reason,
v.file_id as fileId,
v.status as status,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -142,7 +143,8 @@
v.reason as reason,
v.file_id as fileId,
v.status as status,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -164,5 +166,11 @@
WHERE id = #{params.vlogId}
</update>
<!-- 根据fileId查询Vlog信息 -->
<select id="selectByFileId" parameterType="String" resultType="com.wzj.soopin.content.domain.po.Vlog">
/* @SqlParser(filter=true) */
SELECT * FROM t_vlog WHERE file_id = #{fileId}
</select>
</mapper>

View File

@ -20,7 +20,8 @@
v.reason as reason,
v.file_id as fileId,
v.status as status,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -80,7 +81,8 @@
v.reason as reason,
v.file_id as fileId,
v.status as status,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -111,7 +113,8 @@
v.reason as reason,
v.status as status,
v.file_id as fileId,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -162,7 +165,8 @@
v.reason as reason,
v.status as status,
v.file_id as fileId,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN
@ -202,7 +206,8 @@
v.reason as reason,
v.status as status,
v.file_id as fileId,
v.first_frame_img as firstFrameImg
v.first_frame_img as firstFrameImg,
v.id as vlogId
FROM
t_vlog v
LEFT JOIN