feat(relation): 实现用户粉丝列表查询功能
- 新增查询用户粉丝列表接口 - 定义粉丝列表请求参数类 FindFansListReqVO- 定义粉丝信息响应类 FindFansUserRspVO - 在 RelationController 中添加 /fans/list POST 接口 - 在 RelationService 中定义 findFansList 方法 - 在 RelationServiceImpl 中实现粉丝列表查询逻辑 - 支持 Redis 缓存查询与数据库分页查询 - 实现粉丝列表异步同步至 Redis 功能 - 添加 HTTP 客户端测试用例
This commit is contained in:
3
.idea/inspectionProfiles/Project_Default.xml
generated
3
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,6 +1,9 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="ConstantValue" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="REPORT_CONSTANT_REFERENCE_VALUES" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
<Languages>
|
<Languages>
|
||||||
<language minSize="56" name="Java" />
|
<language minSize="56" name="Java" />
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import com.hanserwei.framework.common.response.PageResponse;
|
|||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.user.dto.req.FindFollowingListReqVO;
|
import com.hanserwei.hannote.user.dto.req.FindFollowingListReqVO;
|
||||||
import com.hanserwei.hannote.user.dto.resp.FindFollowingUserRspVO;
|
import com.hanserwei.hannote.user.dto.resp.FindFollowingUserRspVO;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.dto.FindFansUserRspVO;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FindFansListReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.service.RelationService;
|
import com.hanserwei.hannote.user.relation.biz.service.RelationService;
|
||||||
@@ -41,4 +43,10 @@ public class RelationController {
|
|||||||
public PageResponse<FindFollowingUserRspVO> findFollowingList(@Validated @RequestBody FindFollowingListReqVO findFollowingListReqVO) {
|
public PageResponse<FindFollowingUserRspVO> findFollowingList(@Validated @RequestBody FindFollowingListReqVO findFollowingListReqVO) {
|
||||||
return relationService.findFollowingList(findFollowingListReqVO);
|
return relationService.findFollowingList(findFollowingListReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/fans/list")
|
||||||
|
@ApiOperationLog(description = "查询用户粉丝列表")
|
||||||
|
public PageResponse<FindFansUserRspVO> findFansList(@Validated @RequestBody FindFansListReqVO findFansListReqVO) {
|
||||||
|
return relationService.findFansList(findFansListReqVO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.hanserwei.hannote.user.relation.biz.model.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindFansUserRspVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头像
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 粉丝总数
|
||||||
|
*/
|
||||||
|
private Long fansTotal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 笔记总数
|
||||||
|
*/
|
||||||
|
private Long noteTotal;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.hanserwei.hannote.user.relation.biz.model.vo;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class FindFansListReqVO {
|
||||||
|
|
||||||
|
@NotNull(message = "查询用户 ID 不能为空")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@NotNull(message = "页码不能为空")
|
||||||
|
private Integer pageNo = 1; // 默认值为第一页
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import com.hanserwei.framework.common.response.PageResponse;
|
|||||||
import com.hanserwei.framework.common.response.Response;
|
import com.hanserwei.framework.common.response.Response;
|
||||||
import com.hanserwei.hannote.user.dto.req.FindFollowingListReqVO;
|
import com.hanserwei.hannote.user.dto.req.FindFollowingListReqVO;
|
||||||
import com.hanserwei.hannote.user.dto.resp.FindFollowingUserRspVO;
|
import com.hanserwei.hannote.user.dto.resp.FindFollowingUserRspVO;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.dto.FindFansUserRspVO;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FindFansListReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
||||||
|
|
||||||
@@ -30,4 +32,13 @@ public interface RelationService {
|
|||||||
* @return 响应
|
* @return 响应
|
||||||
*/
|
*/
|
||||||
PageResponse<FindFollowingUserRspVO> findFollowingList(FindFollowingListReqVO findFollowingListReqVO);
|
PageResponse<FindFollowingUserRspVO> findFollowingList(FindFollowingListReqVO findFollowingListReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询粉丝列表
|
||||||
|
*
|
||||||
|
* @param findFansListReqVO 查询粉丝列表请求
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
PageResponse<FindFansUserRspVO> findFansList(FindFansListReqVO findFansListReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,18 @@ import com.hanserwei.hannote.user.dto.resp.FindFollowingUserRspVO;
|
|||||||
import com.hanserwei.hannote.user.dto.resp.FindUserByIdRspDTO;
|
import com.hanserwei.hannote.user.dto.resp.FindUserByIdRspDTO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.constant.MQConstants;
|
import com.hanserwei.hannote.user.relation.biz.constant.MQConstants;
|
||||||
import com.hanserwei.hannote.user.relation.biz.constant.RedisKeyConstants;
|
import com.hanserwei.hannote.user.relation.biz.constant.RedisKeyConstants;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.domain.dataobject.FansDO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.domain.dataobject.FollowingDO;
|
import com.hanserwei.hannote.user.relation.biz.domain.dataobject.FollowingDO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.enums.LuaResultEnum;
|
import com.hanserwei.hannote.user.relation.biz.enums.LuaResultEnum;
|
||||||
import com.hanserwei.hannote.user.relation.biz.enums.ResponseCodeEnum;
|
import com.hanserwei.hannote.user.relation.biz.enums.ResponseCodeEnum;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.dto.FindFansUserRspVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.dto.FollowUserMqDTO;
|
import com.hanserwei.hannote.user.relation.biz.model.dto.FollowUserMqDTO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.dto.UnfollowUserMqDTO;
|
import com.hanserwei.hannote.user.relation.biz.model.dto.UnfollowUserMqDTO;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FindFansListReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.FollowUserReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
import com.hanserwei.hannote.user.relation.biz.model.vo.UnfollowUserReqVO;
|
||||||
import com.hanserwei.hannote.user.relation.biz.rpc.UserRpcService;
|
import com.hanserwei.hannote.user.relation.biz.rpc.UserRpcService;
|
||||||
|
import com.hanserwei.hannote.user.relation.biz.service.FansDOService;
|
||||||
import com.hanserwei.hannote.user.relation.biz.service.FollowingDOService;
|
import com.hanserwei.hannote.user.relation.biz.service.FollowingDOService;
|
||||||
import com.hanserwei.hannote.user.relation.biz.service.RelationService;
|
import com.hanserwei.hannote.user.relation.biz.service.RelationService;
|
||||||
import com.hanserwei.hannote.user.relation.biz.util.DateUtils;
|
import com.hanserwei.hannote.user.relation.biz.util.DateUtils;
|
||||||
@@ -59,6 +63,8 @@ public class RelationServiceImpl implements RelationService {
|
|||||||
private RocketMQTemplate rocketMQTemplate;
|
private RocketMQTemplate rocketMQTemplate;
|
||||||
@Resource(name = "relationTaskExecutor")
|
@Resource(name = "relationTaskExecutor")
|
||||||
private ThreadPoolTaskExecutor taskExecutor;
|
private ThreadPoolTaskExecutor taskExecutor;
|
||||||
|
@Resource
|
||||||
|
private FansDOService fansDOService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response<?> follow(FollowUserReqVO followUserReqVO) {
|
public Response<?> follow(FollowUserReqVO followUserReqVO) {
|
||||||
@@ -321,7 +327,6 @@ public class RelationServiceImpl implements RelationService {
|
|||||||
log.info("==> 批量查询用户信息,用户ID: {}", userIds);
|
log.info("==> 批量查询用户信息,用户ID: {}", userIds);
|
||||||
|
|
||||||
// RPC: 批量查询用户信息
|
// RPC: 批量查询用户信息
|
||||||
//noinspection ConstantValue
|
|
||||||
findFollowingUserRspVOS = rpcUserServiceAndDTO2VO(userIds, findFollowingUserRspVOS);
|
findFollowingUserRspVOS = rpcUserServiceAndDTO2VO(userIds, findFollowingUserRspVOS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -358,7 +363,6 @@ public class RelationServiceImpl implements RelationService {
|
|||||||
List<Long> userIds = followingDOS.stream().map(FollowingDO::getFollowingUserId).toList();
|
List<Long> userIds = followingDOS.stream().map(FollowingDO::getFollowingUserId).toList();
|
||||||
|
|
||||||
// RPC: 调用用户服务,并将 DTO 转换为 VO
|
// RPC: 调用用户服务,并将 DTO 转换为 VO
|
||||||
//noinspection ConstantValue
|
|
||||||
findFollowingUserRspVOS = rpcUserServiceAndDTO2VO(userIds, findFollowingUserRspVOS);
|
findFollowingUserRspVOS = rpcUserServiceAndDTO2VO(userIds, findFollowingUserRspVOS);
|
||||||
|
|
||||||
// 异步将关注列表全量同步到 Redis
|
// 异步将关注列表全量同步到 Redis
|
||||||
@@ -372,6 +376,157 @@ public class RelationServiceImpl implements RelationService {
|
|||||||
total);
|
total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResponse<FindFansUserRspVO> findFansList(FindFansListReqVO findFansListReqVO) {
|
||||||
|
// 要查询的用户ID
|
||||||
|
Long userId = findFansListReqVO.getUserId();
|
||||||
|
// 页码
|
||||||
|
Integer pageNo = findFansListReqVO.getPageNo();
|
||||||
|
// 先从Redis中查询
|
||||||
|
String fansListRedisKey = RedisKeyConstants.buildUserFansKey(userId);
|
||||||
|
// 查询目标用户粉丝列表 ZSet 的总大小
|
||||||
|
Long total = redisTemplate.opsForZSet().zCard(fansListRedisKey);
|
||||||
|
|
||||||
|
// 构建回参
|
||||||
|
List<FindFansUserRspVO> findFansUserRspVOS = null;
|
||||||
|
// 每页展示10条数据
|
||||||
|
long limit = 10L;
|
||||||
|
|
||||||
|
if (total != null && total > 0) {
|
||||||
|
// 缓存有数据
|
||||||
|
// 计算一共多少页
|
||||||
|
long totalPage = PageResponse.getTotalPage(total, limit);
|
||||||
|
|
||||||
|
// 请求页码超过总页数
|
||||||
|
if (pageNo > totalPage) {
|
||||||
|
log.info("==> 查询粉丝列表请求页码超过总页数,返回空数据");
|
||||||
|
return PageResponse.success(null, pageNo, total);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备从 Redis 中查询 ZSet 分页数据
|
||||||
|
// 每页 10 个元素,计算偏移量
|
||||||
|
long offset = PageResponse.getOffset(pageNo, limit);
|
||||||
|
|
||||||
|
// 使用 ZREVRANGEBYSCORE 命令按 score 降序获取元素,同时使用 LIMIT 子句实现分页
|
||||||
|
Set<Object> followingUserIdsSet = redisTemplate.opsForZSet()
|
||||||
|
.reverseRangeByScore(fansListRedisKey, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, offset, limit);
|
||||||
|
|
||||||
|
if (CollUtil.isNotEmpty(followingUserIdsSet)) {
|
||||||
|
// 提取所有用户 ID 到集合中
|
||||||
|
List<Long> userIds = followingUserIdsSet.stream().map(object -> Long.valueOf(object.toString())).toList();
|
||||||
|
|
||||||
|
// RPC: 批量查询用户信息
|
||||||
|
findFansUserRspVOS = rpcUserServiceAndCountServiceAndDTO2VO(userIds, findFansUserRspVOS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 若 Redis 中没有数据,则从数据库查询
|
||||||
|
// 先查询记录总量
|
||||||
|
total = fansDOService.count(new LambdaQueryWrapper<>(FansDO.class).eq(FansDO::getUserId, userId));
|
||||||
|
// 获取一共多少页
|
||||||
|
long totalPage = PageResponse.getTotalPage(total, limit);
|
||||||
|
// 请求的页码超出了总页数(只允许查询前 500 页)
|
||||||
|
if (pageNo > totalPage || pageNo > 500) {
|
||||||
|
log.info("==> 查询粉丝列表页码大于总页数或者请求的页码超出了总页数,返回空数据");
|
||||||
|
return PageResponse.success(null, pageNo, total);
|
||||||
|
}
|
||||||
|
// 偏移量
|
||||||
|
long offset = PageResponse.getOffset(pageNo, limit);
|
||||||
|
// 分页查询
|
||||||
|
Page<FansDO> page = fansDOService.page(new Page<>(offset / limit + 1, limit),
|
||||||
|
new LambdaQueryWrapper<>(FansDO.class)
|
||||||
|
.select(FansDO::getFansUserId)
|
||||||
|
.eq(FansDO::getUserId, userId)
|
||||||
|
.orderByDesc(FansDO::getCreateTime));
|
||||||
|
List<FansDO> fansDOS = page.getRecords();
|
||||||
|
|
||||||
|
log.info("==> 查询到粉丝列表:{}", JsonUtils.toJsonString(fansDOS));
|
||||||
|
|
||||||
|
// 若记录不为空
|
||||||
|
if (CollUtil.isNotEmpty(fansDOS)) {
|
||||||
|
// 提取所有用户 ID 到集合中
|
||||||
|
List<Long> userIds = fansDOS.stream().map(FansDO::getFansUserId).toList();
|
||||||
|
|
||||||
|
// RPC: 调用用户服务、计数服务,并将 DTO 转换为 VO
|
||||||
|
findFansUserRspVOS = rpcUserServiceAndCountServiceAndDTO2VO(userIds, findFansUserRspVOS);
|
||||||
|
|
||||||
|
// 异步将粉丝列表同步到 Redis(最多5000条)
|
||||||
|
taskExecutor.submit(() -> syncFansList2Redis(userId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return PageResponse.success(findFansUserRspVOS, pageNo, total);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncFansList2Redis(Long userId) {
|
||||||
|
// 同步粉丝列表到 Redis
|
||||||
|
// 查询粉丝列表,最多5000条
|
||||||
|
Page<FansDO> page = fansDOService.page(new Page<>(1, 5000),
|
||||||
|
new LambdaQueryWrapper<>(FansDO.class)
|
||||||
|
.select(FansDO::getFansUserId, FansDO::getCreateTime)
|
||||||
|
.eq(FansDO::getUserId, userId)
|
||||||
|
.orderByDesc(FansDO::getCreateTime));
|
||||||
|
List<FansDO> fansDOS = page.getRecords();
|
||||||
|
if (CollUtil.isNotEmpty(fansDOS)) {
|
||||||
|
// 用户粉丝列表的Redis Key
|
||||||
|
String fansListRedisKey = RedisKeyConstants.buildUserFansKey(userId);
|
||||||
|
// 随机过期时间,保底一天+随机秒数
|
||||||
|
long expireSeconds = 86400 + RandomUtil.randomLong(0, 86400);
|
||||||
|
// 构建 Lua 参数
|
||||||
|
Object[] luaArgs = buildFansZSetLuaArgs(fansDOS, expireSeconds);
|
||||||
|
|
||||||
|
// 执行 Lua 脚本,批量同步关注关系数据到 Redis 中
|
||||||
|
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
|
||||||
|
script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/follow_batch_add_and_expire.lua")));
|
||||||
|
script.setResultType(Long.class);
|
||||||
|
redisTemplate.execute(script, Collections.singletonList(fansListRedisKey), luaArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 Lua 脚本参数 :粉丝列表
|
||||||
|
*
|
||||||
|
* @param fansDOS 粉丝DO列表
|
||||||
|
* @param expireSeconds 过期时间
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
private Object[] buildFansZSetLuaArgs(List<FansDO> fansDOS, long expireSeconds) {
|
||||||
|
int argsLength = fansDOS.size() * 2 + 1; // 每个粉丝关系有 2 个参数(score 和 value),再加一个过期时间
|
||||||
|
Object[] luaArgs = new Object[argsLength];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (FansDO fansDO : fansDOS) {
|
||||||
|
luaArgs[i] = DateUtils.localDateTime2Timestamp(fansDO.getCreateTime()); // 粉丝的关注时间作为 score
|
||||||
|
luaArgs[i + 1] = fansDO.getFansUserId(); // 粉丝的用户 ID 作为 ZSet value
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaArgs[argsLength - 1] = expireSeconds; // 最后一个参数是 ZSet 的过期时间
|
||||||
|
return luaArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FindFansUserRspVO> rpcUserServiceAndCountServiceAndDTO2VO(List<Long> userIds, List<FindFansUserRspVO> findFansUserRspVOS) {
|
||||||
|
// RPC: 批量查询用户信息
|
||||||
|
List<FindUserByIdRspDTO> findUserByIdRspDTOS = userRpcService.findByIds(userIds);
|
||||||
|
|
||||||
|
// TODO RPC: 批量查询用户的计数数据(笔记总数、粉丝总数)
|
||||||
|
|
||||||
|
// 若不为空,DTO 转 VO
|
||||||
|
if (CollUtil.isNotEmpty(findUserByIdRspDTOS)) {
|
||||||
|
findFansUserRspVOS = findUserByIdRspDTOS.stream()
|
||||||
|
.map(dto -> FindFansUserRspVO.builder()
|
||||||
|
.userId(dto.getId())
|
||||||
|
.avatar(dto.getAvatar())
|
||||||
|
.nickname(dto.getNickName())
|
||||||
|
.noteTotal(0L) // TODO: 这块的数据暂无,后续补充
|
||||||
|
.fansTotal(0L) // TODO: 这块的数据暂无,后续补充
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
return findFansUserRspVOS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全量同步关注列表到 Redis
|
* 全量同步关注列表到 Redis
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -170,6 +170,16 @@ POST http://localhost:8000/relation/relation/following/list
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"userId": 100,
|
||||||
|
"pageNo": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
### 查询用户粉丝列表
|
||||||
|
POST http://localhost:8000/relation/relation/fans/list
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
{
|
{
|
||||||
"userId": 100,
|
"userId": 100,
|
||||||
"pageNo": 1
|
"pageNo": 1
|
||||||
|
|||||||
Reference in New Issue
Block a user