zyp пре 2 дана
родитељ
комит
41eeead37f

+ 76 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCompanyBind.java

@@ -0,0 +1,76 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户客服关联对象 fs_user_company_bind
+ *
+ * @author fs
+ * @date 2025-07-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserCompanyBind extends BaseEntity{
+
+    /** id */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long fsUserId;
+
+    /** 客服id */
+    @Excel(name = "客服id")
+    private Long companyUserId;
+
+    /** 公司ID */
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    /** 课程项目ID */
+    @Excel(name = "课程项目ID")
+    private Long projectId;
+
+    /** 企微用户ID */
+    @Excel(name = "企微用户ID")
+    private Long qwUserId;
+
+    /** 企微外部联系人ID */
+    @Excel(name = "企微外部联系人ID")
+    private Long qwExternalContactId;
+
+    /** 企微主体ID */
+    @Excel(name = "企微主体ID")
+    private Long qwCompanyId;
+
+    /** 课程ID */
+    @Excel(name = "课程ID")
+    private Long courseId;
+
+    /** 视频ID */
+    @Excel(name = "视频ID")
+    private Long videoId;
+
+    /** 看课记录ID */
+    private Long watchLogId;
+
+    /** 完课状态 */
+    @Excel(name = "完课状态")
+    private Integer logType;
+
+    /** 完课时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "完课时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private LocalDateTime finishTime;
+
+
+}

+ 66 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyBindMapper.java

@@ -0,0 +1,66 @@
+package com.fs.course.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsUserCompanyBind;
+import com.fs.course.vo.UserWatchLogListVo;
+import com.fs.qw.param.UserWatchLogParam;
+
+import java.util.List;
+
+/**
+ * 用户客服关联Mapper接口
+ *
+ * @author fs
+ * @date 2025-07-22
+ */
+public interface FsUserCompanyBindMapper extends BaseMapper<FsUserCompanyBind>{
+    /**
+     * 查询用户客服关联
+     *
+     * @param id 用户客服关联主键
+     * @return 用户客服关联
+     */
+    FsUserCompanyBind selectFsUserCompanyBindById(Long id);
+
+    /**
+     * 查询用户客服关联列表
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 用户客服关联集合
+     */
+    List<FsUserCompanyBind> selectFsUserCompanyBindList(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 新增用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    int insertFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 修改用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    int updateFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 删除用户客服关联
+     *
+     * @param id 用户客服关联主键
+     * @return 结果
+     */
+    int deleteFsUserCompanyBindById(Long id);
+
+    /**
+     * 批量删除用户客服关联
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserCompanyBindByIds(Long[] ids);
+
+    List<UserWatchLogListVo> getWatchLogList(UserWatchLogParam param);
+}

+ 84 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCompanyBindService.java

@@ -0,0 +1,84 @@
+package com.fs.course.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.domain.FsUserCompanyBind;
+import com.fs.course.vo.UserWatchLogListVo;
+import com.fs.qw.param.UserWatchLogParam;
+
+import java.util.List;
+
+/**
+ * 用户客服关联Service接口
+ *
+ * @author fs
+ * @date 2025-07-22
+ */
+public interface IFsUserCompanyBindService extends IService<FsUserCompanyBind>{
+    /**
+     * 查询用户客服关联
+     *
+     * @param id 用户客服关联主键
+     * @return 用户客服关联
+     */
+    FsUserCompanyBind selectFsUserCompanyBindById(Long id);
+
+    /**
+     * 查询用户客服关联列表
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 用户客服关联集合
+     */
+    List<FsUserCompanyBind> selectFsUserCompanyBindList(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 新增用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    int insertFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 修改用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    int updateFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind);
+
+    /**
+     * 批量删除用户客服关联
+     *
+     * @param ids 需要删除的用户客服关联主键集合
+     * @return 结果
+     */
+    int deleteFsUserCompanyBindByIds(Long[] ids);
+
+    /**
+     * 删除用户客服关联信息
+     *
+     * @param id 用户客服关联主键
+     * @return 结果
+     */
+    int deleteFsUserCompanyBindById(Long id);
+
+    /**
+     * 根据看课记录看课记录
+     * @param fsUserId       小程序用户ID
+     * @param externalUserId 外部联系人ID
+     * @param watchLogId     看课记录ID
+     */
+    boolean bindFsUser(Long fsUserId, Long externalUserId, Long watchLogId);
+
+    /**
+     * 更新完课装填
+     * @param fsUserId      小程序用户ID
+     * @param qwUserId      员工企微ID
+     * @param companyUserId 员工ID
+     * @param watchLog      看课记录
+     */
+    void finish(Long fsUserId, Long qwUserId, Long companyUserId, FsCourseWatchLog watchLog);
+
+    List<UserWatchLogListVo> getWatchLogList(UserWatchLogParam param);
+}

+ 247 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyBindServiceImpl.java

@@ -0,0 +1,247 @@
+package com.fs.course.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.PubFun;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.domain.FsUserCompanyBind;
+import com.fs.course.domain.FsUserCourse;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.mapper.FsUserCompanyBindMapper;
+import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.service.IFsUserCompanyBindService;
+import com.fs.course.vo.UserWatchLogListVo;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.qw.domain.QwCompany;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.mapper.QwCompanyMapper;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.param.UserWatchLogParam;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 用户客服关联Service业务层处理
+ *
+ * @author fs
+ * @date 2025-07-22
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class FsUserCompanyBindServiceImpl extends ServiceImpl<FsUserCompanyBindMapper, FsUserCompanyBind> implements IFsUserCompanyBindService {
+
+    private final CompanyUserMapper companyUserMapper;
+    private FsUserMapper fsUserMapper;
+    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
+    private QwExternalContactMapper qwExternalContactMapper;
+    private FsUserCourseMapper fsUserCourseMapper;
+    private QwCompanyMapper qwCompanyMapper;
+    private CompanyMapper companyMapper;
+
+    /**
+     * 查询用户客服关联
+     *
+     * @param id 用户客服关联主键
+     * @return 用户客服关联
+     */
+    @Override
+    public FsUserCompanyBind selectFsUserCompanyBindById(Long id) {
+        return baseMapper.selectFsUserCompanyBindById(id);
+    }
+
+    /**
+     * 查询用户客服关联列表
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 用户客服关联
+     */
+    @Override
+    public List<FsUserCompanyBind> selectFsUserCompanyBindList(FsUserCompanyBind fsUserCompanyBind) {
+        return baseMapper.selectFsUserCompanyBindList(fsUserCompanyBind);
+    }
+
+    /**
+     * 新增用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind) {
+        fsUserCompanyBind.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsUserCompanyBind(fsUserCompanyBind);
+    }
+
+    /**
+     * 修改用户客服关联
+     *
+     * @param fsUserCompanyBind 用户客服关联
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserCompanyBind(FsUserCompanyBind fsUserCompanyBind) {
+        fsUserCompanyBind.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsUserCompanyBind(fsUserCompanyBind);
+    }
+
+    /**
+     * 批量删除用户客服关联
+     *
+     * @param ids 需要删除的用户客服关联主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCompanyBindByIds(Long[] ids) {
+        return baseMapper.deleteFsUserCompanyBindByIds(ids);
+    }
+
+    /**
+     * 删除用户客服关联信息
+     *
+     * @param id 用户客服关联主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCompanyBindById(Long id) {
+        return baseMapper.deleteFsUserCompanyBindById(id);
+    }
+
+    @Override
+    public boolean bindFsUser(Long fsUserId, Long externalUserId, Long watchLogId) {
+        try {
+            QwExternalContact qwExternalContact = qwExternalContactMapper.selectById(externalUserId);
+            FsCourseWatchLog watchLog = fsCourseWatchLogMapper.selectById(watchLogId);
+            FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(watchLog.getCourseId());
+            Company company = companyMapper.selectCompanyById(qwExternalContact.getCompanyId());
+            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(qwExternalContact.getCorpId());
+            // 员工ID
+            Long companyUserId = qwExternalContact.getCompanyUserId();
+            // 公司ID
+            Long companyId = qwExternalContact.getCompanyId();
+            // 企微用户ID
+            Long qwUserId = qwExternalContact.getQwUserId();
+            // 项目
+            Long project = course.getProject() == null ? 0 : course.getProject();
+            // 企微主体ID
+            Long qwCompanyId = qwCompany.getId();
+            // 课程ID
+            Long courseId = watchLog.getCourseId();
+            // 视频ID
+            Long videoId = watchLog.getVideoId();
+            // 看课记录ID
+            Long logId = watchLog.getLogId();
+            // 看课状态
+            Integer logType = watchLog.getLogType();
+            if (company.getRepeat() == 1 && project != 0) {
+                List<FsUserCompanyBind> list = baseMapper.selectList(new QueryWrapper<FsUserCompanyBind>().eq("fs_user_id", fsUserId).eq("project_id", project).last(" GROUP BY qw_user_id"));
+                if (!list.isEmpty() && list.stream().noneMatch(e -> e.getQwUserId().equals(qwUserId))) {
+                    log.error("当前客户:{}已经有所属项目{}, 企微ID:{}, 当前企微ID:{}", fsUserId, project, PubFun.listToNewList(list, FsUserCompanyBind::getQwUserId), qwUserId);
+                    return false;
+                }
+            }
+            if (qwExternalContact.getUserRepeat() == 0) {
+                Integer i = baseMapper.selectCount(new QueryWrapper<FsUserCompanyBind>().eq("fs_user_id", fsUserId).ne("company_user_id", companyUserId));
+                if (i > 0) {
+                    qwExternalContact.setUserRepeat(1);
+                    qwExternalContactMapper.updateById(qwExternalContact);
+                }
+            }
+            // 当前登录账号名称
+            FsUserCompanyBind one = baseMapper.selectOne(new QueryWrapper<FsUserCompanyBind>()
+                    .eq("fs_user_id", fsUserId)
+                    .eq("project_id", project)
+                    .eq("course_id", courseId)
+                    .eq("qw_user_id", qwUserId)
+                    .eq("company_user_id", companyUserId)
+                    .eq("video_id", videoId));
+            if (one == null) {
+                FsUserCompanyBind bind = new FsUserCompanyBind();
+                bind.setFsUserId(fsUserId);
+                bind.setCompanyUserId(companyUserId);
+                bind.setCompanyId(companyId);
+                bind.setQwUserId(qwUserId);
+                bind.setQwExternalContactId(externalUserId);
+                bind.setProjectId(project);
+                bind.setQwCompanyId(qwCompanyId);
+                bind.setCourseId(courseId);
+                bind.setVideoId(videoId);
+                bind.setWatchLogId(logId);
+                bind.setLogType(logType);
+                bind.setCreateTime(new Date());
+                bind.setUpdateTime(new Date());
+                if (bind.getLogType() == 2) {
+                    bind.setFinishTime(LocalDateTime.now());
+                }
+                try {
+                    save(bind);
+                } catch (Exception e) {
+                    log.error("添加重粉失败", e);
+                }
+            }
+            return true;
+        }catch (Exception e){
+            log.error("绑定关系错误", e);
+            return false;
+        }
+    }
+
+    @Override
+    public void finish(Long fsUserId, Long qwUserId, Long companyUserId, FsCourseWatchLog watchLog) {
+        FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(watchLog.getCourseId());
+        FsUserCompanyBind one = baseMapper.selectOne(new QueryWrapper<FsUserCompanyBind>()
+                .eq("fs_user_id", fsUserId)
+                .eq("project_id", course.getProject())
+                .eq("course_id", watchLog.getCourseId())
+                .eq("qw_user_id", qwUserId)
+                .eq("company_user_id", companyUserId)
+                .eq("video_id", watchLog.getVideoId()));
+        if(one == null){
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
+            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(companyUser.getCorpId());
+            one = new FsUserCompanyBind();
+            one.setFsUserId(fsUserId);
+            one.setCompanyUserId(companyUserId);
+            one.setCompanyId(companyUser.getCompanyId());
+            one.setQwUserId(qwUserId);
+            one.setQwExternalContactId(watchLog.getQwExternalContactId());
+            one.setProjectId(course.getProject());
+            one.setQwCompanyId(qwCompany != null ? qwCompany.getId() : null);
+            one.setCourseId(watchLog.getCourseId());
+            one.setVideoId(watchLog.getVideoId());
+            one.setWatchLogId(watchLog.getLogId());
+            one.setLogType(2);
+            one.setFinishTime(LocalDateTime.now());
+            one.setCreateTime(new Date());
+            one.setUpdateTime(new Date());
+            try {
+                save(one);
+            } catch (Exception e) {
+                log.error("添加重粉失败", e);
+            }
+        }else{
+            one.setFinishTime(LocalDateTime.now());
+            one.setLogType(2);
+            updateById(one);
+        }
+    }
+
+    @Override
+    public List<UserWatchLogListVo> getWatchLogList(UserWatchLogParam param) {
+        if(param.getExternalUserId() == null &&  param.getFsUserId() == null){
+            return Collections.emptyList();
+        }
+        return baseMapper.getWatchLogList(param);
+    }
+}

+ 10 - 19
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -32,6 +32,7 @@ import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.*;
+import com.fs.course.service.IFsUserCompanyBindService;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.service.IFsVideoResourceService;
@@ -236,6 +237,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     ConfigUtil configUtil;
 
+    @Autowired
+    private IFsUserCompanyBindService fsUserCompanyBindService;
+
 
 
     /**
@@ -782,6 +786,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
             iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId,param.getUserId());
 
+            fsUserCompanyBindService.bindFsUser(param.getUserId(), qwExternalId, log.getLogId());
+
+
 
             if (param.getLinkType()!=null&&param.getLinkType()==5){
                 FsCourseLink fsCourseLink = fsCourseLinkMapper.selectExpireLinkByQwExternalId(param.getQwUserId(), param.getVideoId(), qwExternalId);
@@ -806,25 +813,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             user.setQwExtId(param.getQwExternalId());
             fsUserMapper.updateFsUser(user);
 
-
-//            //小访客特有
-//            SendXfkParam xfkParam=new SendXfkParam();
-//            xfkParam.setCorpId(externalContact.getCorpId());
-//            xfkParam.setUserId(externalContact.getUserId());
-//            xfkParam.setName(externalContact.getName());
-//            xfkParam.setAddWay(externalContact.getAddWay());
-//            xfkParam.setState(externalContact.getState());
-//            if (externalContact.getCreateTime()!=null){
-//                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-//                String formattedTime = sdf.format(externalContact.getCreateTime());
-//                xfkParam.setCreateTime(formattedTime);
-//            }else {
-//                xfkParam.setCreateTime("");
-//            }
-//
-//
-//            xfkService.executeSopByIds(xfkParam);
-
             iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId,param.getUserId());
 
             //绑定上之后 更新观看记录
@@ -836,6 +824,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             log.setUpdateTime(new Date());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
 
+            fsUserCompanyBindService.bindFsUser(param.getUserId(), qwExternalId, log.getLogId());
+
+
             if (param.getLinkType()!=null&&param.getLinkType()==5){
                 FsCourseLink fsCourseLink = fsCourseLinkMapper.selectExpireLinkByQwExternalId(param.getQwUserId(), param.getVideoId(), qwExternalId);
                 return R.error(566,"官方群发通用链接").put("courseLink",fsCourseLink);

+ 30 - 0
fs-service/src/main/java/com/fs/course/vo/UserWatchLogListVo.java

@@ -0,0 +1,30 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 课程对象 fs_user_course
+ *
+ * @author fs
+ * @date 2024-05-15
+ */
+@Data
+public class UserWatchLogListVo {
+
+    private Integer logType;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime finishTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+    private String fsUserName;
+    private String projectName;
+    private String courseName;
+    private String videoName;
+    private String qwUserName;
+
+}

+ 14 - 0
fs-service/src/main/java/com/fs/qw/param/UserWatchLogParam.java

@@ -0,0 +1,14 @@
+package com.fs.qw.param;
+
+import lombok.Data;
+
+@Data
+public class UserWatchLogParam {
+
+    private Long externalUserId;
+    private Long courseId;
+    private Long videoId;
+    private Long userId;
+    private Long fsUserId;
+
+}

+ 2 - 2
fs-service/src/main/resources/application-config-myhk.yml

@@ -88,8 +88,8 @@ ipad:
   ipadUrl: http://qwipad.muyi88.com
 #  aiApi: http://152.136.202.157:3000/api
   aiApi: http://49.232.181.28:3000/api
-  voiceApi:
-  commonApi:
+  voiceApi: http://106.52.21.84:8009
+  commonApi: http://106.52.21.84:7771
 wx_miniapp_temp:
   pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
   inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I

+ 162 - 0
fs-service/src/main/resources/mapper/course/FsUserCompanyBindMapper.xml

@@ -0,0 +1,162 @@
+<?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.course.mapper.FsUserCompanyBindMapper">
+
+    <resultMap type="FsUserCompanyBind" id="FsUserCompanyBindResult">
+        <result property="id"    column="id"    />
+        <result property="fsUserId"    column="fs_user_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="projectId"    column="project_id"    />
+        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="qwExternalContactId"    column="qw_external_contact_id"    />
+        <result property="qwCompanyId"    column="qw_company_id"    />
+        <result property="courseId"    column="course_id"    />
+        <result property="videoId"    column="video_id"    />
+        <result property="watchLogId"    column="watch_log_id"    />
+        <result property="logType"    column="log_type"    />
+        <result property="finishTime"    column="finish_time"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="remark"    column="remark"    />
+    </resultMap>
+
+    <sql id="selectFsUserCompanyBindVo">
+        select id, fs_user_id, company_user_id, company_id, project_id, qw_user_id, qw_external_contact_id, qw_company_id, course_id, video_id, watch_log_id, log_type, finish_time, create_time, create_by, update_by, update_time, remark from fs_user_company_bind
+    </sql>
+
+    <select id="selectFsUserCompanyBindList" parameterType="FsUserCompanyBind" resultMap="FsUserCompanyBindResult">
+        <include refid="selectFsUserCompanyBindVo"/>
+        <where>
+            <if test="fsUserId != null "> and fs_user_id = #{fsUserId}</if>
+            <if test="companyUserId != null "> and company_user_id = #{companyUserId}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="projectId != null "> and project_id = #{projectId}</if>
+            <if test="qwUserId != null "> and qw_user_id = #{qwUserId}</if>
+            <if test="qwExternalContactId != null "> and qw_external_contact_id = #{qwExternalContactId}</if>
+            <if test="qwCompanyId != null "> and qw_company_id = #{qwCompanyId}</if>
+            <if test="courseId != null "> and course_id = #{courseId}</if>
+            <if test="videoId != null "> and video_id = #{videoId}</if>
+            <if test="logType != null "> and log_type = #{logType}</if>
+            <if test="finishTime != null "> and finish_time = #{finishTime}</if>
+        </where>
+    </select>
+
+    <select id="selectFsUserCompanyBindById" parameterType="Long" resultMap="FsUserCompanyBindResult">
+        <include refid="selectFsUserCompanyBindVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertFsUserCompanyBind" parameterType="FsUserCompanyBind" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_user_company_bind
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="fsUserId != null">fs_user_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="projectId != null">project_id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="qwExternalContactId != null">qw_external_contact_id,</if>
+            <if test="qwCompanyId != null">qw_company_id,</if>
+            <if test="courseId != null">course_id,</if>
+            <if test="videoId != null">video_id,</if>
+            <if test="watchLogId != null">watch_log_id,</if>
+            <if test="logType != null">log_type,</if>
+            <if test="finishTime != null">finish_time,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="remark != null">remark,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="fsUserId != null">#{fsUserId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="projectId != null">#{projectId},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="qwExternalContactId != null">#{qwExternalContactId},</if>
+            <if test="qwCompanyId != null">#{qwCompanyId},</if>
+            <if test="courseId != null">#{courseId},</if>
+            <if test="videoId != null">#{videoId},</if>
+            <if test="watchLogId != null">#{watchLogId},</if>
+            <if test="logType != null">#{logType},</if>
+            <if test="finishTime != null">#{finishTime},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="remark != null">#{remark},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsUserCompanyBind" parameterType="FsUserCompanyBind">
+        update fs_user_company_bind
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="fsUserId != null">fs_user_id = #{fsUserId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="projectId != null">project_id = #{projectId},</if>
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="qwExternalContactId != null">qw_external_contact_id = #{qwExternalContactId},</if>
+            <if test="qwCompanyId != null">qw_company_id = #{qwCompanyId},</if>
+            <if test="courseId != null">course_id = #{courseId},</if>
+            <if test="videoId != null">video_id = #{videoId},</if>
+            <if test="watchLogId != null">watch_log_id = #{watchLogId},</if>
+            <if test="logType != null">log_type = #{logType},</if>
+            <if test="finishTime != null">finish_time = #{finishTime},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="remark != null">remark = #{remark},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsUserCompanyBindById" parameterType="Long">
+        delete from fs_user_company_bind where id = #{id}
+    </delete>
+
+    <delete id="deleteFsUserCompanyBindByIds" parameterType="String">
+        delete from fs_user_company_bind where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="getWatchLogList" resultType="com.fs.course.vo.UserWatchLogListVo">
+        select
+        a.*,
+        b.nick_name fsUserName,
+        c.dict_label projectName,
+        e.course_name,
+        IF(g.company_user_id = #{userId}, g.qw_user_name, '其他') qwUserName,
+        f.title videoName
+        from
+        fs_user_company_bind a
+        left join fs_user b on a.fs_user_id = b.user_id
+        left join sys_dict_data c on c.dict_type = 'sys_course_project' and dict_value = a.project_id
+        left join fs_user_course e on a.course_id = e.course_id
+        left join fs_user_course_video f on a.video_id = f.video_id
+        left join qw_user g on g.id = a.qw_user_id
+        <where>
+            <if test="externalUserId != null">
+                and a.qw_external_contact_id = #{externalUserId}
+            </if>
+            <if test="fsUserId != null">
+                and a.fs_user_id = #{fsUserId}
+            </if>
+            <if test="courseId != null">
+                and a.course_id = #{courseId}
+            </if>
+            <if test="videoId != null">
+                and a.video_id = #{videoId}
+            </if>
+        </where>
+        order by create_time desc
+    </select>
+</mapper>