Jelajahi Sumber

feat:未上线的会员统计和查询(pc两个端)

caoliqin 6 hari lalu
induk
melakukan
bdf648e616

+ 104 - 0
fs-admin/src/main/java/com/fs/store/controller/FsUserOnlineStateController.java

@@ -0,0 +1,104 @@
+package com.fs.store.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.store.domain.FsUserOnlineState;
+import com.fs.store.service.IFsUserOnlineStateService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 用户上线情况Controller
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+@RestController
+@RequestMapping("/store/userOnlineState")
+public class FsUserOnlineStateController extends BaseController
+{
+    @Autowired
+    private IFsUserOnlineStateService fsUserOnlineStateService;
+
+    /**
+     * 查询用户上线情况列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserOnlineState fsUserOnlineState)
+    {
+        startPage();
+        List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户上线情况列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:export')")
+    @Log(title = "用户上线情况", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserOnlineState fsUserOnlineState)
+    {
+        List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        ExcelUtil<FsUserOnlineState> util = new ExcelUtil<FsUserOnlineState>(FsUserOnlineState.class);
+        return util.exportExcel(list, "未上线会员");
+    }
+
+    /**
+     * 获取用户上线情况详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(fsUserOnlineStateService.selectFsUserOnlineStateById(userId));
+    }
+
+    /**
+     * 新增用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:add')")
+    @Log(title = "用户上线情况", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserOnlineState fsUserOnlineState)
+    {
+        return toAjax(fsUserOnlineStateService.insertFsUserOnlineState(fsUserOnlineState));
+    }
+
+    /**
+     * 修改用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:edit')")
+    @Log(title = "用户上线情况", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserOnlineState fsUserOnlineState)
+    {
+        return toAjax(fsUserOnlineStateService.updateFsUserOnlineState(fsUserOnlineState));
+    }
+
+    /**
+     * 删除用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:remove')")
+    @Log(title = "用户上线情况", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(fsUserOnlineStateService.deleteFsUserOnlineStateByIds(userIds));
+    }
+
+    @ApiOperation("新增/更新未上线人员-定时任务")
+    @PostMapping("/testTask")
+    public void test(){
+        fsUserOnlineStateService.insertUserNotOnline();
+    }
+}

+ 10 - 0
fs-admin/src/main/java/com/fs/task/StoreTask.java

@@ -136,6 +136,9 @@ public class StoreTask
     @Autowired
     private IFsUserWatchStatisticsService fsUserWatchStatisticsService;
 
+    @Autowired
+    private IFsUserOnlineStateService fsUserOnlineStateService;
+
     public void PushErp() throws ParseException {
         List<Long> ids;
         // 开启审核
@@ -480,4 +483,11 @@ public class StoreTask
         /***************************************进入营期会员看课明细统计定时任务结束**********************************************/
     }
 
+    /**
+     * 定时查询未上线的用户
+     */
+    public void insertUserNotOnline(){
+        fsUserOnlineStateService.insertUserNotOnline();
+    }
+
 }

+ 125 - 0
fs-company/src/main/java/com/fs/store/controller/FsUserOnlineStateController.java

@@ -0,0 +1,125 @@
+package com.fs.store.controller;
+
+import java.util.List;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+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.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.store.domain.FsUserOnlineState;
+import com.fs.store.service.IFsUserOnlineStateService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 用户上线情况Controller
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+@RestController
+@RequestMapping("/store/userOnlineState")
+public class FsUserOnlineStateController extends BaseController
+{
+    @Autowired
+    private IFsUserOnlineStateService fsUserOnlineStateService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询用户上线情况列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserOnlineState fsUserOnlineState)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        // 如果是管理员,可以查询当前公司所有数据
+        if(loginUser.getUser().isAdmin()){
+            fsUserOnlineState.setCompanyId( loginUser.getCompany().getCompanyId());
+        } else{
+            fsUserOnlineState.setCompanyUserId( loginUser.getUser().getUserId());
+        }
+        List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户上线情况列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:export')")
+    @Log(title = "用户上线情况", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserOnlineState fsUserOnlineState)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        // 如果是管理员,可以查询当前公司所有数据
+        if(loginUser.getUser().isAdmin()){
+            fsUserOnlineState.setCompanyId( loginUser.getCompany().getCompanyId());
+        } else{
+            fsUserOnlineState.setCompanyUserId( loginUser.getUser().getUserId());
+        }
+        List<FsUserOnlineState> list = fsUserOnlineStateService.selectFsUserOnlineStateList(fsUserOnlineState);
+        ExcelUtil<FsUserOnlineState> util = new ExcelUtil<FsUserOnlineState>(FsUserOnlineState.class);
+        return util.exportExcel(list, "未上线会员");
+    }
+
+    /**
+     * 获取用户上线情况详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(fsUserOnlineStateService.selectFsUserOnlineStateById(userId));
+    }
+
+    /**
+     * 新增用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:add')")
+    @Log(title = "用户上线情况", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserOnlineState fsUserOnlineState)
+    {
+        return toAjax(fsUserOnlineStateService.insertFsUserOnlineState(fsUserOnlineState));
+    }
+
+    /**
+     * 修改用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:edit')")
+    @Log(title = "用户上线情况", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserOnlineState fsUserOnlineState)
+    {
+        return toAjax(fsUserOnlineStateService.updateFsUserOnlineState(fsUserOnlineState));
+    }
+
+    /**
+     * 删除用户上线情况
+     */
+    @PreAuthorize("@ss.hasPermi('store:userOnlineState:remove')")
+    @Log(title = "用户上线情况", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(fsUserOnlineStateService.deleteFsUserOnlineStateByIds(userIds));
+    }
+
+}

+ 95 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsUserOnlineState.java

@@ -0,0 +1,95 @@
+package com.fs.store.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 用户上线情况对象 fs_user_online_state
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserOnlineState extends BaseEntity{
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /** 用户id */
+    private Long userId;
+
+    /** 用户昵称 */
+    @Excel(name = "用户昵称")
+    private String nickname;
+
+    /** 用户头像 */
+    @Excel(name = "用户头像")
+    private String avatar;
+
+    /** 手机号码 */
+    @Excel(name = "手机号码")
+    private String phone;
+
+    /** 微信小程序OPENID */
+    @Excel(name = "微信小程序OPENID")
+    private String maOpenId;
+
+    /** 微信公众号OPENID */
+    @Excel(name = "微信公众号OPENID")
+    private String mpOpenId;
+
+    /** 关联ID */
+    @Excel(name = "关联ID")
+    private String unionId;
+
+    /** 用户状态,1-正常,0-禁止 */
+    @Excel(name = "用户状态,1-正常,0-禁止")
+    private Integer status;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司名称 */
+    @Excel(name = "所属公司")
+    private String companyName;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 销售名称 */
+    @Excel(name = "所属销售")
+    private String companyUserName;
+
+    /** 上线状态,1-已上线;2-未上线 */
+    @Excel(name = "上线状态,1-已上线;2-未上线")
+    private Integer onlineStatus;
+
+    /** 上线时间(第一次看课的时间) */
+    @Excel(name = "上线时间(第一次看课的时间)")
+    private Date onlineTime;
+
+    /** 看课数量 */
+    @Excel(name = "看课数量")
+    private Integer watchCourseCount;
+
+    /** 参与营期数量 */
+    @Excel(name = "参与营期数量")
+    private Integer partCourseCount;
+
+    /** 最后一次看课时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "最后一次看课时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date lastWatchDate;
+
+    /** 更新时间 */
+    @Excel(name = "更新时间", readConverterExp = "更新时间")
+    private Date updateTime;
+
+}

+ 75 - 0
fs-service-system/src/main/java/com/fs/store/mapper/FsUserOnlineStateMapper.java

@@ -0,0 +1,75 @@
+package com.fs.store.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.store.domain.FsUser;
+import com.fs.store.domain.FsUserOnlineState;
+
+/**
+ * 用户上线情况Mapper接口
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+public interface FsUserOnlineStateMapper extends BaseMapper<FsUserOnlineState>{
+    /**
+     * 查询用户上线情况
+     *
+     * @param userId 用户上线情况主键
+     * @return 用户上线情况
+     */
+    FsUserOnlineState selectFsUserOnlineStateById(Long userId);
+
+    /**
+     * 查询用户上线情况列表
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 用户上线情况集合
+     */
+    List<FsUserOnlineState> selectFsUserOnlineStateList(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 新增用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    int insertFsUserOnlineState(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 修改用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    int updateFsUserOnlineState(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 删除用户上线情况
+     *
+     * @param userId 用户上线情况主键
+     * @return 结果
+     */
+    int deleteFsUserOnlineStateById(Long userId);
+
+    /**
+     * 批量删除用户上线情况
+     *
+     * @param userIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserOnlineStateByIds(Long[] userIds);
+
+    /**
+     * 查询没有看课记录的用户
+     * @return
+     */
+    List<FsUserOnlineState> selectUserNotOnline();
+
+    /**
+     * 查询短时间已经有且仅有一条看课记录的用户(查询的时间需要大于等于定时任务的时间)
+     * @return
+     */
+    List<FsUser> selectExistWatchLogUser();
+
+}

+ 67 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsUserOnlineStateService.java

@@ -0,0 +1,67 @@
+package com.fs.store.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.store.domain.FsUserOnlineState;
+
+/**
+ * 用户上线情况Service接口
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+public interface IFsUserOnlineStateService extends IService<FsUserOnlineState>{
+    /**
+     * 查询用户上线情况
+     *
+     * @param userId 用户上线情况主键
+     * @return 用户上线情况
+     */
+    FsUserOnlineState selectFsUserOnlineStateById(Long userId);
+
+    /**
+     * 查询用户上线情况列表
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 用户上线情况集合
+     */
+    List<FsUserOnlineState> selectFsUserOnlineStateList(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 新增用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    int insertFsUserOnlineState(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 修改用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    int updateFsUserOnlineState(FsUserOnlineState fsUserOnlineState);
+
+    /**
+     * 批量删除用户上线情况
+     *
+     * @param userIds 需要删除的用户上线情况主键集合
+     * @return 结果
+     */
+    int deleteFsUserOnlineStateByIds(Long[] userIds);
+
+    /**
+     * 删除用户上线情况信息
+     *
+     * @param userId 用户上线情况主键
+     * @return 结果
+     */
+    int deleteFsUserOnlineStateById(Long userId);
+
+    /**
+     * 统计未上线的用户(定时更新上线状态)
+     */
+    void insertUserNotOnline();
+
+}

+ 136 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserOnlineStateServiceImpl.java

@@ -0,0 +1,136 @@
+package com.fs.store.service.impl;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.store.domain.FsUser;
+import com.google.common.collect.Lists;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.store.mapper.FsUserOnlineStateMapper;
+import com.fs.store.domain.FsUserOnlineState;
+import com.fs.store.service.IFsUserOnlineStateService;
+
+/**
+ * 用户上线情况Service业务层处理
+ *
+ * @author fs
+ * @date 2025-06-30
+ */
+@Service
+public class FsUserOnlineStateServiceImpl extends ServiceImpl<FsUserOnlineStateMapper, FsUserOnlineState> implements IFsUserOnlineStateService {
+
+    @Autowired
+    private SqlSessionFactory sqlSessionFactory;
+
+    /**
+     * 查询用户上线情况
+     *
+     * @param userId 用户上线情况主键
+     * @return 用户上线情况
+     */
+    @Override
+    public FsUserOnlineState selectFsUserOnlineStateById(Long userId)
+    {
+        return baseMapper.selectFsUserOnlineStateById(userId);
+    }
+
+    /**
+     * 查询用户上线情况列表
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 用户上线情况
+     */
+    @Override
+    public List<FsUserOnlineState> selectFsUserOnlineStateList(FsUserOnlineState fsUserOnlineState)
+    {
+        return baseMapper.selectFsUserOnlineStateList(fsUserOnlineState);
+    }
+
+    /**
+     * 新增用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserOnlineState(FsUserOnlineState fsUserOnlineState)
+    {
+        fsUserOnlineState.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsUserOnlineState(fsUserOnlineState);
+    }
+
+    /**
+     * 修改用户上线情况
+     *
+     * @param fsUserOnlineState 用户上线情况
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserOnlineState(FsUserOnlineState fsUserOnlineState)
+    {
+        return baseMapper.updateFsUserOnlineState(fsUserOnlineState);
+    }
+
+    /**
+     * 批量删除用户上线情况
+     *
+     * @param userIds 需要删除的用户上线情况主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserOnlineStateByIds(Long[] userIds)
+    {
+        return baseMapper.deleteFsUserOnlineStateByIds(userIds);
+    }
+
+    /**
+     * 删除用户上线情况信息
+     *
+     * @param userId 用户上线情况主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserOnlineStateById(Long userId)
+    {
+        return baseMapper.deleteFsUserOnlineStateById(userId);
+    }
+
+    @Override
+    public void insertUserNotOnline() {
+        // 1、获取需要新增/更新的数据
+        // 获取当前所有没有看课记录的用户
+        List<FsUserOnlineState> fsUserOnlineStates = baseMapper.selectUserNotOnline();
+
+        // 2、分批次新增
+        this.batchInsertOnline(fsUserOnlineStates);
+
+        // 3、移除有看课记录的用户
+        List<FsUser> fsUsers = baseMapper.selectExistWatchLogUser();
+        List<Long> moveUserIds = fsUsers.stream().map(FsUser::getUserId).collect(Collectors.toList());
+        if(!moveUserIds.isEmpty()){
+            baseMapper.deleteFsUserOnlineStateByIds(moveUserIds.toArray(new Long[0]));
+        }
+
+    }
+
+    private void batchInsertOnline(List<FsUserOnlineState> list) {
+        // 分批次处理,一次提交500条
+        List<List<FsUserOnlineState>> batches = Lists.partition(list, 500);
+        batches.forEach(batch -> {
+            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
+            try {
+                FsUserOnlineStateMapper mapper = sqlSession.getMapper(FsUserOnlineStateMapper.class);
+                batch.forEach(mapper::insertFsUserOnlineState);
+                sqlSession.commit();
+            } finally {
+                sqlSession.close();
+            }
+        });
+    }
+}

+ 202 - 0
fs-service-system/src/main/resources/mapper/store/FsUserOnlineStateMapper.xml

@@ -0,0 +1,202 @@
+<?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.fs.store.mapper.FsUserOnlineStateMapper">
+
+    <resultMap type="FsUserOnlineState" id="FsUserOnlineStateResult">
+        <result property="id"    column="id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="nickname"    column="nickname"    />
+        <result property="avatar"    column="avatar"    />
+        <result property="phone"    column="phone"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="maOpenId"    column="ma_open_id"    />
+        <result property="mpOpenId"    column="mp_open_id"    />
+        <result property="unionId"    column="union_id"    />
+        <result property="status"    column="status"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="companyName"    column="company_name"    />
+        <result property="companyUserName"    column="company_user_name"    />
+        <result property="onlineStatus"    column="online_status"    />
+        <result property="onlineTime"    column="online_time"    />
+        <result property="watchCourseCount"    column="watch_course_count"    />
+        <result property="partCourseCount"    column="part_course_count"    />
+        <result property="lastWatchDate"    column="last_watch_date"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectFsUserOnlineStateVo">
+        select id, user_id, nickname, avatar, phone, create_time, ma_open_id, mp_open_id, union_id, status, company_id, company_user_id, company_name, company_user_name, online_status, online_time, watch_course_count, part_course_count, last_watch_date, update_time from fs_user_online_state
+    </sql>
+
+    <select id="selectFsUserOnlineStateList" parameterType="FsUserOnlineState" resultMap="FsUserOnlineStateResult">
+        <include refid="selectFsUserOnlineStateVo"/>
+        <where>
+            <if test="nickname != null  and nickname != ''"> and nickname like concat('%', #{nickname}, '%')</if>
+            <if test="avatar != null  and avatar != ''"> and avatar = #{avatar}</if>
+            <if test="phone != null  and phone != ''"> and phone like concat ('%', #{phone}, '%')</if>
+            <if test="maOpenId != null  and maOpenId != ''"> and ma_open_id = #{maOpenId}</if>
+            <if test="mpOpenId != null  and mpOpenId != ''"> and mp_open_id = #{mpOpenId}</if>
+            <if test="unionId != null  and unionId != ''"> and union_id = #{unionId}</if>
+            <if test="status != null "> and status = #{status}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="companyUserId != null "> and company_user_id = #{companyUserId}</if>
+            <if test="companyName != null and companyName !='' "> and company_name like concat('%', #{companyName}, '%')</if>
+            <if test="companyUserName != null and companyUserName !='' "> and company_user_name like concat('%', #{companyUserName}, '%')</if>
+            <if test="onlineStatus != null "> and online_status = #{onlineStatus}</if>
+            <if test="onlineTime != null "> and online_time = #{onlineTime}</if>
+            <if test="watchCourseCount != null "> and watch_course_count = #{watchCourseCount}</if>
+            <if test="partCourseCount != null "> and part_course_count = #{partCourseCount}</if>
+            <if test="lastWatchDate != null "> and last_watch_date = #{lastWatchDate}</if>
+            <if test="updateTime != null "> and update_time = #{updateTime}</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserOnlineStateById" parameterType="Long" resultMap="FsUserOnlineStateResult">
+        <include refid="selectFsUserOnlineStateVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertFsUserOnlineState" parameterType="FsUserOnlineState" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_user_online_state
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="userId != null">user_id,</if>
+            <if test="nickname != null">nickname,</if>
+            <if test="avatar != null">avatar,</if>
+            <if test="phone != null">phone,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="maOpenId != null">ma_open_id,</if>
+            <if test="mpOpenId != null">mp_open_id,</if>
+            <if test="unionId != null">union_id,</if>
+            <if test="status != null">status,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="companyName != null">company_name,</if>
+            <if test="companyUserName != null">company_user_name,</if>
+            <if test="onlineStatus != null">online_status,</if>
+            <if test="onlineTime != null">online_time,</if>
+            <if test="watchCourseCount != null">watch_course_count,</if>
+            <if test="partCourseCount != null">part_course_count,</if>
+            <if test="lastWatchDate != null">last_watch_date,</if>
+            <if test="updateTime != null ">update_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="userId != null">#{userId},</if>
+            <if test="nickname != null">#{nickname},</if>
+            <if test="avatar != null">#{avatar},</if>
+            <if test="phone != null">#{phone},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="maOpenId != null">#{maOpenId},</if>
+            <if test="mpOpenId != null">#{mpOpenId},</if>
+            <if test="unionId != null">#{unionId},</if>
+            <if test="status != null">#{status},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="companyName != null">#{companyName},</if>
+            <if test="companyUserName != null">#{companyUserName},</if>
+            <if test="onlineStatus != null">#{onlineStatus},</if>
+            <if test="onlineTime != null">#{onlineTime},</if>
+            <if test="watchCourseCount != null">#{watchCourseCount},</if>
+            <if test="partCourseCount != null">#{partCourseCount},</if>
+            <if test="lastWatchDate != null">#{lastWatchDate},</if>
+            <if test="updateTime != null ">#{updateTime},</if>
+         </trim>
+        on duplicate key update
+        <trim suffixOverrides=",">
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyName != null">company_Name = #{companyName},</if>
+            <if test="companyUserName != null">company_user_name = #{companyUserName},</if>
+            <if test="updateTime != null ">update_time = #{updateTime}</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsUserOnlineState" parameterType="FsUserOnlineState">
+        update fs_user_online_state
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="nickname != null">nickname = #{nickname},</if>
+            <if test="avatar != null">avatar = #{avatar},</if>
+            <if test="phone != null">phone = #{phone},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="maOpenId != null">ma_open_id = #{maOpenId},</if>
+            <if test="mpOpenId != null">mp_open_id = #{mpOpenId},</if>
+            <if test="unionId != null">union_id = #{unionId},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyName != null">company_Name = #{companyName},</if>
+            <if test="companyUserName != null">company_user_name = #{companyUserName},</if>
+            <if test="onlineStatus != null">online_status = #{onlineStatus},</if>
+            <if test="onlineTime != null">online_time = #{onlineTime},</if>
+            <if test="watchCourseCount != null">watch_course_count = #{watchCourseCount},</if>
+            <if test="partCourseCount != null">part_course_count = #{partCourseCount},</if>
+            <if test="lastWatchDate != null">last_watch_date = #{lastWatchDate},</if>
+            <if test="updateTime != null ">update_time = #{updateTime}</if>
+        </trim>
+        where user_id = #{userId}
+    </update>
+
+    <delete id="deleteFsUserOnlineStateById" parameterType="Long">
+        delete from fs_user_online_state where user_id = #{userId}
+    </delete>
+
+    <delete id="deleteFsUserOnlineStateByIds" parameterType="String">
+        delete from fs_user_online_state where user_id in
+        <foreach item="userId" collection="array" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+    </delete>
+
+    <select id="selectUserNotOnline" resultType="FsUserOnlineState">
+        SELECT
+            a.*,
+            company_user.nick_name as companyUserName,
+            company.company_name
+        FROM
+            (
+                SELECT
+                    user_id,
+                    nickname,
+                    avatar,
+                    phone,
+                    create_time,
+                    ma_open_id,
+                    mp_open_id,
+                    union_id,
+                    STATUS,
+                    company_id,
+                    company_user_id,
+                    2 AS onlineStatus,
+                    0 AS watchCourseCount,
+                    0 AS partCourseCount,
+                    NOW() AS updateTime
+                FROM
+                    fs_user
+                WHERE
+                    is_del = 0
+                  AND user_id NOT IN ( SELECT DISTINCT user_id FROM fs_course_watch_log WHERE send_type = 1 )
+            ) a
+                LEFT JOIN company_user ON company_user.user_id = a.company_user_id
+                LEFT JOIN company ON company.company_id = a.company_id
+    </select>
+
+    <select id="selectExistWatchLogUser" resultType="FsUser">
+        SELECT
+            count( 1 ),
+            fs_course_watch_log.user_id,
+            create_time
+        FROM
+            fs_course_watch_log
+        WHERE
+            send_type = 1
+        GROUP BY
+            fs_course_watch_log.user_id
+        HAVING
+            count( 1 ) = 1
+           AND create_time >= DATE_SUB( NOW(), INTERVAL 15 MINUTE )
+    </select>
+
+</mapper>