问答平台(4),关注列表、粉丝列表

业务层

1
2
- 查询某个用户关注的人(支持分页)。
- 查询某个用户的粉丝(支持分页)。
  • FollowService:增加内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // 查询某个用户关注的人
    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;
    }

    // 查询某个用户的粉丝
    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;
    }

表现层

1
- 处理“查询关注的人”、“查询粉丝”请求。
  • FollowController:增加内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    @RequestMapping(path = "/followees/{userId}", method = RequestMethod.GET)
    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";
    }

    @RequestMapping(path = "/followers/{userId}", method = RequestMethod.GET)
    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";
    }

    private boolean hasFollowed(int userId) {
    if (hostHolder.getUser() == null) {
    return false;
    }

    return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);
    }

页面

1
- 编写“查询关注的人”、“查询粉丝”模板。
  • profile.html
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- 内容 -->
    <!-- 个人信息 -->
    <span>关注了
    <a class="text-primary" th:href="@{|/followees/${user.id}|}" th:text="${followeeCount}">5</a>
    </span>
    <span class="ml-4">关注者
    <a class="text-primary" th:href="@{|/followers/${user.id}|}" th:text="${followerCount}">123</a>
    </span>
  • followee.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    <!-- 内容 -->
    <!-- 选项 -->
    <li class="nav-item">
    <a class="nav-link position-relative active" th:href="@{|/followees/${user.id}|}">
    <i class="text-info" th:utext="${user.username}">Nowcoder</i> 关注的人
    </a>
    </li>
    <li class="nav-item">
    <a class="nav-link position-relative" th:href="@{|/followers/${user.id}|}">
    关注<i class="text-info" th:utext="${user.username}">Nowcoder</i> 的人
    </a>
    </li>
    <a th:href="@{|/user/profile/${user.id}|}" class="text-muted position-absolute rt-0">返回个人主页</a>
    <!-- 关注列表 -->
    <ul class="list-unstyled">
    <li class="media pb-3 pt-3 mb-3 border-bottom position-relative" th:each="map:${users}">
    <a th:href="@{|/user/profile/${map.user.id}|}">
    <img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle user-header" alt="用户头像">
    </a>
    <div class="media-body">
    <h6 class="mt-0 mb-3">
    <span class="text-success" th:utext="${map.user.username}">落基山脉下的闲人</span>
    <span class="float-right text-muted font-size-12">
    关注于 <i th:text="${#dates.format(map.followTime, 'yyyy-MM-dd HH:mm:ss')}">2019-04-28 14:13:25</i>
    </span>
    </h6>
    <div>
    <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:if="${loginUser!=null&&loginUser.id!=map.user.id}"
    th:text="${map.hasFollowed?'已关注':'关注TA'}">关注TA
    </button>
    </div>
    </div>
    </li>
    </ul>
  • follower.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <!-- 内容 -->
    <!-- 选项 -->
    <ul class="nav nav-tabs mb-3">
    <li class="nav-item">
    <a class="nav-link position-relative" th:href="@{|/followees/${user.id}|}">
    <i class="text-info" th:utext="${user.username}">Nowcoder</i> 关注的人
    </a>
    </li>
    <li class="nav-item">
    <a class="nav-link position-relative active" th:href="@{|/followers/${user.id}|}">
    关注 <i class="text-info" th:utext="${user.username}">Nowcoder</i> 的人
    </a>
    </li>
    </ul>
    <a th:href="@{|/user/profile/${user.id}|}" class="text-muted position-absolute rt-0">返回个人主页&gt;</a>
    <!-- 粉丝列表 -->
    <ul class="list-unstyled">
    <li class="media pb-3 pt-3 mb-3 border-bottom position-relative" th:each="map:${users}">
    <a th:href="@{|/user/profile/${map.user.id}|}">
    <img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle user-header" alt="用户头像">
    </a>
    <div class="media-body">
    <h6 class="mt-0 mb-3">
    <span class="text-success" th:utext="${map.user.username}">落基山脉下的闲人</span>
    <span class="float-right text-muted font-size-12">
    关注于 <i th:text="${#dates.format(map.followTime, 'yyyy-MM-dd HH:mm:ss')}">2019-04-28 14:13:25</i>
    </span>
    </h6>
    <div>
    <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:if="${loginUser!=null&&loginUser.id!=map.user.id}"
    th:text="${map.hasFollowed?'已关注':'关注TA'}">关注TA
    </button>
    </div>
    </div>
    </li>
    </ul>

问答平台(4),关注列表、粉丝列表
https://lcf163.github.io/2020/05/27/问答平台(4),关注列表、粉丝列表/
作者
乘风的小站
发布于
2020年5月27日
许可协议