199 lines
8.7 KiB
Java
Raw Normal View History

package edu.whut.smilepicturebackend.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.exception.ThrowUtils;
import edu.whut.smilepicturebackend.manager.FileManager;
import edu.whut.smilepicturebackend.mapper.PictureMapper;
import edu.whut.smilepicturebackend.model.dto.picture.PictureQueryRequest;
import edu.whut.smilepicturebackend.model.dto.picture.PictureUploadRequest;
import edu.whut.smilepicturebackend.model.entity.Picture;
import edu.whut.smilepicturebackend.model.entity.User;
import edu.whut.smilepicturebackend.model.file.UploadPictureResult;
import edu.whut.smilepicturebackend.model.vo.PictureVO;
import edu.whut.smilepicturebackend.model.vo.UserVO;
import edu.whut.smilepicturebackend.service.PictureService;
import edu.whut.smilepicturebackend.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author 张三
* @description 针对表picture(图片)的数据库操作Service实现
* @createDate 2025-06-11 11:23:11
*/
@Service
@RequiredArgsConstructor
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
implements PictureService {
private final FileManager fileManager;
private final UserService userService;
@Override
public void validPicture(Picture picture) {
ThrowUtils.throwIf(picture == null, ErrorCode.PARAMS_ERROR);
// 从对象中取值
Long id = picture.getId();
String url = picture.getUrl();
String introduction = picture.getIntroduction();
// 修改数据时id 不能为空,有参数则校验
ThrowUtils.throwIf(ObjUtil.isNull(id), ErrorCode.PARAMS_ERROR, "id 不能为空");
// 如果传递了 url才校验
if (StrUtil.isNotBlank(url)) {
ThrowUtils.throwIf(url.length() > 1024, ErrorCode.PARAMS_ERROR, "url 过长");
}
if (StrUtil.isNotBlank(introduction)) {
ThrowUtils.throwIf(introduction.length() > 800, ErrorCode.PARAMS_ERROR, "简介过长");
}
}
@Override
public PictureVO uploadPicture(MultipartFile multipartFile, PictureUploadRequest pictureUploadRequest, User loginUser) {
// 校验参数
ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
// 判断是新增还是删除
Long pictureId = null;
if (pictureUploadRequest != null) {
pictureId = pictureUploadRequest.getId();
}
// 如果是更新,判断图片是否存在
if (pictureId != null) {
boolean exists=this.lambdaQuery()
.eq(Picture::getId,pictureId)
.exists();
ThrowUtils.throwIf(!exists, ErrorCode.NOT_FOUND_ERROR, "图片不存在");
}
// 上传图片,得到图片信息
String uploadPathPrefix;
//公共图库下每个用户有自己的userid管理的文件夹。
uploadPathPrefix = String.format("public/%s", loginUser.getId());
UploadPictureResult uploadPictureResult = fileManager.uploadPicture(multipartFile, uploadPathPrefix);
// 构造要入库的图片信息
Picture picture = new Picture();
// 复制同名属性url、name、picSize、picWidth、picHeight、picScale、picFormat
BeanUtils.copyProperties(uploadPictureResult, picture);
picture.setUserId(loginUser.getId());
// 操作数据库
// 如果 pictureId 不为空,表示更新,否则是新增
if (pictureId != null) {
// 如果是更新,需要补充 id 和编辑时间
picture.setId(pictureId);
picture.setEditTime(new Date());
}
boolean result = this.saveOrUpdate(picture);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败,数据库操作失败");
return PictureVO.objToVo(picture);
}
@Override
public LambdaQueryWrapper<Picture> getQueryWrapper(PictureQueryRequest req) {
LambdaQueryWrapper<Picture> qw = Wrappers.lambdaQuery(Picture.class);
if (req == null) {
return qw;
}
// 精简版条件构造
qw.eq(ObjUtil.isNotEmpty(req.getId()), Picture::getId, req.getId())
.eq(ObjUtil.isNotEmpty(req.getUserId()), Picture::getUserId, req.getUserId())
.like(StrUtil.isNotBlank(req.getName()), Picture::getName, req.getName())
.like(StrUtil.isNotBlank(req.getIntroduction()), Picture::getIntroduction, req.getIntroduction())
.like(StrUtil.isNotBlank(req.getPicFormat()), Picture::getPicFormat, req.getPicFormat())
.eq(StrUtil.isNotBlank(req.getCategory()), Picture::getCategory, req.getCategory())
.eq(ObjUtil.isNotEmpty(req.getPicWidth()), Picture::getPicWidth, req.getPicWidth())
.eq(ObjUtil.isNotEmpty(req.getPicHeight()), Picture::getPicHeight, req.getPicHeight())
.eq(ObjUtil.isNotEmpty(req.getPicSize()), Picture::getPicSize, req.getPicSize())
.eq(ObjUtil.isNotEmpty(req.getPicScale()), Picture::getPicScale, req.getPicScale())
.ge(ObjUtil.isNotEmpty(req.getStartEditTime()), Picture::getEditTime, req.getStartEditTime())
.lt(ObjUtil.isNotEmpty(req.getEndEditTime()), Picture::getEditTime, req.getEndEditTime());
// 全字段模糊搜索
if (StrUtil.isNotBlank(req.getSearchText())) {
qw.and(w -> w
.like(Picture::getName, req.getSearchText())
.or()
.like(Picture::getIntroduction, req.getSearchText())
);
}
// JSON 数组 tags 查询
if (CollUtil.isNotEmpty(req.getTags())) {
req.getTags().forEach(tag ->
qw.like(Picture::getTags, "\"" + tag + "\"")
);
}
// 动态排序:转下划线字段名并手工拼接
if (StrUtil.isNotBlank(req.getSortField())) {
String column = StrUtil.toUnderlineCase(req.getSortField());
String direction = "ascend".equalsIgnoreCase(req.getSortOrder()) ? "ASC" : "DESC";
qw.last("ORDER BY " + column + " " + direction);
}
return qw;
}
@Override
public PictureVO getPictureVO(Picture picture, HttpServletRequest request) {
// 对象转封装类
PictureVO pictureVO = PictureVO.objToVo(picture);
// 关联查询用户信息
Long userId = picture.getUserId();
if (userId != null && userId > 0) {
User user = userService.getById(userId);
UserVO userVO = userService.getUserVO(user);
pictureVO.setUser(userVO);
}
return pictureVO;
}
@Override
public Page<PictureVO> getPictureVOPage(Page<Picture> picturePage, HttpServletRequest request) {
List<Picture> pictureList = picturePage.getRecords();
Page<PictureVO> pictureVOPage = new Page<>(picturePage.getCurrent(), picturePage.getSize(), picturePage.getTotal());
if (CollUtil.isEmpty(pictureList)) {
return pictureVOPage;
}
// 对象列表 => 封装对象列表
List<PictureVO> pictureVOList = pictureList.stream()
.map(PictureVO::objToVo)
.collect(Collectors.toList());
// 1. 关联查询用户信息
// 1,2,3,4
Set<Long> userIdSet = pictureList.stream().map(Picture::getUserId).collect(Collectors.toSet());
// 1 => user1, 2 => user2
Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
.collect(Collectors.groupingBy(User::getId));
// 2. 填充信息
pictureVOList.forEach(pictureVO -> {
Long userId = pictureVO.getUserId();
User user = null;
if (userIdUserListMap.containsKey(userId)) {
user = userIdUserListMap.get(userId).get(0);
}
pictureVO.setUser(userService.getUserVO(user));
});
pictureVOPage.setRecords(pictureVOList);
return pictureVOPage;
}
}