From ad2fc69d87a8ba4d2f4b248e571b7207bdd9261e Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期一, 19 五月 2025 18:05:17 +0800 Subject: [PATCH] 集成腾讯云cos、小程序视频发布功能 --- framework/src/main/java/cn/lili/modules/lmk/domain/entity/LmkFile.java | 38 + framework/src/main/java/cn/lili/modules/lmk/domain/form/FileInfoForm.java | 31 framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoForm.java | 64 + framework/src/main/java/cn/lili/cos/CosSTS.java | 40 + framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTagRef.java | 31 framework/src/main/java/cn/lili/modules/lmk/domain/query/WxVideoTagQuery.java | 25 framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java | 91 ++ framework/src/main/java/cn/lili/utils/COSUtil.java | 285 +++++++ buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java | 77 ++ framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java | 171 ++++ pom.xml | 3 framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java | 22 framework/src/main/resources/mapper/lmk/VideoTagRefMapper.xml | 15 framework/src/main/java/cn/lili/cos/COSConfigProperty.java | 105 ++ framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java | 83 ++ framework/src/main/resources/mapper/lmk/VideoMapper.xml | 80 ++ framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java | 83 ++ framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTag.java | 3 manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java | 76 ++ framework/src/main/java/cn/lili/modules/lmk/service/VideoTagService.java | 9 framework/src/main/java/cn/lili/utils/FileUtil.java | 89 ++ framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java | 73 + buyer-api/src/main/java/cn/lili/controller/lmk/VideoTagController.java | 40 + framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java | 34 framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagRefServiceImpl.java | 23 framework/pom.xml | 16 framework/src/main/java/cn/lili/modules/lmk/mapper/VideoTagRefMapper.java | 17 framework/src/main/java/cn/lili/common/exception/FileFormatNotSupport.java | 32 buyer-api/src/test/java/cn/lili/buyer/test/cart/LmkFileTest.java | 2 config/application.yml | 28 framework/src/main/java/cn/lili/modules/lmk/mapper/LmkFileMapper.java | 26 framework/src/main/java/cn/lili/modules/lmk/domain/form/WxVideoTagForm.java | 30 framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java | 93 ++ framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoStatusEnum.java | 48 + framework/src/main/resources/mapper/lmk/VideoTagMapper.xml | 3 framework/src/main/java/cn/lili/modules/lmk/enums/general/FileTypeEnum.java | 54 + framework/src/main/java/cn/lili/modules/lmk/service/VideoTagRefService.java | 15 framework/src/main/java/cn/lili/common/security/context/UserContext.java | 14 framework/src/main/resources/mapper/lmk/LmkFileMapper.xml | 35 common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java | 112 ++ framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagServiceImpl.java | 28 framework/src/main/java/cn/lili/common/exception/BaseException.java | 35 framework/src/main/java/cn/lili/modules/lmk/domain/vo/LmkFileVO.java | 49 + 43 files changed, 2,225 insertions(+), 3 deletions(-) diff --git a/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java b/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java new file mode 100644 index 0000000..7d66e4f --- /dev/null +++ b/buyer-api/src/main/java/cn/lili/controller/lmk/VideoController.java @@ -0,0 +1,77 @@ +package cn.lili.controller.lmk; + +import cn.lili.group.Update; +import cn.lili.group.Add; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import lombok.RequiredArgsConstructor; +import java.util.List; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.NotEmpty; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import cn.lili.modules.lmk.service.VideoService; +import cn.lili.base.Result; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * 瑙嗛鍐呭 鍓嶇鎺у埗鍣� + * + * @author xp + * @since 2025-05-16 + */ +@Validated +@RequiredArgsConstructor +@Api(value = "瑙嗛鍐呭", tags = "瑙嗛鍐呭绠$悊") +@RestController +@RequestMapping("/buyer/lmk/video") +public class VideoController { + + private final VideoService videoService; + + @PostMapping("/publish") + @ApiOperation(value = "鍙戝竷瑙嗛", notes = "鍙戝竷瑙嗛") + public Result publish(@RequestBody @Validated({Add.class}) VideoForm form) { + return videoService.publish(form); + } + + @PutMapping + @ApiOperation(value = "淇敼", notes = "淇敼") + public Result update(@RequestBody @Validated(Update.class) VideoForm form) { + return videoService.update(form); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "ID鍒犻櫎", notes = "ID鍒犻櫎") + public Result removeById(@PathVariable("id") String id) { + return videoService.removeById(id); + } + + @DeleteMapping("/batch") + @ApiOperation(value = "鎵归噺鍒犻櫎", notes = "鎵归噺鍒犻櫎") + public Result remove(@RequestBody @NotEmpty(message = "璇烽�夋嫨鏁版嵁") List<String> ids) { + return videoService.remove(ids); + } + + @GetMapping("/page") + @ApiOperation(value = "鍒嗛〉", notes = "鍒嗛〉") + public Result page(VideoQuery query) { + return videoService.page(query); + } + + @GetMapping("/{id}") + @ApiOperation(value = "璇︽儏", notes = "璇︽儏") + public Result detail(@PathVariable("id") Integer id) { + return videoService.detail(id); + } + + @GetMapping("/list") + @ApiOperation(value = "鍒楄〃", notes = "鍒楄〃") + public Result list() { + return videoService.all(); + } +} diff --git a/buyer-api/src/main/java/cn/lili/controller/lmk/VideoTagController.java b/buyer-api/src/main/java/cn/lili/controller/lmk/VideoTagController.java new file mode 100644 index 0000000..3504538 --- /dev/null +++ b/buyer-api/src/main/java/cn/lili/controller/lmk/VideoTagController.java @@ -0,0 +1,40 @@ +package cn.lili.controller.lmk; + +import cn.lili.base.Result; +import cn.lili.group.Update; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import cn.lili.modules.lmk.domain.query.WxVideoTagQuery; +import cn.lili.modules.lmk.service.VideoService; +import cn.lili.modules.lmk.service.VideoTagService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * 瑙嗛鏍囩 鍓嶇鎺у埗鍣� + * + * @author xp + * @since 2025-05-16 + */ +@Validated +@RequiredArgsConstructor +@Api(value = "瑙嗛鏍囩", tags = "瑙嗛鏍囩") +@RestController +@RequestMapping("/buyer/lmk/video/tag") +public class VideoTagController { + + private final VideoTagService videoTagService; + + @GetMapping("/recommend") + @ApiOperation(value = "鎺ㄨ崘鏍囩", notes = "鎺ㄨ崘鏍囩") + public Result recommend(WxVideoTagQuery query) { + return videoTagService.recommend(query); + } + +} diff --git a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java b/buyer-api/src/test/java/cn/lili/buyer/test/cart/LmkFileTest.java similarity index 98% rename from buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java rename to buyer-api/src/test/java/cn/lili/buyer/test/cart/LmkFileTest.java index b7907bc..e36f97e 100644 --- a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java +++ b/buyer-api/src/test/java/cn/lili/buyer/test/cart/LmkFileTest.java @@ -23,7 +23,7 @@ @Slf4j @ExtendWith(SpringExtension.class) @SpringBootTest -class FileTest { +class LmkFileTest { @Autowired diff --git a/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java b/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java new file mode 100644 index 0000000..5dc9c51 --- /dev/null +++ b/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java @@ -0,0 +1,112 @@ +package cn.lili.controller.lmk; + +import cn.lili.base.Result; +import cn.lili.modules.lmk.service.LmkFileService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.annotations.Delete; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 鏂囦欢淇℃伅 鍓嶇鎺у埗鍣� + * + * @author xp + * @since 2025-05-19 + */ +@Validated +@RequiredArgsConstructor +@Api(value = "鏂囦欢绠$悊", tags = "鏂囦欢绠$悊") +@RestController("lmkFileController") +@RequestMapping("/common/lmk/file") +public class LmkFileController { + + private final LmkFileService lmkFileService; + + /** + * 鍗曟枃浠朵笂浼�(杩斿洖鏈夎繃鏈熸椂闂寸殑閾炬帴) + * + * @param file + * @return + */ + @PostMapping("/upload") + @ApiOperation(value = "鍗曟枃浠朵笂浼�(杩斿洖鏈夎繃鏈熸椂闂寸殑閾炬帴)") + public Result upload(@RequestPart("file") @NotNull MultipartFile file) { + return lmkFileService.uploadObject(file); + } + + + /** + * 澶氭枃浠朵笂浼� + * + * @param files + * @return + */ + @PostMapping("/multi/upload") + @ApiOperation(value = "澶氭枃浠朵笂浼�(杩斿洖鏈夎繃鏈熸椂闂寸殑閾炬帴)") + public Result uploads(@RequestPart("files") @NotEmpty List<MultipartFile> files) { + return lmkFileService.uploadObjects(files); + } + + /** + * 鍒犻櫎鏌愪釜鏂囦欢 + * + * @param fileKey oss鏂囦欢鍚� + * @return + */ + @Delete("/delete/{file_key}") + @ApiOperation(value = "鍒犻櫎鏌愪釜鏂囦欢") + public Result deleteObject(@PathVariable(value = "file_key") String fileKey) { + return lmkFileService.deleteObject(fileKey); + } + + /** + * 鎵归噺鍒犻櫎鏂囦欢 + * + * @param fileKeys + * @return + */ + @Delete("/delete/files") + @ApiOperation(value = "鎵归噺鍒犻櫎鏂囦欢") + public Result deleteObjects(@RequestBody @NotEmpty List<String> fileKeys) { + return lmkFileService.deleteObjects(fileKeys); + } + + /** + * 涓嬭浇鏂囦欢 + * + * @param fileKey + * @return + */ + @GetMapping("/download/{file_key}") + @ApiOperation(value = "涓嬭浇鏂囦欢") + public void downloadFile(@PathVariable(value = "file_key") String fileKey, HttpServletResponse response) { + lmkFileService.downloadObject(fileKey, response); + } + + /** + * 棰勮鏂囦欢 + * + * @param fileKey + * @return + */ + @GetMapping("/preview/{file_key}") + @ApiOperation(value = "鑾峰彇鏂囦欢棰勮url(閾炬帴瀛樺湪鏃舵晥)") + public Result getPreviewUrl(@PathVariable(value = "file_key") String fileKey) { + return Result.ok().data(lmkFileService.getPreviewUrl(fileKey)); + } + + + @GetMapping("/sts") + @ApiOperation(value = "鑾峰彇STS璁块棶浠ょ墝", notes = "鍓嶇鍋氱洿浼�") + public Result getSTSToken() { + return Result.ok().data(lmkFileService.getSTSToken()); + } +} diff --git a/config/application.yml b/config/application.yml index 80ffe59..d5c9fae 100644 --- a/config/application.yml +++ b/config/application.yml @@ -314,3 +314,31 @@ port: 8891 logpath: ./xxl-job/executor logretentiondays: 7 + +# 鑵捐cos-sts閰嶇疆 +cos: + secretId: AKIDYyBCzb1FOPGx0fCXfdOwJVWM1TjqmW3N # 鑵捐ARM鐢ㄦ埛鐨剆ecretId + secretKey: DD1b1LWVIvPlusAOYjnfKm150jO0NYWH # 鑵捐ARM鐢ㄦ埛鐨剆ecretKey + durationSeconds: 1800 # STS涓存椂璁块棶鍑瘉鏈夋晥鏈燂紝鍗曚綅绉掞紝榛樿1800s锛屼富璐﹀彿鏈�闀�2灏忔椂锛屽瓙璐﹀彿(ARM鐢ㄦ埛)36灏忔椂 + bucket: lmk-1308069279 + region: ap-chengdu + urlExpireMinute: 360 # 棰勭鍚島rl鏈夋晥鏃堕棿(鍒嗛挓) + actions: # sts鐨勬潈闄� + - cos:ListMultipartUploads + - cos:GetBucket + - cos:GetObject + - cos:GetObjectTagging + - cos:GetSymlink + - cos:HeadObject + - cos:ListParts + - cos:AbortMultipartUpload + - cos:AppendObject + - cos:CompleteMultipartUpload + - cos:InitiateMultipartUpload + - cos:PostObject + - cos:PutObject + - cos:UploadPart + - cos:DeleteObject + - cos:PutObjectTagging + resources: # 鑳芥搷浣滃摢浜涜祫婧� + - qcs::cos:ap-chengdu:uid/1308069279:lmk-1308069279/* diff --git a/framework/pom.xml b/framework/pom.xml index bfcd88a..3851799 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -15,6 +15,20 @@ <packaging>jar</packaging> <dependencies> + <!-- 鑵捐cos瀵硅薄瀛樺偍鏈嶅姟 --> + <dependency> + <groupId>com.qcloud</groupId> + <artifactId>cos_api</artifactId> + <version>${tx-cos.version}</version> + </dependency> + <dependency> + <groupId>com.qcloud</groupId> + <artifactId>cos-sts_api</artifactId> + <version>3.1.0</version> + </dependency> + + + <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> @@ -471,4 +485,4 @@ </dependencies> -</project> \ No newline at end of file +</project> diff --git a/framework/src/main/java/cn/lili/common/exception/BaseException.java b/framework/src/main/java/cn/lili/common/exception/BaseException.java new file mode 100644 index 0000000..7ddef4c --- /dev/null +++ b/framework/src/main/java/cn/lili/common/exception/BaseException.java @@ -0,0 +1,35 @@ +package cn.lili.common.exception; + +/** + * 鍩虹闈炴鏌ュ紓甯� + * @author 29443 + * @version 1.0 + * @date 2022/4/25 + */ +public class BaseException extends RuntimeException { + + private String msg; + + private Integer code; + + public BaseException(String msg, Throwable cause) { + super(msg, cause); + } + + public BaseException(String msg) { + super(msg); + } + + public BaseException(String msg, Integer code) { + this.msg = msg; + this.code = code; + } + + public String getMsg() { + return msg; + } + + public Integer getCode() { + return code; + } +} diff --git a/framework/src/main/java/cn/lili/common/exception/FileFormatNotSupport.java b/framework/src/main/java/cn/lili/common/exception/FileFormatNotSupport.java new file mode 100644 index 0000000..5b1c87f --- /dev/null +++ b/framework/src/main/java/cn/lili/common/exception/FileFormatNotSupport.java @@ -0,0 +1,32 @@ +package cn.lili.common.exception; + +/** + * @author 29443 + * @version 1.0 + * @date 2022/4/25 + */ +public class FileFormatNotSupport extends BaseException { + + private String suffix; + + public FileFormatNotSupport(String msg, Throwable cause) { + super(msg, cause); + } + + public FileFormatNotSupport(String msg) { + super(msg); + } + + public FileFormatNotSupport(String msg, String suffix) { + super(msg); + this.suffix = suffix; + } + + public FileFormatNotSupport(String msg, Integer code) { + super(msg, code); + } + + public String getSuffix() { + return suffix; + } +} diff --git a/framework/src/main/java/cn/lili/common/security/context/UserContext.java b/framework/src/main/java/cn/lili/common/security/context/UserContext.java index d2770be..cf66baf 100644 --- a/framework/src/main/java/cn/lili/common/security/context/UserContext.java +++ b/framework/src/main/java/cn/lili/common/security/context/UserContext.java @@ -26,6 +26,20 @@ public class UserContext { /** + * 鏍规嵁request鑾峰彇鐢ㄦ埛id + * + * @return 鎺堟潈鐢ㄦ埛 + */ + public static String getCurrentUserId() { + if (RequestContextHolder.getRequestAttributes() != null) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String accessToken = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue()); + return getAuthUser(accessToken).getId(); + } + return null; + } + + /** * 鏍规嵁request鑾峰彇鐢ㄦ埛淇℃伅 * * @return 鎺堟潈鐢ㄦ埛 diff --git a/framework/src/main/java/cn/lili/cos/COSConfigProperty.java b/framework/src/main/java/cn/lili/cos/COSConfigProperty.java new file mode 100644 index 0000000..70c5f4f --- /dev/null +++ b/framework/src/main/java/cn/lili/cos/COSConfigProperty.java @@ -0,0 +1,105 @@ +package cn.lili.cos; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +/** + * 璇诲彇閰嶇疆鏂囦欢鍏充簬cos鐨勯厤缃� + * + * @author锛歺p + * @date锛�2025/5/16 16:23 + */ +@Configuration +@ConfigurationProperties(prefix = "cos") +public class COSConfigProperty { + + /** 鑵捐ARM鐢ㄦ埛鐨剆ecretId */ + private String secretId; + + /** 鑵捐ARM鐢ㄦ埛鐨剆ecretKey */ + private String secretKey; + + /** STS涓存椂璁块棶鍑瘉鏈夋晥鏈燂紝鍗曚綅绉掞紝榛樿1800s锛屼富璐﹀彿鏈�闀�2灏忔椂锛屽瓙璐﹀彿(ARM鐢ㄦ埛)36灏忔椂 */ + private Integer durationSeconds; + + /** bucket鎵�鍦ㄧ殑鍦板煙 */ + private String region; + + /** bucket鍚嶇О */ + private String bucket; + + /** 棰勭鍚島rl杩囨湡鏃堕棿锛堝垎閽燂級 */ + private Integer urlExpireMinute; + + /** sts鐨勬潈闄� */ + private String[] actions; + + /** sts鑳芥搷浣滅殑璧勬簮 */ + private String[] resources; + + public String getSecretId() { + return secretId; + } + + public void setSecretId(String secretId) { + this.secretId = secretId; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public Integer getDurationSeconds() { + return durationSeconds; + } + + public void setDurationSeconds(Integer durationSeconds) { + this.durationSeconds = durationSeconds; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getBucket() { + return bucket; + } + + public void setBucket(String bucket) { + this.bucket = bucket; + } + + public String[] getActions() { + return actions; + } + + public void setActions(String[] actions) { + this.actions = actions; + } + + public String[] getResources() { + return resources; + } + + public void setResources(String[] resources) { + this.resources = resources; + } + + public Integer getUrlExpireMinute() { + return urlExpireMinute; + } + + public void setUrlExpireMinute(Integer urlExpireMinute) { + this.urlExpireMinute = urlExpireMinute; + } +} diff --git a/framework/src/main/java/cn/lili/cos/CosSTS.java b/framework/src/main/java/cn/lili/cos/CosSTS.java new file mode 100644 index 0000000..ae955e1 --- /dev/null +++ b/framework/src/main/java/cn/lili/cos/CosSTS.java @@ -0,0 +1,40 @@ +package cn.lili.cos; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * sts涓存椂璁块棶鍑瘉瀵硅薄 + * @author锛歺p + * @date锛�2025/5/16 16:33 + */ +@Data +@ApiModel("STS涓存椂璁块棶鍑瘉") +public class CosSTS { + + @ApiModelProperty("涓存椂瀵嗛挜id") + private String tmpSecretId; + + @ApiModelProperty("涓存椂瀵嗛挜key") + private String tmpSecretKey; + + @ApiModelProperty("sts-token") + private String sessionToken; + + @ApiModelProperty("sts璧锋晥鏃堕棿") + private Long stsStartTime; + + @ApiModelProperty("sts澶辨晥鏃堕棿") + private Long stsEndTime; + + @ApiModelProperty("bucket") + private String bucket; + + @ApiModelProperty("region") + private String region; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/LmkFile.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/LmkFile.java new file mode 100644 index 0000000..d8fef08 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/LmkFile.java @@ -0,0 +1,38 @@ +package cn.lili.modules.lmk.domain.entity; + +import cn.lili.mybatis.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * 鏂囦欢淇℃伅 + * + * @author xp + * @since 2025-05-19 + */ +@Data +@TableName("lmk_file") +public class LmkFile extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableField("file_key") + /** 鏂囦欢鍞竴鏍囪瘑 */ + private String fileKey; + + @TableField("file_type") + /** 鏂囦欢绫诲瀷 */ + private String fileType; + + @TableField("file_size") + /** 鏂囦欢澶у皬 */ + private Long fileSize; + + @TableField("original_filename") + /** 鏂囦欢鍘熷鍚� */ + private String originalFileName; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java new file mode 100644 index 0000000..6d6bb46 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/Video.java @@ -0,0 +1,83 @@ +package cn.lili.modules.lmk.domain.entity; + +import cn.lili.mybatis.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 瑙嗛鍐呭 + * + * @author xp + * @since 2025-05-16 + */ +@Data +@TableName("lmk_video") +public class Video extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableField("author_id") + /** 浣滆�卛d */ + private String authorId; + + @TableField("cover_url") + /** 鍥剧墖灏侀潰 */ + private String coverUrl; + + @TableField("video_file_key") + /** 瑙嗛鍦板潃 */ + private String videoFileKey; + + @TableField("video_fit") + /** 瑙嗛濉厖妯″紡 */ + private String videoFit; + + @TableField("title") + /** 瑙嗛鏍囬 */ + private String title; + + @TableField("goods_id") + /** 鍟嗗搧id */ + private String goodsId; + + @TableField("goods_view_num") + /** 鍟嗗搧鏌ョ湅娆℃暟 */ + private Long goodsViewNum; + + @TableField("goods_order_num") + /** 鍟嗗搧涓嬪崟娆℃暟 */ + private Long goodsOrderNum; + + @TableField("recommend") + /** 鏄惁鎺ㄨ崘 */ + private Boolean recommend; + + @TableField("status") + /** 鐘舵�� */ + private String status; + + @TableField("play_num") + /** 鎾斁閲� */ + private Long playNum; + + @TableField("collect_num") + /** 鏀惰棌鏁� */ + private Long collectNum; + + @TableField("comment_num") + /** 璇勮鏁� */ + private Long commentNum; + + @TableField("weight") + /** 鏉冮噸 */ + private Double weight; + + @TableField("audit_pass_time") + /** 瀹℃牳閫氳繃鏃堕棿 */ + private LocalDateTime auditPassTime; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTag.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTag.java index 4c2de3b..7ffb17f 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTag.java +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTag.java @@ -26,5 +26,8 @@ /** 鍒涘缓鏂瑰紡 */ private String createType; + @TableField("use_num") + /** 瑙嗛寮曠敤娆℃暟 */ + private Long useNum; } diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTagRef.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTagRef.java new file mode 100644 index 0000000..13ff0fb --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/VideoTagRef.java @@ -0,0 +1,31 @@ +package cn.lili.modules.lmk.domain.entity; + +import cn.lili.mybatis.BaseEntity; +import cn.lili.mybatis.BaseIdEntity; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * 瑙嗛鏍囩涓棿琛� + * + * @author xp + * @since 2025-05-19 + */ +@Data +@TableName("lmk_video_tag_ref") +public class VideoTagRef extends BaseIdEntity { + + private static final long serialVersionUID = 1L; + + @TableField("video_id") + /** 瑙嗛id */ + private String videoId; + + @TableField("video_tag_id") + /** 瑙嗛鏍囩id */ + private String videoTagId; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/form/FileInfoForm.java b/framework/src/main/java/cn/lili/modules/lmk/domain/form/FileInfoForm.java new file mode 100644 index 0000000..eebf1e0 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/form/FileInfoForm.java @@ -0,0 +1,31 @@ +package cn.lili.modules.lmk.domain.form; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.validation.annotation.Validated; + +/** + * 灏忕▼搴忕洿浼狅紝闇�瑕佹妸涓婁紶鐨勬枃浠朵俊鎭紶鍒板悗绔繚瀛� + * + * @author锛歺p + * @date锛�2025/5/19 15:17 + */ +@Data +@Validated +@ApiModel("灏忕▼搴忕洿浼犳枃浠朵俊鎭�") +public class FileInfoForm { + + @ApiModelProperty("鏂囦欢鏍囪瘑") + private String fileKey; + + @ApiModelProperty("鏂囦欢绫诲瀷") + private String fileType; + + @ApiModelProperty("鏂囦欢澶у皬") + private Long fileSize; + + @ApiModelProperty("鏂囦欢鍘熷鍚�") + private String originalFileName; + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoForm.java b/framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoForm.java new file mode 100644 index 0000000..a349f7e --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/form/VideoForm.java @@ -0,0 +1,64 @@ +package cn.lili.modules.lmk.domain.form; + +import cn.lili.group.Update; +import cn.lili.group.Add; +import cn.lili.base.AbsForm; +import cn.lili.modules.lmk.domain.entity.Video; +import org.hibernate.validator.constraints.Length; +import org.springframework.beans.BeanUtils; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import org.springframework.lang.NonNull; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 瑙嗛鍐呭琛ㄥ崟 + * + * @author xp + * @since 2025-05-16 + */ +@Data +@ApiModel(value = "Video琛ㄥ崟", description = "瑙嗛鍐呭琛ㄥ崟") +public class VideoForm extends AbsForm { + + + @NotBlank(message = "瑙嗛涓嶈兘涓虹┖", groups = {Add.class, Update.class}) + @ApiModelProperty("瑙嗛") + private String videoFileKey; + + @NotBlank(message = "鏍囬涓嶈兘涓虹┖", groups = {Add.class, Update.class}) + @ApiModelProperty("鏍囬") + private String title; + + @ApiModelProperty("瑙嗛鏍囩") + @Length(max = 5, message = "鏈�澶氬彧鑳芥坊鍔犱簲涓爣绛�") + private List<WxVideoTagForm> tags = new ArrayList<>(2); + +// @NotBlank(message = "鍟嗗搧id涓嶈兘涓虹┖", groups = {Add.class, Update.class}) + @ApiModelProperty("鍟嗗搧id") + private String goodsId; + + @ApiModelProperty("瑙嗛濉厖妯″紡") + private String videoFit; + + @ApiModelProperty("鏂囦欢淇℃伅") + @Valid + private FileInfoForm fileInfo; + + public static Video getEntityByForm(@NonNull VideoForm form, Video entity) { + if(entity == null) { + entity = new Video(); + } + BeanUtils.copyProperties(form, entity); + return entity; + } + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/form/WxVideoTagForm.java b/framework/src/main/java/cn/lili/modules/lmk/domain/form/WxVideoTagForm.java new file mode 100644 index 0000000..ec9aae7 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/form/WxVideoTagForm.java @@ -0,0 +1,30 @@ +package cn.lili.modules.lmk.domain.form; + +import cn.lili.base.AbsForm; +import cn.lili.group.Add; +import cn.lili.group.Update; +import cn.lili.modules.lmk.domain.entity.VideoTag; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.beans.BeanUtils; +import org.springframework.lang.NonNull; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 瑙嗛鏍囩琛ㄥ崟 + * + * @author xp + * @since 2025-05-13 + */ +@Data +@ApiModel(value = "VideoTag琛ㄥ崟", description = "瑙嗛鏍囩琛ㄥ崟") +public class WxVideoTagForm extends AbsForm { + + @ApiModelProperty("鏍囩鍚嶇О") + private String tagName; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java b/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java new file mode 100644 index 0000000..df533f0 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/query/VideoQuery.java @@ -0,0 +1,22 @@ +package cn.lili.modules.lmk.domain.query; + +import cn.lili.base.AbsQuery; +import java.util.List; +import org.springframework.lang.NonNull; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 瑙嗛鍐呭鏌ヨ + * + * @author xp + * @since 2025-05-16 + */ +@Data +@ApiModel(value = "Video鏌ヨ鍙傛暟", description = "瑙嗛鍐呭鏌ヨ鍙傛暟") +public class VideoQuery extends AbsQuery { +} + diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/query/WxVideoTagQuery.java b/framework/src/main/java/cn/lili/modules/lmk/domain/query/WxVideoTagQuery.java new file mode 100644 index 0000000..61db0e5 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/query/WxVideoTagQuery.java @@ -0,0 +1,25 @@ +package cn.lili.modules.lmk.domain.query; + +import cn.lili.base.AbsQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 瑙嗛鏍囩鏌ヨ + * + * @author xp + * @since 2025-05-13 + */ +@Data +@ApiModel(value = "VideoTag鏌ヨ鍙傛暟", description = "瑙嗛鏍囩鏌ヨ鍙傛暟") +public class WxVideoTagQuery { + + @ApiModelProperty("鏍囩鍚嶇О") + private String tagName; + + @ApiModelProperty("鎼滅储绫诲瀷锛欻OT锛堢儹闂ㄦ爣绛撅級銆丼EARCH锛堟牴鎹緭鍏ョ殑鏍囩鍚嶇О鎼滅储锛�") + private String searchType = "HOT"; + +} + diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/LmkFileVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/LmkFileVO.java new file mode 100644 index 0000000..6801b90 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/LmkFileVO.java @@ -0,0 +1,49 @@ +package cn.lili.modules.lmk.domain.vo; + +import cn.lili.base.AbsVo; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import lombok.experimental.Accessors; +import org.springframework.lang.NonNull; +import org.springframework.beans.BeanUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 鏂囦欢淇℃伅灞曠ず + * + * @author xp + * @since 2025-05-19 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "鏂囦欢淇℃伅鍝嶅簲鏁版嵁", description = "鏂囦欢淇℃伅鍝嶅簲鏁版嵁") +public class LmkFileVO extends AbsVo { + + /** + * 涓存椂璁块棶閾炬帴 + */ + @ApiModelProperty("涓存椂璁块棶閾炬帴") + private String url; + + /** + * fileKey鏁版嵁搴撲繚瀛樼殑鍊� + */ + @ApiModelProperty("鏂囦欢鏍囪瘑") + private String fileKey; + + /** + * 鏂囦欢鍚� + */ + @ApiModelProperty("鏂囦欢鍘熷鍚�") + private String originalName; + + public static LmkFileVO getVoByEntity(@NonNull LmkFile entity, LmkFileVO vo) { + if(vo == null) { + vo = new LmkFileVO(); + } + BeanUtils.copyProperties(entity, vo); + return vo; + } + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java new file mode 100644 index 0000000..77801db --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/VideoVO.java @@ -0,0 +1,91 @@ +package cn.lili.modules.lmk.domain.vo; + +import cn.lili.base.AbsVo; +import cn.lili.modules.lmk.domain.entity.Video; +import java.util.List; +import org.springframework.lang.NonNull; +import org.springframework.beans.BeanUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.util.Date; + +/** + * 瑙嗛鍐呭灞曠ず + * + * @author xp + * @since 2025-05-16 + */ +@Data +@ApiModel(value = "瑙嗛鍐呭鍝嶅簲鏁版嵁", description = "瑙嗛鍐呭鍝嶅簲鏁版嵁") +public class VideoVO extends AbsVo { + + /** 浣滆�卛d */ + @ApiModelProperty("浣滆�卛d") + private String authorId; + + /** 鍥剧墖灏侀潰 */ + @ApiModelProperty("鍥剧墖灏侀潰") + private String coverUrl; + + /** 瑙嗛鍦板潃 */ + @ApiModelProperty("瑙嗛鍦板潃") + private String videoFileKey; + + /** 瑙嗛濉厖妯″紡 */ + @ApiModelProperty("瑙嗛濉厖妯″紡") + private String videoFit; + + /** 瑙嗛鏍囬 */ + @ApiModelProperty("瑙嗛鏍囬") + private String title; + + /** 鍟嗗搧id */ + @ApiModelProperty("鍟嗗搧id") + private String goodsId; + + /** 鍟嗗搧鏌ョ湅娆℃暟 */ + @ApiModelProperty("鍟嗗搧鏌ョ湅娆℃暟") + private Long goodsViewNum; + + /** 鍟嗗搧涓嬪崟娆℃暟 */ + @ApiModelProperty("鍟嗗搧涓嬪崟娆℃暟") + private Long goodsOrderNum; + + /** 鏄惁鎺ㄨ崘 */ + @ApiModelProperty("鏄惁鎺ㄨ崘") + private Boolean recommend; + + /** 鐘舵�� */ + @ApiModelProperty("鐘舵��") + private String status; + + /** 鎾斁閲� */ + @ApiModelProperty("鎾斁閲�") + private Long playNum; + + /** 鏀惰棌鏁� */ + @ApiModelProperty("鏀惰棌鏁�") + private Long collectNum; + + /** 璇勮鏁� */ + @ApiModelProperty("璇勮鏁�") + private Long commentNum; + + /** 鏉冮噸 */ + @ApiModelProperty("鏉冮噸") + private double weight; + + /** 瀹℃牳閫氳繃鏃堕棿 */ + @ApiModelProperty("瀹℃牳閫氳繃鏃堕棿") + private Date auditPassTime; + + public static VideoVO getVoByEntity(@NonNull Video entity, VideoVO vo) { + if(vo == null) { + vo = new VideoVO(); + } + BeanUtils.copyProperties(entity, vo); + return vo; + } + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/enums/general/FileTypeEnum.java b/framework/src/main/java/cn/lili/modules/lmk/enums/general/FileTypeEnum.java new file mode 100644 index 0000000..def0682 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/enums/general/FileTypeEnum.java @@ -0,0 +1,54 @@ +package cn.lili.modules.lmk.enums.general; + + +import java.util.Arrays; +import java.util.List; + +/** + * oss鏂囦欢鍒嗙被鐩綍锛屾枃浠剁被鍨嬬櫧鍚嶅崟 + * @author 29443 + * + */ + +public enum FileTypeEnum { + + IMAGE("image", "鍥剧墖", Arrays.asList("jpg", "png", "jpeg", "gif", "bmp", "webp", "tiff", "svg", "ico", "psd", "raw")), + + VIDEO("video", "瑙嗛", Arrays.asList("mp4", "avi", "rmvb", "mov", "wmv", "flv", "mkv", "mpeg", "mpg", "m4v", "3gp", "webm", "vob", "swf")), + + RADIO("radio", "闊抽", Arrays.asList("mp3", "wma", "wav", "mpeg-4", "cd", "m4a", "aac", "flac", "ogg", "aiff", "ape", "midi", "amr", "ra")), + + TEXT("text", "鏂囨湰鏂囦欢", Arrays.asList("txt", "xls", "xlsx", "doc", "docx", "pdf", "ppt", "pptx", "csv", "rtf", "odt", "ods", "odp", "epub", "mobi", "pages", "numbers", "key")), + + ZIP("zip", "鍘嬬缉鏂囦欢", Arrays.asList("zip", "rar", "7z", "tar", "gz", "bz2", "xz", "iso", "dmg", "pkg", "cab", "z", "lz", "lzma", "lzo")), + ; + + /** + * 绫诲瀷 + */ + private final String type; + + /** + * 绫诲瀷瀵瑰簲鐨勫悗缂� + */ + private final List<String> suffixs; + + /** + * 鎻忚堪 + */ + private final String desc; + + FileTypeEnum(String type, String desc, List<String> suffixs) { + this.type = type; + this.suffixs = suffixs; + this.desc = desc; + } + + public String getType() { + return type; + } + + public List<String> getSuffixs() { + return suffixs; + } +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoStatusEnum.java b/framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoStatusEnum.java new file mode 100644 index 0000000..054913a --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/enums/general/VideoStatusEnum.java @@ -0,0 +1,48 @@ +package cn.lili.modules.lmk.enums.general; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +/** + * 瑙嗛鏍囩鏉ユ簮 + * + * @author锛歺p + * @date锛�2025/5/14 10:30 + */ +@Getter +public enum VideoStatusEnum { + + AUDITING("99", "瀹℃牳涓�"), + PUBLISHED("1", "宸插彂甯�"), + DISABLE("0", "宸蹭笅鏋�"), + REJECT("-1", "瀹℃牳鏈�氳繃"), + ; + + private final String value; + + + private final String desc; + + VideoStatusEnum(String value, String desc) { + this.value = value; + this.desc = desc; + } + + /** + * 鑾峰彇鍚箟 + * + * @param value + * @return + */ + public static String getDescByValue(String value) { + if (StringUtils.isBlank(value)) { + return null; + } + for (VideoStatusEnum e : VideoStatusEnum.values()){ + if (value.equals(e.getValue())) { + return e.getDesc(); + } + } + return null; + } +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/LmkFileMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/LmkFileMapper.java new file mode 100644 index 0000000..e44444f --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/LmkFileMapper.java @@ -0,0 +1,26 @@ +package cn.lili.modules.lmk.mapper; + +import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.domain.vo.LmkFileVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 鏂囦欢淇℃伅 Mapper 鎺ュ彛 + * + * @author xp + * @since 2025-05-19 + */ +@Mapper +public interface LmkFileMapper extends BaseMapper<LmkFile> { + + /** + * 鏌ユ壘鏂囦欢淇℃伅 + * + * @param fileKey + * @return + */ + LmkFile getByFileKey(String fileKey); + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java new file mode 100644 index 0000000..33a8bd5 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoMapper.java @@ -0,0 +1,34 @@ +package cn.lili.modules.lmk.mapper; + +import cn.lili.modules.lmk.domain.entity.Video; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import cn.lili.modules.lmk.domain.vo.VideoVO; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 瑙嗛鍐呭 Mapper 鎺ュ彛 + * + * @author xp + * @since 2025-05-16 + */ +@Mapper +public interface VideoMapper extends BaseMapper<Video> { + + /** + * id鏌ユ壘瑙嗛鍐呭 + * @param id + * @return + */ + VideoVO getById(Integer id); + + /** + * 鍒嗛〉 + */ + IPage getPage(IPage page, @Param("query") VideoQuery query); + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoTagRefMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoTagRefMapper.java new file mode 100644 index 0000000..7548bf6 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/VideoTagRefMapper.java @@ -0,0 +1,17 @@ +package cn.lili.modules.lmk.mapper; + +import cn.lili.modules.lmk.domain.entity.VideoTagRef; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 瑙嗛鏍囩涓棿琛� Mapper 鎺ュ彛 + * + * @author xp + * @since 2025-05-19 + */ +@Mapper +public interface VideoTagRefMapper extends BaseMapper<VideoTagRef> { + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java b/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java new file mode 100644 index 0000000..bdc3b61 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java @@ -0,0 +1,83 @@ +package cn.lili.modules.lmk.service; + +import cn.lili.base.Result; +import cn.lili.cos.CosSTS; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.domain.form.FileInfoForm; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * 鏂囦欢淇℃伅 鏈嶅姟绫� + * + * @author xp + * @since 2025-05-19 + */ +public interface LmkFileService extends IService<LmkFile> { + + /** + * 涓婁紶鍗曚釜鏂囦欢 + * + * @param file + * @return + */ + Result uploadObject(MultipartFile file); + + /** + * 涓婁紶澶氫釜鏂囦欢 + * + * @param files + * @return + */ + Result uploadObjects(List<MultipartFile> files); + + /** + * 鍒犻櫎鍗曚釜鏂囦欢 + * + * @param fileKey + * @return + */ + Result deleteObject(String fileKey); + + /** + * 鍒犻櫎澶氫釜鏂囦欢 + * + * @param fileKeys + * @return + */ + Result deleteObjects(List<String> fileKeys); + + /** + * 涓嬭浇鏂囦欢 + * + * @param fileKey + * @param response + * @return + */ + void downloadObject(String fileKey, HttpServletResponse response); + + /** + * 棰勮鏂囦欢 + * + * @param fileKey + * @return + */ + String getPreviewUrl(String fileKey); + + /** + * 鑾峰彇sts涓存椂璁块棶鍑瘉 + * + * @return + */ + CosSTS getSTSToken(); + + /** + * 淇濆瓨鏂囦欢淇℃伅 + * + * @param fileInfo + */ + void addByForm(FileInfoForm fileInfo); +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java b/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java new file mode 100644 index 0000000..583109b --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/VideoService.java @@ -0,0 +1,73 @@ +package cn.lili.modules.lmk.service; + +import cn.lili.modules.lmk.domain.entity.Video; +import com.baomidou.mybatisplus.extension.service.IService; +import cn.lili.base.Result; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import java.util.List; + +/** + * 瑙嗛鍐呭 鏈嶅姟绫� + * + * @author xp + * @since 2025-05-16 + */ +public interface VideoService extends IService<Video> { + + /** + * 娣诲姞 + * @param form + * @return + */ + Result add(VideoForm form); + + /** + * 淇敼 + * @param form + * @return + */ + Result update(VideoForm form); + + /** + * 鎵归噺鍒犻櫎 + * @param ids + * @return + */ + Result remove(List<String> ids); + + /** + * id鍒犻櫎 + * @param id + * @return + */ + Result removeById(String id); + + /** + * 鍒嗛〉鏌ヨ + * @param query + * @return + */ + Result page(VideoQuery query); + + /** + * 鏍规嵁id鏌ユ壘 + * @param id + * @return + */ + Result detail(Integer id); + + /** + * 鍒楄〃 + * @return + */ + Result all(); + + /** + * 鍙戝竷瑙嗛 + * + * @param form + * @return + */ + Result publish(VideoForm form); +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagRefService.java b/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagRefService.java new file mode 100644 index 0000000..a07e767 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagRefService.java @@ -0,0 +1,15 @@ +package cn.lili.modules.lmk.service; + +import cn.lili.modules.lmk.domain.entity.VideoTagRef; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * 瑙嗛鏍囩涓棿琛� 鏈嶅姟绫� + * + * @author xp + * @since 2025-05-19 + */ +public interface VideoTagRefService extends IService<VideoTagRef> { + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagService.java b/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagService.java index 08cf306..0395373 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagService.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/VideoTagService.java @@ -1,6 +1,7 @@ package cn.lili.modules.lmk.service; import cn.lili.modules.lmk.domain.entity.VideoTag; +import cn.lili.modules.lmk.domain.query.WxVideoTagQuery; import com.baomidou.mybatisplus.extension.service.IService; import cn.lili.base.Result; import cn.lili.modules.lmk.domain.form.VideoTagForm; @@ -62,4 +63,12 @@ * @return */ Result all(); + + /** + * 鎺ㄨ崘鏍囩 + * + * @param query + * @return + */ + Result recommend(WxVideoTagQuery query); } diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java new file mode 100644 index 0000000..4076c84 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java @@ -0,0 +1,93 @@ +package cn.lili.modules.lmk.service.impl; + +import cn.lili.base.Result; +import cn.lili.common.exception.ServiceException; +import cn.lili.cos.CosSTS; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.domain.form.FileInfoForm; +import cn.lili.modules.lmk.domain.vo.LmkFileVO; +import cn.lili.modules.lmk.mapper.LmkFileMapper; +import cn.lili.modules.lmk.service.LmkFileService; +import cn.lili.utils.COSUtil; +import cn.lili.utils.FileUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * 鏂囦欢淇℃伅 鏈嶅姟瀹炵幇绫� + * + * @author xp + * @since 2025-05-19 + */ +@Service +@RequiredArgsConstructor +public class LmkFileServiceImpl extends ServiceImpl<LmkFileMapper, LmkFile> implements LmkFileService { + + private final LmkFileMapper lmkFileMapper; + private final COSUtil cosUtil; + + + @Override + public Result uploadObject(MultipartFile file) { + LmkFile fileInfo = FileUtil.getFileInfo(file); + try { + cosUtil.upload(file.getInputStream(), fileInfo); + lmkFileMapper.insert(fileInfo); + } catch (IOException e) { + e.printStackTrace(); + throw new ServiceException("涓婁紶寮傚父锛岃閲嶈瘯"); + } + String url = cosUtil.getPreviewUrl(fileInfo.getFileKey()); + LmkFileVO fileVo = new LmkFileVO().setUrl(url).setFileKey(fileInfo.getFileKey()); + return Result.ok("涓婁紶鎴愬姛").data(fileVo); + } + + @Override + public Result uploadObjects(List<MultipartFile> files) { + return null; + } + + @Override + public Result deleteObject(String fileKey) { + cosUtil.deleteFile(fileKey); + return Result.ok("鍒犻櫎鎴愬姛"); + } + + @Override + public Result deleteObjects(List<String> fileKeys) { + cosUtil.deleteFiles(fileKeys); + return Result.ok("鍒犻櫎鎴愬姛"); + } + + @Override + public void downloadObject(String fileKey, HttpServletResponse response) { + cosUtil.download(fileKey, response); + } + + @Override + public String getPreviewUrl(String fileKey) { + return cosUtil.getPreviewUrl(fileKey); + } + + @Override + public CosSTS getSTSToken() { + return cosUtil.getSTS(); + } + + @Override + @Transactional(propagation = Propagation.REQUIRED) + public void addByForm(FileInfoForm fileInfo) { + LmkFile file = new LmkFile(); + BeanUtils.copyProperties(fileInfo, file); + baseMapper.insert(file); + } +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java new file mode 100644 index 0000000..f2f75a8 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoServiceImpl.java @@ -0,0 +1,171 @@ +package cn.lili.modules.lmk.service.impl; + +import cn.lili.common.security.context.UserContext; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.domain.entity.VideoTag; +import cn.lili.modules.lmk.domain.entity.VideoTagRef; +import cn.lili.modules.lmk.enums.general.TagCreateTypeEnum; +import cn.lili.modules.lmk.enums.general.VideoStatusEnum; +import cn.lili.modules.lmk.service.LmkFileService; +import cn.lili.modules.lmk.service.VideoTagRefService; +import cn.lili.modules.lmk.service.VideoTagService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import cn.lili.modules.lmk.domain.entity.Video; +import cn.lili.modules.lmk.mapper.VideoMapper; +import cn.lili.modules.lmk.service.VideoService; +import cn.lili.base.Result; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.vo.VideoVO; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import lombok.RequiredArgsConstructor; +import cn.lili.utils.PageUtil; +import org.springframework.beans.BeanUtils; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 瑙嗛鍐呭 鏈嶅姟瀹炵幇绫� + * + * @author xp + * @since 2025-05-16 + */ +@Service +@RequiredArgsConstructor +public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService { + + private final VideoMapper videoMapper; + private final VideoTagService videoTagService; + private final VideoTagRefService videoTagRefService; + private final LmkFileService lmkFileService; + + /** + * 娣诲姞 + * @param form + * @return + */ + @Override + public Result add(VideoForm form) { + Video entity = VideoForm.getEntityByForm(form, null); + baseMapper.insert(entity); + return Result.ok("娣诲姞鎴愬姛"); + } + + /** + * 淇敼 + * @param form + * @return + */ + @Override + public Result update(VideoForm form) { + Video entity = baseMapper.selectById(form.getId()); + + // 涓虹┖鎶汭llegalArgumentException锛屽仛鍏ㄥ眬寮傚父澶勭悊 + Assert.notNull(entity, "璁板綍涓嶅瓨鍦�"); + BeanUtils.copyProperties(form, entity); + baseMapper.updateById(entity); + return Result.ok("淇敼鎴愬姛"); + } + + /** + * 鎵归噺鍒犻櫎 + * @param ids + * @return + */ + @Override + public Result remove(List<String> ids) { + baseMapper.deleteBatchIds(ids); + return Result.ok("鍒犻櫎鎴愬姛"); + } + + /** + * id鍒犻櫎 + * @param id + * @return + */ + @Override + public Result removeById(String id) { + baseMapper.deleteById(id); + return Result.ok("鍒犻櫎鎴愬姛"); + } + + /** + * 鍒嗛〉鏌ヨ + * @param query + * @return + */ + @Override + public Result page(VideoQuery query) { + IPage<VideoVO> page = PageUtil.getPage(query, VideoVO.class); + baseMapper.getPage(page, query); + return Result.ok().data(page.getRecords()).total(page.getTotal()); + } + + /** + * 鏍规嵁id鏌ユ壘 + * @param id + * @return + */ + @Override + public Result detail(Integer id) { + VideoVO vo = baseMapper.getById(id); + Assert.notNull(vo, "璁板綍涓嶅瓨鍦�"); + return Result.ok().data(vo); + } + + /** + * 鍒楄〃 + * @return + */ + @Override + public Result all() { + List<Video> entities = baseMapper.selectList(null); + List<VideoVO> vos = entities.stream() + .map(entity -> VideoVO.getVoByEntity(entity, null)) + .collect(Collectors.toList()); + return Result.ok().data(vos); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Result publish(VideoForm form) { + // 1.淇濆瓨瑙嗛 + Video video = VideoForm.getEntityByForm(form, null); + video.setAuthorId(UserContext.getCurrentUserId()); + video.setStatus(VideoStatusEnum.AUDITING.getValue()); + baseMapper.insert(video); + // 2.澶勭悊鏍囩 + List<VideoTagRef> videoTagRefs = form.getTags().stream().map(tag -> { + VideoTagRef videoTagRef = new VideoTagRef(); + videoTagRef.setVideoId(video.getId()); + if (StringUtils.isBlank(tag.getId())) { + VideoTag videoTag = new LambdaQueryChainWrapper<>(videoTagService.getBaseMapper()) + .eq(VideoTag::getTagName, tag.getTagName()) + .one(); + if (Objects.nonNull(videoTag)) { + videoTagRef.setVideoTagId(videoTag.getId()); + } else { + videoTag = new VideoTag(); + videoTag.setTagName(tag.getTagName()); + videoTag.setCreateType(TagCreateTypeEnum.USER.getValue()); + videoTagService.save(videoTag); + videoTagRef.setVideoTagId(videoTag.getId()); + } + } else { + videoTagRef.setVideoTagId(tag.getId()); + } + return videoTagRef; + }).collect(Collectors.toList()); + videoTagRefService.saveBatch(videoTagRefs); + // 3.淇濆瓨瑙嗛鏂囦欢淇℃伅 + lmkFileService.addByForm(form.getFileInfo()); + return Result.ok("鍙戝竷鎴愬姛锛岃棰戝鏍镐腑~"); + } +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagRefServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagRefServiceImpl.java new file mode 100644 index 0000000..b727397 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagRefServiceImpl.java @@ -0,0 +1,23 @@ +package cn.lili.modules.lmk.service.impl; + +import cn.lili.modules.lmk.domain.entity.VideoTagRef; +import cn.lili.modules.lmk.mapper.VideoTagRefMapper; +import cn.lili.modules.lmk.service.VideoTagRefService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 瑙嗛鏍囩涓棿琛� 鏈嶅姟瀹炵幇绫� + * + * @author xp + * @since 2025-05-19 + */ +@Service +@RequiredArgsConstructor +public class VideoTagRefServiceImpl extends ServiceImpl<VideoTagRefMapper, VideoTagRef> implements VideoTagRefService { + + private final VideoTagRefMapper videoTagRefMapper; + + +} diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagServiceImpl.java index 9702c31..baa1946 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/VideoTagServiceImpl.java @@ -1,11 +1,13 @@ package cn.lili.modules.lmk.service.impl; +import cn.lili.modules.lmk.domain.query.WxVideoTagQuery; import cn.lili.modules.lmk.enums.general.TagCreateTypeEnum; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.VideoTag; import cn.lili.modules.lmk.mapper.VideoTagMapper; import cn.lili.modules.lmk.service.VideoTagService; import cn.lili.base.Result; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import cn.lili.modules.lmk.domain.form.VideoTagForm; import cn.lili.modules.lmk.domain.vo.VideoTagVO; @@ -16,6 +18,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -121,4 +124,29 @@ .collect(Collectors.toList()); return Result.ok().data(vos); } + + + @Override + public Result recommend(WxVideoTagQuery query) { + List<VideoTagVO> tags = new ArrayList<>(3); + switch (query.getSearchType()) { + case "HOT": + // TODO 鐑棬鏍囩閫氳繃瀹氭椂浠诲姟缁熻琛╨mk_video_tag_ref鏁伴噺鍒發mk_video_tag涓� + tags = new LambdaQueryChainWrapper<>(baseMapper) + .orderByDesc(VideoTag::getUseNum) + .last("limit 3") + .list().stream().map(entity -> { + return VideoTagVO.getVoByEntity(entity, null); + }).collect(Collectors.toList()); + case "SEARCH": + tags = new LambdaQueryChainWrapper<>(baseMapper) + .orderByDesc(VideoTag::getUseNum) + .like(VideoTag::getTagName, query.getTagName()) + .last("limit 3") + .list().stream().map(entity -> { + return VideoTagVO.getVoByEntity(entity, null); + }).collect(Collectors.toList()); + } + return Result.ok().data(tags); + } } diff --git a/framework/src/main/java/cn/lili/utils/COSUtil.java b/framework/src/main/java/cn/lili/utils/COSUtil.java new file mode 100644 index 0000000..23a2c23 --- /dev/null +++ b/framework/src/main/java/cn/lili/utils/COSUtil.java @@ -0,0 +1,285 @@ +package cn.lili.utils; + +import cn.lili.cos.COSConfigProperty; +import cn.lili.cos.CosSTS; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicSessionCredentials; +import com.qcloud.cos.exception.CosClientException; +import com.qcloud.cos.exception.CosServiceException; +import com.qcloud.cos.http.HttpMethodName; +import com.qcloud.cos.model.*; +import com.qcloud.cos.region.Region; +import com.tencent.cloud.CosStsClient; +import com.tencent.cloud.Policy; +import com.tencent.cloud.Response; +import com.tencent.cloud.Statement; +import com.tencent.cloud.cos.util.Jackson; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.net.URLEncoder; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author锛歺p + * @date锛�2025/5/16 16:31 + */ +@Component +@RequiredArgsConstructor +public class COSUtil { + + private final COSConfigProperty cosConfigProperty; + + /** + * 鑾峰彇sts涓存椂璁块棶鍑瘉 + * + * @return + */ + public CosSTS getSTS() { + TreeMap<String, Object> config = new TreeMap<String, Object>(); + try { + config.put("secretId", cosConfigProperty.getSecretId()); + config.put("secretKey", cosConfigProperty.getSecretKey()); + + // 鍒濆鍖� policy + Policy policy = new Policy(); + + // 璁剧疆鍩熷悕: + // 濡傛灉鎮ㄤ娇鐢ㄤ簡鑵捐浜� cvm锛屽彲浠ヨ缃唴閮ㄥ煙鍚� + //config.put("host", "sts.internal.tencentcloudapi.com"); + + // 涓存椂瀵嗛挜鏈夋晥鏃堕暱锛屽崟浣嶆槸绉掞紝榛樿 1800 绉掞紝鐩墠涓昏处鍙锋渶闀� 2 灏忔椂锛堝嵆 7200 绉掞級锛屽瓙璐﹀彿鏈�闀� 36 灏忔椂锛堝嵆 129600锛夌 + config.put("durationSeconds", cosConfigProperty.getDurationSeconds()); + // 鎹㈡垚鎮ㄧ殑 bucket + config.put("bucket", cosConfigProperty.getBucket()); + // 鎹㈡垚 bucket 鎵�鍦ㄥ湴鍖� + config.put("region", cosConfigProperty.getRegion()); + + // 寮�濮嬫瀯寤轰竴鏉� statement + Statement statement = new Statement(); + // 澹版槑璁剧疆鐨勭粨鏋滄槸鍏佽鎿嶄綔 + statement.setEffect("allow"); + /** + * 瀵嗛挜鐨勬潈闄愬垪琛ㄣ�傚繀椤诲湪杩欓噷鎸囧畾鏈涓存椂瀵嗛挜鎵�闇�瑕佺殑鏉冮檺銆� + * 鏉冮檺鍒楄〃璇峰弬瑙� https://cloud.tencent.com/document/product/436/31923 + * 瑙勫垯涓� {project}:{interfaceName} + * project : 浜у搧缂╁啓 cos鐩稿叧鎺堟潈涓哄�间负cos,鏁版嵁涓囪薄(鏁版嵁澶勭悊)鐩稿叧鎺堟潈鍊间负ci + * 鎺堟潈鎵�鏈夋帴鍙g敤*琛ㄧず锛屼緥濡� cos:*,ci:* + * 娣诲姞涓�鎵规搷浣滄潈闄� : + */ + statement.addActions(cosConfigProperty.getActions()); + + /** + * 杩欓噷鏀规垚鍏佽鐨勮矾寰勫墠缂�锛屽彲浠ユ牴鎹嚜宸辩綉绔欑殑鐢ㄦ埛鐧诲綍鎬佸垽鏂厑璁镐笂浼犵殑鍏蜂綋璺緞 + * 璧勬簮琛ㄨ揪寮忚鍒欏垎瀵硅薄瀛樺偍(cos)鍜屾暟鎹竾璞�(ci)涓ょ + * 鏁版嵁澶勭悊銆佸鏍哥浉鍏虫帴鍙i渶瑕佹巿浜坈i璧勬簮鏉冮檺 + * cos : qcs::cos:{region}:uid/{appid}:{bucket}/{path} + * ci : qcs::ci:{region}:uid/{appid}:bucket/{bucket}/{path} + * 鍒椾妇鍑犵鍏稿瀷鐨剓path}鎺堟潈鍦烘櫙锛� + * 1銆佸厑璁歌闂墍鏈夊璞★細"*" + * 2銆佸厑璁歌闂寚瀹氱殑瀵硅薄锛�"a/a1.txt", "b/b1.txt" + * 3銆佸厑璁歌闂寚瀹氬墠缂�鐨勫璞★細"a*", "a/*", "b/*" + * 濡傛灉濉啓浜嗏��*鈥濓紝灏嗗厑璁哥敤鎴疯闂墍鏈夎祫婧愶紱闄ら潪涓氬姟闇�瑕侊紝鍚﹀垯璇锋寜鐓ф渶灏忔潈闄愬師鍒欐巿浜堢敤鎴风浉搴旂殑璁块棶鏉冮檺鑼冨洿銆� + * + * 绀轰緥锛氭巿鏉僥xamplebucket-1250000000 bucket鐩綍涓嬬殑鎵�鏈夎祫婧愮粰cos鍜宑i 鎺堟潈涓ゆ潯Resource + */ + statement.addResources(cosConfigProperty.getResources()); + + // 鎶婁竴鏉� statement 娣诲姞鍒� policy + // 鍙互娣诲姞澶氭潯 + policy.addStatement(statement); + // 灏� Policy 绀轰緥杞寲鎴� String锛屽彲浠ヤ娇鐢ㄤ换浣� json 杞寲鏂瑰紡锛岃繖閲屾槸鏈� SDK 鑷甫鐨勬帹鑽愭柟寮� + config.put("policy", Jackson.toJsonPrettyString(policy)); + + Response response = CosStsClient.getCredential(config); + System.out.println(response.credentials.tmpSecretId); + System.out.println(response.credentials.tmpSecretKey); + System.out.println(response.credentials.sessionToken); + + CosSTS cosSTS = new CosSTS(); + cosSTS.setTmpSecretId(response.credentials.tmpSecretId); + cosSTS.setTmpSecretKey(response.credentials.tmpSecretKey); + cosSTS.setSessionToken(response.credentials.sessionToken); + Date now = new Date(); + cosSTS.setStsStartTime(now.getTime() / 1000); + // 棰勭暀30s鐨勮姹傛椂闂达紝闃叉缁欏皬绋嬪簭鐨勭粨鏉熸椂闂磋秴杩囧疄闄呯殑缁撴潫鏃堕棿 + cosSTS.setStsEndTime(cosSTS.getStsStartTime() + cosConfigProperty.getDurationSeconds() - 30); + cosSTS.setBucket(cosConfigProperty.getBucket()); + cosSTS.setRegion(cosConfigProperty.getRegion()); + return cosSTS; + } catch (Exception e) { + e.printStackTrace(); + throw new IllegalArgumentException("get sts error"); + } + } + + /** + * 鍒濆鍖朿os瀹㈡埛绔� + * + * @return COSClient cos瀹㈡埛绔� + */ + public COSClient initClient() { + CosSTS sts = this.getSTS(); + BasicSessionCredentials cred = new BasicSessionCredentials(sts.getTmpSecretId(), sts.getTmpSecretKey(), sts.getSessionToken()); + // 2 璁剧疆 bucket 鐨勫湴鍩� + // clientConfig 涓寘鍚簡璁剧疆 region, https(榛樿 http), 瓒呮椂, 浠g悊绛� set 鏂规硶, 浣跨敤鍙弬瑙佹簮鐮佹垨鑰呭父瑙侀棶棰� Java SDK 閮ㄥ垎 + Region region = new Region(cosConfigProperty.getRegion()); //COS_REGION 鍙傛暟锛氶厤缃垚瀛樺偍妗� bucket 鐨勫疄闄呭湴鍩燂紝渚嬪 ap-beijing锛屾洿澶� COS 鍦板煙鐨勭畝绉拌鍙傝 https://cloud.tencent.com/document/product/436/6224 + ClientConfig clientConfig = new ClientConfig(region); + // 3 鐢熸垚 cos 瀹㈡埛绔� + COSClient cosClient = new COSClient(cred, clientConfig); + return cosClient; + } + + /** + * 鏈�绠�鍗曠殑涓婁紶鏂囦欢 + * + * @param fileInput 鏂囦欢 + * @param fileInfo 鏂囦欢淇℃伅 + * @return fileKey 鏂囦欢璺緞锛屾垨鑰呭彨鍞竴鏍囪瘑 + */ + public void upload(InputStream fileInput, LmkFile fileInfo) { + COSClient cosClient = this.initClient(); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(fileInfo.getFileType()); + objectMetadata.setContentLength(fileInfo.getFileSize()); + +// objectMetadata.setContentDisposition("attachment;filename=" + URLEncoder.encode(fileInfo.getOriginalFilename(), "UTF-8")); + // 鎸囧畾鏂囦欢涓婁紶鍒� COS 涓婄殑璺緞锛屽嵆瀵硅薄閿�備緥濡傚璞¢敭涓� folder/picture.jpg锛屽垯琛ㄧず灏嗘枃浠� picture.jpg 涓婁紶鍒� folder 璺緞涓� + PutObjectRequest putObjectRequest = new PutObjectRequest(cosConfigProperty.getBucket(), fileInfo.getFileKey(), fileInput, objectMetadata); + PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest); + System.out.println(putObjectResult); + cosClient.shutdown(); + } + + /** + * 涓嬭浇鏂囦欢 + * + * @param fileKey 鏂囦欢璺緞锛屾垨鑰呭彨鍞竴鏍囪瘑 + * @param response + */ + public void download(String fileKey, HttpServletResponse response) { + COSClient cosClient = this.initClient(); + GetObjectRequest getObjectRequest = new GetObjectRequest(cosConfigProperty.getBucket(), fileKey); + + try { + // 鑾峰彇COS瀵硅薄 + COSObject cosObject = cosClient.getObject(getObjectRequest); + + // 鑾峰彇瀵硅薄鍏冩暟鎹� + ObjectMetadata metadata = cosObject.getObjectMetadata(); + String contentType = metadata.getContentType(); + long contentLength = metadata.getContentLength(); + String filename = fileKey.substring(fileKey.lastIndexOf('/') + 1); + + // 璁剧疆鍝嶅簲澶� + response.setContentType(contentType != null ? contentType : "application/octet-stream"); + response.setContentLengthLong(contentLength); + response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\""); + + // 鑾峰彇杈撳叆娴佸拰杈撳嚭娴� + try (InputStream cosObjectInput = cosObject.getObjectContent(); + OutputStream responseOutputStream = response.getOutputStream()) { + + // 浣跨敤缂撳啿鍖轰紶杈撴暟鎹� + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = cosObjectInput.read(buffer)) != -1) { + responseOutputStream.write(buffer, 0, bytesRead); + } + responseOutputStream.flush(); + } + } catch (CosServiceException e) { + // COS鏈嶅姟寮傚父 + e.printStackTrace(); + throw new RuntimeException("瀛樺偍鏈嶅姟寮傚父"); + } catch (CosClientException e) { + // COS瀹㈡埛绔紓甯� + e.printStackTrace(); + throw new RuntimeException("瀛樺偍鏈嶅姟瀹㈡埛绔紓甯�"); + } catch (IOException e) { + // IO寮傚父 + e.printStackTrace(); + throw new RuntimeException("鏂囦欢璇诲彇寮傚父"); + } finally { + // 纭繚COS瀹㈡埛绔叧闂� + if (cosClient != null) { + cosClient.shutdown(); + } + } + } + + + /** + * 鑾峰彇鍦ㄧ嚎璁块棶鏂囦欢鍦板潃 + * + * @param fileKey + * @return + */ + public String getPreviewUrl(String fileKey) { + COSClient cosClient = this.initClient(); + // 璁剧疆绛惧悕杩囨湡鏃堕棿(鍙��), 鑻ユ湭杩涜璁剧疆鍒欓粯璁や娇鐢� ClientConfig 涓殑绛惧悕杩囨湡鏃堕棿(1灏忔椂) + // 杩欓噷璁剧疆绛惧悕鍦ㄥ崐涓皬鏃跺悗杩囨湡 + Date expirationDate = new Date(System.currentTimeMillis() + cosConfigProperty.getUrlExpireMinute() * 60 * 1000); + // 濉啓鏈璇锋眰鐨勫弬鏁帮紝闇�涓庡疄闄呰姹傜浉鍚岋紝鑳藉闃叉鐢ㄦ埛绡℃敼姝ょ鍚嶇殑 HTTP 璇锋眰鐨勫弬鏁� + Map<String, String> params = new HashMap<String, String>(); + // 濉啓鏈璇锋眰鐨勫ご閮紝闇�涓庡疄闄呰姹傜浉鍚岋紝鑳藉闃叉鐢ㄦ埛绡℃敼姝ょ鍚嶇殑 HTTP 璇锋眰鐨勫ご閮� + Map<String, String> headers = new HashMap<String, String>(); + // 璇锋眰鐨� HTTP 鏂规硶锛屼笂浼犺姹傜敤 PUT锛屼笅杞借姹傜敤 GET锛屽垹闄よ姹傜敤 DELETE + HttpMethodName method = HttpMethodName.GET; + URL url = cosClient.generatePresignedUrl(cosConfigProperty.getBucket(), fileKey, expirationDate, method, headers, params); + System.out.println(url.toString()); + // 纭鏈繘绋嬩笉鍐嶄娇鐢� cosClient 瀹炰緥涔嬪悗锛屽叧闂嵆鍙� + cosClient.shutdown(); + return url.toString(); + } + + + /** + * 鍒犻櫎鍗曚釜鏂囦欢 + * + * @param fileKey + */ + public void deleteFile(String fileKey) { + COSClient cosClient = this.initClient(); + try { + cosClient.deleteObject(cosConfigProperty.getBucket(), fileKey); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("鏂囦欢鍒犻櫎澶辫触"); + } finally { + cosClient.shutdown(); + } + } + + /** + * 鍒犻櫎澶氫釜鏂囦欢 + * + * @param fileKeys + */ + public void deleteFiles(List<String> fileKeys) { + if (CollectionUtils.isEmpty(fileKeys)) { + return; + } + List<DeleteObjectsRequest.KeyVersion> keys = fileKeys.stream().map(key -> new DeleteObjectsRequest.KeyVersion(key)).collect(Collectors.toList()); + COSClient cosClient = this.initClient(); + try { + DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(cosConfigProperty.getBucket()); + deleteObjectsRequest.setKeys(keys); + cosClient.deleteObjects(deleteObjectsRequest); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("鏂囦欢鍒犻櫎澶辫触"); + } finally { + cosClient.shutdown(); + } + } + +} diff --git a/framework/src/main/java/cn/lili/utils/FileUtil.java b/framework/src/main/java/cn/lili/utils/FileUtil.java new file mode 100644 index 0000000..bd6ef39 --- /dev/null +++ b/framework/src/main/java/cn/lili/utils/FileUtil.java @@ -0,0 +1,89 @@ +package cn.lili.utils; + +import cn.lili.common.exception.FileFormatNotSupport; +import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.enums.general.FileTypeEnum; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; + +/** + * @author 29443 + * @version 1.0 + * @date 2022/4/25 + */ +public class FileUtil { + + /** + * 鑾峰彇鏂囦欢鍚庣紑 + * + * @param fileName + * @return + */ + public static String getSuffix(String fileName) { + String suffix = fileName.substring(fileName.lastIndexOf('.') + 1); + return suffix; + } + + /** + * 鑾峰彇璇ユ枃浠朵笂浼犲埌oss鍝釜鐩綍 + * + * @param suffix 鏂囦欢鍚庣紑 + * @return + */ + public static String getFileType(String suffix) { + String fileType = ""; + for (FileTypeEnum type : FileTypeEnum.values()) { + if (type.getSuffixs().contains(suffix)) { + fileType = type.getType(); + return fileType; + } + } + if (StringUtils.isBlank(fileType)) { + throw new FileFormatNotSupport("鏂囦欢鏍煎紡" + suffix + "涓嶆敮鎸�", 500); + } + return fileType; + } + + /** + * 鑾峰彇鏂囦欢鐨勪俊鎭紝璋冪敤姝ゆ柟娉曢粯璁ゆ櫘閫氫笂浼� + * + * @param file + * @return + */ + public static LmkFile getFileInfo(MultipartFile file) { + String originalFilename = file.getOriginalFilename(); + String random = generateFileKey(); + String suffix = getSuffix(originalFilename); + String fileType = getFileType(suffix); + String fileKey = String.format("%s/%s.%s", fileType, random, suffix); + + LmkFile fileInfo = new LmkFile(); + fileInfo.setFileKey(fileKey); + fileInfo.setOriginalFileName(originalFilename); + fileInfo.setFileType(file.getContentType()); + fileInfo.setFileSize(file.getSize()); + + return fileInfo; + } + + + /** + * 鑾峰彇fileKey + * + * @return + */ + public static String generateFileKey() { + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + String no = format.format(new Date()); + Random random = new Random(); + for (int i = 0; i < 5; i++) { + no += random.nextInt(10); + } + return no; + } + +} diff --git a/framework/src/main/resources/mapper/lmk/LmkFileMapper.xml b/framework/src/main/resources/mapper/lmk/LmkFileMapper.xml new file mode 100644 index 0000000..8ffe3e7 --- /dev/null +++ b/framework/src/main/resources/mapper/lmk/LmkFileMapper.xml @@ -0,0 +1,35 @@ +<?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="cn.lili.modules.lmk.mapper.LmkFileMapper"> + + <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 --> + <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.entity.LmkFile"> + <id column="id" property="id"/> + <result column="file_key" property="fileKey" /> + <result column="file_type" property="fileType" /> + <result column="file_size" property="fileSize" /> + <result column="original_filename" property="originalFileName" /> + </resultMap> + + + + + + + + <select id="getByFileKey" resultMap="BaseResultMap"> + SELECT + LF.file_key, + LF.file_type, + LF.file_size, + LF.original_filename, + LF.deleted_flag, + LF.id + FROM + lmk_file LF + WHERE + LF.file_key = #{flieKey} AND LF.delete_flag = 0 + </select> + + +</mapper> diff --git a/framework/src/main/resources/mapper/lmk/VideoMapper.xml b/framework/src/main/resources/mapper/lmk/VideoMapper.xml new file mode 100644 index 0000000..de55ef3 --- /dev/null +++ b/framework/src/main/resources/mapper/lmk/VideoMapper.xml @@ -0,0 +1,80 @@ +<?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="cn.lili.modules.lmk.mapper.VideoMapper"> + + <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 --> + <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.VideoVO"> + <id column="id" property="id"/> + <result column="author_id" property="authorId" /> + <result column="cover_url" property="coverUrl" /> + <result column="video_file_key" property="videoFileKey" /> + <result column="video_fit" property="videoFit" /> + <result column="title" property="title" /> + <result column="goods_id" property="goodsId" /> + <result column="goods_view_num" property="goodsViewNum" /> + <result column="goods_order_num" property="goodsOrderNum" /> + <result column="recommend" property="recommend" /> + <result column="status" property="status" /> + <result column="play_num" property="playNum" /> + <result column="collect_num" property="collectNum" /> + <result column="comment_num" property="commentNum" /> + <result column="weight" property="weight" /> + <result column="audit_pass_time" property="auditPassTime" /> + </resultMap> + + + + + + + + <select id="getById" resultMap="BaseResultMap"> + SELECT + LV.author_id, + LV.cover_url, + LV.video_fit, + LV.video_file_key, + LV.title, + LV.goods_id, + LV.goods_view_num, + LV.goods_order_num, + LV.recommend, + LV.status, + LV.play_num, + LV.collect_num, + LV.comment_num, + LV.weight, + LV.audit_pass_time, + LV.id + FROM + lmk_video LV + WHERE + LV.id = #{id} AND LV.delete_flag = 0 + </select> + + + <select id="getPage" resultMap="BaseResultMap"> + SELECT + LV.author_id, + LV.cover_url, + LV.video_fit, + LV.video_file_key, + LV.title, + LV.goods_id, + LV.goods_view_num, + LV.goods_order_num, + LV.recommend, + LV.status, + LV.play_num, + LV.collect_num, + LV.comment_num, + LV.weight, + LV.audit_pass_time, + LV.id + FROM + lmk_video LV + WHERE + LV.delete_flag = 0 + </select> + +</mapper> diff --git a/framework/src/main/resources/mapper/lmk/VideoTagMapper.xml b/framework/src/main/resources/mapper/lmk/VideoTagMapper.xml index d63d4f4..86a95c7 100644 --- a/framework/src/main/resources/mapper/lmk/VideoTagMapper.xml +++ b/framework/src/main/resources/mapper/lmk/VideoTagMapper.xml @@ -6,6 +6,7 @@ <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.VideoTagVO"> <id column="id" property="id"/> <result column="tag_name" property="tagName" /> + <result column="use_num" property="useNum" /> <result column="create_type" property="createType"/> <result column="update_time" property="updateTime" /> </resultMap> @@ -19,6 +20,7 @@ <select id="getById" resultMap="BaseResultMap"> SELECT LVT.tag_name, + LVT.use_num, LVT.create_type, LVT.update_time, LVT.id @@ -32,6 +34,7 @@ <select id="getPage" resultMap="BaseResultMap"> SELECT LVT.tag_name, + LVT.use_num, LVT.create_type, LVT.update_time, LVT.id diff --git a/framework/src/main/resources/mapper/lmk/VideoTagRefMapper.xml b/framework/src/main/resources/mapper/lmk/VideoTagRefMapper.xml new file mode 100644 index 0000000..95bafd6 --- /dev/null +++ b/framework/src/main/resources/mapper/lmk/VideoTagRefMapper.xml @@ -0,0 +1,15 @@ +<?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="cn.lili.modules.lmk.mapper.VideoTagRefMapper"> + + <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 --> + <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.entity.VideoTagRef"> + <id column="id" property="id"/> + <result column="video_id" property="videoId" /> + <result column="video_tag_id" property="videoTagId" /> + </resultMap> + + + + +</mapper> diff --git a/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java b/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java new file mode 100644 index 0000000..48a84ca --- /dev/null +++ b/manager-api/src/main/java/cn/lili/controller/lmk/VideoController.java @@ -0,0 +1,76 @@ +package cn.lili.controller.lmk; + +import cn.lili.group.Update; +import cn.lili.group.Add; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import lombok.RequiredArgsConstructor; +import java.util.List; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.NotEmpty; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import cn.lili.modules.lmk.service.VideoService; +import cn.lili.base.Result; +import cn.lili.modules.lmk.domain.form.VideoForm; +import cn.lili.modules.lmk.domain.query.VideoQuery; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + * 瑙嗛鍐呭 鍓嶇鎺у埗鍣� + * + * @author xp + * @since 2025-05-16 + */ +@Validated +@RequiredArgsConstructor +@Api(value = "瑙嗛鍐呭", tags = "瑙嗛鍐呭绠$悊") +@RestController +@RequestMapping("/manager/lmk/video") +public class VideoController { + + private final VideoService videoService; + + @PostMapping + @ApiOperation(value = "娣诲姞", notes = "娣诲姞") + public Result add(@RequestBody @Validated(Add.class) VideoForm form) { + return videoService.add(form); + } + + @PutMapping + @ApiOperation(value = "淇敼", notes = "淇敼") + public Result update(@RequestBody @Validated(Update.class) VideoForm form) { + return videoService.update(form); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "ID鍒犻櫎", notes = "ID鍒犻櫎") + public Result removeById(@PathVariable("id") String id) { + return videoService.removeById(id); + } + + @DeleteMapping("/batch") + @ApiOperation(value = "鎵归噺鍒犻櫎", notes = "鎵归噺鍒犻櫎") + public Result remove(@RequestBody @NotEmpty(message = "璇烽�夋嫨鏁版嵁") List<String> ids) { + return videoService.remove(ids); + } + + @GetMapping("/page") + @ApiOperation(value = "鍒嗛〉", notes = "鍒嗛〉") + public Result page(VideoQuery query) { + return videoService.page(query); + } + + @GetMapping("/{id}") + @ApiOperation(value = "璇︽儏", notes = "璇︽儏") + public Result detail(@PathVariable("id") Integer id) { + return videoService.detail(id); + } + + @GetMapping("/list") + @ApiOperation(value = "鍒楄〃", notes = "鍒楄〃") + public Result list() { + return videoService.all(); + } +} diff --git a/pom.xml b/pom.xml index af61ff3..3727158 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,7 @@ <cos.version>5.6.97</cos.version> <tencentcloud.version>3.1.693</tencentcloud.version> <kuaidi100-api.version>1.0.11</kuaidi100-api.version> + <tx-cos.version>5.6.227</tx-cos.version> </properties> <modules> @@ -138,4 +139,4 @@ </snapshots> </repository> </repositories> -</project> \ No newline at end of file +</project> -- Gitblit v1.8.0