本文介绍 SpringBoot + Spring Data JPA + Thymeleaf 实现关注取消关注互相关注的功能。采用 Bootstrap + ajax 显示数据,样式是模仿慕课网,获取样式,点此直达。
本项目也使用了Spring Data JPA 分页功能,因为数据比较少,所以设置一页显示一个。
动态效果图如下,点击放大
user 表主要是有一个 id 主键, fan_size 粉丝数,follow_size 关注数 ;
relationship 表有两个字段 from_user_id,to_user_id ,组成联合主键。
本文使用的是是 Spring Data JPA,无需设计数据表,直接通过实体生成。
User.java
其他与本文无关的字段,这里省掉了。
Relationship.java
RelationshipPK.java
UserRepository.java
RelationshipRepository.java
RelationshipService.java
RelationshipServiceImpl.java
UserSpaceController.java
HTML
JS
CSS
本文地址:https://liuyanzhao.com/8077.html
本项目也使用了Spring Data JPA 分页功能,因为数据比较少,所以设置一页显示一个。
动态效果图如下,点击放大
一、数据库设计
user 表主要是有一个 id 主键, fan_size 粉丝数,follow_size 关注数 ;
relationship 表有两个字段 from_user_id,to_user_id ,组成联合主键。
本文使用的是是 Spring Data JPA,无需设计数据表,直接通过实体生成。
二、实体
User.java
- package com.liuyanzhao.forum.entity;
- import lombok.Data;
- import javax.persistence.*;
- import javax.validation.constraints.NotEmpty;
- import javax.validation.constraints.Size;
- import java.io.Serializable;
- /**
- * @author 言曌
- * @date 2018/3/19 下午9:54
- */
- @Entity
- @Data
- public class User implements Serializable {
- private static final long serialVersionUID = 6147345506206285446L;
- @Id // 主键
- @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
- private Integer id; // 用户的唯一标识
- @NotEmpty(message = "昵称不能为空")
- @Size(min = 2, max = 12, message = "昵称长度必须为2-12个字符")
- @Column(nullable = false, length = 12)
- private String nickname;
- @NotEmpty(message = "用户名不能为空")
- @Size(min = 4, max = 20, message = "用户名长度必须为4-20个字符")
- @Column(nullable = false, length = 20, unique = true)
- private String username; // 用户账号,用户登录时的唯一标识
- @NotEmpty(message = "密码不能为空")
- @Size(max = 100, message = "密码长度最多100个字符")
- @Column(length = 100)
- private String password; // 登录时密码
- @Column(length = 200)
- @Size(max = 200, message = "头像链接长度最多200个字符")
- private String avatar; // 头像图片地址
- private Integer followSize = 0;//关注数
- private Integer fanSize = 0; //粉丝数
- @Transient
- private Integer isFriend = 0;//关系,0表示没有关系,2表示互相关注
- public User() {
- }
- }
其他与本文无关的字段,这里省掉了。
Relationship.java
- package com.liuyanzhao.forum.entity;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.Id;
- import javax.persistence.IdClass;
- /**
- * @author 言曌
- * @date 2018/4/24 下午9:38
- */
- @Entity
- @IdClass(RelationshipPK.class)
- public class Relationship {
- private Integer fromUserId;
- private Integer toUserId;
- public Relationship() {
- }
- public Relationship(Integer fromUserId, Integer toUserId) {
- this.fromUserId = fromUserId;
- this.toUserId = toUserId;
- }
- @Id
- @Column(name = "from_user_id", nullable = false)
- public Integer getFromUserId() {
- return fromUserId;
- }
- public void setFromUserId(Integer fromUserId) {
- this.fromUserId = fromUserId;
- }
- @Id
- @Column(name = "to_user_id", nullable = false)
- public Integer getToUserId() {
- return toUserId;
- }
- public void setToUserId(Integer toUserId) {
- this.toUserId = toUserId;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Relationship that = (Relationship) o;
- if (fromUserId != null ? !fromUserId.equals(that.fromUserId) : that.fromUserId != null) return false;
- if (toUserId != null ? !toUserId.equals(that.toUserId) : that.toUserId != null) return false;
- return true;
- }
- @Override
- public int hashCode() {
- int result = fromUserId != null ? fromUserId.hashCode() : 0;
- result = 31 * result + (toUserId != null ? toUserId.hashCode() : 0);
- return result;
- }
- }
RelationshipPK.java
- package com.liuyanzhao.forum.entity;
- import javax.persistence.Column;
- import javax.persistence.Id;
- import java.io.Serializable;
- /**
- * @author 言曌
- * @date 2018/4/24 下午9:38
- */
- public class RelationshipPK implements Serializable {
- private Integer fromUserId;
- private Integer toUserId;
- @Column(name = "from_user_id", nullable = false)
- @Id
- public Integer getFromUserId() {
- return fromUserId;
- }
- public void setFromUserId(Integer fromUserId) {
- this.fromUserId = fromUserId;
- }
- @Column(name = "to_user_id", nullable = false)
- @Id
- public Integer getToUserId() {
- return toUserId;
- }
- public void setToUserId(Integer toUserId) {
- this.toUserId = toUserId;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- RelationshipPK that = (RelationshipPK) o;
- if (fromUserId != null ? !fromUserId.equals(that.fromUserId) : that.fromUserId != null) return false;
- if (toUserId != null ? !toUserId.equals(that.toUserId) : that.toUserId != null) return false;
- return true;
- }
- @Override
- public int hashCode() {
- int result = fromUserId != null ? fromUserId.hashCode() : 0;
- result = 31 * result + (toUserId != null ? toUserId.hashCode() : 0);
- return result;
- }
- }
三、Dao 层
UserRepository.java
- package com.liuyanzhao.forum.repository;
- import com.liuyanzhao.forum.entity.User;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.jpa.repository.Query;
- import java.util.Collection;
- import java.util.List;
- /**
- * @author 言曌
- * @date 2018/3/20 下午5:26
- */
- public interface UserRepository extends JpaRepository<User, Integer> {
- /**
- * 根据id集合查询用户,分页查询
- *
- * @param ids
- * @return
- */
- Page<User> findByIdIn(List<Integer> ids, Pageable pageable);
- /**
- * 根据id集合查询用户,不分页
- *
- * @param ids
- * @return
- */
- List<User> findByIdIn(List<Integer> ids);
- }
RelationshipRepository.java
- package com.liuyanzhao.forum.repository;
- import com.liuyanzhao.forum.entity.Relationship;
- import com.liuyanzhao.forum.entity.RelationshipPK;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.jpa.repository.Query;
- import org.springframework.data.repository.query.Param;
- import java.util.List;
- /**
- * @author 言曌
- * @date 2018/4/24 下午9:47
- */
- public interface RelationshipRepository extends JpaRepository<Relationship, RelationshipPK> {
- /**
- * 根据关注者id查找所有记录(查找关注的人的id)
- *
- * @param fromUserId
- * @return
- */
- @Query("select toUserId from Relationship where fromUserId =:fromUserId")
- List<Integer> findByFromUserId(@Param("fromUserId") Integer fromUserId);
- /**
- * 根据被关注者查找所有记录(查找粉丝的id)
- *
- * @param toUserId
- * @return
- */
- @Query("select fromUserId from Relationship where toUserId =:toUserId")
- List<Integer> findByToUserId(@Param("toUserId") Integer toUserId);
- /**
- * 查询该用户的互相关注id
- * @param userId
- * @return
- */
- @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)
- List<Integer> findFriendsByUserId(Integer userId);
- /**
- * 查询关注数
- * @param fromUserId
- * @return
- */
- Integer countByFromUserId(Integer fromUserId);
- /**
- * 查询粉丝数
- * @param toUserId
- * @return
- */
- Integer countByToUserId(Integer toUserId);
- }
四、Service 层
RelationshipService.java
- package com.liuyanzhao.forum.service;
- import com.liuyanzhao.forum.entity.Relationship;
- import com.liuyanzhao.forum.entity.User;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import java.util.List;
- /**
- * @author 言曌
- * @date 2018/4/24 下午10:10
- */
- public interface RelationshipService {
- /**
- * 列出所有的关注者
- *
- * @return
- */
- Page<User> listFollows(Integer userId, Pageable pageable);
- /**
- * 列出所有的粉丝
- *
- * @return
- */
- Page<User> listFans(Integer userId, Pageable pageable);
- /**
- * 列出互相关注的id
- *
- * @param userId
- * @return
- */
- List<Integer> listFriends(Integer userId);
- /**
- * 添加关系
- *
- * @param relationship
- */
- void saveRelationship(Relationship relationship);
- /**
- * 去除关系
- *
- * @param relationship
- */
- void removeRelationship(Relationship relationship);
- /**
- * 更新关注数
- */
- void updateFollowSize(Integer userId);
- /**
- * 更新粉丝数
- */
- void updateFanSize(Integer userId);
- }
RelationshipServiceImpl.java
- package com.liuyanzhao.forum.service.impl;
- import com.liuyanzhao.forum.entity.Relationship;
- import com.liuyanzhao.forum.entity.User;
- import com.liuyanzhao.forum.repository.RelationshipRepository;
- import com.liuyanzhao.forum.repository.UserRepository;
- import com.liuyanzhao.forum.service.RelationshipService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.stereotype.Service;
- import java.util.List;
- /**
- * @author 言曌
- * @date 2018/4/24 下午10:23
- */
- @Service
- public class RelationshipServiceImpl implements RelationshipService {
- @Autowired
- private RelationshipRepository relationshipRepository;
- @Autowired
- private UserRepository userRepository;
- @Override
- public Page<User> listFollows(Integer userId, Pageable pageable) {
- List<Integer> relationshipList = relationshipRepository.findByFromUserId(userId);
- Page<User> userPage = userRepository.findByIdIn(relationshipList, pageable);
- return userPage;
- }
- @Override
- public Page<User> listFans(Integer userId, Pageable pageable) {
- List<Integer> relationshipList = relationshipRepository.findByToUserId(userId);
- Page<User> userPage = userRepository.findByIdIn(relationshipList, pageable);
- return userPage;
- }
- @Override
- public List<Integer> listFriends(Integer userId) {
- List<Integer> relationshipList = relationshipRepository.findFriendsByUserId(userId);
- // List<User> userList = userRepository.findByIdIn(relationshipList);
- return relationshipList;
- }
- @Override
- public void saveRelationship(Relationship relationship) {
- //添加关注
- relationshipRepository.save(relationship);
- //更新双方关注数和粉丝数
- updateFollowSize(relationship.getFromUserId());
- updateFanSize(relationship.getToUserId());
- }
- @Override
- public void removeRelationship(Relationship relationship) {
- //删除关系
- relationshipRepository.delete(relationship);
- //更新双方关注数和粉丝数
- updateFollowSize(relationship.getFromUserId());
- updateFanSize(relationship.getToUserId());
- }
- @Override
- public void updateFollowSize(Integer userId) {
- User user = userRepository.findById(userId).get();
- user.setFollowSize(relationshipRepository.countByFromUserId(userId));
- userRepository.save(user);
- }
- @Override
- public void updateFanSize(Integer userId) {
- User user = userRepository.findById(userId).get();
- user.setFanSize(relationshipRepository.countByToUserId(userId));
- userRepository.save(user);
- }
- }
五、Controller 层
UserSpaceController.java
- package com.liuyanzhao.forum.controller;
- import com.liuyanzhao.forum.controller.common.BaseController;
- import com.liuyanzhao.forum.entity.*;
- import com.liuyanzhao.forum.repository.UserRepository;
- import com.liuyanzhao.forum.service.*;
- import com.liuyanzhao.forum.vo.Response;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.PageRequest;
- import org.springframework.http.ResponseEntity;
- import org.springframework.security.access.prepost.PreAuthorize;
- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.*;
- import org.springframework.web.servlet.ModelAndView;
- import java.util.List;
- /**
- * @author 言曌
- * @date 2018/4/24 下午1:15
- */
- @RequestMapping("/manage")
- @Controller
- @PreAuthorize("hasAnyAuthority('ROLE_ADMIN','ROLE_USER')") // 指定角色权限才能操作方法
- public class UserSpaceController extends BaseController {
- @Autowired
- private RelationshipService relationshipService;
- @Autowired
- private UserRepository userRepository;
- @GetMapping("/relationships")
- public String relationships() {
- return "forward:/manage/relationships/follows";
- }
- //粉丝-关注 start
- /**
- * 我的关注者列表
- * @param userId
- * @param optType
- * @return
- */
- @GetMapping("/relationships/follows")
- public ModelAndView follows(
- @RequestParam(value = "async", required = false) boolean async,
- @RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
- @RequestParam(value = "size", defaultValue = "1", required = false) Integer size,
- Model model) {
- Long startTime = System.currentTimeMillis();
- User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
- PageRequest pageRequest = new PageRequest(page - 1, size);
- Page<User> userPage = relationshipService.listFollows(user.getId(), pageRequest);
- List<Integer> friendIds = relationshipService.listFriends(user.getId());
- List<User> userList = userPage.getContent();
- for (int i = 0; i < userList.size(); i++) {
- if (friendIds.contains(userList.get(i).getId())) {
- userPage.getContent().get(i).setIsFriend(2);
- }
- }
- model.addAttribute("userPage", userPage);
- Long endTime = System.currentTimeMillis();
- System.out.println("耗时" + (endTime - startTime) + "ms");
- model.addAttribute("is_follows", true);
- return new ModelAndView(async == true ? "home/userspace/relationship :: .tab-pane" : "home/userspace/relationship");
- }
- /**
- * 我的粉丝列表
- * @param userId
- * @param optType
- * @return
- */
- @GetMapping("/relationships/fans")
- public ModelAndView fans(
- @RequestParam(value = "async", required = false) boolean async,
- @RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
- @RequestParam(value = "size", defaultValue = "1", required = false) Integer size,
- Model model) {
- Long startTime = System.currentTimeMillis();
- User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
- PageRequest pageRequest = new PageRequest(page - 1, size);
- Page<User> userPage = relationshipService.listFans(user.getId(), pageRequest);
- List<Integer> friendIds = relationshipService.listFriends(user.getId());
- List<User> userList = userPage.getContent();
- for (int i = 0; i < userList.size(); i++) {
- if (friendIds.contains(userList.get(i).getId())) {
- userPage.getContent().get(i).setIsFriend(2);
- }
- }
- model.addAttribute("userPage", userPage);
- Long endTime = System.currentTimeMillis();
- System.out.println("耗时" + (endTime - startTime) + "ms");
- model.addAttribute("is_fans", "true");
- return new ModelAndView(async == true ? "home/userspace/relationship :: .tab-pane" : "home/userspace/relationship");
- }
- /**
- * 添加关系
- * @param userId
- * @param optType
- * @return
- */
- @PostMapping("/relationships")
- public ResponseEntity<Response> followUser(Integer userId, String optType) {
- User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
- //1、判断用户是否存在
- User temp = userRepository.findById(userId).get();
- if (temp == null) {
- return ResponseEntity.ok().body(new Response(false, "用户不存在"));
- }
- //2、判断是关注还是取消关注
- //关注
- if ("follow".equals(optType)) {
- relationshipService.saveRelationship(new Relationship(user.getId(), userId));
- } else if ("notfollow".equals(optType)) {
- //取消关注
- relationshipService.removeRelationship(new Relationship(user.getId(), userId));
- } else {
- //非法操作
- return ResponseEntity.ok().body(new Response(false, "非法操作"));
- }
- Integer fanSize = userRepository.findById(userId).get().getFanSize();
- return ResponseEntity.ok().body(new Response(true, "操作成功",fanSize));
- }
- //粉丝-关注 end
- }
七、视图层
HTML
- <div class="box">
- <div class="box-header with-border">
- <h3 class="box-title">关系管理</h3>
- </div>
- <div class="box-body" id="right-box-body">
- <div id="right-box-body-replace">
- <div class="nav-tabs-custom" style="box-shadow: 0 0;">
- <ul class="nav nav-tabs">
- <li th:class="${is_follows}?active:''">
- <a href="javascript:void(0)" data-toggle="tab"
- class="relationship-tab-btn"
- data-th-attr="data-type=follows">我的关注</a>
- </li>
- <li th:class="${is_fans}?active:''">
- <a href="javascript:void(0)" data-toggle="tab"
- class="relationship-tab-btn" data-th-attr="data-type=fans">我的粉丝</a>
- </li>
- </ul>
- <div class="tab-content">
- <div class="tab-pane active">
- <div class="concern-list" th:if="${userPage.totalElements != 0}">
- <ul>
- <li class="box" th:each="user : ${userPage.content}">
- <div class="left-img">
- <a href="/u/3078817" target="_blank">
- <img th:src="${user.avatar}"
- class="top_head">
- </a>
- </div>
- <div class="right-c">
- <div class="title">
- <a th:href="@{'/u/'+${user.username}}" target="_blank">
- <span class="nickname"
- th:text="${user.nickname}">言曌</span>
- </a>
- </div>
- <p class="desc" title="全栈工程师"
- th:text="${user.job.name}">全栈工程师</p>
- <div class="fs-line">
- <a href="/u/3078817/follows" class="u-target">
- <span class="group">
- <em>关注</em>
- <em class="u-margin-l-5 follow-size" th:text="${user.followSize}">3</em>
- </span>
- </a>
- <a href="/u/3078817/fans"
- class="u-target u-margin-l-15">
- <span class="group">
- <em>粉丝</em>
- <em class="u-margin-l-5 fan-size" th:text="${user.fanSize}">61</em>
- </span>
- </a>
- </div>
- <div class="btn-line" th:if="${is_follows}">
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=follow"
- class="btn-o btn-green-o js-concern-follow"
- style="display: none;">关注</a>
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=notfollow"
- class="btn-o btn-gray-o js-concern-already"
- th:if="${user.isFriend!=2}">已关注</a>
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=notfollow"
- class="btn-o btn-gray-o js-concern-mutual"
- th:if="${user.isFriend==2}">互相关注</a>
- <a href="/u/2478917/messages?uid=3078817"
- target="_blank"
- class="btn-o btn-gray-o js-concern-msg">私信</a>
- </div>
- <div class="btn-line" th:if="${is_fans}">
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=follow"
- class="btn-o btn-green-o js-concern-follow"
- th:if="${user.isFriend!=2}">关注</a>
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=follow"
- class="btn-o btn-green-o js-concern-follow"
- style="display: none;"
- th:if="${user.isFriend==2}">关注</a>
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=notfollow"
- class="btn-o btn-gray-o js-concern-mutual"
- th:if="${user.isFriend!=2}"
- style="display: none;">互相关注</a>
- <a href="javascript:void(0)"
- data-th-attr="data-uid=${user.id},opt-type=notfollow"
- class="btn-o btn-gray-o js-concern-mutual"
- th:if="${user.isFriend==2}">互相关注</a>
- <a href="/u/2478917/messages?uid=3078817"
- target="_blank"
- class="btn-o btn-gray-o js-concern-msg">私信</a>
- </div>
- </div>
- </li>
- </ul>
- </div>
- <div class="clear"></div>
- <!--分页-->
- <div id="pagenation" th:if="${userPage.totalPages >= 2}">
- <nav aria-label="Page navigation" th:object="${userPage}">
- <ul class="pagination"
- data-th-attr="data-type=${is_follows}?follows:fans">
- <li data-th-classappend="*{first} ? 'disabled' : ''">
- <a href="javascript:void(0)"
- data-th-attr="pageIndex=${userPage.number}"
- aria-label="Previous">
- <span aria-hidden="true">上一页</span>
- </a>
- </li>
- <li th:each="i: ${#numbers.sequence(1, userPage.totalPages)}"
- data-th-classappend="${(userPage.number + 1) eq i} ? 'active' : ''">
- <a href="javascript:void(0)"
- data-th-attr="pageIndex=${i}">
- <span aria-hidden="true" th:text="${i}"></span>
- </a>
- </li>
- <li data-th-classappend="*{last} ? 'disabled' : ''">
- <a href="javascript:void(0)"
- data-th-attr="pageIndex=${userPage.number} + 2"
- aria-label="Next">
- <span aria-hidden="true">下一页</span>
- </a>
- </li>
- </ul>
- </nav>
- </div>
- <div class="nodata" th:if="${userPage.totalElements == 0}">
- <span th:if="${is_follows}">您还没有关注任何用户</span>
- <span th:if="${is_follows}">您还没有任何粉丝</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
JS
- //重新获取数据
- $(document).on('click', '.relationship-tab-btn', function () {
- var _ctx = $("meta[name='ctx']").attr("content");
- var url = _ctx + "/manage/relationships/" + $(this).attr("data-type");
- $.ajax({
- url: url,
- data: {async: true},
- success: function (data) {
- $(".tab-content").html(data)
- },
- error: function () {
- layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
- }
- });
- });
- //分页
- $(document).on('click', '.pagination a', function () {
- var _ctx = $("meta[name='ctx']").attr("content");
- var page = $(this).attr('pageIndex');
- var data_type = $(this).parents("ul").attr("data-type");
- var url = _ctx + "/manage/relationships/" + data_type;
- $.ajax({
- url: url,
- data: {
- async: true,
- page: page,
- },
- success: function (data) {
- $(".tab-content").html(data)
- },
- error: function () {
- layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
- }
- });
- });
- //取消关注
- $(document).on('click', '.js-concern-already,.js-concern-mutual', function () {
- var current = $(this);
- var _ctx = $("meta[name='ctx']").attr("content");
- var token = $("meta[name='_csrf']").attr("content");
- var header = $("meta[name='_csrf_header']").attr("content");
- var url = _ctx + "/manage/relationships/";
- $.ajax({
- url: url,
- type: 'POST',
- data: {
- optType: current.attr('opt-type'),
- userId: current.attr('data-uid'),
- },
- beforeSend: function (request) {
- request.setRequestHeader(header, token); // 添加 CSRF Token
- },
- success: function (data) {
- current.hide();
- current.prev("a").show();
- current.parents(".box").find(".fan-size").html(data.body);
- },
- error: function () {
- layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
- }
- });
- });
- //关注
- $(document).on('click', '.js-concern-follow', function () {
- var current = $(this);
- var _ctx = $("meta[name='ctx']").attr("content");
- var token = $("meta[name='_csrf']").attr("content");
- var header = $("meta[name='_csrf_header']").attr("content");
- var url = _ctx + "/manage/relationships/";
- $.ajax({
- url: url,
- type: 'POST',
- data: {
- optType: current.attr('opt-type'),
- userId: current.attr('data-uid'),
- },
- beforeSend: function (request) {
- request.setRequestHeader(header, token); // 添加 CSRF Token
- },
- success: function (data) {
- current.hide();
- current.next("a").show();
- current.parents(".box").find(".fan-size").html(data.body);
- },
- error: function () {
- layer.msg("出现错误,请尝试刷新页面!", {icon: 2, anim: 6});
- }
- });
- });
CSS
- ol, ul {
- list-style: none;
- }
- .concern-list {
- padding-top: 20px;
- padding-bottom: 20px;
- width: 100%;
- }
- .concern-list ul {
- margin-left: -18px;
- }
- .concern-list .box {
- float: left;
- width: 32%;
- padding: 20px;
- background-color: #f8fafc;
- margin-left: 1%;
- margin-bottom: 15px;
- min-height: 114px;
- }
- .concern-list .left-img {
- float: left;
- position: relative;
- width: 40px;
- height: 40px;
- top: 0;
- }
- .concern-list .left-img .top_head {
- position: absolute;
- top: 0;
- border-radius: 25px;
- width: 40px;
- height: 40px;
- z-index: 1;
- }
- .concern-list .rightright-c {
- margin-left: 50px;
- }
- .concern-list .rightright-c .title {
- font-weight: 700;
- color: #07111b;
- padding-bottom: 8px;
- width: 100%;
- }
- .concern-list .rightright-c .title .nickname {
- text-overflow: ellipsis;
- overflow: hidden;
- whitewhite-space: nowrap;
- max-width: 60%;
- display: inline-block;
- vertical-align: middle;
- }
- .concern-list .rightright-c .desc {
- text-overflow: ellipsis;
- overflow: hidden;
- whitewhite-space: nowrap;
- min-height: 18px;
- }
- .concern-list .rightright-c .desc, .concern-list .rightright-c .fs-line {
- color: #93999f;
- padding-bottom: 8px;
- font-size: 12px;
- }
- .concern-list .rightright-c .desc, .concern-list .rightright-c .fs-line {
- color: #93999f;
- padding-bottom: 8px;
- font-size: 12px;
- }
- .concern-list .rightright-c .fs-line .u-target {
- color: #93999f!important;
- }
- .concern-list .rightright-c .fs-line .group {
- display: inline-block;
- }
- em{
- font-style: normal;
- font-weight: 400;
- }
- .concern-list .rightright-c .fs-line .u-target {
- color: #93999f!important;
- }
- concern-list .u-margin-l-5 {
- margin-left: 5px;
- }
- .concern-list .hide {
- display: none;
- }
- .concern-list .btn-gray-o {
- border: 1px solid #d0d6d9;
- color: #787d82;
- background-color: #fff;
- margin-right: 14px;
- }
- .concern-list .btn-o {
- padding: 6px 0;
- margin-bottom: 0;
- font-size: 12px;
- font-weight: 400;
- line-height: 1.42857143;
- whitewhite-space: nowrap;
- vertical-align: middle;
- cursor: pointer;
- width: 76px;
- display: block;
- float: left;
- }
- .concern-list .btn-o{
- text-align: center;
- }
- .concern-list .btn-green-o {
- border: 1px solid #00b43c;
- color: #00b43c;
- background-color: #fff;
- margin-right: 14px;
- }
- .nodata {
- height: 420px;
- line-height: 420px;
- font-size: 18px;
- color: #b5b9bc;
- text-align: center;
- }
本文地址:https://liuyanzhao.com/8077.html
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏