17 changed files with 828 additions and 26 deletions
@ -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<MiniAdoptionDiaryMedia> { |
||||
|
|
||||
|
} |
||||
@ -1,7 +1,28 @@ |
|||||
package com.youlai.boot.mini.model.dto; |
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 lombok.Data; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
@Data |
@Data |
||||
public class DeleteAdoptionDiaryDTO { |
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; |
||||
|
|
||||
} |
} |
||||
|
|||||
@ -1,7 +1,36 @@ |
|||||
package com.youlai.boot.mini.model.dto; |
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 lombok.Data; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
@Data |
@Data |
||||
public class DeleteAdoptionDiaryMediaDTO { |
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; |
||||
|
|
||||
} |
} |
||||
|
|||||
@ -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; |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -1,9 +1,36 @@ |
|||||
package com.youlai.boot.mini.model.form; |
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 io.swagger.v3.oas.annotations.media.Schema; |
||||
|
import jakarta.validation.constraints.NotBlank; |
||||
|
import jakarta.validation.constraints.NotNull; |
||||
import lombok.Data; |
import lombok.Data; |
||||
|
import org.hibernate.validator.constraints.Length; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
@Data |
@Data |
||||
@Schema(description = "评论点赞请求参数") |
@Schema(description = "领养日记表单对象") |
||||
public class AdoptionDiaryForm { |
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<String> mediaUrlList; |
||||
} |
} |
||||
|
|||||
@ -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<MiniAdoptionDiaryMediaVO> images; |
||||
|
|
||||
|
@Schema(description = "视频信息", example = "[]") |
||||
|
private List<MiniAdoptionDiaryMediaVO> videos; |
||||
|
|
||||
|
} |
||||
@ -1,7 +1,70 @@ |
|||||
package com.youlai.boot.mini.model.vo; |
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 lombok.Data; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
@Data |
@Data |
||||
public class AdoptionDiaryVO { |
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; |
||||
|
|
||||
} |
} |
||||
|
|||||
@ -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; |
||||
|
} |
||||
@ -1,64 +1,404 @@ |
|||||
package com.youlai.boot.mini.service.impl; |
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.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.MiniAdoptionDiaryMapper; |
||||
|
import com.youlai.boot.mini.mapper.MiniAdoptionDiaryMediaMapper; |
||||
import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryDTO; |
import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryDTO; |
||||
import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryMediaDTO; |
import com.youlai.boot.mini.model.dto.DeleteAdoptionDiaryMediaDTO; |
||||
import com.youlai.boot.mini.model.dto.EditVisibilityDTO; |
import com.youlai.boot.mini.model.dto.EditVisibilityDTO; |
||||
import com.youlai.boot.mini.model.entity.MiniAdoptionDiary; |
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.form.AdoptionDiaryForm; |
||||
import com.youlai.boot.mini.model.query.OwnAdoptionDiaryQuery; |
import com.youlai.boot.mini.model.query.OwnAdoptionDiaryQuery; |
||||
import com.youlai.boot.mini.model.vo.AdoptionDiaryVO; |
import com.youlai.boot.mini.model.vo.AdoptionDiaryVO; |
||||
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; |
|
||||
import com.youlai.boot.mini.service.AdoptionDiaryService; |
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.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
import org.springframework.web.multipart.MultipartFile; |
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.List; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
@Slf4j |
||||
@Service |
@Service |
||||
|
@RequiredArgsConstructor |
||||
public class AdoptionDiaryServiceImpl extends ServiceImpl<MiniAdoptionDiaryMapper, MiniAdoptionDiary> implements AdoptionDiaryService { |
public class AdoptionDiaryServiceImpl extends ServiceImpl<MiniAdoptionDiaryMapper, MiniAdoptionDiary> 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 |
@Override |
||||
public List<String> saveFile(List<MultipartFile> images, List<MultipartFile> videos) { |
public List<String> saveFile(List<MultipartFile> images, List<MultipartFile> videos) { |
||||
return List.of(); |
long currentTimestamp = System.currentTimeMillis(); |
||||
|
List<String> 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 |
@Override |
||||
public SaveStrayAnimalVO saveAdoptionDiary(AdoptionDiaryForm formData) { |
@Transactional(rollbackFor = Exception.class) |
||||
return null; |
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<MiniAdoptionDiaryMedia> 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 |
@Override |
||||
public void updateAdoptionDiary(String diaryUuid, AdoptionDiaryForm formData) { |
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<MiniAdoptionDiaryMedia> wrapper = new LambdaUpdateWrapper<>(); |
||||
|
wrapper.in(MiniAdoptionDiaryMedia::getSourceUrl, formData.getMediaUrlList()) |
||||
|
.isNull(MiniAdoptionDiaryMedia::getDiaryId) |
||||
|
.set(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()); |
||||
|
miniAdoptionDiaryMediaMapper.update(null, wrapper); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
@Override |
@Override |
||||
|
@Transactional(rollbackFor = Exception.class) |
||||
public void deleteMediaSource(DeleteAdoptionDiaryMediaDTO deleteAdoptionDiaryMediaDTO) { |
public void deleteMediaSource(DeleteAdoptionDiaryMediaDTO deleteAdoptionDiaryMediaDTO) { |
||||
|
List<String> 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<MiniAdoptionDiaryMedia> queryWrapper = new LambdaQueryWrapper<>(); |
||||
|
queryWrapper.in(MiniAdoptionDiaryMedia::getUuid, diaryMediaUuidList) |
||||
|
.eq(MiniAdoptionDiaryMedia::getDiaryId, diary.getId()) |
||||
|
.eq(MiniAdoptionDiaryMedia::getDeleted, false); |
||||
|
|
||||
|
List<MiniAdoptionDiaryMedia> mediaList = miniAdoptionDiaryMediaMapper.selectList(queryWrapper); |
||||
|
|
||||
|
if (CollectionUtils.isNotEmpty(mediaList)) { |
||||
|
// 删除阿里云OSS源文件
|
||||
|
List<String> storageKeyList = mediaList.stream() |
||||
|
.map(MiniAdoptionDiaryMedia::getStorageKey) |
||||
|
.toList(); |
||||
|
aliyunFileService.deleteMultiFile(storageKeyList); |
||||
|
|
||||
|
long currentTimestamp = System.currentTimeMillis(); |
||||
|
|
||||
|
// 逻辑删除数据库记录
|
||||
|
miniAdoptionDiaryMediaMapper.update( |
||||
|
null, |
||||
|
new LambdaUpdateWrapper<MiniAdoptionDiaryMedia>() |
||||
|
.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 |
@Override |
||||
public void saveMediaSource(String diaryUuid, List<MultipartFile> images, List<MultipartFile> videos) { |
public void saveMediaSource(String diaryUuid, List<MultipartFile> images, List<MultipartFile> 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 |
@Override |
||||
|
@Transactional(rollbackFor = Exception.class) |
||||
public void updateVisibility(String diaryUuid, EditVisibilityDTO editVisibilityDTO) { |
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<MiniAdoptionDiary> 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 |
@Override |
||||
public void delete(DeleteAdoptionDiaryDTO deleteAdoptionDiaryDTO) { |
public void delete(DeleteAdoptionDiaryDTO deleteAdoptionDiaryDTO) { |
||||
|
LambdaUpdateWrapper<MiniAdoptionDiary> updateWrapper = new LambdaUpdateWrapper<>(); |
||||
|
updateWrapper.in(MiniAdoptionDiary::getUuid, deleteAdoptionDiaryDTO.getDiaryUuidList()) |
||||
|
.set(MiniAdoptionDiary::getDeleted, 1); |
||||
|
|
||||
|
update(null, updateWrapper); |
||||
} |
} |
||||
|
|
||||
@Override |
@Override |
||||
public List<AdoptionDiaryVO> getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams) { |
public IPage<AdoptionDiaryVO> getSelfCreatedPage(OwnAdoptionDiaryQuery queryParams) { |
||||
return List.of(); |
Long userId = SecurityUtils.getUserId(); |
||||
|
queryParams.setMiniUserId(userId); |
||||
|
queryParams.setCreatorId(userId); |
||||
|
|
||||
|
int pageNum = queryParams.getPageNum(); |
||||
|
int pageSize = queryParams.getPageSize(); |
||||
|
Page<AdoptionDiaryVO> page = new Page<>(pageNum, pageSize); |
||||
|
|
||||
|
IPage<AdoptionDiaryVO> 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;
|
||||
|
// }
|
||||
|
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper |
||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
|
||||
|
<mapper namespace="com.youlai.boot.mini.mapper.MiniAdoptionDiaryMediaMapper"> |
||||
|
|
||||
|
|
||||
|
</mapper> |
||||
Loading…
Reference in new issue