视频列表

This commit is contained in:
曹佳豪 2025-06-11 10:21:42 +08:00
parent 8a9dfeb883
commit 847f8b0372
7 changed files with 296 additions and 186 deletions

View File

@ -4,13 +4,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tencentcloudapi.vod.v20180717.models.*;
import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.mapper.MyLikedVlogMapper;
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.RedisOperator;
import com.wzj.soopin.content.utils.TencentCloudUtil;
import com.wzj.soopin.member.domain.vo.FansVO;
import com.wzj.soopin.member.mapper.FansMapper;
import com.wzj.soopin.member.service.IFansService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -20,11 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Slf4j
@Api(tags = "管理端-视频上传接口")
@ -35,46 +30,40 @@ public class VlogUploadController extends BaseInfoProperties {
@Autowired
private VlogUploadService vlogUploadService;
@Autowired
private VlogService vlogService;
@Autowired
private TencentCloudUtil tencentCloudUtil;
@Autowired
private com.wzj.soopin.content.mapper.VlogMapper vlogMapper;
@Autowired
private com.wzj.soopin.content.mapper.CommentMapper commentMapper;
@Autowired
private RedisOperator redis;
@Autowired
private MyLikedVlogMapper myLikedVlogMapper;
@Autowired
private IFansService fansService;
@ApiOperation("获取腾讯云点播视频列表")
@GetMapping("/list")
public GraceJSONResult getVodList(
@ApiParam(value = "页码", defaultValue = "1") @RequestParam(required = false, defaultValue = "1") Integer pageNum,
@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,
@ApiParam(value = "媒体文件封装格式mp4、mov等") @RequestParam(required = false) String[] mediaTypes,
@ApiParam(value = "文件名,支持模糊搜索") @RequestParam(required = false) String[] names,
@ApiParam(value = "当前页码", defaultValue = "1") @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
@ApiParam(value = "每页记录数", defaultValue = "10") @RequestParam(value = "size", required = false, defaultValue = "10") Integer size,
@ApiParam(value = "文件状态") @RequestParam(required = false) String[] status,
@ApiParam(value = "文件类型") @RequestParam(required = false) String[] categories,
@ApiParam(value = "媒体文件来源") @RequestParam(required = false) String[] sourceTypes,
@ApiParam(value = "媒体文件封装格式") @RequestParam(required = false) String[] mediaTypes,
@ApiParam(value = "文件名") @RequestParam(required = false) String[] names,
@ApiParam(value = "文件名前缀") @RequestParam(required = false) String[] namePrefixes,
@ApiParam(value = "文件描述,支持模糊搜索") @RequestParam(required = false) String[] descriptions,
@ApiParam(value = "文件描述") @RequestParam(required = false) String[] descriptions,
@ApiParam(value = "标签") @RequestParam(required = false) String[] tags,
@ApiParam(value = "分类ID") @RequestParam(required = false) Long[] classIds,
@ApiParam(value = "存储地区ap-guangzhou") @RequestParam(required = false) String[] storageRegions,
@ApiParam(value = "创建时间范围-开始时间格式yyyy-MM-dd'T'HH:mm:ss'Z'") @RequestParam(required = false) String createTimeAfter,
@ApiParam(value = "创建时间范围-结束时间格式yyyy-MM-dd'T'HH:mm:ss'Z'") @RequestParam(required = false) String createTimeBefore,
@ApiParam(value = "排序字段目前仅支持CreateTime") @RequestParam(required = false, defaultValue = "CreateTime") String sortField,
@ApiParam(value = "排序方式可选值Desc降序、Asc升序") @RequestParam(required = false, defaultValue = "Desc") String sortOrder,
@ApiParam(value = "需要返回的信息类型可选值basicInfo基础信息、metaData元信息、transcodeInfo转码信息") @RequestParam(required = false) String[] filters) {
@ApiParam(value = "存储地区") @RequestParam(required = false) String[] storageRegions,
@ApiParam(value = "创建时间范围-开始时间") @RequestParam(required = false) String createTimeAfter,
@ApiParam(value = "创建时间范围-结束时间") @RequestParam(required = false) String createTimeBefore,
@ApiParam(value = "排序字段", defaultValue = "CreateTime", allowableValues = "CreateTime,LikeCounts,CommentsCounts,Name,Status")
@RequestParam(required = false, defaultValue = "CreateTime") String sortField,
@ApiParam(value = "排序方式", defaultValue = "Asc", allowableValues = "Asc,Desc")
@RequestParam(required = false, defaultValue = "Asc") String sortOrder,
@ApiParam(value = "需要返回的信息类型") @RequestParam(required = false) String[] filters) {
try {
// 验证密钥配置
String secretId = tencentCloudUtil.getSecretId();
@ -84,12 +73,41 @@ public class VlogUploadController extends BaseInfoProperties {
return GraceJSONResult.errorMsg("腾讯云密钥未配置");
}
// 验证分页参数
if (current < 1) {
current = 1;
}
if (size < 1 || size > 50) {
size = 10;
}
// 计算实际的offset
long offset = (long) ((current - 1) * size);
if (offset < 0) {
offset = 0;
}
// 打印分页参数
log.info("分页参数 - 当前页码: {}, 每页记录数: {}, 偏移量: {}", current, size, offset);
log.info("排序参数 - 排序字段: {}, 排序方式: {}", sortField, sortOrder);
// 验证排序参数
List<String> validSortFields = Arrays.asList("CreateTime", "LikeCounts", "CommentsCounts", "Name", "Status");
List<String> validSortOrders = Arrays.asList("Asc", "Desc");
if (!validSortFields.contains(sortField)) {
return GraceJSONResult.errorMsg("无效的排序字段,支持的字段有:" + String.join(",", validSortFields));
}
if (!validSortOrders.contains(sortOrder)) {
return GraceJSONResult.errorMsg("无效的排序方式,只能是 Asc(升序) 或 Desc(降序)");
}
// 创建请求对象
SearchMediaRequest req = new SearchMediaRequest();
// 设置分页参数
req.setOffset((long) ((pageNum - 1) * pageSize));
req.setLimit((long) pageSize);
req.setOffset(offset);
req.setLimit((long) size);
// 设置排序
SortBy sort = new SortBy();
@ -129,13 +147,14 @@ public class VlogUploadController extends BaseInfoProperties {
// 调用腾讯云API获取视频列表
log.info("开始调用腾讯云 SearchMedia API");
SearchMediaResponse resp = vlogUploadService.searchMedia(req);
log.info("腾讯云 SearchMedia API 调用成功");
log.info("腾讯云 SearchMedia API 调用成功,总记录数: {}", resp.getTotalCount());
// 处理响应结果
Map<String, Object> result = new HashMap<>();
result.put("totalCount", resp.getTotalCount());
result.put("pageNum", pageNum);
result.put("pageSize", pageSize);
result.put("total", resp.getTotalCount());
result.put("current", current);
result.put("size", size);
result.put("pages", (resp.getTotalCount() + size - 1) / size); // 总页数
List<Map<String, Object>> mediaList = new ArrayList<>();
if (resp.getMediaInfoSet() != null) {
@ -161,44 +180,21 @@ public class VlogUploadController extends BaseInfoProperties {
mediaMap.put("storageClass", basicInfo.getStorageClass());
mediaMap.put("tagSet", basicInfo.getTagSet());
// 先通过fileId查询本地数据库获取视频信息
com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectByFileId(mediaInfo.getFileId());
if (vlog != null) {
mediaMap.put("vlogId", vlog.getId());
mediaMap.put("title",vlog.getTitle());
// 点赞数通过点赞表统计
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
mediaMap.put("likeCounts", likeCounts);
// 评论数
Integer commentCount = commentMapper.countByVlogId(vlog.getId());
mediaMap.put("commentCounts", commentCount);
// 获取视频统计信息
Map<String, Object> statistics = vlogService.getVlogStatistics(mediaInfo.getFileId());
mediaMap.putAll(statistics);
// 获取粉丝数量优先 Redis无则 MySQL
String fansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId());
Integer fansCounts = 0;
if (StringUtils.isNotBlank(fansCountsStr)) {
fansCounts = Integer.valueOf(fansCountsStr);
} else {
// Redis 中没有从数据库查询
fansCounts = fansService.countFansByVlogerId(vlog.getVlogerId());
// 可以选择在这里将数据库查询结果写入 Redis以便下次使用
if (fansCounts != null) {
redis.set(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId(), String.valueOf(fansCounts));
}
}
mediaMap.put("fansCounts", fansCounts);
} else {
mediaMap.put("vlogId", null);
mediaMap.put("likeCounts", 0);
mediaMap.put("commentCounts", 0);
mediaMap.put("fansCounts", 0);
// 获取视频上传者信息
Map<String, String> uploaderInfo = vlogService.getVlogUploaderInfo(mediaInfo.getFileId());
if (uploaderInfo != null) {
mediaMap.put("nickname", uploaderInfo.get("name"));
mediaMap.put("mobile", uploaderInfo.get("phone"));
}
mediaList.add(mediaMap);
}
}
result.put("list", mediaList);
result.put("records", mediaList); // 改为 records 以匹配前端预期
return GraceJSONResult.ok(result);
} catch (Exception e) {
@ -243,48 +239,14 @@ public class VlogUploadController extends BaseInfoProperties {
@GetMapping("/detail")
public GraceJSONResult vlogDetail(@RequestParam String fileId) {
try {
// 先通过fileId查询本地数据库获取vlog信息
com.wzj.soopin.content.domain.po.Vlog vlog = vlogMapper.selectByFileId(fileId);
Map<String, Object> result = new HashMap<>();
// 获取视频基本信息
Map<String, Object> result = vlogService.getVlogDetailInfo(fileId);
if (vlog != null) {
log.info("找到视频信息: vlogId={}, fileId={}", vlog.getId(), fileId);
// 如果找到vlog信息使用fileId查询腾讯云
Object vodDetail = vlogUploadService.getVlogDetail(fileId);
if (vodDetail instanceof Map) {
result.putAll((Map<String, Object>) vodDetail);
} else {
result.put("vodDetail", vodDetail);
}
// 添加评论信息
List<Map<String, Object>> comments = commentMapper.selectCommentsByVlogId(vlog.getId());
result.put("comments", comments);
// 添加点赞数通过点赞表统计
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
result.put("likeCounts", likeCounts);
result.put("vlogId", vlog.getId());
// 查询点赞用户信息
List<Map<String, Object>> likedUsers = myLikedVlogMapper.selectLikedUsersByVlogId(vlog.getId());
result.put("likedUsers", likedUsers);
IPage<FansVO> fansList = fansService.queryMyFans(vlog.getVlogerId(),0,10);
result.put("fansList", fansList);
} else {
log.info("未找到视频信息, fileId={}", fileId);
// 如果没有找到vlog信息只返回腾讯云视频信息
Object vodDetail = vlogUploadService.getVlogDetail(fileId);
if (vodDetail instanceof Map) {
result.putAll((Map<String, Object>) vodDetail);
} else {
result.put("vodDetail", vodDetail);
}
// 设置默认值
result.put("comments", Collections.emptyList());
result.put("likeCounts", 0);
result.put("likedUsers", Collections.emptyList());
result.put("fansList", Collections.emptyList());
// 获取视频上传者信息
Map<String, String> uploaderInfo = vlogService.getVlogUploaderInfo(fileId);
if (uploaderInfo != null) {
result.put("uploaderName", uploaderInfo.get("name"));
result.put("uploaderPhone", uploaderInfo.get("phone"));
}
return GraceJSONResult.ok(result);
@ -293,6 +255,7 @@ public class VlogUploadController extends BaseInfoProperties {
return GraceJSONResult.errorMsg("获取视频详情失败: " + e.getMessage());
}
}
@ApiOperation(value = "禁播/解禁视频", notes = "禁播/解禁视频接口")
@PostMapping("/forbid")
public GraceJSONResult forbidMediaDistribution(@RequestBody Map<String, Object> params) {
@ -339,4 +302,25 @@ public class VlogUploadController extends BaseInfoProperties {
return GraceJSONResult.errorMsg("操作失败: " + e.getMessage());
}
}
@ApiOperation(value = "根据vlogerId查询用户信息", notes = "查询视频上传者的姓名和电话")
@GetMapping("/user-info")
public GraceJSONResult getUserInfoByVlogerId(@RequestParam String vlogerId) {
try {
if (StringUtils.isBlank(vlogerId)) {
return GraceJSONResult.errorMsg("vlogerId不能为空");
}
// 获取视频上传者信息
Map<String, String> uploaderInfo = vlogService.getVlogUploaderInfo(vlogerId);
if (uploaderInfo == null || uploaderInfo.isEmpty()) {
return GraceJSONResult.errorMsg("未找到对应的用户信息");
}
return GraceJSONResult.ok(uploaderInfo);
} catch (Exception e) {
log.error("获取用户信息失败", e);
return GraceJSONResult.errorMsg("获取用户信息失败: " + e.getMessage());
}
}
}

View File

@ -1,10 +1,14 @@
package com.wzj.soopin.content.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wzj.soopin.content.domain.bo.VlogBO;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
import com.wzj.soopin.content.utils.PagedGridResult;
import java.util.List;
import java.util.Map;
public interface VlogService {
/**
* 修改视频首帧图
@ -100,72 +104,41 @@ public interface VlogService {
* 把counts输入数据库
*/
public void flushCounts(String vlogId, Integer counts);
// /**
// * 查询首页/搜索的vlog列表
// */
// public PagedGridResult getIndexVlogList(String userId,
// String search,
// Integer page,
// Integer pageSize);
//
// /**
// * 根据视频主键查询vlog
// */
// public IndexVlogVO getVlogDetailById(String userId, String vlogId);
//
// /**
// * 用户把视频改为公开/私密的视频
// */
// public void changeToPrivateOrPublic(String userId,
// String vlogId,
// Integer yesOrNo);
//
// /**
// * 查询用的公开/私密的视频列表
// */
// public PagedGridResult queryMyVlogList(String userId,
// Integer page,
// Integer pageSize,
// Integer yesOrNo);
//
// /**
// * 用户点赞/喜欢视频
// */
// public void userLikeVlog(String userId, String vlogId);
//
// /**
// * 用户取消点赞/喜欢视频
// */
// public void userUnLikeVlog(String userId, String vlogId);
//
// /**
// * 获得用户点赞视频的总数
// */
// public Integer getVlogBeLikedCounts(String vlogId);
//
// /**
// * 查询用户点赞过的短视频
// */
// public PagedGridResult getMyLikedVlogList(String userId,
// Integer page,
// Integer pageSize);
//
// /**
// * 查询用户关注的博主发布的短视频列表
// */
// public PagedGridResult getMyFollowVlogList(String myId,
// Integer page,
// Integer pageSize);
//
// /**
// * 查询朋友发布的短视频列表
// */
// public PagedGridResult getMyFriendVlogList(String myId,
// Integer page,
// Integer pageSize);
//
// /**
// * 根据主键查询vlog
// */
// public Vlog getVlog(String id);
/**
* 通过 fileId 获取视频信息
*/
Vlog getVlogByFileId(String fileId);
/**
* 获取视频统计信息
*/
Map<String, Object> getVlogStatistics(String fileId);
/**
* 获取视频详细信息
*/
Map<String, Object> getVlogDetailInfo(String fileId);
/**
* 获取视频评论列表
*/
List<Map<String, Object>> getVlogComments(String vlogId);
/**
* 获取视频点赞用户列表
*/
List<Map<String, Object>> getLikedUsers(String vlogId);
/**
* 获取视频点赞数
*/
int getLikeCounts(String vlogId);
/**
* 获取视频上传者信息
* @param fileId 视频文件ID
* @return 包含上传者姓名和手机号的Map
*/
Map<String, String> getVlogUploaderInfo(String fileId);
}

View File

@ -10,15 +10,21 @@ import com.wzj.soopin.content.domain.base.BaseInfoProperties;
import com.wzj.soopin.content.domain.bo.VlogBO;
import com.wzj.soopin.content.domain.po.MyLikedVlog;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.domain.po.Users;
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
import com.wzj.soopin.content.enums.YesOrNo;
import com.wzj.soopin.content.mapper.CommentMapper;
import com.wzj.soopin.content.mapper.MyLikedVlogMapper;
import com.wzj.soopin.content.mapper.UsersMapper;
import com.wzj.soopin.content.mapper.VlogMapper;
import com.wzj.soopin.content.mapper.VlogMapperCustom;
import com.wzj.soopin.content.service.MsgService;
import com.wzj.soopin.content.service.VlogService;
import com.wzj.soopin.content.utils.PagedGridResult;
import com.wzj.soopin.content.utils.RedisOperator;
import com.wzj.soopin.content.utils.Sid;
import com.wzj.soopin.content.utils.TencentCloudUtil;
import com.wzj.soopin.member.domain.vo.FansVO;
import com.wzj.soopin.member.service.IFansService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
@ -44,6 +50,14 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
private MsgService msgService;
@Autowired
private Sid sid;
@Autowired
private CommentMapper commentMapper;
@Autowired
private RedisOperator redis;
@Autowired
private TencentCloudUtil tencentCloudUtil;
@Autowired
private UsersMapper usersMapper;
@Transactional
@Override
@ -352,4 +366,141 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
return null;
}
@Override
public Vlog getVlogByFileId(String fileId) {
return vlogMapper.selectByFileId(fileId);
}
@Override
public Map<String, Object> getVlogStatistics(String fileId) {
Map<String, Object> result = new HashMap<>();
// 获取视频基本信息
Vlog vlog = vlogMapper.selectByFileId(fileId);
if (vlog != null) {
result.put("vlogId", vlog.getId());
result.put("title", vlog.getTitle());
result.put("width",vlog.getWidth());
result.put("height",vlog.getHeight());
// 点赞数通过点赞表统计
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
result.put("likeCounts", likeCounts);
// 评论数
Integer commentCount = commentMapper.countByVlogId(vlog.getId());
result.put("commentCounts", commentCount);
// 获取粉丝数量优先 Redis无则 MySQL
String fansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId());
Integer fansCounts = 0;
if (StringUtils.isNotBlank(fansCountsStr)) {
fansCounts = Integer.valueOf(fansCountsStr);
} else {
// fansCounts = fansService.countFansByVlogerId(vlog.getVlogerId());
// if (fansCounts != null) {
// redis.set(REDIS_MY_FANS_COUNTS + ":" + vlog.getVlogerId(), String.valueOf(fansCounts));
// }
}
result.put("fansCounts", fansCounts);
} else {
result.put("vlogId", null);
result.put("likeCounts", 0);
result.put("commentCounts", 0);
result.put("fansCounts", 0);
}
return result;
}
@Override
public Map<String, Object> getVlogDetailInfo(String fileId) {
Map<String, Object> result = new HashMap<>();
// 获取视频基本信息
Vlog vlog = vlogMapper.selectByFileId(fileId);
if (vlog != null) {
// 如果找到vlog信息使用fileId查询腾讯云
// Object vodDetail = tencentCloudUtil.getVodMediaInfo(fileId);
// if (vodDetail instanceof Map) {
// result.putAll((Map<String, Object>) vodDetail);
// } else {
// result.put("vodDetail", vodDetail);
// }
// 添加评论信息
List<Map<String, Object>> comments = commentMapper.selectCommentsByVlogId(vlog.getId());
result.put("comments", comments);
// 添加点赞数和点赞用户信息
int likeCounts = myLikedVlogMapper.countLikesByVlogId(vlog.getId());
result.put("likeCounts", likeCounts);
result.put("vlogId", vlog.getId());
List<Map<String, Object>> likedUsers = myLikedVlogMapper.selectLikedUsersByVlogId(vlog.getId());
result.put("likedUsers", likedUsers);
// 添加粉丝列表
// Page<FansVO> fansPage = fansService.queryMyFans(vlog.getVlogerId(), 0, 10);
// result.put("fansList", fansPage);
} else {
// 如果没有找到vlog信息只返回腾讯云视频信息
// Object vodDetail = tencentCloudUtil.getVodMediaInfo(fileId);
// if (vodDetail instanceof Map) {
// result.putAll((Map<String, Object>) vodDetail);
// } else {
// result.put("vodDetail", vodDetail);
// }
// 设置默认值
result.put("comments", Collections.emptyList());
result.put("likeCounts", 0);
result.put("likedUsers", Collections.emptyList());
result.put("fansList", Collections.emptyList());
}
return result;
}
@Override
public List<Map<String, Object>> getVlogComments(String vlogId) {
return commentMapper.selectCommentsByVlogId(vlogId);
}
@Override
public List<Map<String, Object>> getLikedUsers(String vlogId) {
return myLikedVlogMapper.selectLikedUsersByVlogId(vlogId);
}
@Override
public int getLikeCounts(String vlogId) {
return myLikedVlogMapper.countLikesByVlogId(vlogId);
}
@Override
public Map<String, String> getVlogUploaderInfo(String fileId) {
// 通过 fileId 获取视频信息
Vlog vlog = vlogMapper.selectByFileId(fileId);
if (vlog == null) {
return null;
}
// 获取上传者ID
String uploaderId = vlog.getVlogerId();
if (uploaderId == null) {
return null;
}
// t_users 表获取用户信息
Users user = usersMapper.selectById(uploaderId);
if (user == null) {
return null;
}
Map<String, String> result = new HashMap<>();
result.put("name", user.getNickname());
result.put("phone", user.getMobile());
return result;
}
}

View File

@ -33,10 +33,10 @@ public class TencentCloudProperties {
/**
* 点播配置
*/
private Vod vod = new Vod();
private VodProperties vod = new VodProperties();
@Data
public static class Vod {
public static class VodProperties {
/**
* 应用ID
*/

View File

@ -0,0 +1,2 @@
ALTER TABLE t_vlog
ADD COLUMN remark varchar(500) DEFAULT NULL COMMENT '备注';

View File

@ -31,5 +31,5 @@ public interface IFansService {
Integer pageSize);
Integer countFansByVlogerId(String vlogerId);
// Integer countFansByVlogerId(String vlogerId);
}

View File

@ -108,8 +108,8 @@ public class FansServiceImpl extends ServiceImpl<FansMapper, Fans> implements IF
return null;
}
@Override
public Integer countFansByVlogerId(String vlogerId) {
return baseMapper.countFansByVlogerId(vlogerId);
}
// @Override
// public Integer countFansByVlogerId(String vlogerId) {
// return baseMapper.countFansByVlogerId(vlogerId);
// }
}