diff --git a/README.md b/README.md
index bc5e6684b..85a42d891 100644
--- a/README.md
+++ b/README.md
@@ -53,3 +53,8 @@ Destroyed(销毁之后)
 activate(keep-alive组件激活时调用) 
 deactivated(keep-alive组件停用时调用) 
 errorCaptured(这个组件的作用是接受子孙组件报错是调用,三个参数 错误对象、错误的组件、错误信息)
+
+
+redis 分页
+    //  pageNum=5&pageSize=15  第几页 每页 15条
+       //pageNum 起 &pageSize 结束
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserFollowController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserFollowController.java
new file mode 100644
index 000000000..c162739a5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserFollowController.java
@@ -0,0 +1,172 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import java.util.Map;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisUtil;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysUserFollow;
+import com.ruoyi.system.service.ISysUserFollowService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 我的关注Controller
+ *
+ * @author ruoyi
+ * @date 2021-01-24
+ */
+@RestController
+@RequestMapping("/system/follow")
+public class SysUserFollowController extends BaseController
+{
+    @Autowired
+    private ISysUserFollowService sysUserFollowService;
+    @Autowired
+    private RedisUtil redisUtil;
+
+
+
+    /**
+     * 查看我的关注列表
+     */
+    @GetMapping("/listFollwUser")
+    public TableDataInfo listFollwUser()
+    {
+        startPage();
+        List<Map<String,Object>> list = sysUserFollowService.listFollwUser(getAuthUser().getUserId());
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 查看我的粉丝列表
+     */
+    @GetMapping("/listFansUser")
+    public TableDataInfo listFansUser()
+    {
+        startPage();
+        List<Map<String,Object>> list = sysUserFollowService.listFansUser(getAuthUser().getUserId());
+        return getDataTable(list);
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    /**
+     * 查询我的关注列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysUserFollow sysUserFollow)
+    {
+        startPage();
+        List<SysUserFollow> list = sysUserFollowService.selectSysUserFollowList(sysUserFollow);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出我的关注列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:export')")
+    @Log(title = "我的关注", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(SysUserFollow sysUserFollow)
+    {
+        List<SysUserFollow> list = sysUserFollowService.selectSysUserFollowList(sysUserFollow);
+        ExcelUtil<SysUserFollow> util = new ExcelUtil<SysUserFollow>(SysUserFollow.class);
+        return util.exportExcel(list, "follow");
+    }
+
+    /**
+     * 获取我的关注详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(sysUserFollowService.selectSysUserFollowById(id));
+    }
+
+    /**
+     * 新增我的关注
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:add')")
+    @Log(title = "我的关注", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysUserFollow sysUserFollow)
+    {
+        return toAjax(sysUserFollowService.insertSysUserFollow(sysUserFollow));
+    }
+
+    /**
+     * 修改我的关注
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:edit')")
+    @Log(title = "我的关注", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody SysUserFollow sysUserFollow)
+    {
+        return toAjax(sysUserFollowService.updateSysUserFollow(sysUserFollow));
+    }
+
+    /**
+     * 删除我的关注
+     */
+    @PreAuthorize("@ss.hasPermi('system:follow:remove')")
+    @Log(title = "我的关注", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(sysUserFollowService.deleteSysUserFollowByIds(ids));
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/test/controller/redisTest.java b/ruoyi-admin/src/main/java/com/ruoyi/web/test/controller/redisTest.java
new file mode 100644
index 000000000..ad45b5f50
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/test/controller/redisTest.java
@@ -0,0 +1,21 @@
+package com.ruoyi.web.test.controller;
+
+import com.ruoyi.common.core.redis.RedisUtil;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @Auther: Wang
+ * @Date: 2021/01/24 14:04
+ * 功能描述:
+ */
+public class redisTest extends BaseSpringBootTest{
+
+    @Autowired
+    RedisUtil redisUtil;
+
+    @Test
+    public void redisdemo(){
+        redisUtil.sAdd("user:follow:1","1","2");
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisKey.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisKey.java
new file mode 100644
index 000000000..785f5ca09
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisKey.java
@@ -0,0 +1,11 @@
+package com.ruoyi.common.core.redis;
+
+/**
+ * @Auther: Wang
+ * @Date: 2021/01/24 16:52
+ * 功能描述:RedisKey key 工具
+ */
+public class RedisKey {
+
+    public static final String USER_FOLLOW ="USER:FOLLOW:";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisUtil.java
new file mode 100644
index 000000000..af99ee06c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisUtil.java
@@ -0,0 +1,1354 @@
+package com.ruoyi.common.core.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.DataType;
+import org.springframework.data.redis.core.Cursor;
+import org.springframework.data.redis.core.ScanOptions;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+/**
+ * @Auther: Wang
+ * @Date: 2021/01/17 19:24
+ * 功能描述:
+ * Redis工具类*/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisUtil {
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    /** -------------------key相关操作--------------------- */
+
+    /**
+     * 删除key
+     *
+     * @param key
+     */
+    public void delete(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 批量删除key
+     *
+     * @param keys
+     */
+    public void delete(Collection<String> keys) {
+        redisTemplate.delete(keys);
+    }
+
+    /**
+     * 序列化key
+     *
+     * @param key
+     * @return
+     */
+    public byte[] dump(String key) {
+        return redisTemplate.dump(key);
+    }
+
+    /**
+     * 是否存在key
+     *
+     * @param key
+     * @return
+     */
+    public Boolean hasKey(String key) {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 设置过期时间
+     *
+     * @param key
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public Boolean expire(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 设置过期时间
+     *
+     * @param key
+     * @param date
+     * @return
+     */
+    public Boolean expireAt(String key, Date date) {
+        return redisTemplate.expireAt(key, date);
+    }
+
+    /**
+     * 查找匹配的key
+     *
+     * @param pattern
+     * @return
+     */
+    public Set<String> keys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+    /**
+     * 将当前数据库的 key 移动到给定的数据库 db 当中
+     *
+     * @param key
+     * @param dbIndex
+     * @return
+     */
+    public Boolean move(String key, int dbIndex) {
+        return redisTemplate.move(key, dbIndex);
+    }
+
+    /**
+     * 移除 key 的过期时间,key 将持久保持
+     *
+     * @param key
+     * @return
+     */
+    public Boolean persist(String key) {
+        return redisTemplate.persist(key);
+    }
+
+    /**
+     * 返回 key 的剩余的过期时间
+     *
+     * @param key
+     * @param unit
+     * @return
+     */
+    public Long getExpire(String key, TimeUnit unit) {
+        return redisTemplate.getExpire(key, unit);
+    }
+
+    /**
+     * 返回 key 的剩余的过期时间
+     *
+     * @param key
+     * @return
+     */
+    public Long getExpire(String key) {
+        return redisTemplate.getExpire(key);
+    }
+
+    /**
+     * 从当前数据库中随机返回一个 key
+     *
+     * @return
+     */
+    public String randomKey() {
+        return redisTemplate.randomKey();
+    }
+
+    /**
+     * 修改 key 的名称
+     *
+     * @param oldKey
+     * @param newKey
+     */
+    public void rename(String oldKey, String newKey) {
+        redisTemplate.rename(oldKey, newKey);
+    }
+
+    /**
+     * 仅当 newkey 不存在时,将 oldKey 改名为 newkey
+     *
+     * @param oldKey
+     * @param newKey
+     * @return
+     */
+    public Boolean renameIfAbsent(String oldKey, String newKey) {
+        return redisTemplate.renameIfAbsent(oldKey, newKey);
+    }
+
+    /**
+     * 返回 key 所储存的值的类型
+     *
+     * @param key
+     * @return
+     */
+    public DataType type(String key) {
+        return redisTemplate.type(key);
+    }
+
+    /** -------------------string相关操作--------------------- */
+
+    /**
+     * 设置指定 key 的值
+     * @param key
+     * @param value
+     */
+    public void set(String key, String value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 获取指定 key 的值
+     * @param key
+     * @return
+     */
+    public String get(String key) {
+        return redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 返回 key 中字符串值的子字符
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public String getRange(String key, long start, long end) {
+        return redisTemplate.opsForValue().get(key, start, end);
+    }
+
+    /**
+     * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public String getAndSet(String key, String value) {
+        return redisTemplate.opsForValue().getAndSet(key, value);
+    }
+
+    /**
+     * 对 key 所储存的字符串值,获取指定偏移量上的位(bit)
+     *
+     * @param key
+     * @param offset
+     * @return
+     */
+    public Boolean getBit(String key, long offset) {
+        return redisTemplate.opsForValue().getBit(key, offset);
+    }
+
+    /**
+     * 批量获取
+     *
+     * @param keys
+     * @return
+     */
+    public List<String> multiGet(Collection<String> keys) {
+        return redisTemplate.opsForValue().multiGet(keys);
+    }
+
+    /**
+     * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value
+     *
+     * @param key 位置
+     * @param value
+     *            值,true为1, false为0
+     * @return
+     */
+    public boolean setBit(String key, long offset, boolean value) {
+        return redisTemplate.opsForValue().setBit(key, offset, value);
+    }
+
+    /**
+     * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
+     *
+     * @param key
+     * @param value
+     * @param timeout
+     *            过期时间
+     * @param unit
+     *            时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
+     *            秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
+     */
+    public void setEx(String key, String value, long timeout, TimeUnit unit) {
+        redisTemplate.opsForValue().set(key, value, timeout, unit);
+    }
+
+    /**
+     * 只有在 key 不存在时设置 key 的值
+     *
+     * @param key
+     * @param value
+     * @return 之前已经存在返回false,不存在返回true
+     */
+    public boolean setIfAbsent(String key, String value) {
+        return redisTemplate.opsForValue().setIfAbsent(key, value);
+    }
+
+    /**
+     * 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
+     *
+     * @param key
+     * @param value
+     * @param offset
+     *            从指定位置开始覆写
+     */
+    public void setRange(String key, String value, long offset) {
+        redisTemplate.opsForValue().set(key, value, offset);
+    }
+
+    /**
+     * 获取字符串的长度
+     *
+     * @param key
+     * @return
+     */
+    public Long size(String key) {
+        return redisTemplate.opsForValue().size(key);
+    }
+
+    /**
+     * 批量添加
+     *
+     * @param maps
+     */
+    public void multiSet(Map<String, String> maps) {
+        redisTemplate.opsForValue().multiSet(maps);
+    }
+
+    /**
+     * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
+     *
+     * @param maps
+     * @return 之前已经存在返回false,不存在返回true
+     */
+    public boolean multiSetIfAbsent(Map<String, String> maps) {
+        return redisTemplate.opsForValue().multiSetIfAbsent(maps);
+    }
+
+    /**
+     * 增加(自增长), 负数则为自减
+     *
+     * @param key
+     * @return
+     */
+    public Long incrBy(String key, long increment) {
+        return redisTemplate.opsForValue().increment(key, increment);
+    }
+
+    /**
+     *
+     * @param key
+     * @return
+     */
+    public Double incrByFloat(String key, double increment) {
+        return redisTemplate.opsForValue().increment(key, increment);
+    }
+
+    /**
+     * 追加到末尾
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Integer append(String key, String value) {
+        return redisTemplate.opsForValue().append(key, value);
+    }
+
+    /** -------------------hash相关操作------------------------- */
+
+    /**
+     * 获取存储在哈希表中指定字段的值
+     *
+     * @param key
+     * @param field
+     * @return
+     */
+    public Object hGet(String key, String field) {
+        return redisTemplate.opsForHash().get(key, field);
+    }
+
+    /**
+     * 获取所有给定字段的值
+     *
+     * @param key
+     * @return
+     */
+    public Map<Object, Object> hGetAll(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 获取所有给定字段的值
+     *
+     * @param key
+     * @param fields
+     * @return
+     */
+    public List<Object> hMultiGet(String key, Collection<Object> fields) {
+        return redisTemplate.opsForHash().multiGet(key, fields);
+    }
+
+    public void hPut(String key, String hashKey, String value) {
+        redisTemplate.opsForHash().put(key, hashKey, value);
+    }
+
+    public void hPutAll(String key, Map<String, String> maps) {
+        redisTemplate.opsForHash().putAll(key, maps);
+    }
+
+    /**
+     * 仅当hashKey不存在时才设置
+     *
+     * @param key
+     * @param hashKey
+     * @param value
+     * @return
+     */
+    public Boolean hPutIfAbsent(String key, String hashKey, String value) {
+        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
+    }
+
+    /**
+     * 删除一个或多个哈希表字段
+     *
+     * @param key
+     * @param fields
+     * @return
+     */
+    public Long hDelete(String key, Object... fields) {
+        return redisTemplate.opsForHash().delete(key, fields);
+    }
+
+    /**
+     * 查看哈希表 key 中,指定的字段是否存在
+     *
+     * @param key
+     * @param field
+     * @return
+     */
+    public boolean hExists(String key, String field) {
+        return redisTemplate.opsForHash().hasKey(key, field);
+    }
+
+    /**
+     * 为哈希表 key 中的指定字段的整数值加上增量 increment
+     *
+     * @param key
+     * @param field
+     * @param increment
+     * @return
+     */
+    public Long hIncrBy(String key, Object field, long increment) {
+        return redisTemplate.opsForHash().increment(key, field, increment);
+    }
+
+    /**
+     * 为哈希表 key 中的指定字段的整数值加上增量 increment
+     *
+     * @param key
+     * @param field
+     * @param delta
+     * @return
+     */
+    public Double hIncrByFloat(String key, Object field, double delta) {
+        return redisTemplate.opsForHash().increment(key, field, delta);
+    }
+
+    /**
+     * 获取所有哈希表中的字段
+     *
+     * @param key
+     * @return
+     */
+    public Set<Object> hKeys(String key) {
+        return redisTemplate.opsForHash().keys(key);
+    }
+
+    /**
+     * 获取哈希表中字段的数量
+     *
+     * @param key
+     * @return
+     */
+    public Long hSize(String key) {
+        return redisTemplate.opsForHash().size(key);
+    }
+
+    /**
+     * 获取哈希表中所有值
+     *
+     * @param key
+     * @return
+     */
+    public List<Object> hValues(String key) {
+        return redisTemplate.opsForHash().values(key);
+    }
+
+    /**
+     * 迭代哈希表中的键值对
+     *
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<Entry<Object, Object>> hScan(String key, ScanOptions options) {
+        return redisTemplate.opsForHash().scan(key, options);
+    }
+
+    /** ------------------------list相关操作---------------------------- */
+
+    /**
+     * 通过索引获取列表中的元素
+     *
+     * @param key
+     * @param index
+     * @return
+     */
+    public String lIndex(String key, long index) {
+        return redisTemplate.opsForList().index(key, index);
+    }
+
+    /**
+     * 获取列表指定范围内的元素
+     *
+     * @param key
+     * @param start
+     *            开始位置, 0是开始位置
+     * @param end
+     *            结束位置, -1返回所有
+     * @return
+     */
+    public List<String> lRange(String key, long start, long end) {
+        return redisTemplate.opsForList().range(key, start, end);
+    }
+
+    /**
+     * 存储在list头部
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPush(String key, String value) {
+        return redisTemplate.opsForList().leftPush(key, value);
+    }
+
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushAll(String key, String... value) {
+        return redisTemplate.opsForList().leftPushAll(key, value);
+    }
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushAll(String key, Collection<String> value) {
+        return redisTemplate.opsForList().leftPushAll(key, value);
+    }
+
+    /**
+     * 当list存在的时候才加入
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushIfPresent(String key, String value) {
+        return redisTemplate.opsForList().leftPushIfPresent(key, value);
+    }
+
+    /**
+     * 如果pivot存在,再pivot前面添加
+     *
+     * @param key
+     * @param pivot
+     * @param value
+     * @return
+     */
+    public Long lLeftPush(String key, String pivot, String value) {
+        return redisTemplate.opsForList().leftPush(key, pivot, value);
+    }
+
+    /**
+     * 储存list 尾部
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPush(String key, String value) {
+        return redisTemplate.opsForList().rightPush(key, value);
+    }
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushAll(String key, String... value) {
+        return redisTemplate.opsForList().rightPushAll(key, value);
+    }
+
+    /**
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushAll(String key, Collection<String> value) {
+        return redisTemplate.opsForList().rightPushAll(key, value);
+    }
+
+    /**
+     * 为已存在的列表添加值
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushIfPresent(String key, String value) {
+        return redisTemplate.opsForList().rightPushIfPresent(key, value);
+    }
+
+    /**
+     * 在pivot元素的右边添加值
+     *
+     * @param key
+     * @param pivot
+     * @param value
+     * @return
+     */
+    public Long lRightPush(String key, String pivot, String value) {
+        return redisTemplate.opsForList().rightPush(key, pivot, value);
+    }
+
+    /**
+     * 通过索引设置列表元素的值
+     *
+     * @param key
+     * @param index
+     *            位置
+     * @param value
+     */
+    public void lSet(String key, long index, String value) {
+        redisTemplate.opsForList().set(key, index, value);
+    }
+
+    /**
+     * 移出并获取列表的第一个元素
+     *
+     * @param key
+     * @return 删除的元素
+     */
+    public String lLeftPop(String key) {
+        return redisTemplate.opsForList().leftPop(key);
+    }
+
+    /**
+     * 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param key
+     * @param timeout
+     *            等待时间
+     * @param unit
+     *            时间单位
+     * @return
+     */
+    public String lBLeftPop(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().leftPop(key, timeout, unit);
+    }
+
+    /**
+     * 移除并获取列表最后一个元素
+     *
+     * @param key
+     * @return 删除的元素
+     */
+    public String lRightPop(String key) {
+        return redisTemplate.opsForList().rightPop(key);
+    }
+
+    /**
+     * 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param key
+     * @param timeout
+     *            等待时间
+     * @param unit
+     *            时间单位
+     * @return
+     */
+    public String lBRightPop(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().rightPop(key, timeout, unit);
+    }
+
+    /**
+     * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
+     *
+     * @param sourceKey
+     * @param destinationKey
+     * @return
+     */
+    public String lRightPopAndLeftPush(String sourceKey, String destinationKey) {
+        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+                destinationKey);
+    }
+
+    /**
+     * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param sourceKey
+     * @param destinationKey
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public String lBRightPopAndLeftPush(String sourceKey, String destinationKey,
+                                        long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+                destinationKey, timeout, unit);
+    }
+
+    /**
+     * 删除集合中值等于value得元素
+     *
+     * @param key
+     * @param index
+     *            index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素;
+     *            index<0, 从尾部开始删除第一个值等于value的元素;
+     * @param value
+     * @return
+     */
+    public Long lRemove(String key, long index, String value) {
+        return redisTemplate.opsForList().remove(key, index, value);
+    }
+
+    /**
+     * 裁剪list
+     *
+     * @param key
+     * @param start
+     * @param end
+     */
+    public void lTrim(String key, long start, long end) {
+        redisTemplate.opsForList().trim(key, start, end);
+    }
+
+    /**
+     * 获取列表长度
+     *
+     * @param key
+     * @return
+     */
+    public Long lLen(String key) {
+        return redisTemplate.opsForList().size(key);
+    }
+
+    /** --------------------set相关操作-------------------------- */
+
+    /**
+     * set添加元素
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long sAdd(String key, String... values) {
+        return redisTemplate.opsForSet().add(key, values);
+    }
+
+    /**
+     * set移除元素
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long sRemove(String key, Object... values) {
+        return redisTemplate.opsForSet().remove(key, values);
+    }
+
+    /**
+     * 移除并返回集合的一个随机元素
+     *
+     * @param key
+     * @return
+     */
+    public String sPop(String key) {
+        return redisTemplate.opsForSet().pop(key);
+    }
+
+    /**
+     * 将元素value从一个集合移到另一个集合
+     *
+     * @param key
+     * @param value
+     * @param destKey
+     * @return
+     */
+    public Boolean sMove(String key, String value, String destKey) {
+        return redisTemplate.opsForSet().move(key, value, destKey);
+    }
+
+    /**
+     * 获取集合的大小
+     *
+     * @param key
+     * @return
+     */
+    public Long sSize(String key) {
+        return redisTemplate.opsForSet().size(key);
+    }
+
+    /**
+     * 判断集合是否包含value
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Boolean sIsMember(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+
+    /**
+     * 获取两个集合的交集
+     *
+     * @param key
+     * @param otherKey
+     * @return
+     */
+    public Set<String> sIntersect(String key, String otherKey) {
+        return redisTemplate.opsForSet().intersect(key, otherKey);
+    }
+
+    /**
+     * 获取key集合与多个集合的交集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sIntersect(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().intersect(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的交集存储到destKey集合中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sIntersectAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().intersectAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * key集合与多个集合的交集存储到destKey集合中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sIntersectAndStore(String key, Collection<String> otherKeys,
+                                   String destKey) {
+        return redisTemplate.opsForSet().intersectAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     * 获取两个集合的并集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sUnion(String key, String otherKeys) {
+        return redisTemplate.opsForSet().union(key, otherKeys);
+    }
+
+    /**
+     * 获取key集合与多个集合的并集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sUnion(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().union(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的并集存储到destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sUnionAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
+    }
+
+    /**
+     * key集合与多个集合的并集存储到destKey中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sUnionAndStore(String key, Collection<String> otherKeys,
+                               String destKey) {
+        return redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
+    }
+
+    /**
+     * 获取两个集合的差集
+     *
+     * @param key
+     * @param otherKey
+     * @return
+     */
+    public Set<String> sDifference(String key, String otherKey) {
+        return redisTemplate.opsForSet().difference(key, otherKey);
+    }
+
+    /**
+     * 获取key集合与多个集合的差集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sDifference(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().difference(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的差集存储到destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sDifference(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().differenceAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * key集合与多个集合的差集存储到destKey中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sDifference(String key, Collection<String> otherKeys,
+                            String destKey) {
+        return redisTemplate.opsForSet().differenceAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     * 获取集合所有元素
+     *
+     * @param key
+     * @return
+     */
+    public Set<String> setMembers(String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 随机获取集合中的一个元素
+     *
+     * @param key
+     * @return
+     */
+    public String sRandomMember(String key) {
+        return redisTemplate.opsForSet().randomMember(key);
+    }
+
+    /**
+     * 随机获取集合中count个元素
+     *
+     * @param key
+     * @param count
+     * @return
+     */
+    public List<String> sRandomMembers(String key, long count) {
+        return redisTemplate.opsForSet().randomMembers(key, count);
+    }
+
+    /**
+     * 随机获取集合中count个元素并且去除重复的
+     *
+     * @param key
+     * @param count
+     * @return
+     */
+    public Set<String> sDistinctRandomMembers(String key, long count) {
+        return redisTemplate.opsForSet().distinctRandomMembers(key, count);
+    }
+
+    /**
+     *
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<String> sScan(String key, ScanOptions options) {
+        return redisTemplate.opsForSet().scan(key, options);
+    }
+
+    /**------------------zSet相关操作--------------------------------*/
+
+    /**
+     * 添加元素,有序集合是按照元素的score值由小到大排列
+     *
+     * @param key
+     * @param value
+     * @param score
+     * @return
+     */
+    public Boolean zAdd(String key, String value, double score) {
+        return redisTemplate.opsForZSet().add(key, value, score);
+    }
+
+    /**
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long zAdd(String key, Set<TypedTuple<String>> values) {
+        return redisTemplate.opsForZSet().add(key, values);
+    }
+
+    /**
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long zRemove(String key, Object... values) {
+        return redisTemplate.opsForZSet().remove(key, values);
+    }
+
+    /**
+     * 增加元素的score值,并返回增加后的值
+     *
+     * @param key
+     * @param value
+     * @param delta
+     * @return
+     */
+    public Double zIncrementScore(String key, String value, double delta) {
+        return redisTemplate.opsForZSet().incrementScore(key, value, delta);
+    }
+
+    /**
+     * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
+     *
+     * @param key
+     * @param value
+     * @return 0表示第一位
+     */
+    public Long zRank(String key, Object value) {
+        return redisTemplate.opsForZSet().rank(key, value);
+    }
+
+    /**
+     * 返回元素在集合的排名,按元素的score值由大到小排列
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long zReverseRank(String key, Object value) {
+        return redisTemplate.opsForZSet().reverseRank(key, value);
+    }
+
+    /**
+     * 获取集合的元素, 从小到大排序
+     *
+     * @param key
+     * @param start
+     *            开始位置
+     * @param end
+     *            结束位置, -1查询所有
+     * @return
+     */
+    public Set<String> zRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().range(key, start, end);
+    }
+
+    /**
+     * 获取集合元素, 并且把score值也获取
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeWithScores(String key, long start,
+                                                    long end) {
+        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
+    }
+
+    /**
+     * 根据Score值查询集合元素
+     *
+     * @param key
+     * @param min
+     *            最小值
+     * @param max
+     *            最大值
+     * @return
+     */
+    public Set<String> zRangeByScore(String key, double min, double max) {
+        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从小到大排序
+     *
+     * @param key
+     * @param min
+     *            最小值
+     * @param max
+     *            最大值
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+                                                           double min, double max) {
+        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
+    }
+
+    /**
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+                                                           double min, double max, long start, long end) {
+        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,
+                start, end);
+    }
+
+    /**
+     * 获取集合的元素, 从大到小排序
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<String> zReverseRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().reverseRange(key, start, end);
+    }
+
+    /**
+     * 获取集合的元素, 从大到小排序, 并返回score值
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zReverseRangeWithScores(String key,
+                                                           long start, long end) {
+        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start,
+                end);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从大到小排序
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Set<String> zReverseRangeByScore(String key, double min,
+                                            double max) {
+        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从大到小排序
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Set<TypedTuple<String>> zReverseRangeByScoreWithScores(
+            String key, double min, double max) {
+        return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,
+                min, max);
+    }
+
+    /**
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<String> zReverseRangeByScore(String key, double min,
+                                            double max, long start, long end) {
+        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max,
+                start, end);
+    }
+
+    /**
+     * 根据score值获取集合元素数量
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Long zCount(String key, double min, double max) {
+        return redisTemplate.opsForZSet().count(key, min, max);
+    }
+
+    /**
+     * 获取集合大小
+     *
+     * @param key
+     * @return
+     */
+    public Long zSize(String key) {
+        return redisTemplate.opsForZSet().size(key);
+    }
+
+    /**
+     * 获取集合大小
+     *
+     * @param key
+     * @return
+     */
+    public Long zZCard(String key) {
+        return redisTemplate.opsForZSet().zCard(key);
+    }
+
+    /**
+     * 获取集合中value元素的score值
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Double zScore(String key, Object value) {
+        return redisTemplate.opsForZSet().score(key, value);
+    }
+
+    /**
+     * 移除指定索引位置的成员
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Long zRemoveRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().removeRange(key, start, end);
+    }
+
+    /**
+     * 根据指定的score值的范围来移除成员
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Long zRemoveRangeByScore(String key, double min, double max) {
+        return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
+    }
+
+    /**
+     * 获取key和otherKey的并集并存储在destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long zUnionAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);
+    }
+
+    /**
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long zUnionAndStore(String key, Collection<String> otherKeys,
+                               String destKey) {
+        return redisTemplate.opsForZSet()
+                .unionAndStore(key, otherKeys, destKey);
+    }
+
+    /**
+     * 交集
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long zIntersectAndStore(String key, String otherKey,
+                                   String destKey) {
+        return redisTemplate.opsForZSet().intersectAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * 交集
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long zIntersectAndStore(String key, Collection<String> otherKeys,
+                                   String destKey) {
+        return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     *
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<TypedTuple<String>> zScan(String key, ScanOptions options) {
+        return redisTemplate.opsForZSet().scan(key, options);
+    }
+}
diff --git a/ruoyi-note/src/main/java/com/ruoyi/note/domain/NmNoteContent.java b/ruoyi-note/src/main/java/com/ruoyi/note/domain/NmNoteContent.java
index 37721c57f..786a0ee23 100644
--- a/ruoyi-note/src/main/java/com/ruoyi/note/domain/NmNoteContent.java
+++ b/ruoyi-note/src/main/java/com/ruoyi/note/domain/NmNoteContent.java
@@ -15,21 +15,28 @@ import com.ruoyi.common.core.domain.BaseEntity;
  * @date 2020-09-12
  */
 @Data
-@AllArgsConstructor
-@NoArgsConstructor
+
 public class NmNoteContent
 {
 
     /** 便签主键ID */
     private Long noteId;
 
-    /** markdown编辑器内容 */
-    @Excel(name = "markdown编辑器内容")
-    private String markdownContent;
-
     /** ueditor编辑器内容 */
     @Excel(name = "ueditor编辑器内容")
     private String ueditorContent;
 
+    /** markdown编辑器内容 */
+    @Excel(name = "markdown编辑器内容")
+    private String markdownContent;
 
+    public NmNoteContent() {
+
+    }
+
+    public NmNoteContent(Long noteId, String ueditorContent, String markdownContent) {
+        this.noteId = noteId;
+        this.ueditorContent = ueditorContent;
+        this.markdownContent = markdownContent;
+    }
 }
diff --git a/ruoyi-note/src/main/java/com/ruoyi/note/service/impl/NmNoteServiceImpl.java b/ruoyi-note/src/main/java/com/ruoyi/note/service/impl/NmNoteServiceImpl.java
index 115a53620..542e76b1e 100644
--- a/ruoyi-note/src/main/java/com/ruoyi/note/service/impl/NmNoteServiceImpl.java
+++ b/ruoyi-note/src/main/java/com/ruoyi/note/service/impl/NmNoteServiceImpl.java
@@ -80,11 +80,14 @@ public class NmNoteServiceImpl implements INmNoteService {
      */
     @Override
     public int insertNmNote(NmNote nmNote) {
+        Long uuid = defaultUidGenerator.getUID();
         nmNote.setCreateTime(DateUtils.getNowDate());
         nmNote.setTitle(DateUtil.now());
-        nmNote.setTiymceUeditor(defaultUidGenerator.getUID());
+        nmNote.setTiymceUeditor(uuid);
+        //文章内容
+        nmNoteContentService.insertNmNoteContent(new NmNoteContent(uuid,null,"请开始你的记录~"));
         //创建文章>>mongodb
-        redisCache.setCacheObject(Constants.NM_NOTE_CONTENT+nmNote.getTiymceUeditor(),"请开始你的创作!");
+       // redisCache.setCacheObject(Constants.NM_NOTE_CONTENT+nmNote.getTiymceUeditor(),"请开始你的创作!");
         return nmNoteMapper.insertSelective(nmNote);
     }
 
@@ -133,18 +136,11 @@ public class NmNoteServiceImpl implements INmNoteService {
         NmNote nmNote = new NmNote();
         nmNote.setNoteId(noteId);
         nmNote.setUserId(userID);
-        NmNote isnmNote1 = nmNoteMapper.selectOne(nmNote);
-        //查询对应的文章数据
-        //1.查redis缓存
-        String noteContent = redisCache.getCacheObject(Constants.NM_NOTE_CONTENT + isnmNote1.getTiymceUeditor());
-        if (noteContent != null && !"".equals(noteContent)) {
-            isnmNote1.setUeditorContent(noteContent);
-        } else {
-        // 2不存在就走mogodb
-            List<NoteContentMgDb> NoteContentMgDb = noteRepositoryService.findById(isnmNote1.getTiymceUeditor() + "");
-            isnmNote1.setUeditorContent(NoteContentMgDb.get(0).getNoteContent());
-        }
-        return isnmNote1;
+        NmNote nmNoteS =  nmNoteMapper.selectOne(nmNote);
+        //获取文章
+        NmNoteContent nmNoteContent =  nmNoteContentService.selectNmNoteContentById(nmNoteS.getTiymceUeditor());
+        nmNoteS.setUeditorContent(nmNoteContent.getUeditorContent());
+        return nmNoteS;
     }
 
     /**
@@ -156,8 +152,10 @@ public class NmNoteServiceImpl implements INmNoteService {
     @Override
     public int userUpdateNote(NmNote nmNote) {
         //储存到redis中  只缓存频繁操作的文章内容
-        redisCache.setCacheObject(Constants.NM_NOTE_CONTENT+nmNote.getTiymceUeditor(),nmNote.getUeditorContent());
-        // 更新标题信息
+       // redisCache.setCacheObject(Constants.NM_NOTE_CONTENT+nmNote.getTiymceUeditor(),nmNote.getUeditorContent());
+        // 更新文章信息
+        nmNoteContentService.updateNmNoteContent(new NmNoteContent(nmNote.getTiymceUeditor(),nmNote.getUeditorContent(),null));
+
         return  nmNoteMapper.updateNmNote(nmNote);
     }
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserFollow.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserFollow.java
new file mode 100644
index 000000000..10d690893
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserFollow.java
@@ -0,0 +1,83 @@
+package com.ruoyi.system.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import javax.persistence.Column;
+import java.util.Date;
+
+/**
+ * 我的关注对象 sys_user_follow
+ *
+ * @author ruoyi
+ * @date 2021-01-24
+ */
+public class SysUserFollow
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 关注的用户id */
+    @Excel(name = "关注的用户id")
+    private Long followUserId;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Column(name = "create_time")
+    private Date createTime;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+    public void setFollowUserId(Long followUserId)
+    {
+        this.followUserId = followUserId;
+    }
+
+    public Long getFollowUserId()
+    {
+        return followUserId;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return "SysUserFollow{" +
+                "id=" + id +
+                ", userId=" + userId +
+                ", followUserId=" + followUserId +
+                ", createTime=" + createTime +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserFollowMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserFollowMapper.java
new file mode 100644
index 000000000..8341a6826
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserFollowMapper.java
@@ -0,0 +1,87 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import java.util.Map;
+
+import com.ruoyi.system.domain.SysUserFollow;
+
+/**
+ * 我的关注Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-01-24
+ */
+public interface SysUserFollowMapper
+{
+    /**
+     * 查询我的关注
+     *
+     * @param id 我的关注ID
+     * @return 我的关注
+     */
+    public SysUserFollow selectSysUserFollowById(Long id);
+
+    /**
+     * 查询我的关注列表
+     *
+     * @param sysUserFollow 我的关注
+     * @return 我的关注集合
+     */
+    public List<SysUserFollow> selectSysUserFollowList(SysUserFollow sysUserFollow);
+
+    /**
+     * 新增我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    public int insertSysUserFollow(SysUserFollow sysUserFollow);
+
+    /**
+     * 修改我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    public int updateSysUserFollow(SysUserFollow sysUserFollow);
+
+    /**
+     * 删除我的关注
+     *
+     * @param id 我的关注ID
+     * @return 结果
+     */
+    public int deleteSysUserFollowById(Long id);
+
+    /**
+     * 批量删除我的关注
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteSysUserFollowByIds(Long[] ids);
+
+    /**
+     * 查看我的关注列表  删
+     *
+     * @param  userId
+     * @return
+     */
+    List<String> listFollwUser(Long userId);
+
+    /**
+     * 查看我的关注列表
+     *
+     * @param  userId
+     * @return
+     */
+    List<Map<String,Object>> listFollwUserByUid(Long userId);
+
+    /**
+     * 查看我的粉丝列表
+     *
+     * @param  userId
+     * @return
+     */
+    List<Map<String, Object>> listFansUserByUid(Long userId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserFollowService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserFollowService.java
new file mode 100644
index 000000000..017d6c6b6
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserFollowService.java
@@ -0,0 +1,81 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.ruoyi.system.domain.SysUserFollow;
+
+/**
+ * 我的关注Service接口
+ *
+ * @author ruoyi
+ * @date 2021-01-24
+ */
+public interface ISysUserFollowService
+{
+    /**
+     * 查询我的关注
+     *
+     * @param id 我的关注ID
+     * @return 我的关注
+     */
+    public SysUserFollow selectSysUserFollowById(Long id);
+
+    /**
+     * 查询我的关注列表
+     *
+     * @param sysUserFollow 我的关注
+     * @return 我的关注集合
+     */
+    public List<SysUserFollow> selectSysUserFollowList(SysUserFollow sysUserFollow);
+
+    /**
+     * 新增我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    public int insertSysUserFollow(SysUserFollow sysUserFollow);
+
+    /**
+     * 修改我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    public int updateSysUserFollow(SysUserFollow sysUserFollow);
+
+    /**
+     * 批量删除我的关注
+     *
+     * @param ids 需要删除的我的关注ID
+     * @return 结果
+     */
+    public int deleteSysUserFollowByIds(Long[] ids);
+
+    /**
+     * 删除我的关注信息
+     *
+     * @param id 我的关注ID
+     * @return 结果
+     */
+    public int deleteSysUserFollowById(Long id);
+
+
+
+    /**
+     * 查看我的关注列表
+     *
+     * @param  userId
+     * @return
+     */
+    List<Map<String,Object>> listFollwUser(Long userId);
+
+    /**
+     * 查看我的粉丝列表
+     *
+     * @param  userId
+     * @return
+     */
+    List<Map<String,Object>> listFansUser(Long userId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserFollowServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserFollowServiceImpl.java
new file mode 100644
index 000000000..f2853395c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserFollowServiceImpl.java
@@ -0,0 +1,167 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.*;
+
+import com.ruoyi.common.core.redis.RedisKey;
+import com.ruoyi.common.core.redis.RedisUtil;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.mapper.SysUserFollowMapper;
+import com.ruoyi.system.domain.SysUserFollow;
+import com.ruoyi.system.service.ISysUserFollowService;
+
+/**
+ * 我的关注Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-01-24
+ */
+@Service
+public class SysUserFollowServiceImpl implements ISysUserFollowService
+{
+    @Autowired
+    private SysUserFollowMapper sysUserFollowMapper;
+    @Autowired
+    private RedisUtil redisUtil;
+
+    /**
+     * 查询我的关注
+     *
+     * @param id 我的关注ID
+     * @return 我的关注
+     */
+    @Override
+    public SysUserFollow selectSysUserFollowById(Long id)
+    {
+        return sysUserFollowMapper.selectSysUserFollowById(id);
+    }
+
+    /**
+     * 查询我的关注列表
+     *
+     * @param sysUserFollow 我的关注
+     * @return 我的关注
+     */
+    @Override
+    public List<SysUserFollow> selectSysUserFollowList(SysUserFollow sysUserFollow)
+    {
+        return sysUserFollowMapper.selectSysUserFollowList(sysUserFollow);
+    }
+
+    /**
+     * 新增我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    @Override
+    public int insertSysUserFollow(SysUserFollow sysUserFollow)
+    {
+        sysUserFollow.setCreateTime(DateUtils.getNowDate());
+        return sysUserFollowMapper.insertSysUserFollow(sysUserFollow);
+    }
+
+    /**
+     * 修改我的关注
+     *
+     * @param sysUserFollow 我的关注
+     * @return 结果
+     */
+    @Override
+    public int updateSysUserFollow(SysUserFollow sysUserFollow)
+    {
+        return sysUserFollowMapper.updateSysUserFollow(sysUserFollow);
+    }
+
+    /**
+     * 批量删除我的关注
+     *
+     * @param ids 需要删除的我的关注ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysUserFollowByIds(Long[] ids)
+    {
+        return sysUserFollowMapper.deleteSysUserFollowByIds(ids);
+    }
+
+    /**
+     * 删除我的关注信息
+     *
+     * @param id 我的关注ID
+     * @return 结果
+     */
+    @Override
+    public int deleteSysUserFollowById(Long id)
+    {
+        return sysUserFollowMapper.deleteSysUserFollowById(id);
+    }
+
+
+    /**
+     * 查看我的关注列表
+     *
+     * @param  userId
+     * @return
+     */
+    @Override
+    public List<Map<String,Object>> listFollwUser(Long userId) {
+
+        return   sysUserFollowMapper.listFollwUserByUid(userId);
+    }
+
+
+
+    /**
+     *
+     * redis 分页计算
+     * @param
+     * @return
+     */
+    public static HashMap<String, Long> redisPage(Long pageNum, Long pageSize) {
+        HashMap<String, Long> map = new HashMap<String, Long>();
+        if (pageNum == 1L) {
+            pageNum = 0L;
+            pageSize = pageSize - 1;
+        } else {
+            pageNum = pageNum * pageSize;
+            pageSize = (pageNum + 1) * pageSize - 1;
+        }
+        map.put("pageNum", pageNum);
+        map.put("pageSize", pageSize);
+        return map;
+    }
+
+//    /**
+//     * 查看我的关注列表
+//     *
+//     * @param  userId
+//     * @return
+//     */
+//    @Override
+//    public List<String> listFollwUser(Long userId, Long pageNum, Long pageSize) {
+//        //  pageNum=5&pageSize=15  第几页 每页 15条    pageNum 起 &pageSize 结束
+//        HashMap<String, Long> map = redisPage(pageNum,pageSize);
+//        List<String> list = redisUtil.lRange(RedisKey.USER_FOLLOW + userId ,map.get("pageNum"), map.get("pageSize"));
+//        if (null == list || list.isEmpty()) {
+//            //查库 --> 无序
+//            list = sysUserFollowMapper.listFollwUser(userId);
+//            if (null != list && !list.isEmpty()) {
+//                //list<Long> 转 数组
+//                redisUtil.lRightPushAll(RedisKey.USER_FOLLOW + userId, list.stream().toArray(String[]::new));
+//            }
+//        }
+//        return list;
+//    }
+
+//    @Override
+//    public List<String> listFansUser(Long userId) {
+//        return null;
+//    }
+
+    @Override
+    public List<Map<String, Object>> listFansUser(Long userId) {
+        return sysUserFollowMapper.listFansUserByUid(userId);
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserFollowMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserFollowMapper.xml
new file mode 100644
index 000000000..9e85da4a4
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserFollowMapper.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysUserFollowMapper">
+
+    <resultMap type="SysUserFollow" id="SysUserFollowResult">
+        <result property="id"    column="id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="followUserId"    column="follow_user_id"    />
+        <result property="createTime"    column="create_time"    />
+    </resultMap>
+
+    <sql id="selectSysUserFollowVo">
+        select id, user_id, follow_user_id, create_time from sys_user_follow
+    </sql>
+
+    <select id="selectSysUserFollowList" parameterType="SysUserFollow" resultMap="SysUserFollowResult">
+        <include refid="selectSysUserFollowVo"/>
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="followUserId != null "> and follow_user_id = #{followUserId}</if>
+        </where>
+    </select>
+
+
+    <select id="selectSysUserFollowById" parameterType="Long" resultMap="SysUserFollowResult">
+        <include refid="selectSysUserFollowVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="listFollwUser" parameterType="Long" resultType="String">
+        select follow_user_id from sys_user_follow where user_id = #{userId}
+    </select>
+
+    <select id="listFollwUserByUid" parameterType="Long" resultType="java.util.Map">
+        select f.follow_user_id as userId,u.user_name as userName,u.avatar from sys_user_follow as f,sys_user as u where u.user_id = f.follow_user_id and f.user_id = #{userId}
+    </select>
+    <select id="listFansUserByUid" parameterType="Long" resultType="java.util.Map">
+        select f.user_id as userId,u.user_name as userName,u.avatar from sys_user_follow as f,sys_user as u where u.user_id = f.user_id and f.follow_user_id = #{userId}
+    </select>
+
+    <insert id="insertSysUserFollow" parameterType="SysUserFollow" useGeneratedKeys="true" keyProperty="id">
+        insert into sys_user_follow
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="userId != null">user_id,</if>
+            <if test="followUserId != null">follow_user_id,</if>
+            <if test="createTime != null">create_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="userId != null">#{userId},</if>
+            <if test="followUserId != null">#{followUserId},</if>
+            <if test="createTime != null">#{createTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateSysUserFollow" parameterType="SysUserFollow">
+        update sys_user_follow
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="followUserId != null">follow_user_id = #{followUserId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteSysUserFollowById" parameterType="Long">
+        delete from sys_user_follow where id = #{id}
+    </delete>
+
+    <delete id="deleteSysUserFollowByIds" parameterType="String">
+        delete from sys_user_follow where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>
diff --git a/ruoyi-ui/src/views/bookmark/bookmark/index.vue b/ruoyi-ui/src/views/bookmark/bookmark/index.vue
index 6157576cc..68bb4fca5 100644
--- a/ruoyi-ui/src/views/bookmark/bookmark/index.vue
+++ b/ruoyi-ui/src/views/bookmark/bookmark/index.vue
@@ -343,7 +343,7 @@
         sousuo: '',
         drawer: false,
         // 遮罩层
-        loading: true,
+        // loading: true,
         // 弹出层标题
         title: "",
         // 是否显示弹出层
@@ -454,10 +454,10 @@
         return format(time, 'zh_CN'); //转换成类似于几天前的格式
       },
     },
-    mounted() {
-
-      // document.querySelector("#datalist").addEventListener('scroll', this.handleScroll)
-    },
+    // mounted() {
+    //
+    //   // document.querySelector("#datalist").addEventListener('scroll', this.handleScroll)
+    // },
     computed: {
       /**list加载完毕就禁止滚动**/
 
@@ -1411,7 +1411,7 @@
   .sousou-input i {
     font-size: 15px;
   }
- 
+
 
   .header-list {
     display: flex;
@@ -1485,7 +1485,7 @@
   }
 
   .mianUrl-botoom{
-    height: 900px;
+  padding-bottom: 20px;
 
   }
   .openurl{
diff --git a/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue b/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue
index 453e54e07..7403c5e0e 100644
--- a/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue
+++ b/ruoyi-ui/src/views/bookmark/common/ImportHtml.vue
@@ -1,6 +1,6 @@
 <template>
-  <div>
-
+  <div >
+    <div style="width:360px;height:260px;margin: 0 auto;margin-top: 40px">
     <!-- 用户导入对话框 -->
 <!--    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>-->
       <el-upload
@@ -26,13 +26,15 @@
 <!--          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据-->
 <!--          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>-->
 <!--        </div>-->
-        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入".html"格式文件!</div>
+        <div class="el-upload__tip title"   slot="tip">提示:仅允许导入".html"格式文件!</div>
       </el-upload>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" class="  mdui-text-center  mdui-btn mdui-btn-raised mdui-text-color-blue-900  mdui-color-light-blue-100" @click="submitFileForm">确 定</el-button>
 <!--        <el-button @click="upload.open = false">取 消</el-button>-->
-        <button class="mdui-btn mdui-btn-raised mdui-btn-dense  mdui-color-light-blue-100  mdui-ripple">Button</button>
+        <button @click="submitUpload"  class="isbutton mdui-btn mdui-btn-block mdui-btn-raised mdui-btn-dense  mdui-color-blue-100  mdui-ripple">导 入 书 签</button>
       </div>
+
+    </div>
 <!--    </el-dialog>-->
 
 <!--    <el-button-->
@@ -150,10 +152,11 @@
 
 <style scoped>
   .text{
-    border: #6f7180 1px solid;
+    border: #cecece 1px solid;
     border-radius: 10px;
-    margin-top: 10px;
-    background-color: #e9e9e9;
+    margin: 20px;
+    background-color: #fafcff;
+    margin-top:  30px;
   }
 
   .structure {
@@ -173,4 +176,20 @@
    li{
     list-style:none;
   }
+  .main{
+
+  }
+  .upload-demo{
+  }
+  .title {
+    color: red;
+    width: 360px;
+    height: 10px;
+    text-align: center;
+    margin-top: 7px;
+  }
+  .isbutton{
+  margin-top: 10px;
+
+  }
 </style>
diff --git a/ruoyi-ui/src/views/bookmark/common/NqEdit.vue b/ruoyi-ui/src/views/bookmark/common/NqEdit.vue
index 5b70a4e49..f0546605e 100644
--- a/ruoyi-ui/src/views/bookmark/common/NqEdit.vue
+++ b/ruoyi-ui/src/views/bookmark/common/NqEdit.vue
@@ -1,17 +1,23 @@
 <template>
-  <div class="home" >
+  <div class="home" v-loading="loading" >
 
     <div class="nqtitle">
       <div class="mdui-textfield mdui-textfield-floating-label inputtop">
         <input class="mdui-textfield-input edittitle" v-model="queryParamsAndMg.title" type="text" required/>
       </div>
       <div class="common">
-        <el-tag type="info" size="small" >{{queryParamsAndMg.updateTime==null?'0000:00:00':queryParamsAndMg.updateTime}}</el-tag>
+        <el-tag type="info" size="small" >{{queryParamsAndMg.updateTime==null?'2020-12-13 21:24:35':queryParamsAndMg.updateTime}}</el-tag>
         <el-link type="info" icon="el-icon-edit" class="editNote" @click="updateEdit">{{updateOpn}}</el-link>
-        <el-link type="info"  icon="el-icon-delete" class="editNote">删除</el-link>
+        <el-link type="info"  icon="el-icon-delete" class="editNote delete">删除</el-link>
+        <el-link type="info"  icon="el-icon-refresh-right" class="editNote">刷新</el-link>
+        <el-link type="info"  icon="el-icon-connection" class="editNote">分享</el-link>
+        <el-link type="info"  class="editNote">|</el-link>
+        <el-link type="info"  icon="el-icon-lock" class="editNote">加密</el-link>
+<!--        <el-link type="info"  icon="el-icon-unlock" class="editNote">未加密</el-link>-->
+        <el-link type="info"  icon="el-icon-key" class="editNote">改密</el-link>
       </div>
     </div>
-        <div v-loading="loading"  v-if="!showEditor" class="mian" v-html="queryParamsAndMg.ueditorContent">
+        <div  v-if="!showEditor" class="mian" v-html="queryParamsAndMg.ueditorContent">
 
 
         </div>
@@ -65,9 +71,8 @@
       updateEditor:null
     },
     mounted() {
-
       this.showEditor=this.updateEditor;
-      this.getNoteById();
+
     },
     updated() {
 
@@ -98,12 +103,13 @@
           ueditorContent: undefined,
         },
         showEditor:false,
-        loading:false,
-        updateOpn:'编辑'
+        loading:true,
+        updateOpn:'编辑',
       }
     },
     created() {
 
+      this.getNoteById();
     },
     methods: {
       /** 实时更新文章的信息 */
@@ -121,7 +127,7 @@
       /** 查询便签管理列表 */
       getNoteById() {
         var that = this;
-        that.loading=true;
+
         var blueditor = that.ueditor != null && that.ueditor != '' && that.ueditor != undefined;
         var blnoteId = that.noteid != null && that.noteid != '' && that.noteid != undefined;
         if (blueditor) {
@@ -133,9 +139,10 @@
         if (blueditor && blnoteId) {
           userGetNoteInfo(this.queryParamsAndMg.noteId).then(response => {
             that.queryParamsAndMg = response.data;
+            that.loading=false;
           });
         }
-        that.loading=false;
+
       },
       //鼠标单击的事件
       onClick(e, editor) {
@@ -179,12 +186,11 @@
   }
 
   .mian {
-    height: 100%;
+    height: auto;
     overflow-y: auto;
-    width: 1000px;
+    width:auto;
     /*text-indent: 10px;*/
     padding: 10px;
-    margin-bottom: 10px;
     opacity: 0.9;
     margin: 15px;
     border: 1px solid #D4D4D4;
@@ -210,6 +216,7 @@
   .nqtitle{
     margin-left: 13px;
     margin-bottom: 10px;
+    margin-right: 17px;
   }
   .inputtop{
     padding-top: 6px;
@@ -219,5 +226,8 @@
     align-items: center;
     height: 22px;
   }
+  .delete{
+    color: #ff3b2f;
+  }
 
 </style>
diff --git a/ruoyi-yunbookmark/src/main/resources/mapper/bookmark/SqBookmarkMapper.xml b/ruoyi-yunbookmark/src/main/resources/mapper/bookmark/SqBookmarkMapper.xml
index a6fd8057f..aac0356c3 100644
--- a/ruoyi-yunbookmark/src/main/resources/mapper/bookmark/SqBookmarkMapper.xml
+++ b/ruoyi-yunbookmark/src/main/resources/mapper/bookmark/SqBookmarkMapper.xml
@@ -18,14 +18,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="idelete"    column="IDelete"    />
         <result property="start"    column="Start"    />
         <result property="createTime"    column="create_time"    />
-        <collection property="sqTags"
-                    javaType="java.util.ArrayList"
-                    ofType="java.util.Map"
-                    select="com.ruoyi.bookmark.mapper.SqBookmarkTagMapper.selectSqTaListById"
-                    column="bookmark_id">
+<!--        <collection property="sqTags"-->
+<!--                    javaType="java.util.ArrayList"-->
+<!--                    ofType="java.util.Map"-->
+<!--                    select="com.ruoyi.bookmark.mapper.SqBookmarkTagMapper.selectSqTaListById"-->
+<!--                    column="bookmark_id">-->
 
 
-        </collection>
+<!--        </collection>-->
 
     </resultMap>