图片模块

This commit is contained in:
huangge1199 2025-07-28 14:33:30 +08:00
parent 9c0c536f57
commit d39b589aca
10 changed files with 491 additions and 35 deletions

View File

@ -1,21 +1,33 @@
package com.huangge1199.picture.controller;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huangge1199.picture.annotation.AuthCheck;
import com.huangge1199.picture.common.DeleteRequest;
import com.huangge1199.picture.common.R;
import com.huangge1199.picture.constant.UserConstant;
import com.huangge1199.picture.exception.ErrorCode;
import com.huangge1199.picture.exception.MyException;
import com.huangge1199.picture.exception.ThrowUtils;
import com.huangge1199.picture.model.Picture;
import com.huangge1199.picture.model.dto.picture.PictureEditRequest;
import com.huangge1199.picture.model.dto.picture.PictureQueryRequest;
import com.huangge1199.picture.model.dto.picture.PictureUpdateRequest;
import com.huangge1199.picture.model.dto.picture.PictureUploadRequest;
import com.huangge1199.picture.model.entity.User;
import com.huangge1199.picture.model.vo.PictureTagCategory;
import com.huangge1199.picture.model.vo.PictureVO;
import com.huangge1199.picture.service.PictureService;
import com.huangge1199.picture.service.UserService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 图片
@ -47,4 +59,153 @@ public class PictureController {
return R.ok(pictureVO);
}
/**
* 删除图片
*/
@PostMapping("/delete")
public R<Boolean> deletePicture(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
if (deleteRequest == null || deleteRequest.getId() <= 0) {
throw new MyException(ErrorCode.PARAMS_ERROR);
}
User loginUser = userService.getLoginUser(request);
long id = deleteRequest.getId();
// 判断是否存在
Picture oldPicture = pictureService.getById(id);
ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可删除
if (!oldPicture.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
throw new MyException(ErrorCode.NO_AUTH_ERROR);
}
// 操作数据库
boolean result = pictureService.removeById(id);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return R.ok(true);
}
/**
* 更新图片仅管理员可用
*/
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public R<Boolean> updatePicture(@RequestBody PictureUpdateRequest pictureUpdateRequest) {
if (pictureUpdateRequest == null || pictureUpdateRequest.getId() <= 0) {
throw new MyException(ErrorCode.PARAMS_ERROR);
}
// 将实体类和 DTO 进行转换
Picture picture = new Picture();
BeanUtils.copyProperties(pictureUpdateRequest, picture);
// 注意将 list 转为 string
picture.setTags(JSONUtil.toJsonStr(pictureUpdateRequest.getTags()));
// 数据校验
pictureService.validPicture(picture);
// 判断是否存在
long id = pictureUpdateRequest.getId();
Picture oldPicture = pictureService.getById(id);
ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR);
// 操作数据库
boolean result = pictureService.updateById(picture);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return R.ok(true);
}
/**
* 根据 id 获取图片仅管理员可用
*/
@GetMapping("/get")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public R<Picture> getPictureById(long id, HttpServletRequest request) {
ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
// 查询数据库
Picture picture = pictureService.getById(id);
ThrowUtils.throwIf(picture == null, ErrorCode.NOT_FOUND_ERROR);
// 获取封装类
return R.ok(picture);
}
/**
* 根据 id 获取图片封装类
*/
@GetMapping("/get/vo")
public R<PictureVO> getPictureVOById(long id, HttpServletRequest request) {
ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
// 查询数据库
Picture picture = pictureService.getById(id);
ThrowUtils.throwIf(picture == null, ErrorCode.NOT_FOUND_ERROR);
// 获取封装类
return R.ok(pictureService.getPictureVO(picture, request));
}
/**
* 分页获取图片列表仅管理员可用
*/
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public R<Page<Picture>> listPictureByPage(@RequestBody PictureQueryRequest pictureQueryRequest) {
long current = pictureQueryRequest.getCurrent();
long size = pictureQueryRequest.getPageSize();
// 查询数据库
Page<Picture> picturePage = pictureService.page(new Page<>(current, size),
pictureService.getQueryWrapper(pictureQueryRequest));
return R.ok(picturePage);
}
/**
* 分页获取图片列表封装类
*/
@PostMapping("/list/page/vo")
public R<Page<PictureVO>> listPictureVOByPage(@RequestBody PictureQueryRequest pictureQueryRequest,
HttpServletRequest request) {
long current = pictureQueryRequest.getCurrent();
long size = pictureQueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
// 查询数据库
Page<Picture> picturePage = pictureService.page(new Page<>(current, size),
pictureService.getQueryWrapper(pictureQueryRequest));
// 获取封装类
return R.ok(pictureService.getPictureVOPage(picturePage, request));
}
/**
* 编辑图片给用户使用
*/
@PostMapping("/edit")
public R<Boolean> editPicture(@RequestBody PictureEditRequest pictureEditRequest, HttpServletRequest request) {
if (pictureEditRequest == null || pictureEditRequest.getId() <= 0) {
throw new MyException(ErrorCode.PARAMS_ERROR);
}
// 在此处将实体类和 DTO 进行转换
Picture picture = new Picture();
BeanUtils.copyProperties(pictureEditRequest, picture);
// 注意将 list 转为 string
picture.setTags(JSONUtil.toJsonStr(pictureEditRequest.getTags()));
// 设置编辑时间
picture.setEditTime(new Date());
// 数据校验
pictureService.validPicture(picture);
User loginUser = userService.getLoginUser(request);
// 判断是否存在
long id = pictureEditRequest.getId();
Picture oldPicture = pictureService.getById(id);
ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可编辑
if (!oldPicture.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
throw new MyException(ErrorCode.NO_AUTH_ERROR);
}
// 操作数据库
boolean result = pictureService.updateById(picture);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return R.ok(true);
}
@GetMapping("/tag_category")
public R<PictureTagCategory> listPictureTagCategory() {
PictureTagCategory pictureTagCategory = new PictureTagCategory();
List<String> tagList = Arrays.asList("热门", "搞笑", "生活", "高清", "艺术", "校园", "背景", "简历", "创意");
List<String> categoryList = Arrays.asList("模板", "电商", "表情包", "素材", "海报");
pictureTagCategory.setTagList(tagList);
pictureTagCategory.setCategoryList(categoryList);
return R.ok(pictureTagCategory);
}
}

View File

@ -0,0 +1,43 @@
package com.huangge1199.picture.model.dto.picture;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* PictureUpdateRequest
*
* @author huangge1199
* @since 2025/7/26 11:18:05
*/
@Data
public class PictureEditRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 图片名称
*/
private String name;
/**
* 简介
*/
private String introduction;
/**
* 分类
*/
private String category;
/**
* 标签
*/
private List<String> tags;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,82 @@
package com.huangge1199.picture.model.dto.picture;
import com.huangge1199.picture.common.PageRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* PictureQueryRequest
*
* @author huangge1199
* @since 2025/7/26 14:52:17
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class PictureQueryRequest extends PageRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 图片名称
*/
private String name;
/**
* 简介
*/
private String introduction;
/**
* 分类
*/
private String category;
/**
* 标签
*/
private List<String> tags;
/**
* 文件体积
*/
private Long picSize;
/**
* 图片宽度
*/
private Integer picWidth;
/**
* 图片高度
*/
private Integer picHeight;
/**
* 图片比例
*/
private Double picScale;
/**
* 图片格式
*/
private String picFormat;
/**
* 搜索词同时搜名称简介等
*/
private String searchText;
/**
* 用户 id
*/
private Long userId;
private static final long serialVersionUID = 1L;
}

View File

@ -3,6 +3,7 @@ package com.huangge1199.picture.model.dto.picture;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* PictureUpdateRequest
@ -18,5 +19,26 @@ public class PictureUpdateRequest implements Serializable {
*/
private Long id;
/**
* 图片名称
*/
private String name;
/**
* 简介
*/
private String introduction;
/**
* 分类
*/
private String category;
/**
* 标签
*/
private List<String> tags;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,27 @@
package com.huangge1199.picture.model.vo;
import lombok.Data;
import java.util.List;
/**
* 图片标签分类列表视图
* PictureTagCategory
*
* @author huangge1199
* @since 2025/7/28 11:05:52
*/
@Data
public class PictureTagCategory {
/**
* 标签列表
*/
private List<String> tagList;
/**
* 分类列表
*/
private List<String> categoryList;
}

View File

@ -1,12 +1,16 @@
package com.huangge1199.picture.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huangge1199.picture.model.Picture;
import com.baomidou.mybatisplus.extension.service.IService;
import com.huangge1199.picture.model.dto.picture.PictureQueryRequest;
import com.huangge1199.picture.model.dto.picture.PictureUploadRequest;
import com.huangge1199.picture.model.entity.User;
import com.huangge1199.picture.model.vo.PictureVO;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
@ -27,4 +31,11 @@ public interface PictureService extends IService<Picture> {
PictureUploadRequest pictureUploadRequest,
User loginUser) throws Exception;
QueryWrapper<Picture> getQueryWrapper(PictureQueryRequest pictureQueryRequest);
PictureVO getPictureVO(Picture picture, HttpServletRequest request);
Page<PictureVO> getPictureVOPage(Page<Picture> picturePage, HttpServletRequest request);
void validPicture(Picture picture);
}

View File

@ -1,27 +0,0 @@
package com.huangge1199.picture.service;
import com.huangge1199.picture.model.dto.picture.PictureUploadRequest;
import com.huangge1199.picture.model.entity.User;
import com.huangge1199.picture.model.vo.PictureVO;
import org.springframework.web.multipart.MultipartFile;
/**
* PictureSevice
*
* @author huangge1199
* @since 2025/7/26 13:34:02
*/
public interface PictureSevice {
/**
* 上传图片
*
* @param multipartFile
* @param pictureUploadRequest
* @param loginUser
* @return
*/
PictureVO uploadPicture(MultipartFile multipartFile,
PictureUploadRequest pictureUploadRequest,
User loginUser);
}

View File

@ -87,10 +87,18 @@ public interface UserService extends IService<User> {
/**
* 获取查询条件
* @param userQueryRequest
*
* @param userQueryRequest 查询条件
* @return
*/
QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest);
/**
* 是否为管理员
*
* @param user
* @return
*/
boolean isAdmin(User user);
}

View File

@ -1,26 +1,36 @@
package com.huangge1199.picture.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huangge1199.picture.exception.ErrorCode;
import com.huangge1199.picture.exception.ThrowUtils;
import com.huangge1199.picture.model.Picture;
import com.huangge1199.picture.model.dto.file.UploadPictureResult;
import com.huangge1199.picture.model.dto.picture.PictureQueryRequest;
import com.huangge1199.picture.model.dto.picture.PictureUploadRequest;
import com.huangge1199.picture.model.entity.User;
import com.huangge1199.picture.model.vo.PictureVO;
import com.huangge1199.picture.model.vo.UserVO;
import com.huangge1199.picture.service.PictureService;
import com.huangge1199.picture.mapper.PictureMapper;
import com.huangge1199.picture.service.UserService;
import com.huangge1199.picture.utils.MinioUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author hyy
@ -34,6 +44,9 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
@Resource
private MinioUtil minioUtil;
@Resource
private UserService userService;
@Override
public PictureVO uploadPicture(MultipartFile multipartFile, PictureUploadRequest pictureUploadRequest, User loginUser) throws Exception {
ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
@ -83,6 +96,117 @@ public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
return PictureVO.objToVo(picture);
}
@Override
public QueryWrapper<Picture> getQueryWrapper(PictureQueryRequest pictureQueryRequest) {
QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
if (pictureQueryRequest == null) {
return queryWrapper;
}
// 从对象中取值
Long id = pictureQueryRequest.getId();
Long userId = pictureQueryRequest.getUserId();
String name = pictureQueryRequest.getName();
String introduction = pictureQueryRequest.getIntroduction();
String category = pictureQueryRequest.getCategory();
List<String> tags = pictureQueryRequest.getTags();
Long picSize = pictureQueryRequest.getPicSize();
Integer picWidth = pictureQueryRequest.getPicWidth();
Integer picHeight = pictureQueryRequest.getPicHeight();
Double picScale = pictureQueryRequest.getPicScale();
String picFormat = pictureQueryRequest.getPicFormat();
String searchText = pictureQueryRequest.getSearchText();
String sortField = pictureQueryRequest.getSortField();
String sortOrder = pictureQueryRequest.getSortOrder();
// 从多字段中搜索
if (StrUtil.isNotBlank(searchText)) {
// 需要拼接查询条件
queryWrapper.and(qw -> qw.like("name", searchText)
.or()
.like("introduction", searchText)
);
}
queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
queryWrapper.like(StrUtil.isNotBlank(name), "name", name);
queryWrapper.like(StrUtil.isNotBlank(introduction), "introduction", introduction);
queryWrapper.like(StrUtil.isNotBlank(picFormat), "picFormat", picFormat);
queryWrapper.eq(StrUtil.isNotBlank(category), "category", category);
queryWrapper.eq(ObjUtil.isNotEmpty(picWidth), "picWidth", picWidth);
queryWrapper.eq(ObjUtil.isNotEmpty(picHeight), "picHeight", picHeight);
queryWrapper.eq(ObjUtil.isNotEmpty(picSize), "picSize", picSize);
queryWrapper.eq(ObjUtil.isNotEmpty(picScale), "picScale", picScale);
// JSON 数组查询
if (CollUtil.isNotEmpty(tags)) {
for (String tag : tags) {
queryWrapper.like("tags", "\"" + tag + "\"");
}
}
// 排序
queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField);
return queryWrapper;
}
@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. 关联查询用户信息
Set<Long> userIdSet = pictureList.stream().map(Picture::getUserId).collect(Collectors.toSet());
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;
}
@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 不能为空");
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, "简介过长");
}
}
}

View File

@ -193,6 +193,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
return queryWrapper;
}
@Override
public boolean isAdmin(User user) {
return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
}
}