yl-backend/src/main/java/com/guwan/backend/service/impl/VideoServiceImpl.java

241 lines
7.9 KiB
Java

package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.dto.video.VideoDTO;
import com.guwan.backend.entity.Video;
import com.guwan.backend.entity.VideoLike;
import com.guwan.backend.mapper.VideoLikeMapper;
import com.guwan.backend.mapper.VideoMapper;
import com.guwan.backend.service.VideoService;
import com.guwan.backend.service.VideoSearchService;
import com.guwan.backend.util.MinioUtil;
import com.guwan.backend.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class VideoServiceImpl implements VideoService {
private final VideoMapper videoMapper;
private final MinioUtil minioUtil;
private final SecurityUtil securityUtil;
private final VideoLikeMapper videoLikeMapper;
private final VideoSearchService videoSearchService;
@Override
@Transactional
@OperationLog(description = "上传视频", operationType = "上传")
public VideoDTO uploadVideo(String fileUrl, String title, String description, String tags) {
// 获取当前用户
Long userId = securityUtil.getCurrentUserId();
if (userId == null) {
throw new IllegalStateException("用户未登录");
}
try {
// 上传视频文件到MinIO
String url = fileUrl;
// 创建视频记录
Video video = new Video();
video.setTitle(title);
video.setDescription(description);
video.setUrl(url);
// video.setSize(file.getSize());
video.setUserId(userId);
video.setStatus("PUBLISHED");
video.setTags(tags);
video.setViewCount(0);
video.setLikeCount(0);
videoMapper.insert(video);
// 保存到ES
videoSearchService.saveOrUpdate(video);
return convertToDTO(video);
} catch (Exception e) {
log.error("上传视频失败", e);
throw new RuntimeException("上传视频失败", e);
}
}
@Override
@Transactional
@OperationLog(description = "更新视频信息", operationType = "更新")
public VideoDTO updateVideo(VideoDTO videoDTO) {
Video video = videoMapper.selectById(videoDTO.getId());
if (video == null) {
throw new IllegalArgumentException("视频不存在");
}
// 检查权限
Long currentUserId = securityUtil.getCurrentUserId();
if (!video.getUserId().equals(currentUserId)) {
throw new IllegalStateException("无权修改此视频");
}
BeanUtils.copyProperties(videoDTO, video, "id", "userId", "url", "createdTime");
videoMapper.updateById(video);
return convertToDTO(video);
}
@Override
@Transactional
@OperationLog(description = "删除视频", operationType = "删除")
public void deleteVideo(Long id) {
Video video = videoMapper.selectById(id);
if (video == null) {
return;
}
// 检查权限
Long currentUserId = securityUtil.getCurrentUserId();
if (!video.getUserId().equals(currentUserId)) {
throw new IllegalStateException("无权删除此视频");
}
// 从MinIO中删除视频文件
String fileName = video.getUrl().substring(video.getUrl().lastIndexOf("/") + 1);
minioUtil.deleteFile("videos", fileName);
// 删除数据库记录
videoMapper.deleteById(id);
// 从ES中删除
videoSearchService.delete(id);
}
@Override
@OperationLog(description = "获取视频详情", operationType = "查询")
public VideoDTO getVideoById(Long id) {
Video video = videoMapper.selectById(id);
return convertToDTO(video);
}
@Override
@OperationLog(description = "获取视频列表", operationType = "查询")
public IPage<VideoDTO> getVideoList(Integer pageNum, Integer pageSize, String keyword) {
Page<Video> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<Video> wrapper = new LambdaQueryWrapper<Video>()
.eq(Video::getStatus, "PUBLISHED")
.like(keyword != null, Video::getTitle, keyword)
.or()
.like(keyword != null, Video::getDescription, keyword)
.orderByDesc(Video::getCreatedTime);
IPage<Video> videoPage = videoMapper.selectPage(page, wrapper);
return videoPage.convert(this::convertToDTO);
}
@Override
@Transactional
@OperationLog(description = "增加视频观看次数", operationType = "更新")
public void incrementViewCount(Long id) {
Video video = videoMapper.selectById(id);
if (video != null) {
video.setViewCount(video.getViewCount() + 1);
videoMapper.updateById(video);
// 更新ES中的观看次数
videoSearchService.updateViewCount(id, video.getViewCount());
}
}
@Override
@Transactional
@OperationLog(description = "视频点赞/取消点赞", operationType = "更新")
public void toggleLike(Long id) {
// 获取当前用户
Long userId = securityUtil.getCurrentUserId();
if (userId == null) {
throw new IllegalStateException("用户未登录");
}
// 检查视频是否存在
Video video = videoMapper.selectById(id);
if (video == null) {
throw new IllegalArgumentException("视频不存在");
}
// 检查是否已点赞
LambdaQueryWrapper<VideoLike> wrapper = new LambdaQueryWrapper<VideoLike>()
.eq(VideoLike::getVideoId, id)
.eq(VideoLike::getUserId, userId);
VideoLike like = videoLikeMapper.selectOne(wrapper);
if (like == null) {
// 未点赞,添加点赞记录
like = new VideoLike();
like.setVideoId(id);
like.setUserId(userId);
videoLikeMapper.insert(like);
// 更新视频点赞数
video.setLikeCount(video.getLikeCount() + 1);
} else {
// 已点赞,取消点赞
videoLikeMapper.deleteById(like.getId());
// 更新视频点赞数
video.setLikeCount(video.getLikeCount() - 1);
}
videoMapper.updateById(video);
// 更新ES中的点赞次数
videoSearchService.updateLikeCount(id, video.getLikeCount());
}
// 添加新方法:检查用户是否已点赞
public boolean hasLiked(Long videoId) {
Long userId = securityUtil.getCurrentUserId();
if (userId == null) {
return false;
}
LambdaQueryWrapper<VideoLike> wrapper = new LambdaQueryWrapper<VideoLike>()
.eq(VideoLike::getVideoId, videoId)
.eq(VideoLike::getUserId, userId);
return videoLikeMapper.selectCount(wrapper) > 0;
}
@Override
public List<VideoDTO> searchVideosByEs(String keyword) {
return videoSearchService.search(keyword);
}
@Override
public List<VideoDTO> getSimilarVideosByEs(Long id, int limit) {
return videoSearchService.findSimilar(id, limit);
}
private VideoDTO convertToDTO(Video video) {
if (video == null) {
return null;
}
VideoDTO dto = new VideoDTO();
BeanUtils.copyProperties(video, dto);
// 设置是否已点赞
// dto.setHasLiked(hasLiked(video.getId()));
return dto;
}
}