修改vlog视频后台管理

This commit is contained in:
cjh 2025-06-06 09:35:15 +08:00
parent f7a100b025
commit 4d0b6cb113
10 changed files with 276 additions and 50 deletions

View File

@ -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

View File

@ -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

View File

@ -38,7 +38,7 @@
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.270</version>
<version>3.1.1030</version>
</dependency>
<!--腾讯云点播-->
@ -169,19 +169,48 @@
<!-- <version>3.1.1030</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; 腾讯云SDK公共模块 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>-->
<!-- <artifactId>tencentcloud-sdk-java-common</artifactId>-->
<!-- <version>3.1.1030</version>-->
<!-- </dependency>-->
<!-- 腾讯云SDK公共模块 -->
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-common</artifactId>
<version>3.1.1030</version>
</dependency>
<!-- &lt;!&ndash; 腾讯云SDK模型模块 &ndash;&gt;-->
<!-- 腾讯云SDK核心模块 -->
<!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>-->
<!-- <artifactId>tencentcloud-sdk-java-models</artifactId>-->
<!-- <artifactId>tencentcloud-sdk-java-core</artifactId>-->
<!-- <version>3.1.1030</version>-->
<!-- </dependency>-->
</dependencies>
<repositories>
<!-- 腾讯云 Maven 仓库 -->
<repository>
<id>tencent-cloud-sdk</id>
<name>tencent-cloud-sdk</name>
<url>https://mirrors.tencent.com/nexus/repository/maven-public/</url>
</repository>
<!-- 阿里云 Maven 仓库 -->
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Maven 中央仓库 -->
<repository>
<id>central</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>
</project>

View File

@ -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<String, Object> callbackData) {
@ -364,4 +368,6 @@ public class VlogController extends BaseInfoProperties {
pageSize);
return GraceJSONResult.ok(gridResult);
}
}

View File

@ -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<String, Object> params) {
try {
// 参数验证
if (params == null) {
return GraceJSONResult.errorMsg("参数不能为空");
}
Object fileIdsObj = params.get("fileIds");
String operation = (String) params.get("operation");
List<String> fileIds;
if (fileIdsObj instanceof String) {
// 如果是单个字符串转换为列表
fileIds = Collections.singletonList((String) fileIdsObj);
} else if (fileIdsObj instanceof List) {
// 如果已经是列表直接使用
fileIds = (List<String>) 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());
}
}
}

View File

@ -56,4 +56,11 @@ public interface VlogMapper extends BaseMapper<Vlog> {
public List<IndexVlogVO> selectMyPublic(@Param("paramMap")Map<String, Object> map);
public List<IndexVlogVO> getVlogDetailFromId(@Param("paramMap")Map<String, Object> map);
/**
* 更新视频审核状态
* @param params 包含vlogIdstatusreason和auditTime的Map
* @return 影响的行数
*/
int updateVlogStatus(@Param("params") Map<String, Object> params);
}

View File

@ -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<String> fileIds, String operation);
}

View File

@ -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"});
// 设置审核模板ID10为预置模板
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<String, Object> 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<String> 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());
}
}
// 视频删除
@ -183,7 +289,8 @@ public class VlogUploadServiceImpl implements VlogUploadService {
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) {

View File

@ -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;

View File

@ -155,6 +155,14 @@
AND v.first_frame_img IS NOT NULL
</select>
<!-- 更新视频审核状态 -->
<update id="updateVlogStatus">
UPDATE t_vlog
SET status = #{params.status},
reason = #{params.reason},
audit_time = #{params.auditTime}
WHERE id = #{params.vlogId}
</update>
</mapper>