SpringBoot Spring Data JPA Thymeleaf 实现关注者和粉丝,互相关注分页显示

本文介绍 SpringBoot + Spring Data JPA + Thymeleaf 实现关注取消关注互相关注的功能。采用 Bootstrap + ajax 显示数据,样式是模仿慕课网,获取样式,点此直达。

本项目也使用了Spring Data JPA 分页功能,因为数据比较少,所以设置一页显示一个。

动态效果图如下,点击放大

SpringBoot Spring Data JPA Thymeleaf 实现关注者和粉丝,互相关注分页显示

 

 

一、数据库设计

user 表主要是有一个 id 主键, fan_size 粉丝数,follow_size 关注数 ;

relationship 表有两个字段 from_user_id,to_user_id ,组成联合主键。

本文使用的是是 Spring Data JPA,无需设计数据表,直接通过实体生成。

 

 

二、实体

User.java

  1. package com.liuyanzhao.forum.entity;
  2. import lombok.Data;
  3. import javax.persistence.*;
  4. import javax.validation.constraints.NotEmpty;
  5. import javax.validation.constraints.Size;
  6. import java.io.Serializable;
  7. /**
  8.  * @author 言曌
  9.  * @date 2018/3/19 下午9:54
  10.  */
  11. @Entity
  12. @Data
  13. public class User implements Serializable {
  14.     private static final long serialVersionUID = 6147345506206285446L;
  15.     @Id // 主键
  16.     @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
  17.     private Integer id; // 用户的唯一标识
  18.     @NotEmpty(message = "昵称不能为空")
  19.     @Size(min = 2, max = 12, message = "昵称长度必须为2-12个字符")
  20.     @Column(nullable = false, length = 12)
  21.     private String nickname;
  22.     @NotEmpty(message = "用户名不能为空")
  23.     @Size(min = 4, max = 20, message = "用户名长度必须为4-20个字符")
  24.     @Column(nullable = false, length = 20, unique = true)
  25.     private String username; // 用户账号,用户登录时的唯一标识
  26.     @NotEmpty(message = "密码不能为空")
  27.     @Size(max = 100, message = "密码长度最多100个字符")
  28.     @Column(length = 100)
  29.     private String password; // 登录时密码
  30.     @Column(length = 200)
  31.     @Size(max = 200, message = "头像链接长度最多200个字符")
  32.     private String avatar; // 头像图片地址
  33.     private Integer followSize = 0;//关注数
  34.     private Integer fanSize = 0//粉丝数
  35.     @Transient
  36.     private Integer isFriend = 0;//关系,0表示没有关系,2表示互相关注
  37.     public User() {
  38.     }
  39. }

其他与本文无关的字段,这里省掉了。

 

Relationship.java

  1. package com.liuyanzhao.forum.entity;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.Id;
  5. import javax.persistence.IdClass;
  6. /**
  7.  * @author 言曌
  8.  * @date 2018/4/24 下午9:38
  9.  */
  10. @Entity
  11. @IdClass(RelationshipPK.class)
  12. public class Relationship {
  13.     private Integer fromUserId;
  14.     private Integer toUserId;
  15.     public Relationship() {
  16.     }
  17.     public Relationship(Integer fromUserId, Integer toUserId) {
  18.         this.fromUserId = fromUserId;
  19.         this.toUserId = toUserId;
  20.     }
  21.     @Id
  22.     @Column(name = "from_user_id", nullable = false)
  23.     public Integer getFromUserId() {
  24.         return fromUserId;
  25.     }
  26.     public void setFromUserId(Integer fromUserId) {
  27.         this.fromUserId = fromUserId;
  28.     }
  29.     @Id
  30.     @Column(name = "to_user_id", nullable = false)
  31.     public Integer getToUserId() {
  32.         return toUserId;
  33.     }
  34.     public void setToUserId(Integer toUserId) {
  35.         this.toUserId = toUserId;
  36.     }
  37.     @Override
  38.     public boolean equals(Object o) {
  39.         if (this == o) return true;
  40.         if (o == null || getClass() != o.getClass()) return false;
  41.         Relationship that = (Relationship) o;
  42.         if (fromUserId != null ? !fromUserId.equals(that.fromUserId) : that.fromUserId != nullreturn false;
  43.         if (toUserId != null ? !toUserId.equals(that.toUserId) : that.toUserId != nullreturn false;
  44.         return true;
  45.     }
  46.     @Override
  47.     public int hashCode() {
  48.         int result = fromUserId != null ? fromUserId.hashCode() : 0;
  49.         result = 31 * result + (toUserId != null ? toUserId.hashCode() : 0);
  50.         return result;
  51.     }
  52. }

 

RelationshipPK.java

  1. package com.liuyanzhao.forum.entity;
  2. import javax.persistence.Column;
  3. import javax.persistence.Id;
  4. import java.io.Serializable;
  5. /**
  6.  * @author 言曌
  7.  * @date 2018/4/24 下午9:38
  8.  */
  9. public class RelationshipPK implements Serializable {
  10.     private Integer fromUserId;
  11.     private Integer toUserId;
  12.     @Column(name = "from_user_id", nullable = false)
  13.     @Id
  14.     public Integer getFromUserId() {
  15.         return fromUserId;
  16.     }
  17.     public void setFromUserId(Integer fromUserId) {
  18.         this.fromUserId = fromUserId;
  19.     }
  20.     @Column(name = "to_user_id", nullable = false)
  21.     @Id
  22.     public Integer getToUserId() {
  23.         return toUserId;
  24.     }
  25.     public void setToUserId(Integer toUserId) {
  26.         this.toUserId = toUserId;
  27.     }
  28.     @Override
  29.     public boolean equals(Object o) {
  30.         if (this == o) return true;
  31.         if (o == null || getClass() != o.getClass()) return false;
  32.         RelationshipPK that = (RelationshipPK) o;
  33.         if (fromUserId != null ? !fromUserId.equals(that.fromUserId) : that.fromUserId != nullreturn false;
  34.         if (toUserId != null ? !toUserId.equals(that.toUserId) : that.toUserId != nullreturn false;
  35.         return true;
  36.     }
  37.     @Override
  38.     public int hashCode() {
  39.         int result = fromUserId != null ? fromUserId.hashCode() : 0;
  40.         result = 31 * result + (toUserId != null ? toUserId.hashCode() : 0);
  41.         return result;
  42.     }
  43. }

 

三、Dao 层

UserRepository.java

  1. package com.liuyanzhao.forum.repository;
  2. import com.liuyanzhao.forum.entity.User;
  3. import org.springframework.data.domain.Page;
  4. import org.springframework.data.domain.Pageable;
  5. import org.springframework.data.jpa.repository.JpaRepository;
  6. import org.springframework.data.jpa.repository.Query;
  7. import java.util.Collection;
  8. import java.util.List;
  9. /**
  10.  * @author 言曌
  11.  * @date 2018/3/20 下午5:26
  12.  */
  13. public interface UserRepository extends JpaRepository<User, Integer> {
  14.     /**
  15.      * 根据id集合查询用户,分页查询
  16.      *
  17.      * @param ids
  18.      * @return
  19.      */
  20.     Page<User> findByIdIn(List<Integer> ids, Pageable pageable);
  21.     /**
  22.      * 根据id集合查询用户,不分页
  23.      *
  24.      * @param ids
  25.      * @return
  26.      */
  27.     List<User> findByIdIn(List<Integer> ids);
  28. }

 

RelationshipRepository.java

  1. package com.liuyanzhao.forum.repository;
  2. import com.liuyanzhao.forum.entity.Relationship;
  3. import com.liuyanzhao.forum.entity.RelationshipPK;
  4. import org.springframework.data.jpa.repository.JpaRepository;
  5. import org.springframework.data.jpa.repository.Query;
  6. import org.springframework.data.repository.query.Param;
  7. import java.util.List;
  8. /**
  9.  * @author 言曌
  10.  * @date 2018/4/24 下午9:47
  11.  */
  12. public interface RelationshipRepository extends JpaRepository<Relationship, RelationshipPK> {
  13.     /**
  14.      * 根据关注者id查找所有记录(查找关注的人的id)
  15.      *
  16.      * @param fromUserId
  17.      * @return
  18.      */
  19.     @Query("select toUserId from Relationship where fromUserId =:fromUserId")
  20.     List<Integer> findByFromUserId(@Param("fromUserId") Integer fromUserId);
  21.     /**
  22.      * 根据被关注者查找所有记录(查找粉丝的id)
  23.      *
  24.      * @param toUserId
  25.      * @return
  26.      */
  27.     @Query("select fromUserId from Relationship where toUserId =:toUserId")
  28.     List<Integer> findByToUserId(@Param("toUserId") Integer toUserId);
  29.     /**
  30.      * 查询该用户的互相关注id
  31.      * @param userId
  32.      * @return
  33.      */
  34.     @Query(value = "SELECT DISTINCT t1.from_user_id FROM (SELECT * FROM relationship WHERE to_user_id = ?1)  AS t1 INNER JOIN relationship t2 ON t1.from_user_id = t2.to_user_id", nativeQuery = true)
  35.     List<Integer> findFriendsByUserId(Integer userId);
  36.     /**
  37.      * 查询关注数
  38.      * @param fromUserId
  39.      * @return
  40.      */
  41.     Integer countByFromUserId(Integer fromUserId);
  42.     /**
  43.      * 查询粉丝数
  44.      * @param toUserId
  45.      * @return
  46.      */
  47.     Integer countByToUserId(Integer toUserId);
  48. }

 

 

四、Service 层

RelationshipService.java

  1. package com.liuyanzhao.forum.service;
  2. import com.liuyanzhao.forum.entity.Relationship;
  3. import com.liuyanzhao.forum.entity.User;
  4. import org.springframework.data.domain.Page;
  5. import org.springframework.data.domain.Pageable;
  6. import java.util.List;
  7. /**
  8.  * @author 言曌
  9.  * @date 2018/4/24 下午10:10
  10.  */
  11. public interface RelationshipService {
  12.     /**
  13.      * 列出所有的关注者
  14.      *
  15.      * @return
  16.      */
  17.     Page<User> listFollows(Integer userId, Pageable pageable);
  18.     /**
  19.      * 列出所有的粉丝
  20.      *
  21.      * @return
  22.      */
  23.     Page<User> listFans(Integer userId, Pageable pageable);
  24.     /**
  25.      * 列出互相关注的id
  26.      *
  27.      * @param userId
  28.      * @return
  29.      */
  30.     List<Integer> listFriends(Integer userId);
  31.     /**
  32.      * 添加关系
  33.      *
  34.      * @param relationship
  35.      */
  36.     void saveRelationship(Relationship relationship);
  37.     /**
  38.      * 去除关系
  39.      *
  40.      * @param relationship
  41.      */
  42.     void removeRelationship(Relationship relationship);
  43.     /**
  44.      * 更新关注数
  45.      */
  46.     void updateFollowSize(Integer userId);
  47.     /**
  48.      * 更新粉丝数
  49.      */
  50.     void updateFanSize(Integer userId);
  51. }

 

RelationshipServiceImpl.java

  1. package com.liuyanzhao.forum.service.impl;
  2. import com.liuyanzhao.forum.entity.Relationship;
  3. import com.liuyanzhao.forum.entity.User;
  4. import com.liuyanzhao.forum.repository.RelationshipRepository;
  5. import com.liuyanzhao.forum.repository.UserRepository;
  6. import com.liuyanzhao.forum.service.RelationshipService;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.data.domain.Page;
  9. import org.springframework.data.domain.Pageable;
  10. import org.springframework.stereotype.Service;
  11. import java.util.List;
  12. /**
  13.  * @author 言曌
  14.  * @date 2018/4/24 下午10:23
  15.  */
  16. @Service
  17. public class RelationshipServiceImpl implements RelationshipService {
  18.     @Autowired
  19.     private RelationshipRepository relationshipRepository;
  20.     @Autowired
  21.     private UserRepository userRepository;
  22.     @Override
  23.     public Page<User> listFollows(Integer userId, Pageable pageable) {
  24.         List<Integer> relationshipList = relationshipRepository.findByFromUserId(userId);
  25.         Page<User> userPage = userRepository.findByIdIn(relationshipList, pageable);
  26.         return userPage;
  27.     }
  28.     @Override
  29.     public Page<User> listFans(Integer userId, Pageable pageable) {
  30.         List<Integer> relationshipList = relationshipRepository.findByToUserId(userId);
  31.         Page<User> userPage = userRepository.findByIdIn(relationshipList, pageable);
  32.         return userPage;
  33.     }
  34.     @Override
  35.     public List<Integer> listFriends(Integer userId) {
  36.         List<Integer> relationshipList = relationshipRepository.findFriendsByUserId(userId);
  37. //        List<User> userList = userRepository.findByIdIn(relationshipList);
  38.         return relationshipList;
  39.     }
  40.     @Override
  41.     public void saveRelationship(Relationship relationship) {
  42.         //添加关注
  43.         relationshipRepository.save(relationship);
  44.         //更新双方关注数和粉丝数
  45.         updateFollowSize(relationship.getFromUserId());
  46.         updateFanSize(relationship.getToUserId());
  47.     }
  48.     @Override
  49.     public void removeRelationship(Relationship relationship) {
  50.         //删除关系
  51.         relationshipRepository.delete(relationship);
  52.         //更新双方关注数和粉丝数
  53.         updateFollowSize(relationship.getFromUserId());
  54.         updateFanSize(relationship.getToUserId());
  55.     }
  56.     @Override
  57.     public void updateFollowSize(Integer userId) {
  58.         User user = userRepository.findById(userId).get();
  59.         user.setFollowSize(relationshipRepository.countByFromUserId(userId));
  60.         userRepository.save(user);
  61.     }
  62.     @Override
  63.     public void updateFanSize(Integer userId) {
  64.         User user = userRepository.findById(userId).get();
  65.         user.setFanSize(relationshipRepository.countByToUserId(userId));
  66.         userRepository.save(user);
  67.     }
  68. }

 

 

五、Controller 层

UserSpaceController.java

  1. package com.liuyanzhao.forum.controller;
  2. import com.liuyanzhao.forum.controller.common.BaseController;
  3. import com.liuyanzhao.forum.entity.*;
  4. import com.liuyanzhao.forum.repository.UserRepository;
  5. import com.liuyanzhao.forum.service.*;
  6. import com.liuyanzhao.forum.vo.Response;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.data.domain.Page;
  9. import org.springframework.data.domain.PageRequest;
  10. import org.springframework.http.ResponseEntity;
  11. import org.springframework.security.access.prepost.PreAuthorize;
  12. import org.springframework.security.core.context.SecurityContextHolder;
  13. import org.springframework.stereotype.Controller;
  14. import org.springframework.ui.Model;
  15. import org.springframework.web.bind.annotation.*;
  16. import org.springframework.web.servlet.ModelAndView;
  17. import java.util.List;
  18. /**
  19.  * @author 言曌
  20.  * @date 2018/4/24 下午1:15
  21.  */
  22. @RequestMapping("/manage")
  23. @Controller
  24. @PreAuthorize("hasAnyAuthority('ROLE_ADMIN','ROLE_USER')")  // 指定角色权限才能操作方法
  25. public class UserSpaceController extends BaseController {
  26.     @Autowired
  27.     private RelationshipService relationshipService;
  28.     @Autowired
  29.     private UserRepository userRepository;
  30.     @GetMapping("/relationships")
  31.     public String relationships() {
  32.         return "forward:/manage/relationships/follows";
  33.     }
  34.     //粉丝-关注 start
  35.   /**
  36.      * 我的关注者列表
  37.      * @param userId
  38.      * @param optType
  39.      * @return
  40.      */
  41.     @GetMapping("/relationships/follows")
  42.     public ModelAndView follows(
  43.             @RequestParam(value = "async", required = falseboolean async,
  44.             @RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
  45.             @RequestParam(value = "size", defaultValue = "1", required = false) Integer size,
  46.             Model model) {
  47.         Long startTime = System.currentTimeMillis();
  48.         User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  49.         PageRequest pageRequest = new PageRequest(page - 1, size);
  50.         Page<User> userPage = relationshipService.listFollows(user.getId(), pageRequest);
  51.         List<Integer> friendIds = relationshipService.listFriends(user.getId());
  52.         List<User> userList = userPage.getContent();
  53.         for (int i = 0; i < userList.size(); i++) {
  54.             if (friendIds.contains(userList.get(i).getId())) {
  55.                 userPage.getContent().get(i).setIsFriend(2);
  56.             }
  57.         }
  58.         model.addAttribute("userPage", userPage);
  59.         Long endTime = System.currentTimeMillis();
  60.         System.out.println("耗时" + (endTime - startTime) + "ms");
  61.         model.addAttribute("is_follows"true);
  62.         return new ModelAndView(async == true ? "home/userspace/relationship :: .tab-pane" : "home/userspace/relationship");
  63.     }
  64.   /**
  65.      * 我的粉丝列表
  66.      * @param userId
  67.      * @param optType
  68.      * @return
  69.      */
  70.     @GetMapping("/relationships/fans")
  71.     public ModelAndView fans(
  72.             @RequestParam(value = "async", required = falseboolean async,
  73.             @RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
  74.             @RequestParam(value = "size", defaultValue = "1", required = false) Integer size,
  75.             Model model) {
  76.         Long startTime = System.currentTimeMillis();
  77.         User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  78.         PageRequest pageRequest = new PageRequest(page - 1, size);
  79.         Page<User> userPage = relationshipService.listFans(user.getId(), pageRequest);
  80.         List<Integer> friendIds = relationshipService.listFriends(user.getId());
  81.         List<User> userList = userPage.getContent();
  82.         for (int i = 0; i < userList.size(); i++) {
  83.             if (friendIds.contains(userList.get(i).getId())) {
  84.                 userPage.getContent().get(i).setIsFriend(2);
  85.             }
  86.         }
  87.         model.addAttribute("userPage", userPage);
  88.         Long endTime = System.currentTimeMillis();
  89.         System.out.println("耗时" + (endTime - startTime) + "ms");
  90.         model.addAttribute("is_fans""true");
  91.         return new ModelAndView(async == true ? "home/userspace/relationship :: .tab-pane" : "home/userspace/relationship");
  92.     }
  93.     /**
  94.      * 添加关系
  95.      * @param userId
  96.      * @param optType
  97.      * @return
  98.      */
  99.     @PostMapping("/relationships")
  100.     public ResponseEntity<Response> followUser(Integer userId, String optType) {
  101.         User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  102.         //1、判断用户是否存在
  103.         User temp = userRepository.findById(userId).get();
  104.         if (temp == null) {
  105.             return ResponseEntity.ok().body(new Response(false"用户不存在"));
  106.         }
  107.         //2、判断是关注还是取消关注
  108.         //关注
  109.         if ("follow".equals(optType)) {
  110.             relationshipService.saveRelationship(new Relationship(user.getId(), userId));
  111.         } else if ("notfollow".equals(optType)) {
  112.             //取消关注
  113.             relationshipService.removeRelationship(new Relationship(user.getId(), userId));
  114.         } else {
  115.             //非法操作
  116.             return ResponseEntity.ok().body(new Response(false"非法操作"));
  117.         }
  118.         Integer fanSize = userRepository.findById(userId).get().getFanSize();
  119.         return ResponseEntity.ok().body(new Response(true"操作成功",fanSize));
  120.     }
  121.     //粉丝-关注 end
  122. }

 

 

七、视图层

HTML

  1. <div class="box">
  2.     <div class="box-header with-border">
  3.         <h3 class="box-title">关系管理</h3>
  4.     </div>
  5.     <div class="box-body" id="right-box-body">
  6.         <div id="right-box-body-replace">
  7.             <div class="nav-tabs-custom" style="box-shadow: 0 0;">
  8.                 <ul class="nav nav-tabs">
  9.                     <li th:class="${is_follows}?active:''">
  10.                         <a href="javascript:void(0)" data-toggle="tab"
  11.                            class="relationship-tab-btn"
  12.                            data-th-attr="data-type=follows">我的关注</a>
  13.                     </li>
  14.                     <li th:class="${is_fans}?active:''">
  15.                         <a href="javascript:void(0)" data-toggle="tab"
  16.                            class="relationship-tab-btn" data-th-attr="data-type=fans">我的粉丝</a>
  17.                     </li>
  18.                 </ul>
  19.                 <div class="tab-content">
  20.                     <div class="tab-pane active">
  21.                         <div class="concern-list" th:if="${userPage.totalElements != 0}">
  22.                             <ul>
  23.                                 <li class="box" th:each="user : ${userPage.content}">
  24.                                     <div class="left-img">
  25.                                         <a href="/u/3078817" target="_blank">
  26.                                             <img th:src="${user.avatar}"
  27.                                                  class="top_head">
  28.                                         </a>
  29.                                     </div>
  30.                                     <div class="right-c">
  31.                                         <div class="title">
  32.                                             <a th:href="@{'/u/'+${user.username}}" target="_blank">
  33.                                                 <span class="nickname"
  34.                                                       th:text="${user.nickname}">言曌</span>
  35.                                             </a>
  36.                                         </div>
  37.                                         <p class="desc" title="全栈工程师"
  38.                                            th:text="${user.job.name}">全栈工程师</p>
  39.                                         <div class="fs-line">
  40.                                             <a href="/u/3078817/follows" class="u-target">
  41.                                                 <span class="group">
  42.                                                     <em>关注</em>
  43.                                                     <em class="u-margin-l-5 follow-size" th:text="${user.followSize}">3</em>
  44.                                                 </span>
  45.                                             </a>
  46.                                             <a href="/u/3078817/fans"
  47.                                                class="u-target u-margin-l-15">
  48.                                                 <span class="group">
  49.                                                     <em>粉丝</em>
  50.                                                     <em class="u-margin-l-5 fan-size" th:text="${user.fanSize}">61</em>
  51.                                                 </span>
  52.                                             </a>
  53.                                         </div>
  54.                                         <div class="btn-line" th:if="${is_follows}">
  55.                                             <a href="javascript:void(0)"
  56.                                                data-th-attr="data-uid=${user.id},opt-type=follow"
  57.                                                class="btn-o btn-green-o js-concern-follow"
  58.                                                style="display: none;">关注</a>
  59.                                             <a href="javascript:void(0)"
  60.                                                data-th-attr="data-uid=${user.id},opt-type=notfollow"
  61.                                                class="btn-o btn-gray-o js-concern-already"
  62.                                                th:if="${user.isFriend!=2}">已关注</a>
  63.                                             <a href="javascript:void(0)"
  64.                                                data-th-attr="data-uid=${user.id},opt-type=notfollow"
  65.                                                class="btn-o btn-gray-o js-concern-mutual"
  66.                                                th:if="${user.isFriend==2}">互相关注</a>
  67.                                             <a href="/u/2478917/messages?uid=3078817"
  68.                                                target="_blank"
  69.                                                class="btn-o btn-gray-o  js-concern-msg">私信</a>
  70.                                         </div>
  71.                                         <div class="btn-line" th:if="${is_fans}">
  72.                                             <a href="javascript:void(0)"
  73.                                                data-th-attr="data-uid=${user.id},opt-type=follow"
  74.                                                class="btn-o btn-green-o js-concern-follow"
  75.                                                th:if="${user.isFriend!=2}">关注</a>
  76.                                             <a href="javascript:void(0)"
  77.                                                data-th-attr="data-uid=${user.id},opt-type=follow"
  78.                                                class="btn-o btn-green-o js-concern-follow"
  79.                                                style="display: none;"
  80.                                                th:if="${user.isFriend==2}">关注</a>
  81.                                             <a href="javascript:void(0)"
  82.                                                data-th-attr="data-uid=${user.id},opt-type=notfollow"
  83.                                                class="btn-o btn-gray-o js-concern-mutual"
  84.                                                th:if="${user.isFriend!=2}"
  85.                                                style="display: none;">互相关注</a>
  86.                                             <a href="javascript:void(0)"
  87.                                                data-th-attr="data-uid=${user.id},opt-type=notfollow"
  88.                                                class="btn-o btn-gray-o js-concern-mutual"
  89.                                                th:if="${user.isFriend==2}">互相关注</a>
  90.                                             <a href="/u/2478917/messages?uid=3078817"
  91.                                                target="_blank"
  92.                                                class="btn-o btn-gray-o  js-concern-msg">私信</a>
  93.                                         </div>
  94.                                     </div>
  95.                                 </li>
  96.                             </ul>
  97.                         </div>
  98.                         <div class="clear"></div>
  99.                         <!--分页-->
  100.                         <div id="pagenation" th:if="${userPage.totalPages >= 2}">
  101.                             <nav aria-label="Page navigation" th:object="${userPage}">
  102.                                 <ul class="pagination"
  103.                                     data-th-attr="data-type=${is_follows}?follows:fans">
  104.                                     <li data-th-classappend="*{first} ? 'disabled' : ''">
  105.                                         <a href="javascript:void(0)"
  106.                                            data-th-attr="pageIndex=${userPage.number}"
  107.                                            aria-label="Previous">
  108.                                             <span aria-hidden="true">上一页</span>
  109.                                         </a>
  110.                                     </li>
  111.                                     <li th:each="i: ${#numbers.sequence(1, userPage.totalPages)}"
  112.                                         data-th-classappend="${(userPage.number + 1) eq i} ? 'active' : ''">
  113.                                         <a href="javascript:void(0)"
  114.                                            data-th-attr="pageIndex=${i}">
  115.                                             <span aria-hidden="true" th:text="${i}"></span>
  116.                                         </a>
  117.                                     </li>
  118.                                     <li data-th-classappend="*{last} ? 'disabled' : ''">
  119.                                         <a href="javascript:void(0)"
  120.                                            data-th-attr="pageIndex=${userPage.number} + 2"
  121.                                            aria-label="Next">
  122.                                             <span aria-hidden="true">下一页</span>
  123.                                         </a>
  124.                                     </li>
  125.                                 </ul>
  126.                             </nav>
  127.                         </div>
  128.                         <div class="nodata" th:if="${userPage.totalElements == 0}">
  129.                             <span th:if="${is_follows}">您还没有关注任何用户</span>
  130.                             <span th:if="${is_follows}">您还没有任何粉丝</span>
  131.                         </div>
  132.                     </div>
  133.                 </div>
  134.             </div>
  135.         </div>
  136.     </div>
  137. </div>

 

JS

  1. //重新获取数据
  2. $(document).on('click', '.relationship-tab-btn', function () {
  3.     var _ctx = $("meta[name='ctx']").attr("content");
  4.     var url = _ctx + "/manage/relationships/" + $(this).attr("data-type");
  5.     $.ajax({
  6.         url: url,
  7.         data: {async: true},
  8.         success: function (data) {
  9.             $(".tab-content").html(data)
  10.         },
  11.         error: function () {
  12.             layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
  13.         }
  14.     });
  15. });
  16. //分页
  17. $(document).on('click', '.pagination a', function () {
  18.     var _ctx = $("meta[name='ctx']").attr("content");
  19.     var page = $(this).attr('pageIndex');
  20.     var data_type = $(this).parents("ul").attr("data-type");
  21.     var url = _ctx + "/manage/relationships/" + data_type;
  22.     $.ajax({
  23.         url: url,
  24.         data: {
  25.             async: true,
  26.             page: page,
  27.         },
  28.         success: function (data) {
  29.             $(".tab-content").html(data)
  30.         },
  31.         error: function () {
  32.             layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
  33.         }
  34.     });
  35. });
  36. //取消关注
  37. $(document).on('click', '.js-concern-already,.js-concern-mutual', function () {
  38.     var current = $(this);
  39.     var _ctx = $("meta[name='ctx']").attr("content");
  40.     var token = $("meta[name='_csrf']").attr("content");
  41.     var header = $("meta[name='_csrf_header']").attr("content");
  42.     var url = _ctx + "/manage/relationships/";
  43.     $.ajax({
  44.         url: url,
  45.         type: 'POST',
  46.         data: {
  47.             optType: current.attr('opt-type'),
  48.             userId: current.attr('data-uid'),
  49.         },
  50.         beforeSend: function (request) {
  51.             request.setRequestHeader(header, token); // 添加  CSRF Token
  52.         },
  53.         success: function (data) {
  54.             current.hide();
  55.             current.prev("a").show();
  56.             current.parents(".box").find(".fan-size").html(data.body);
  57.         },
  58.         error: function () {
  59.             layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
  60.         }
  61.     });
  62. });
  63. //关注
  64. $(document).on('click', '.js-concern-follow', function () {
  65.     var current = $(this);
  66.     var _ctx = $("meta[name='ctx']").attr("content");
  67.     var token = $("meta[name='_csrf']").attr("content");
  68.     var header = $("meta[name='_csrf_header']").attr("content");
  69.     var url = _ctx + "/manage/relationships/";
  70.     $.ajax({
  71.         url: url,
  72.         type: 'POST',
  73.         data: {
  74.             optType: current.attr('opt-type'),
  75.             userId: current.attr('data-uid'),
  76.         },
  77.         beforeSend: function (request) {
  78.             request.setRequestHeader(header, token); // 添加  CSRF Token
  79.         },
  80.         success: function (data) {
  81.             current.hide();
  82.             current.next("a").show();
  83.             current.parents(".box").find(".fan-size").html(data.body);
  84.         },
  85.         error: function () {
  86.             layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
  87.         }
  88.     });
  89. });

 

CSS

  1. ol, ul {
  2.     list-stylenone;
  3. }
  4. .concern-list {
  5.     padding-top20px;
  6.     padding-bottom20px;
  7.     width: 100%;
  8. }
  9. .concern-list ul {
  10.     margin-left: -18px;
  11. }
  12. .concern-list .box {
  13.     floatleft;
  14.     width: 32%;
  15.     padding20px;
  16.     background-color#f8fafc;
  17.     margin-left: 1%;
  18.     margin-bottom15px;
  19.     min-height114px;
  20. }
  21. .concern-list .left-img {
  22.     floatleft;
  23.     positionrelative;
  24.     width40px;
  25.     height40px;
  26.     top: 0;
  27. }
  28. .concern-list .left-img .top_head {
  29.     positionabsolute;
  30.     top: 0;
  31.     border-radius: 25px;
  32.     width40px;
  33.     height40px;
  34.     z-index: 1;
  35. }
  36. .concern-list .rightright-c {
  37.     margin-left50px;
  38. }
  39. .concern-list .rightright-c .title {
  40.     font-weight: 700;
  41.     color#07111b;
  42.     padding-bottom8px;
  43.     width: 100%;
  44. }
  45. .concern-list .rightright-c .title .nickname {
  46.     text-overflow: ellipsis;
  47.     overflowhidden;
  48.     whitewhite-spacenowrap;
  49.     max-width: 60%;
  50.     displayinline-block;
  51.     vertical-alignmiddle;
  52. }
  53. .concern-list .rightright-c .desc {
  54.     text-overflow: ellipsis;
  55.     overflowhidden;
  56.     whitewhite-spacenowrap;
  57.     min-height18px;
  58. }
  59. .concern-list .rightright-c .desc, .concern-list .rightright-c .fs-line {
  60.     color#93999f;
  61.     padding-bottom8px;
  62.     font-size12px;
  63. }
  64. .concern-list .rightright-c .desc, .concern-list .rightright-c .fs-line {
  65.     color#93999f;
  66.     padding-bottom8px;
  67.     font-size12px;
  68. }
  69. .concern-list .rightright-c .fs-line .u-target {
  70.     color#93999f!important;
  71. }
  72. .concern-list .rightright-c .fs-line .group {
  73.     displayinline-block;
  74. }
  75. em{
  76.     font-stylenormal;
  77.     font-weight: 400;
  78. }
  79. .concern-list .rightright-c .fs-line .u-target {
  80.     color#93999f!important;
  81. }
  82. concern-list .u-margin-l-5 {
  83.     margin-left5px;
  84. }
  85. .concern-list .hide {
  86.     displaynone;
  87. }
  88. .concern-list .btn-gray-o {
  89.     border1px solid #d0d6d9;
  90.     color#787d82;
  91.     background-color#fff;
  92.     margin-right14px;
  93. }
  94. .concern-list .btn-o {
  95.     padding6px 0;
  96.     margin-bottom: 0;
  97.     font-size12px;
  98.     font-weight: 400;
  99.     line-height: 1.42857143;
  100.     whitewhite-spacenowrap;
  101.     vertical-alignmiddle;
  102.     cursorpointer;
  103.     width76px;
  104.     displayblock;
  105.     floatleft;
  106. }
  107. .concern-list .btn-o{
  108.     text-aligncenter;
  109. }
  110. .concern-list .btn-green-o {
  111.     border1px solid #00b43c;
  112.     color#00b43c;
  113.     background-color#fff;
  114.     margin-right14px;
  115. }
  116. .nodata {
  117.     height420px;
  118.     line-height420px;
  119.     font-size18px;
  120.     color#b5b9bc;
  121.     text-aligncenter;
  122. }

 

本文地址:https://liuyanzhao.com/8077.html

 

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: