diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 5967e647b..83bff12cd 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -49,35 +49,35 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
- url: jdbc:mysql://127.0.0.1:3306/sys?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
- username: root
- password: 123
- # # 从库数据源
- # slave:
- # lazy: true
- # type: ${spring.datasource.type}
- # driverClassName: com.mysql.cj.jdbc.Driver
- # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
- # username:
- # password:
- # oracle:
- # type: ${spring.datasource.type}
- # driverClassName: oracle.jdbc.OracleDriver
- # url: jdbc:oracle:thin:@//localhost:1521/XE
- # username: ROOT
- # password: root
- # postgres:
- # type: ${spring.datasource.type}
- # driverClassName: org.postgresql.Driver
- # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
- # username: root
- # password: root
- # sqlserver:
- # type: ${spring.datasource.type}
- # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
- # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
- # username: SA
- # password: root
+ url: jdbc:mysql://82.156.121.2:23306/wzj?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
+ username: wzj
+ password: A085F27A43B0
+# # 从库数据源
+# slave:
+# lazy: true
+# type: ${spring.datasource.type}
+# driverClassName: com.mysql.cj.jdbc.Driver
+# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
+# username:
+# password:
+# oracle:
+# type: ${spring.datasource.type}
+# driverClassName: oracle.jdbc.OracleDriver
+# url: jdbc:oracle:thin:@//localhost:1521/XE
+# username: ROOT
+# password: root
+# postgres:
+# type: ${spring.datasource.type}
+# driverClassName: org.postgresql.Driver
+# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
+# username: root
+# password: root
+# sqlserver:
+# type: ${spring.datasource.type}
+# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
+# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
+# username: SA
+# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 3a8d2b399..7e584b3dd 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -117,6 +117,7 @@ security:
- /*/api-docs/**
- /warm-flow-ui/token-name
- /admin/vlog/upload/detail/**
+ - /admin/vlog/upload/**
# - /admin/vlog/upload/pull
# - /admin/vlog/upload/pull/batch
# - /admin/vlog/upload/list
diff --git a/ruoyi-modules/ruoyi-content/pom.xml b/ruoyi-modules/ruoyi-content/pom.xml
index dbd6f002e..75faf0a54 100644
--- a/ruoyi-modules/ruoyi-content/pom.xml
+++ b/ruoyi-modules/ruoyi-content/pom.xml
@@ -38,7 +38,7 @@
com.tencentcloudapi
tencentcloud-sdk-java
- 3.1.270
+ 3.1.1030
@@ -169,19 +169,48 @@
-
-
-
-
-
-
+
+
+ com.tencentcloudapi
+ tencentcloud-sdk-java-common
+ 3.1.1030
+
-
+
-
+
+
+
+
+
+ tencent-cloud-sdk
+ tencent-cloud-sdk
+ https://mirrors.tencent.com/nexus/repository/maven-public/
+
+
+
+
+ aliyun
+ aliyun
+ https://maven.aliyun.com/repository/public
+
+ true
+
+
+ false
+
+
+
+
+
+ central
+ Maven Central
+ https://repo1.maven.org/maven2/
+
+
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java
index 0246a4806..27dbbda19 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/VlogController.java
@@ -7,9 +7,11 @@ import com.wzj.soopin.content.domain.bo.VlogBO;
import com.wzj.soopin.content.enums.YesOrNo;
import com.wzj.soopin.content.result.GraceJSONResult;
import com.wzj.soopin.content.service.VlogService;
+import com.wzj.soopin.content.service.VlogUploadService;
import com.wzj.soopin.content.utils.PagedGridResult;
import com.wzj.soopin.content.utils.QcCloud;
import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +32,8 @@ public class VlogController extends BaseInfoProperties {
private VlogService vlogService;
@Autowired
private QcCloud qcCloud;
+ @Autowired
+ private VlogUploadService vlogUploadService;
@PostMapping("vodCallBack")
public GraceJSONResult vodCallBack(@RequestBody Map callbackData) {
@@ -364,4 +368,6 @@ public class VlogController extends BaseInfoProperties {
pageSize);
return GraceJSONResult.ok(gridResult);
}
+
+
}
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java
index 7cba65770..04e826501 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/controller/admin/VlogUploadController.java
@@ -10,8 +10,10 @@ import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
+import org.springframework.util.StringUtils;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,11 +32,14 @@ public class VlogUploadController {
@Autowired
private TencentCloudUtil tencentCloudUtil;
+ @Autowired
+ private com.wzj.soopin.content.mapper.VlogMapper vlogMapper;
+
@ApiOperation("获取腾讯云点播视频列表")
@GetMapping("/list")
public GraceJSONResult getVodList(
@ApiParam(value = "页码", defaultValue = "1") @RequestParam(required = false, defaultValue = "1") Integer pageNum,
- @ApiParam(value = "每页记录数", defaultValue = "20") @RequestParam(required = false, defaultValue = "20") Integer pageSize,
+ @ApiParam(value = "每页记录数", defaultValue = "10") @RequestParam(required = false, defaultValue = "10") Integer pageSize,
@ApiParam(value = "文件状态,可选值:Normal(正常)、SystemForbidden(平台封禁)、Forbidden(主动封禁)") @RequestParam(required = false) String[] status,
@ApiParam(value = "文件类型,可选值:Video(视频)、Audio(音频)、Image(图片)") @RequestParam(required = false) String[] categories,
@ApiParam(value = "媒体文件来源,可选值:Upload(上传)、Record(直播录制)等") @RequestParam(required = false) String[] sourceTypes,
@@ -192,10 +197,64 @@ public class VlogUploadController {
@GetMapping("/detail")
public GraceJSONResult vlogDetail(@RequestParam String vlogId) {
try {
- return GraceJSONResult.ok(vlogUploadService.getVlogDetail(vlogId));
+ // 先查询本地数据库获取 fileId
+ com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectById(vlogId);
+ if (vlog != null && StringUtils.hasText(vlog.getFileId())) {
+ // 如果找到 fileId,使用 fileId 查询腾讯云
+ return GraceJSONResult.ok(vlogUploadService.getVlogDetail(vlog.getFileId()));
+ } else {
+ // 如果没有找到 fileId,直接使用 vlogId 查询
+ return GraceJSONResult.ok(vlogUploadService.getVlogDetail(vlogId));
+ }
} catch (Exception e) {
log.error("获取视频详情失败", e);
return GraceJSONResult.errorMsg("获取视频详情失败: " + e.getMessage());
}
}
+ @ApiOperation(value = "禁播/解禁视频", notes = "禁播/解禁视频接口")
+ @PostMapping("/forbid")
+ public GraceJSONResult forbidMediaDistribution(@RequestBody Map params) {
+ try {
+ // 参数验证
+ if (params == null) {
+ return GraceJSONResult.errorMsg("参数不能为空");
+ }
+
+ Object fileIdsObj = params.get("fileIds");
+ String operation = (String) params.get("operation");
+
+ List fileIds;
+ if (fileIdsObj instanceof String) {
+ // 如果是单个字符串,转换为列表
+ fileIds = Collections.singletonList((String) fileIdsObj);
+ } else if (fileIdsObj instanceof List) {
+ // 如果已经是列表,直接使用
+ fileIds = (List) fileIdsObj;
+ } else {
+ return GraceJSONResult.errorMsg("媒体文件ID格式不正确");
+ }
+
+ if (fileIds.isEmpty()) {
+ return GraceJSONResult.errorMsg("媒体文件ID列表不能为空");
+ }
+ if (fileIds.size() > 20) {
+ return GraceJSONResult.errorMsg("每次最多可提交20个媒体文件");
+ }
+ if (!"forbid".equals(operation) && !"recover".equals(operation)) {
+ return GraceJSONResult.errorMsg("操作类型无效,只能是forbid(禁播)或recover(解禁)");
+ }
+
+ // 调用服务层方法
+ vlogUploadService.forbidMediaDistribution(fileIds, operation);
+
+ // 返回成功结果
+ return GraceJSONResult.ok("操作成功");
+ } catch (IllegalArgumentException e) {
+ log.error("参数错误: {}", e.getMessage());
+ return GraceJSONResult.errorMsg(e.getMessage());
+ } catch (Exception e) {
+ log.error("操作失败: {}", e.getMessage(), e);
+ return GraceJSONResult.errorMsg("操作失败: " + e.getMessage());
+ }
+ }
}
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/mapper/VlogMapper.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/mapper/VlogMapper.java
index 560f00d8e..9a53d685d 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/mapper/VlogMapper.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/mapper/VlogMapper.java
@@ -56,4 +56,11 @@ public interface VlogMapper extends BaseMapper {
public List selectMyPublic(@Param("paramMap")Map map);
public List getVlogDetailFromId(@Param("paramMap")Map map);
+
+ /**
+ * 更新视频审核状态
+ * @param params 包含vlogId、status、reason和auditTime的Map
+ * @return 影响的行数
+ */
+ int updateVlogStatus(@Param("params") Map params);
}
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogUploadService.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogUploadService.java
index a7abd3071..4878fea2d 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogUploadService.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogUploadService.java
@@ -5,6 +5,7 @@ import com.tencentcloudapi.vod.v20180717.models.PullUploadResponse;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaResponse;
+import java.util.List;
import java.util.Map;
public interface VlogUploadService {
@@ -39,4 +40,11 @@ public interface VlogUploadService {
void deleteVlog(String vlogId);
// 新增:视频详情
Object getVlogDetail(String vlogId);
+
+ /**
+ * 禁播/解禁媒体
+ * @param fileIds 媒体文件ID列表
+ * @param operation 操作类型:forbid-禁播,recover-解禁
+ */
+ void forbidMediaDistribution(List fileIds, String operation);
}
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogUploadServiceImpl.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogUploadServiceImpl.java
index 7e1f5259b..c4039f7b7 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogUploadServiceImpl.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogUploadServiceImpl.java
@@ -16,6 +16,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -152,13 +154,117 @@ public class VlogUploadServiceImpl implements VlogUploadService {
// 视频审核
@Override
public void auditVlog(String vlogId, Integer status, String reason) {
- // 这里假设 status=1为通过,status=2为不通过
- // 可根据实际业务调整
- // 直接更新数据库状态
- // 你可以用 VlogMapper 或 VlogService
- // 这里只做伪代码示例
- // vlogMapper.updateStatus(vlogId, status, reason);
- log.info("审核视频 vlogId={}, status={}, reason={}", vlogId, status, reason);
+ try {
+ // 参数验证
+ if (vlogId == null || vlogId.trim().isEmpty()) {
+ throw new IllegalArgumentException("视频ID不能为空");
+ }
+ if (status == null || (status != 1 && status != 2)) {
+ throw new IllegalArgumentException("审核状态无效,只能是1(通过)或2(不通过)");
+ }
+ // 只有当状态为不通过(2)时才需要原因说明
+ if (status == 2 && (reason == null || reason.trim().isEmpty())) {
+ throw new IllegalArgumentException("审核不通过时,必须提供原因说明");
+ }
+
+ // 获取VOD客户端实例
+ VodClient client = tencentCloudUtil.getVodClient();
+
+ // 创建审核请求
+ com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoRequest req = new com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoRequest();
+ req.setFileId(vlogId);
+
+ // 设置审核内容,包括视频和封面
+ req.setReviewContents(new String[]{"Media", "Cover"});
+
+ // 设置审核模板ID,10为预置模板
+ req.setDefinition(10L);
+
+ // 设置任务优先级
+ req.setTasksPriority(0L);
+
+ // 设置来源上下文,用于透传用户请求信息
+ req.setSessionContext(String.format("status=%d&reason=%s", status, reason != null ? reason : ""));
+
+ // 调用审核API
+ com.tencentcloudapi.vod.v20180717.models.ReviewAudioVideoResponse resp = client.ReviewAudioVideo(req);
+
+ // 记录审核结果
+ log.info("视频审核任务已提交 - vlogId: {}, status: {}, reason: {}, taskId: {}",
+ vlogId, status, reason, resp.getTaskId());
+
+ // TODO: 暂时注释掉数据库操作,等待数据库表创建完成后再启用
+ /*
+ // 更新本地数据库状态
+ Map updateMap = new HashMap<>();
+ updateMap.put("vlogId", vlogId);
+ updateMap.put("status", status);
+ updateMap.put("reason", reason);
+ updateMap.put("auditTime", new Date());
+ vlogMapper.updateVlogStatus(updateMap);
+
+ // 记录审核日志
+ log.info("视频状态已更新 - vlogId: {}, status: {}, reason: {}", vlogId, status, reason);
+ */
+
+ } catch (TencentCloudSDKException e) {
+ log.error("视频审核失败 - vlogId: {}, error: {}", vlogId, e.getMessage(), e);
+ throw new RuntimeException("视频审核失败: " + e.getMessage());
+ } catch (Exception e) {
+ log.error("更新视频状态失败 - vlogId: {}, error: {}", vlogId, e.getMessage(), e);
+ throw new RuntimeException("更新视频状态失败: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 禁播/解禁媒体
+ * @param fileIds 媒体文件ID列表
+ * @param operation 操作类型:forbid-禁播,recover-解禁
+ */
+ @Override
+ public void forbidMediaDistribution(List fileIds, String operation) {
+ try {
+ // 参数验证
+ if (fileIds == null || fileIds.isEmpty()) {
+ throw new IllegalArgumentException("媒体文件ID列表不能为空");
+ }
+ if (fileIds.size() > 20) {
+ throw new IllegalArgumentException("每次最多可提交20个媒体文件");
+ }
+ if (!"forbid".equals(operation) && !"recover".equals(operation)) {
+ throw new IllegalArgumentException("操作类型无效,只能是forbid(禁播)或recover(解禁)");
+ }
+
+ // 获取VOD客户端实例
+ VodClient client = tencentCloudUtil.getVodClient();
+
+ // 创建禁播/解禁请求
+ com.tencentcloudapi.vod.v20180717.models.ForbidMediaDistributionRequest req = new com.tencentcloudapi.vod.v20180717.models.ForbidMediaDistributionRequest();
+ req.setFileIds(fileIds.toArray(new String[0]));
+ req.setOperation(operation);
+
+ // 调用禁播/解禁API
+ com.tencentcloudapi.vod.v20180717.models.ForbidMediaDistributionResponse resp = client.ForbidMediaDistribution(req);
+
+ // 记录操作结果
+ log.info("媒体{}操作已提交 - fileIds: {}, notExistFileIds: {}",
+ operation.equals("forbid") ? "禁播" : "解禁",
+ fileIds,
+ resp.getNotExistFileIdSet());
+
+ // 如果有不存在的文件ID,记录警告日志
+ if (resp.getNotExistFileIdSet() != null && resp.getNotExistFileIdSet().length > 0) {
+ log.warn("部分文件不存在 - fileIds: {}", Arrays.toString(resp.getNotExistFileIdSet()));
+ }
+
+ } catch (TencentCloudSDKException e) {
+ log.error("媒体{}操作失败 - fileIds: {}, error: {}",
+ operation.equals("forbid") ? "禁播" : "解禁",
+ fileIds,
+ e.getMessage(),
+ e);
+ throw new RuntimeException("媒体" + (operation.equals("forbid") ? "禁播" : "解禁") + "失败: " + e.getMessage());
+ }
}
// 视频删除
@@ -178,12 +284,13 @@ public class VlogUploadServiceImpl implements VlogUploadService {
paramMap.put("vlogId", vlogId);
List vlogList = vlogMapperCustom.getVlogDetailById(paramMap);
com.wzj.soopin.content.domain.vo.IndexVlogVO vlog = vlogList != null && !vlogList.isEmpty() ? vlogList.get(0) : null;
-
+
com.tencentcloudapi.vod.v20180717.models.MediaInfo mediaInfo = null;
if (vlog == null) {
// 若本地无,尝试从云点播获取
com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest req = new com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest();
- req.setFileIds(new String[]{vlogId});
+ String fileId = vlogId; // 这里假设传入的 vlogId 就是 fileId
+ req.setFileIds(new String[]{fileId});
VodClient client = tencentCloudUtil.getVodClient();
com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req);
if (resp.getMediaInfoSet() != null && resp.getMediaInfoSet().length > 0) {
diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/utils/Props.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/utils/Props.java
index c906b8673..1a4fb563a 100644
--- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/utils/Props.java
+++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/utils/Props.java
@@ -6,7 +6,8 @@ import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Properties;
-import static com.squareup.okhttp.internal.Util.closeQuietly;
+
+import static com.google.common.io.Closeables.closeQuietly;
import static java.io.File.separator;
diff --git a/ruoyi-modules/ruoyi-content/src/main/resources/mapper/content/VlogMapper.xml b/ruoyi-modules/ruoyi-content/src/main/resources/mapper/content/VlogMapper.xml
index b64289b24..89b1af3a5 100644
--- a/ruoyi-modules/ruoyi-content/src/main/resources/mapper/content/VlogMapper.xml
+++ b/ruoyi-modules/ruoyi-content/src/main/resources/mapper/content/VlogMapper.xml
@@ -155,6 +155,14 @@
AND v.first_frame_img IS NOT NULL
+
+
+ UPDATE t_vlog
+ SET status = #{params.status},
+ reason = #{params.reason},
+ audit_time = #{params.auditTime}
+ WHERE id = #{params.vlogId}
+