5.6 KiB
5.6 KiB
关注列表、粉丝列表
业务层:
- 查询某个用户关注的人,支持分页
- 查询某个用户的粉丝,支持分页
表现层:
- 处理 “查询关注的人”、“查询粉丝” 的请求
- 编写 “查询关注的人”、“查询粉丝” 模板
Service
/**
* 分页查询某个用户关注的人(偷个懒,此处没有做对其他实体的关注)
* @param userId
* @param offset
* @param limit
* @return
*/
public List<Map<String, Object>> findFollowees(int userId, int offset, int limit) {
String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);
if (targetIds == null) {
return null;
}
List<Map<String, Object>> list = new ArrayList<>();
for (Integer targetId : targetIds) {
Map<String, Object> map = new HashMap<>();
User user = userService.findUserById(targetId);
map.put("user", user);
Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);
map.put("followTime", new Date(score.longValue()));
list.add(map);
}
return list;
}
/**
* 分页查询某个用户的粉丝(偷个懒,此处没有做对其他实体的粉丝)
* @param userId
* @param offset
* @param limit
* @return
*/
public List<Map<String, Object>> findFollowers(int userId, int offset, int limit) {
String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
Set<Integer> targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);
if (targetIds == null) {
return null;
}
List<Map<String, Object>> list = new ArrayList<>();
for (Integer targetId : targetIds) {
Map<String, Object> map = new HashMap<>();
User user = userService.findUserById(targetId);
map.put("user", user);
Double score = redisTemplate.opsForZSet().score(followerKey, targetId);
map.put("followTime", new Date(score.longValue()));
list.add(map);
}
return list;
}
Controller
/**
* 某个用户的关注列表(人)
* @param userId
* @param page
* @param model
* @return
*/
@GetMapping("/followees/{userId}")
public String getFollowees(@PathVariable("userId") int userId, Page page, Model model) {
User user = userService.findUserById(userId);
if (user == null) {
throw new RuntimeException("该用户不存在");
}
model.addAttribute("user", user);
page.setLimit(5);
page.setPath("/followees/" + userId);
page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER));
// 获取关注列表
List<Map<String, Object>> userList = followService.findFollowees(userId, page.getOffset(), page.getLimit());
if (userList != null) {
for (Map<String, Object> map : userList) {
User u = (User) map.get("user"); // 被关注的用户
map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户
}
}
model.addAttribute("users", userList);
return "/site/followee";
}
/**
* 某个用户的粉丝列表
* @param userId
* @param page
* @param model
* @return
*/
@GetMapping("/followers/{userId}")
public String getFollowers(@PathVariable("userId") int userId, Page page, Model model) {
User user = userService.findUserById(userId);
if (user == null) {
throw new RuntimeException("该用户不存在");
}
model.addAttribute("user", user);
page.setLimit(5);
page.setPath("/followers/" + userId);
page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId));
// 获取关注列表
List<Map<String, Object>> userList = followService.findFollowers(userId, page.getOffset(), page.getLimit());
if (userList != null) {
for (Map<String, Object> map : userList) {
User u = (User) map.get("user"); // 被关注的用户
map.put("hasFollowed", hasFollowed(u.getId())); // 判断当前登录用户是否已关注这个关注列表中的某个用户
}
}
model.addAttribute("users", userList);
return "/site/follower";
}
/**
* 判断当前登录用户是否已关注某个用户
* @param userId 某个用户
* @return
*/
private boolean hasFollowed(int userId) {
if (hostHolder.getUser() == null) {
return false;
}
return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);
}
前端
<a th:href="@{|/followees/${user.id}|}" >
关注了 <span th:text="${followeeCount}"></span> 人
</a>
<a th:href="@{|/followers/${user.id}|}">
关注者 <span th:text="${followerCount}"></span> 人
</a>
对应的关注界面 followee.html
和粉丝界面 follower.html
,以 followee.html
为例:
<li th:each="map:${users}">
<a th:href="@{|/user/profile/${map.user.id}|}">
<img th:src="${map.user.headerUrl}" alt="用户头像" >
</a>
<span th:text="${map.user.username}"></span>
<span >
关注于 <i th:text="${#dates.format(map.followTime, 'yyyy-MM-dd HH:mm:ss')}"></i></span>
<input type="hidden" id="entityId" th:value="${map.user.id}">
<button type="button" th:class="|btn ${map.hasFollowed ? 'btn-secondary' : 'btn-info'} btn-sm float-right mr-5 follow-btn|"
th:text="${map.hasFollowed ? '已关注' : '关注TA'}"
th:if="${loginUser!=null && loginUser.id!=map.user.id}"></button>
</div>
</li>