From 47978101624c5e1c057ffd41c3002252f1877931 Mon Sep 17 00:00:00 2001 From: glx <783262171@qq.com> Date: Wed, 20 May 2026 15:50:34 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=86=E5=85=BB=E6=97=A5=E8=AE=B0=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../freemarker/MyBatisPlusGenerator.java | 1 + .../boot/common/enums/LogModuleEnum.java | 4 +- .../controller/AdoptionDiaryController.java | 21 +- .../mini/mapper/MiniAdoptionDiaryMapper.java | 15 + .../mapper/MiniAdoptionDiaryMediaMapper.java | 14 + .../model/dto/DeleteAdoptionDiaryDTO.java | 21 ++ .../dto/DeleteAdoptionDiaryMediaDTO.java | 29 ++ .../mini/model/entity/MiniAdoptionDiary.java | 6 +- .../model/entity/MiniAdoptionDiaryMedia.java | 94 +++++ .../mini/model/form/AdoptionDiaryForm.java | 29 +- .../mini/model/vo/AdoptionDiaryDetailsVO.java | 17 + .../boot/mini/model/vo/AdoptionDiaryVO.java | 63 ++++ .../model/vo/MiniAdoptionDiaryMediaVO.java | 35 ++ .../mini/service/AdoptionDiaryService.java | 7 +- .../impl/AdoptionDiaryServiceImpl.java | 352 +++++++++++++++++- .../mapper/mini/MiniAdoptionDiaryMapper.xml | 137 +++++++ .../mini/MiniAdoptionDiaryMediaMapper.xml | 9 + 17 files changed, 828 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMediaMapper.java create mode 100644 src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiaryMedia.java create mode 100644 src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryDetailsVO.java create mode 100644 src/main/java/com/youlai/boot/mini/model/vo/MiniAdoptionDiaryMediaVO.java create mode 100644 src/main/resources/mapper/mini/MiniAdoptionDiaryMediaMapper.xml diff --git a/src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java b/src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java index 35d4156..d0b3131 100644 --- a/src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java +++ b/src/main/java/com/youlai/boot/codegen/freemarker/MyBatisPlusGenerator.java @@ -105,6 +105,7 @@ public class MyBatisPlusGenerator { ,new TableConfig("mini_stray_animal_note_collect", IdType.AUTO, "mini") ,new TableConfig("mini_stray_animal_note_view", IdType.AUTO, "mini") ,new TableConfig("mini_adoption_diary", IdType.AUTO, "mini") + ,new TableConfig("mini_adoption_diary_media", IdType.AUTO, "mini") // ,new TableConfig("mini_stray_animal", IdType.AUTO, "mini") // ,new TableConfig("mini_stray_animal", IdType.INPUT, "minitest") diff --git a/src/main/java/com/youlai/boot/common/enums/LogModuleEnum.java b/src/main/java/com/youlai/boot/common/enums/LogModuleEnum.java index 194761c..6c12cd2 100644 --- a/src/main/java/com/youlai/boot/common/enums/LogModuleEnum.java +++ b/src/main/java/com/youlai/boot/common/enums/LogModuleEnum.java @@ -33,8 +33,8 @@ public enum LogModuleEnum implements IBaseEnum { POINT_RECORD(101, "积分流水"), POINT_RULE(102, "积分规则"), SIGN_RECORD(103, "签到记录"), - STRAY_ANIMAL_NOTE_COMMENT(104, "流浪动物笔记评论"), - ADOPTION_DIARY_INFO(105, "领养日记信息"); + STRAY_ANIMAL_NOTE_COMMENT(110, "流浪动物笔记评论"), + ADOPTION_DIARY_INFO(112, "领养日记信息"); @EnumValue private final Integer value; diff --git a/src/main/java/com/youlai/boot/mini/controller/AdoptionDiaryController.java b/src/main/java/com/youlai/boot/mini/controller/AdoptionDiaryController.java index dcfd179..46b3f78 100644 --- a/src/main/java/com/youlai/boot/mini/controller/AdoptionDiaryController.java +++ b/src/main/java/com/youlai/boot/mini/controller/AdoptionDiaryController.java @@ -11,8 +11,7 @@ import com.youlai.boot.mini.model.dto.*; import com.youlai.boot.mini.model.form.AdoptionDiaryForm; import com.youlai.boot.mini.model.query.OwnAdoptionDiaryQuery; import com.youlai.boot.mini.model.vo.AdoptionDiaryVO; -import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; -import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO; +import com.youlai.boot.mini.model.vo.AdoptionDiaryDetailsVO; import com.youlai.boot.mini.service.AdoptionDiaryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -29,6 +28,7 @@ import java.util.List; @RestController @RequestMapping("/api/v1/mini/adoptionDiary") @RequiredArgsConstructor + public class AdoptionDiaryController { private final AdoptionDiaryService adoptionDiaryService; @@ -51,8 +51,8 @@ public class AdoptionDiaryController { public Result saveAdoptionDiary( @Valid @RequestBody AdoptionDiaryForm formData ) { - SaveStrayAnimalVO vo = adoptionDiaryService.saveAdoptionDiary(formData); - return Result.success(vo); + String diaryUuid = adoptionDiaryService.saveAdoptionDiary(formData); + return Result.success(diaryUuid); } @Operation(summary = "编辑领养日记信息(不包含图片/视频媒体资源)") @@ -121,12 +121,11 @@ public class AdoptionDiaryController { return PageResult.success(adoptionDiaryService.getSelfCreatedPage(queryParams)); } - @Operation(summary = "获取领养日记详情") - @RequestMapping(value = "/getDetails/{animalUuid}", method = RequestMethod.GET) - public Result getDetails( - @PathVariable String animalUuid){ - return Result.success(adoptionDiaryService.getDetails(animalUuid, SecurityUtils.getUserId())); - } - +// @Operation(summary = "获取领养日记详情") +// @RequestMapping(value = "/getDetails/{animalUuid}", method = RequestMethod.GET) +// public Result getDetails( +// @PathVariable String diaryUuid){ +// return Result.success(adoptionDiaryService.getDetails(diaryUuid, SecurityUtils.getUserId())); +// } } diff --git a/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMapper.java b/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMapper.java index f7b445c..cc9df4f 100644 --- a/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMapper.java +++ b/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMapper.java @@ -1,7 +1,12 @@ package com.youlai.boot.mini.mapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.youlai.boot.mini.model.entity.MiniAdoptionDiary; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.boot.mini.model.query.OwnAdoptionDiaryQuery; +import com.youlai.boot.mini.model.vo.AdoptionDiaryVO; +import org.apache.ibatis.annotations.Param; /** * 领养日记表 Mapper 接口 @@ -11,4 +16,14 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface MiniAdoptionDiaryMapper extends BaseMapper { + /** + * 分页查询领养日记列表 + */ + IPage getDiaryPage(Page page, @Param("query") OwnAdoptionDiaryQuery query); + + /** + * 查询领养日记详情 + */ + AdoptionDiaryVO getDiaryDetails(@Param("diaryUuid") String diaryUuid, @Param("miniUserId") Long miniUserId); + } diff --git a/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMediaMapper.java b/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMediaMapper.java new file mode 100644 index 0000000..73da2b0 --- /dev/null +++ b/src/main/java/com/youlai/boot/mini/mapper/MiniAdoptionDiaryMediaMapper.java @@ -0,0 +1,14 @@ +package com.youlai.boot.mini.mapper; + +import com.youlai.boot.mini.model.entity.MiniAdoptionDiaryMedia; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* 领养日记资源表 Mapper 接口 +* +* @author jwy +* @since +*/ +public interface MiniAdoptionDiaryMediaMapper extends BaseMapper { + +} diff --git a/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryDTO.java b/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryDTO.java index 41a9b4c..73099e1 100644 --- a/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryDTO.java +++ b/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryDTO.java @@ -1,7 +1,28 @@ package com.youlai.boot.mini.model.dto; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import lombok.Data; +import java.util.List; + @Data public class DeleteAdoptionDiaryDTO { + + @NotEmpty(message = "uuid不能为空") + @ArraySchema( + arraySchema = @Schema( + description = "领养日记uuid列表", + example = "[\"uuid1\",\"uuid2\"]", + requiredMode = Schema.RequiredMode.REQUIRED + ), + schema = @Schema( + description = "领养日记uuid", + example = "uuid1" + ) + ) + private List<@NotBlank(message = "uuid不能为空") String> diaryUuidList; + } diff --git a/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryMediaDTO.java b/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryMediaDTO.java index 5895d6b..9148159 100644 --- a/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryMediaDTO.java +++ b/src/main/java/com/youlai/boot/mini/model/dto/DeleteAdoptionDiaryMediaDTO.java @@ -1,7 +1,36 @@ package com.youlai.boot.mini.model.dto; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import lombok.Data; +import java.util.List; + @Data public class DeleteAdoptionDiaryMediaDTO { + + @NotEmpty(message = "媒体资源uuid不能为空") + @ArraySchema( + arraySchema = @Schema( + description = "领养日记媒体资源uuid列表", + example = "[\"uuid1\",\"uuid2\"]", + requiredMode = Schema.RequiredMode.REQUIRED + ), + schema = @Schema( + description = "媒体资源uuid", + example = "uuid1" + ) + ) + private List<@NotBlank(message = "uuid不能为空") String> diaryMediaUuidList; + + @NotBlank(message = "领养日记uuid不能为空") + @Schema( + description = "领养日记uuid", + example = "2d7890db8a6e47016ccef2d679d5a2c8", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private String diaryUuid; + } diff --git a/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java b/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java index c165154..6b2708f 100644 --- a/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java +++ b/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; public class MiniAdoptionDiary implements Serializable { @TableId(value = "id", type = IdType.AUTO) - @Schema(description = "笔记ID") + @Schema(description = "领养日记主键ID") private Long id; @@ -37,11 +37,11 @@ public class MiniAdoptionDiary implements Serializable { private Long miniUserId; @TableField("title") - @Schema(description = "笔记标题") + @Schema(description = "领养日记标题") private String title; @TableField("content") - @Schema(description = "笔记正文内容") + @Schema(description = "领养日记正文内容") private String content; @TableField("visibility") diff --git a/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiaryMedia.java b/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiaryMedia.java new file mode 100644 index 0000000..094b8b7 --- /dev/null +++ b/src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiaryMedia.java @@ -0,0 +1,94 @@ +package com.youlai.boot.mini.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +@Getter +@Setter +@ToString +@Accessors(chain = true) +@TableName("mini_adoption_diary_media") +@Schema(description = "领养日记资源表") +public class MiniAdoptionDiaryMedia implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + @Schema(description = "领养日记媒体主键id") + private Long id; + + + @TableField("uuid") + @Schema(description = "uuid唯一标识,前后端用这个进行数据交互") + private String uuid; + + @TableField("diary_id") + @Schema(description = "领养日记ID") + private Long diaryId; + + @TableField("media_type") + @Schema(description = "媒体类型,image-图片,video-视频") + private String mediaType; + + @TableField("source_url") + @Schema(description = "资源URL") + private String sourceUrl; + + @TableField("storage_key") + @Schema(description = "对象存储中的key") + private String storageKey; + + @TableField("thumbnail_url") + @Schema(description = "缩略图URL(视频需要)") + private String thumbnailUrl; + + @TableField("width") + @Schema(description = "宽度(像素)") + private Integer width; + + @TableField("height") + @Schema(description = "高度(像素)") + private Integer height; + + @TableField("duration") + @Schema(description = "时长(秒,视频用)") + private Integer duration; + + @TableField("create_time") + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + @TableField("create_timestamp") + @Schema(description = "创建时间毫秒级时间戳") + private Long createTimestamp; + + @TableField("create_by") + @Schema(description = "创建人ID") + private Long createBy; + + @TableField("update_time") + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + + @TableField("update_timestamp") + @Schema(description = "更新时间毫秒级时间戳") + private Long updateTimestamp; + + @TableField("update_by") + @Schema(description = "修改人ID") + private Long updateBy; + + @TableField("is_deleted") + @Schema(description = "逻辑删除标识(0-未删除 1-已删除)") + private Boolean deleted; + + +} diff --git a/src/main/java/com/youlai/boot/mini/model/form/AdoptionDiaryForm.java b/src/main/java/com/youlai/boot/mini/model/form/AdoptionDiaryForm.java index 3072c00..beb22d8 100644 --- a/src/main/java/com/youlai/boot/mini/model/form/AdoptionDiaryForm.java +++ b/src/main/java/com/youlai/boot/mini/model/form/AdoptionDiaryForm.java @@ -1,9 +1,36 @@ package com.youlai.boot.mini.model.form; +import com.youlai.boot.common.annotation.EnumValid; +import com.youlai.boot.mini.model.enums.VisibilityEnum; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; @Data -@Schema(description = "评论点赞请求参数") +@Schema(description = "领养日记表单对象") public class AdoptionDiaryForm { + + @NotNull(message = "关联的动物ID不能为空") + @Schema(description = "关联的流浪动物ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long strayAnimalId; + + @NotBlank(message = "日记标题不能为空") + @Length(max = 200, message = "标题不能超过200个字符") + @Schema(description = "领养日记标题", example = "我家猫猫到家的第一个月", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + + @Schema(description = "领养日记正文内容", example = "今天是猫猫到家的第30天,已经完全适应新家了~") + private String content; + + @NotBlank(message = "可见性范围不能为空") + @EnumValid(enumClass = VisibilityEnum.class, message = "可见性范围不合法") + @Schema(description = "可见性范围:public-公开,private-仅自己,friends-仅好友", example = "public") + private String visibility; + + @Schema(description = "上传的媒体资源URL列表") + private List mediaUrlList; } diff --git a/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryDetailsVO.java b/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryDetailsVO.java new file mode 100644 index 0000000..c8b75ea --- /dev/null +++ b/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryDetailsVO.java @@ -0,0 +1,17 @@ +package com.youlai.boot.mini.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +public class AdoptionDiaryDetailsVO { + + @Schema(description = "图片信息", example = "[]") + private List images; + + @Schema(description = "视频信息", example = "[]") + private List videos; + +} diff --git a/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryVO.java b/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryVO.java index 0c29bed..214ef56 100644 --- a/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryVO.java +++ b/src/main/java/com/youlai/boot/mini/model/vo/AdoptionDiaryVO.java @@ -1,7 +1,70 @@ package com.youlai.boot.mini.model.vo; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.Date; + @Data public class AdoptionDiaryVO { + + @Schema(description = "领养日记ID", hidden = true) + private Long id; + + @Schema(description = "作者uuid") + private String authorUuid; + + @Schema(description = "作者昵称") + private String authorName; + + @Schema(description = "作者头像") + private String authorAvatar; + + @Schema(description = "领养日记UUID", requiredMode = Schema.RequiredMode.REQUIRED) + private String diaryUuid; + + @Schema(description = "关联的流浪动物UUID") + private String animalUuid; + + @Schema(description = "关联的流浪动物名称") + private String animalName; + + @Schema(description = "封面图片url") + private String firstImageUrl; + + @Schema(description = "日记标题", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + + @Schema(description = "日记内容摘要") + private String content; + + @Schema(description = "可见性范围:public-公开,private-仅自己,friends-仅好友", example = "public") + private String visibility; + + @Schema(description = "浏览数") + private Integer viewCount; + + @Schema(description = "点赞数") + private Integer likeCount; + + @Schema(description = "评论数") + private Integer commentCount; + + @Schema(description = "收藏数") + private Integer collectCount; + + @Schema(description = "当前用户是否已点赞") + private Boolean isLiked; + + @Schema(description = "当前用户是否收藏") + private Boolean isCollected; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + @Schema(description = "审核状态:0通过,1审核中,2审核未通过", example = "0") + private Integer auditStatus; + } diff --git a/src/main/java/com/youlai/boot/mini/model/vo/MiniAdoptionDiaryMediaVO.java b/src/main/java/com/youlai/boot/mini/model/vo/MiniAdoptionDiaryMediaVO.java new file mode 100644 index 0000000..09a5c36 --- /dev/null +++ b/src/main/java/com/youlai/boot/mini/model/vo/MiniAdoptionDiaryMediaVO.java @@ -0,0 +1,35 @@ +package com.youlai.boot.mini.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class MiniAdoptionDiaryMediaVO { + + @Schema(type = "string", description = "资源ID") + private String diaryMediaUuid; + + @Schema(type = "string", description = "领养日记UUID", example = "0677d62d63ec693bf1bd6dab8a877dc1", requiredMode = Schema.RequiredMode.REQUIRED) + private String diaryUuid; + + @Schema(description = "媒体类型,image-图片,video-视频") + private String mediaType; + + @Schema(description = "资源URL") + private String sourceUrl; + + @Schema(description = "对象存储中的key") + private String storageKey; + + @Schema(description = "缩略图URL(视频需要)") + private String thumbnailUrl; + + @Schema(description = "宽度(像素)") + private Integer width; + + @Schema(description = "高度(像素)") + private Integer height; + + @Schema(description = "时长(秒,视频用)") + private Integer duration; +} diff --git a/src/main/java/com/youlai/boot/mini/service/AdoptionDiaryService.java b/src/main/java/com/youlai/boot/mini/service/AdoptionDiaryService.java index 9392b2c..53c9ae2 100644 --- a/src/main/java/com/youlai/boot/mini/service/AdoptionDiaryService.java +++ b/src/main/java/com/youlai/boot/mini/service/AdoptionDiaryService.java @@ -1,5 +1,6 @@ package com.youlai.boot.mini.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryDTO; import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryMediaDTO; @@ -19,7 +20,7 @@ public interface AdoptionDiaryService extends IService { List saveFile(List images, List videos); - SaveStrayAnimalVO saveAdoptionDiary(@Valid AdoptionDiaryForm formData); + String saveAdoptionDiary(@Valid AdoptionDiaryForm formData); void updateAdoptionDiary(String diaryUuid, AdoptionDiaryForm formData); @@ -31,8 +32,8 @@ public interface AdoptionDiaryService extends IService { void delete(DeleteAdoptionDiaryDTO deleteAdoptionDiaryDTO); - List getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams); + IPage getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams); - StrayAnimalDetailsVO getDetails(String animalUuid, Long userId); +// AdoptionDiaryVO getDetails(String diaryUuid, Long userId); } diff --git a/src/main/java/com/youlai/boot/mini/service/impl/AdoptionDiaryServiceImpl.java b/src/main/java/com/youlai/boot/mini/service/impl/AdoptionDiaryServiceImpl.java index 7038d14..dff0455 100644 --- a/src/main/java/com/youlai/boot/mini/service/impl/AdoptionDiaryServiceImpl.java +++ b/src/main/java/com/youlai/boot/mini/service/impl/AdoptionDiaryServiceImpl.java @@ -1,64 +1,404 @@ package com.youlai.boot.mini.service.impl; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.boot.common.exception.MsgException; +import com.youlai.boot.common.util.FileUtils; +import com.youlai.boot.common.util.JavaVCUtils; +import com.youlai.boot.common.util.RandomNumberUtils; +import com.youlai.boot.file.service.impl.AliyunFileService; +import com.youlai.boot.framework.security.util.SecurityUtils; import com.youlai.boot.mini.mapper.MiniAdoptionDiaryMapper; +import com.youlai.boot.mini.mapper.MiniAdoptionDiaryMediaMapper; import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryDTO; import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryMediaDTO; import com.youlai.boot.mini.model.dto.EditVisibilityDTO; import com.youlai.boot.mini.model.entity.MiniAdoptionDiary; +import com.youlai.boot.mini.model.entity.MiniAdoptionDiaryMedia; +import com.youlai.boot.mini.model.enums.AnimalNoteMediaTypeEnum; import com.youlai.boot.mini.model.form.AdoptionDiaryForm; import com.youlai.boot.mini.model.query.OwnAdoptionDiaryQuery; import com.youlai.boot.mini.model.vo.AdoptionDiaryVO; -import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; import com.youlai.boot.mini.service.AdoptionDiaryService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.UUID; +@Slf4j @Service +@RequiredArgsConstructor public class AdoptionDiaryServiceImpl extends ServiceImpl implements AdoptionDiaryService { + private final AliyunFileService aliyunFileService; + private final MiniAdoptionDiaryMediaMapper miniAdoptionDiaryMediaMapper; + + private final static String OSS_THUMBNAIL_DIR = "adoption_diary/thumbnail/"; + private final static String OSS_IMAGE_DIR = "adoption_diary/image/"; + private final static String OSS_VIDEO_DIR = "adoption_diary/video/"; + + @Value("${oss.aliyun.endpoint}") + private String endpoint; + + @Value("${oss.aliyun.bucket-name}") + private String bucketName; + + public String getDefaultCoverHost() { + return "https://" + bucketName + "." + endpoint; + } @Override public List saveFile(List images, List videos) { - return List.of(); + long currentTimestamp = System.currentTimeMillis(); + List urlList = new ArrayList<>(); + // 处理图片 + if (CollUtil.isNotEmpty(images)) { + for (MultipartFile image : images) { + try { + String objectName = OSS_IMAGE_DIR + + currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8) + + "." + + FilenameUtils.getExtension(image.getOriginalFilename()); + String url = aliyunFileService.uploadFile(objectName, image.getInputStream()); + MiniAdoptionDiaryMedia media = new MiniAdoptionDiaryMedia(); + media.setUuid(UUID.randomUUID().toString()); + media.setMediaType(AnimalNoteMediaTypeEnum.IMAGE.name().toLowerCase()); + media.setSourceUrl(url); + media.setStorageKey(objectName); + BufferedImage imageInfo = ImageIO.read(image.getInputStream()); + media.setWidth(imageInfo.getWidth()); + media.setHeight(imageInfo.getHeight()); + media.setCreateTimestamp(currentTimestamp); + media.setCreateTime(new Date(currentTimestamp)); + media.setCreateBy(SecurityUtils.getUserId()); + + int result = miniAdoptionDiaryMediaMapper.insert(media); + if (result > 0) { + urlList.add(url); + } + } catch (Exception e) { + log.error("领养日记图片上传失败", e); + } + } + } + + // 处理视频 (如果有) + if (CollUtil.isNotEmpty(videos)) { + String tmpPath = System.getProperty("user.dir") + "/tmp"; + for (MultipartFile video : videos) { + try { + String fileName = currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8); + String objectName = OSS_VIDEO_DIR + + fileName + + "." + + FilenameUtils.getExtension(video.getOriginalFilename()); + String url = aliyunFileService.uploadFile(objectName, video.getInputStream()); + MiniAdoptionDiaryMedia media = new MiniAdoptionDiaryMedia(); + media.setUuid(UUID.randomUUID().toString()); + media.setMediaType(AnimalNoteMediaTypeEnum.VIDEO.name().toLowerCase()); + media.setSourceUrl(url); + media.setStorageKey(objectName); + media.setCreateTimestamp(currentTimestamp); + media.setCreateTime(new Date(currentTimestamp)); + media.setCreateBy(SecurityUtils.getUserId()); + //时长 + FileUtils.saveFile(video, tmpPath, fileName); + String videoPath = tmpPath + File.separator + fileName; + double duration = JavaVCUtils.getVideoDuration(videoPath); + media.setDuration((int) Math.ceil(duration)); + //缩略图 + BufferedImage thumbnail = JavaVCUtils.getVideoThumbnail(videoPath, 1); + String thumbnailFileName = currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8); + String thumbnailObjectName = OSS_THUMBNAIL_DIR + + thumbnailFileName + + ".png"; + String thumbnailUrl = aliyunFileService.uploadFile(thumbnailObjectName, + FileUtils.bufferedImageToInputStream(thumbnail, "png")); + media.setThumbnailUrl(thumbnailUrl); + + int result = miniAdoptionDiaryMediaMapper.insert(media); + if (result > 0) { + urlList.add(url); + } + + FileUtils.delete(videoPath); + } catch (Exception e) { + log.error("领养日记视频上传失败", e); + } + } + } + return urlList; } @Override - public SaveStrayAnimalVO saveAdoptionDiary(AdoptionDiaryForm formData) { - return null; + @Transactional(rollbackFor = Exception.class) + public String saveAdoptionDiary(AdoptionDiaryForm formData) { + long currentTimestamp = System.currentTimeMillis(); + Long userId = SecurityUtils.getUserId(); + + // 1. 保存领养日记基本信息 + MiniAdoptionDiary diary = new MiniAdoptionDiary(); + diary.setUuid(UUID.randomUUID().toString()); + diary.setMiniUserId(userId); + diary.setStrayAnimalId(formData.getStrayAnimalId()); + diary.setTitle(formData.getTitle()); + diary.setContent(formData.getContent()); + diary.setVisibility(formData.getVisibility()); + diary.setViewCount(0); + diary.setLikeCount(0); + diary.setCommentCount(0); + diary.setCollectCount(0); + diary.setCreateBy(userId); + diary.setCreateTime(new Date(currentTimestamp)); + diary.setCreateTimestamp(currentTimestamp); + diary.setDeleted(false); + save(diary); + + // 2. 关联之前上传的媒体文件 + if (CollUtil.isNotEmpty(formData.getMediaUrlList())) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.in(MiniAdoptionDiaryMedia::getSourceUrl, formData.getMediaUrlList()) + .isNull(MiniAdoptionDiaryMedia::getDiaryId) + .set(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()); + miniAdoptionDiaryMediaMapper.update(null, wrapper); + } + + // 3.返回领养日记uuid + return diary.getUuid(); } @Override public void updateAdoptionDiary(String diaryUuid, AdoptionDiaryForm formData) { + MiniAdoptionDiary diary = lambdaQuery().eq(MiniAdoptionDiary::getUuid, diaryUuid).one(); + if (diary == null) { + return; + } + long currentTimestamp = System.currentTimeMillis(); + // 更新基本信息 + diary.setTitle(formData.getTitle()); + diary.setContent(formData.getContent()); + diary.setUpdateBy(SecurityUtils.getUserId()); + diary.setUpdateTime(new Date(currentTimestamp)); + diary.setUpdateTimestamp(currentTimestamp); + updateById(diary); + // 关联新的媒体文件 + if (CollUtil.isNotEmpty(formData.getMediaUrlList())) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.in(MiniAdoptionDiaryMedia::getSourceUrl, formData.getMediaUrlList()) + .isNull(MiniAdoptionDiaryMedia::getDiaryId) + .set(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()); + miniAdoptionDiaryMediaMapper.update(null, wrapper); + } } @Override + @Transactional(rollbackFor = Exception.class) public void deleteMediaSource(DeleteAdoptionDiaryMediaDTO deleteAdoptionDiaryMediaDTO) { + List diaryMediaUuidList = deleteAdoptionDiaryMediaDTO.getDiaryMediaUuidList(); + Long userId = SecurityUtils.getUserId(); + // 校验领养日记是否存在 + MiniAdoptionDiary diary = lambdaQuery() + .eq(MiniAdoptionDiary::getUuid, deleteAdoptionDiaryMediaDTO.getDiaryUuid()) + .eq(MiniAdoptionDiary::getDeleted, false) + .one(); + if (diary == null) { + throw new MsgException("领养日记不存在"); + } + + // 查询要删除的媒体资源 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(MiniAdoptionDiaryMedia::getUuid, diaryMediaUuidList) + .eq(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()) + .eq(MiniAdoptionDiaryMedia::getDeleted, false); + + List mediaList = miniAdoptionDiaryMediaMapper.selectList(queryWrapper); + + if (CollectionUtils.isNotEmpty(mediaList)) { + // 删除阿里云OSS源文件 + List storageKeyList = mediaList.stream() + .map(MiniAdoptionDiaryMedia::getStorageKey) + .toList(); + aliyunFileService.deleteMultiFile(storageKeyList); + + long currentTimestamp = System.currentTimeMillis(); + + // 逻辑删除数据库记录 + miniAdoptionDiaryMediaMapper.update( + null, + new LambdaUpdateWrapper() + .in(MiniAdoptionDiaryMedia::getUuid, diaryMediaUuidList) + .eq(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()) + .set(MiniAdoptionDiaryMedia::getDeleted, true) + .set(MiniAdoptionDiaryMedia::getUpdateTimestamp, currentTimestamp) + .set(MiniAdoptionDiaryMedia::getUpdateTime, new Date(currentTimestamp)) + .set(MiniAdoptionDiaryMedia::getUpdateBy, userId) + ); + } } @Override public void saveMediaSource(String diaryUuid, List images, List videos) { + MiniAdoptionDiary diary = lambdaQuery().eq(MiniAdoptionDiary::getUuid, diaryUuid).one(); + if (diary == null) { + return; + } + long currentTimestamp = System.currentTimeMillis(); + // 处理图片 + if (CollUtil.isNotEmpty(images)) { + for (MultipartFile image : images) { + try { + String objectName = OSS_IMAGE_DIR + + currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8) + + "." + + FilenameUtils.getExtension(image.getOriginalFilename()); + String url = aliyunFileService.uploadFile(objectName, image.getInputStream()); + MiniAdoptionDiaryMedia media = new MiniAdoptionDiaryMedia(); + media.setUuid(UUID.randomUUID().toString()); + media.setDiaryId(diary.getId()); + media.setMediaType(AnimalNoteMediaTypeEnum.IMAGE.name().toLowerCase()); + media.setSourceUrl(url); + media.setStorageKey(objectName); + BufferedImage imageInfo = ImageIO.read(image.getInputStream()); + media.setWidth(imageInfo.getWidth()); + media.setHeight(imageInfo.getHeight()); + media.setCreateTimestamp(currentTimestamp); + media.setCreateTime(new Date(currentTimestamp)); + media.setCreateBy(SecurityUtils.getUserId()); + miniAdoptionDiaryMediaMapper.insert(media); + } catch (Exception e) { + log.error("领养日记补充图片上传失败", e); + } + } + } + // 处理视频 + if (CollUtil.isNotEmpty(videos)) { + String tmpPath = System.getProperty("user.dir") + "/tmp"; + for (MultipartFile video : videos) { + try { + String fileName = currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8); + String objectName = OSS_VIDEO_DIR + + fileName + + "." + + FilenameUtils.getExtension(video.getOriginalFilename()); + String url = aliyunFileService.uploadFile(objectName, video.getInputStream()); + MiniAdoptionDiaryMedia media = new MiniAdoptionDiaryMedia(); + media.setUuid(UUID.randomUUID().toString()); + media.setDiaryId(diary.getId()); + media.setMediaType(AnimalNoteMediaTypeEnum.VIDEO.name().toLowerCase()); + media.setSourceUrl(url); + media.setStorageKey(objectName); + media.setCreateTimestamp(currentTimestamp); + media.setCreateTime(new Date(currentTimestamp)); + media.setCreateBy(SecurityUtils.getUserId()); + // 时长 + FileUtils.saveFile(video, tmpPath, fileName); + String videoPath = tmpPath + File.separator + fileName; + double duration = JavaVCUtils.getVideoDuration(videoPath); + media.setDuration((int) Math.ceil(duration)); + // 缩略图 + BufferedImage thumbnail = JavaVCUtils.getVideoThumbnail(videoPath, 1); + String thumbnailFileName = currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8); + String thumbnailObjectName = OSS_THUMBNAIL_DIR + + thumbnailFileName + + ".png"; + String thumbnailUrl = aliyunFileService.uploadFile(thumbnailObjectName, + FileUtils.bufferedImageToInputStream(thumbnail, "png")); + media.setThumbnailUrl(thumbnailUrl); + miniAdoptionDiaryMediaMapper.insert(media); + FileUtils.delete(videoPath); + } catch (Exception e) { + log.error("领养日记补充视频上传失败", e); + } + } + } } @Override + @Transactional(rollbackFor = Exception.class) public void updateVisibility(String diaryUuid, EditVisibilityDTO editVisibilityDTO) { + Long userId = SecurityUtils.getUserId(); + + // 校验领养日记是否存在,且是当前用户创建的 + MiniAdoptionDiary diary = lambdaQuery() + .eq(MiniAdoptionDiary::getUuid, diaryUuid) + .eq(MiniAdoptionDiary::getMiniUserId, userId) + .eq(MiniAdoptionDiary::getDeleted, false) + .one(); + if (diary == null) { + throw new MsgException("领养日记不存在"); + } + + // 更新可见范围 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(MiniAdoptionDiary::getId, diary.getId()) + .set(MiniAdoptionDiary::getVisibility, editVisibilityDTO.getVisibility()) + .set(MiniAdoptionDiary::getUpdateTime, new Date()) + .set(MiniAdoptionDiary::getUpdateTimestamp, System.currentTimeMillis()) + .set(MiniAdoptionDiary::getUpdateBy, userId); + + update(updateWrapper); } @Override public void delete(DeleteAdoptionDiaryDTO deleteAdoptionDiaryDTO) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.in(MiniAdoptionDiary::getUuid, deleteAdoptionDiaryDTO.getDiaryUuidList()) + .set(MiniAdoptionDiary::getDeleted, 1); + update(null, updateWrapper); } @Override - public List getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams) { - return List.of(); + public IPage getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams) { + Long userId = SecurityUtils.getUserId(); + queryParams.setMiniUserId(userId); + queryParams.setCreatorId(userId); + + int pageNum = queryParams.getPageNum(); + int pageSize = queryParams.getPageSize(); + Page page = new Page<>(pageNum, pageSize); + + IPage result = baseMapper.getDiaryPage(page, queryParams); + + // 处理默认封面 + if (result.getTotal() > 0) { + result.getRecords().forEach(item -> { + if (cn.hutool.core.util.StrUtil.isBlank(item.getFirstImageUrl())) { + // 领养日记默认封面图 + item.setFirstImageUrl(getDefaultCoverHost() + "/default_diary.png"); + } + }); + } + return result; } +// @Override +// public AdoptionDiaryVO getDetails(String diaryUuid, Long userId) { +// AdoptionDiaryVO diaryVO = miniAdoptionDiaryMapper.getDiaryDetails(diaryUuid, userId); +// if (diaryVO != null && cn.hutool.core.util.StrUtil.isBlank(diaryVO.getFirstImageUrl())) { +// diaryVO.setFirstImageUrl(getDefaultCoverHost() + "/default_diary.png"); +// } +// return diaryVO; +// } } diff --git a/src/main/resources/mapper/mini/MiniAdoptionDiaryMapper.xml b/src/main/resources/mapper/mini/MiniAdoptionDiaryMapper.xml index 8184451..7ef4ed7 100644 --- a/src/main/resources/mapper/mini/MiniAdoptionDiaryMapper.xml +++ b/src/main/resources/mapper/mini/MiniAdoptionDiaryMapper.xml @@ -5,5 +5,142 @@ + + + diff --git a/src/main/resources/mapper/mini/MiniAdoptionDiaryMediaMapper.xml b/src/main/resources/mapper/mini/MiniAdoptionDiaryMediaMapper.xml new file mode 100644 index 0000000..84d3a58 --- /dev/null +++ b/src/main/resources/mapper/mini/MiniAdoptionDiaryMediaMapper.xml @@ -0,0 +1,9 @@ + + + + + + +