Переглянути джерело

1、直播记录:直播数,看播记录,看播时长,领奖记录(时间点)出处、积分,优惠券查看。核销明细
点播记录:企微侧边栏内容

yys 4 днів тому
батько
коміт
d4b320c3cd
20 змінених файлів з 551 додано та 9 видалено
  1. 5 0
      fs-service/src/main/java/com/fs/live/domain/LiveWatchConfig.java
  2. 8 0
      fs-service/src/main/java/com/fs/live/mapper/LiveMapper.java
  3. 34 4
      fs-service/src/main/java/com/fs/live/mapper/LiveWatchUserMapper.java
  4. 21 0
      fs-service/src/main/java/com/fs/live/param/LiveWatchUserDetailParam.java
  5. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveWatchUserService.java
  6. 43 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java
  7. 44 0
      fs-service/src/main/java/com/fs/live/vo/LiveWatchUserDetailVO.java
  8. 8 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  9. 4 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  10. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java
  11. 2 0
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  12. 5 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  13. 5 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  14. 2 0
      fs-service/src/main/java/com/fs/qwApi/param/QwExternalContactHParam.java
  15. 4 1
      fs-service/src/main/resources/mapper/live/LiveMapper.xml
  16. 12 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  17. 108 0
      fs-user-app/src/main/java/com/fs/app/controller/AppBaseController.java
  18. 58 0
      fs-user-app/src/main/java/com/fs/app/controller/app/AppQwStatisticsController.java
  19. 158 0
      fs-user-app/src/main/java/com/fs/app/controller/app/AppQwUserController.java
  20. 26 0
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveWatchUserController.java

+ 5 - 0
fs-service/src/main/java/com/fs/live/domain/LiveWatchConfig.java

@@ -53,6 +53,11 @@ public class LiveWatchConfig extends BaseEntity{
      */
     private Object completionTypes;
 
+    /**
+     * 完课要求百分比 观看时长占直播总时长的比例
+     */
+    private Long completionRate;
+
     /** 领取提示语 */
     @Excel(name = "领取提示语")
     private String receivePrompt;

+ 8 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveMapper.java

@@ -29,6 +29,14 @@ public interface LiveMapper
     @DataSource(DataSourceType.SLAVE)
     public Live selectLiveByLiveId(Long liveId);
 
+    /**
+     * 查询直播
+     *
+     * @param liveId 直播主键
+     * @return 直播
+     */
+    public Live selectLiveByLiveIdNotDel(Long liveId);
+
     /**
      * 查询企业直播
      * @param liveId        直播间ID

+ 34 - 4
fs-service/src/main/java/com/fs/live/mapper/LiveWatchUserMapper.java

@@ -4,10 +4,7 @@ package com.fs.live.mapper;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.live.domain.LiveWatchUser;
-import com.fs.live.vo.LiveDashBoardDataVo;
-import com.fs.live.vo.LiveWatchUserEntry;
-import com.fs.live.vo.LiveWatchUserStatistics;
-import com.fs.live.vo.LiveWatchUserVO;
+import com.fs.live.vo.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
@@ -179,4 +176,37 @@ public interface LiveWatchUserMapper {
      * @return 插入的记录数
      */
     int batchInsertLiveWatchUser(@Param("list") List<LiveWatchUser> liveWatchUsers);
+
+    @Select("SELECT\n" +
+            "  lwu.live_id,\n" +
+            "  lv.live_img_url,\n" +
+            "  lv.live_name,\n" +
+            "  u.user_id AS userId,\n" +
+            "  COALESCE(u.nickname, u.nick_name, '未知用户') AS userName,\n" +
+            "  COALESCE(SUM(CASE WHEN lwu.live_flag = 1 AND lwu.replay_flag = 0 THEN lwu.online_seconds ELSE 0 END), 0) AS liveWatchDuration,\n" +
+            "  COALESCE(SUM(CASE WHEN lwu.live_flag = 0 AND lwu.replay_flag = 1 THEN lwu.online_seconds ELSE 0 END), 0) AS playbackWatchDuration,\n" +
+            "  COALESCE(c.company_name, '') AS companyName,\n" +
+            "  COALESCE(cu.user_name, '') AS salesName,\n" +
+            "  MAX(lwu.reward_type) AS rewardType,\n" +
+            "  lwu.update_time \n" +
+            "FROM\n" +
+            "  live_watch_user lwu\n" +
+            "  LEFT JOIN live lv on lwu.live_id= lv.live_id\n" +
+            "  LEFT JOIN fs_user u ON lwu.user_id = u.user_id\n" +
+            "  LEFT JOIN live_user_first_entry lufe ON lwu.live_id = lufe.live_id\n" +
+            "  AND lwu.user_id = lufe.user_id\n" +
+            "  LEFT JOIN company c ON lufe.company_id = c.company_id\n" +
+            "  LEFT JOIN company_user cu ON lufe.company_user_id = cu.user_id\n" +
+            "WHERE\n" +
+            "  lwu.user_id = #{userId}\n" +
+            "GROUP BY\n" +
+            "  lwu.live_id,\n" +
+            "  u.user_id,\n" +
+            "  u.nick_name,\n" +
+            "  u.nickname ,\n" +
+            "  c.company_name,\n" +
+            "  cu.user_name\n" +
+            "ORDER BY\n" +
+            "  liveWatchDuration DESC")
+    List<LiveWatchUserDetailVO> getLiveWatchUserDetail(@Param("userId") Long userId);
 }

+ 21 - 0
fs-service/src/main/java/com/fs/live/param/LiveWatchUserDetailParam.java

@@ -0,0 +1,21 @@
+package com.fs.live.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class LiveWatchUserDetailParam  {
+    /**
+    * 用户的id
+    */
+    private Long userId;
+    /**
+    * 销售账号id
+    */
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "页码,默认为1")
+    private Integer pageNum =1;
+    @ApiModelProperty(value = "页大小,默认为100")
+    private Integer pageSize = 100;
+}

+ 2 - 0
fs-service/src/main/java/com/fs/live/service/ILiveWatchUserService.java

@@ -5,6 +5,7 @@ import com.fs.common.core.domain.R;
 import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.live.domain.LiveWatchUser;
 import com.fs.live.param.LiveIsAddKfParam;
+import com.fs.live.vo.LiveWatchUserDetailVO;
 import com.fs.live.vo.LiveWatchUserEntry;
 import com.fs.live.vo.LiveWatchUserVO;
 
@@ -130,6 +131,7 @@ public interface ILiveWatchUserService {
     LiveWatchUser selectLiveWatchUserByFlag(Long liveId, Long userId, Integer liveFlag, Integer replayFlag);
 
     R liveIsAddKf(LiveIsAddKfParam param);
+    List<LiveWatchUserDetailVO> getLiveWatchUserDetail(Long userId);
 
     LiveWatchUserEntry selectLiveWatchAndCompanyUserByFlag(Long liveId, Long userId, Integer liveFlag, Integer replayFlag);
 

+ 43 - 4
fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java

@@ -20,10 +20,7 @@ import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsUserService;
 import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.service.IFsUserScrmService;
-import com.fs.live.domain.Live;
-import com.fs.live.domain.LiveVideo;
-import com.fs.live.domain.LiveWatchLog;
-import com.fs.live.domain.LiveWatchUser;
+import com.fs.live.domain.*;
 import com.fs.live.mapper.*;
 import com.fs.live.param.LiveIsAddKfParam;
 import com.fs.live.service.ILiveWatchUserService;
@@ -1460,4 +1457,46 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
         return value != null ? value : 0L;
     }
 
+
+
+    @Override
+    public List<LiveWatchUserDetailVO> getLiveWatchUserDetail(Long userId) {
+        List<LiveWatchUserDetailVO> liveWatchUserDetail = baseMapper.getLiveWatchUserDetail(userId);
+        liveWatchUserDetail.forEach(item->{
+            Live live = liveMapper.selectLiveByLiveIdNotDel(item.getLiveId());
+            LiveWatchConfig config = JSON.parseObject(live.getConfigJson(), LiveWatchConfig.class);
+            item.setLiveStatus(live.getStatus());
+            if (config!=null && config.getEnabled() && 3 == config.getParticipateCondition()) {
+
+                Long completionRate = config.getCompletionRate();
+
+                //根据直播间id 查询 直播视频时长,来判断是否 完课
+                List<LiveVideo> videos = liveVideoMapper.selectByLiveId(item.getLiveId());
+                //视频时长
+                Long videoDuration = videos.stream()
+                        .filter(v -> v.getVideoType() != null && (v.getVideoType() == 1 || v.getVideoType() == 2))
+                        .mapToLong(v -> v.getDuration() != null ? v.getDuration() : 0L)
+                        .sum();
+
+                // 视频时长 * 100 作为完课阈值
+                long threshold = videoDuration * completionRate;
+
+                long liveWatch = item.getLiveWatchDuration() != null ? item.getLiveWatchDuration() : 0L;
+                long playbackWatch = item.getPlaybackWatchDuration() != null ? item.getPlaybackWatchDuration() : 0L;
+
+                boolean liveCompleted = liveWatch * 100 >= threshold ;
+                boolean playbackCompleted = playbackWatch * 100 >= threshold;
+
+                item.setIsCompleted(liveCompleted || playbackCompleted ? 1 : 0);
+
+            }
+
+
+
+        });
+
+
+        return liveWatchUserDetail;
+    }
+
 }

+ 44 - 0
fs-service/src/main/java/com/fs/live/vo/LiveWatchUserDetailVO.java

@@ -0,0 +1,44 @@
+package com.fs.live.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+@Data
+public class LiveWatchUserDetailVO {
+
+    private Long userId;
+
+    private String userName;
+
+    private Long LiveId;
+
+    private String LiveName;
+    private String liveImgUrl;
+
+    /** 对应的分公司 */
+    private String companyName;
+
+    /** 分公司的销售是谁 */
+    private String salesName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String updateTime;
+
+    /** 今天看了直播多长时间(秒) */
+    private Long liveWatchDuration = 0L;
+
+    /** 看了回放多长时间(秒) */
+    private Long playbackWatchDuration = 0L;
+
+    /**
+     * 是否领取奖励 1红包 2积分 3没设置
+     */
+    private Integer rewardType;
+
+    /** 是否完课 1是 0否 */
+    private Integer isCompleted;
+    /**
+    * 直播间是否删除 1 是 0否
+    */
+    private Integer liveStatus;
+}

+ 8 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -685,4 +685,12 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
 
     QwExternalContact selectQwExternalContactLastByFsUserAndCompany(@Param("companyUserId") Long companyUserId,
                                                                     @Param("userId") String userId);
+    @Select("SELECT id,external_user_id,name,avatar,remark,description,fs_user_id FROM  qw_external_contact " +
+            "WHERE user_id = #{map.userId}   " +
+            "AND corp_id =#{map.corpId} " +
+            "AND fs_user_id = #{map.fsUserId} " +
+            "AND `status` != 4 " +
+            "ORDER BY id desc " +
+            "limit 1 ")
+    QwExternalContact getQwExternalContactDetail(@Param("map")QwExternalContactHParam param);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -538,4 +538,8 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     List<Long> selectIdByCompanyUserId(@Param("companyUserId")Long companyUserId);
 
     List<QwUserCompanyDTO> selectQwUserCompanyDTOByCompanyUserId(Long companyUserId);
+
+
+    List<QwUserVO> selectQwUserListByCompanyUserIdAndFsUserId(@Param("companyUserId")Long companyUserId,@Param("fsUserId") Long fsUserId);
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java

@@ -297,4 +297,6 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
     List<SalesAppDownloadStatDTO> exportSalesAppDownloadStats(AppDownloadParam param);
 
     QwExternalContact selectQwExternalContactLastByFsUserAndCompany(Long companyUserId, String userId);
+
+    QwExternalContact getQwExternalContactDetail(QwExternalContactHParam param);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/service/IQwUserService.java

@@ -231,4 +231,6 @@ public interface IQwUserService
     QwUserVO getQwUserCompanyInfo(Long qwUserId);
 
     List<QwUserCompanyDTO> selectQwUserCompanyDTOByCompanyUserId(Long companyUserId);
+
+    List<QwUserVO> selectQwUserListByCompanyUserIdAndFsUserId(Long companyUserId,Long fsUserId);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -6218,4 +6218,9 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
     public QwExternalContact selectQwExternalContactLastByFsUserAndCompany(Long companyUserId, String userId) {
         return qwExternalContactMapper.selectQwExternalContactLastByFsUserAndCompany(companyUserId,userId);
     }
+
+    @Override
+    public QwExternalContact getQwExternalContactDetail(QwExternalContactHParam param) {
+        return qwExternalContactMapper.getQwExternalContactDetail(param);
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -1801,4 +1801,9 @@ public class QwUserServiceImpl implements IQwUserService
     public QwUserVO getQwUserCompanyInfo(Long qwUserId) {
         return qwUserMapper.getQwUserCompanyInfo( qwUserId);
     }
+
+    @Override
+    public List<QwUserVO> selectQwUserListByCompanyUserIdAndFsUserId(Long companyUserId, Long fsUserId) {
+        return qwUserMapper.selectQwUserListByCompanyUserIdAndFsUserId(companyUserId,fsUserId);
+    }
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qwApi/param/QwExternalContactHParam.java

@@ -11,4 +11,6 @@ public class QwExternalContactHParam {
     private  String externalUserId;
 
     private  String corpId;
+
+    private  Long fsUserId;
 }

+ 4 - 1
fs-service/src/main/resources/mapper/live/LiveMapper.xml

@@ -115,7 +115,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectLiveVo"/>
         where live_id = #{liveId}
     </select>
-
+    <select id="selectLiveByLiveIdNotDel" parameterType="Long" resultMap="LiveResult">
+        <include refid="selectLiveVo"/>
+        where live_id = #{liveId}
+    </select>
     <select id="selectLiveByLiveIdAndCompanyIdAndCompanyUserId" resultMap="LiveResult">
         <include refid="selectLiveVo"/>
         where live_id = #{liveId} and company_id = #{companyId} and company_user_id = #{companyUserId}

+ 12 - 0
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -385,4 +385,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select * from qw_user where company_user_id = #{companyUserId}
     </select>
 
+    <select id="selectQwUserListByCompanyUserIdAndFsUserId" resultType="com.fs.qw.vo.QwUserVO">
+        select
+            qu.*,
+            qc.corp_name
+        from qw_user qu
+                 inner join qw_company qc on qu.corp_id = qc.corp_id
+                 left join qw_external_contact qwe on qu.qw_user_id = qwe.user_id
+        where qu.is_del = 0 and qu.app_key is not null
+          AND qwe.fs_user_id =#{fsUserId}
+          and qu.company_user_id = #{companyUserId}
+    </select>
+
 </mapper>

+ 108 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -13,6 +13,10 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.sql.SqlUtil;
+import com.fs.company.domain.CompanyUserUser;
+import com.fs.company.service.ICompanyUserUserService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsUserService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.jsonwebtoken.Claims;
@@ -28,6 +32,11 @@ public class AppBaseController {
 	@Autowired
     public RedisCache redisCache;
 
+	@Autowired
+	private ICompanyUserUserService companyUserUserService;
+
+	@Autowired
+	private IFsUserService userService;
 	public String getUserId()
 	{
 		Object userId = ServletUtils.getRequest().getAttribute("userId");
@@ -62,6 +71,24 @@ public class AppBaseController {
 		}
 		throw new CustomException("未登录", 403);
 	}
+	/**
+	 * 销售登录的token(登录进去是手动看课的)
+	 */
+	public String getCompanyUserCourseId( )
+	{
+		String companyUserId = ServletUtils.getRequest().getHeader("corpUserCourseToken");
+		if (StringUtils.isNotEmpty(companyUserId)){
+			Claims claims=jwtUtils.getClaimByToken(companyUserId);
+			if(claims!=null){
+				String userId = claims.getSubject().toString();
+				return userId;
+			}
+			else{
+				return null;
+			}
+		}
+		return null;
+	}
 
 	/**
 	 * 设置请求分页数据
@@ -131,4 +158,85 @@ public class AppBaseController {
 		return AjaxResult.error();
 	}
 
+	/** C 端本人,或销售名下客户(CompanyUserToken fs_user_id和company_user_id之间的绑定关系) */
+	protected R denyIfCannotAccessFsUser(Long fsUserId) {
+		if (fsUserId == null) {
+			return R.error("非法操作");
+		}
+		if (isCurrentUser(fsUserId)) {
+			return null;
+		}
+		try {
+			Long companyUserId = Long.parseLong(getCompanyUserCourseId());
+			CompanyUserUser query = new CompanyUserUser();
+			query.setCompanyUserId(companyUserId);
+			query.setUserId(fsUserId);
+			List<CompanyUserUser> bindings = companyUserUserService.selectCompanyUserUserList(query);
+			if (bindings != null && !bindings.isEmpty()) {
+				return null;
+			}
+		} catch (CustomException ignored) {
+		}
+		return R.error("非法操作");
+	}
+
+
+	protected boolean isCurrentUser(Long userId) {
+		if (userId == null || StringUtils.isEmpty(getUserId())) {
+			return false;
+		}
+		return userId.equals(Long.parseLong(getUserId()));
+	}
+
+
+	protected R denyIfNotCurrentUser(Long userId) {
+		if (!isCurrentUser(userId)) {
+			return R.error("非法操作");
+		}
+		return null;
+	}
+
+	/**
+	* 互医 客服登录(问诊 套餐包订单版)
+	*/
+	protected R denyIfNotCurrentCompanyUser(Long companyUserId) {
+		if (!isCurrentCompanyUser(companyUserId)) {
+			return R.error("非法操作");
+		}
+		return null;
+	}
+
+
+	protected boolean isCurrentCompanyUser(Long companyUserId) {
+		if (companyUserId == null) {
+			return false;
+		}
+		try {
+			return companyUserId.equals(getCompanyUserId());
+		} catch (CustomException e) {
+			return false;
+		}
+	}
+
+	/**
+	 * 销售登录(app手动发课版)
+	 */
+	protected R denyIfNotCurrentCourseCompanyUser(Long companyUserId) {
+		if (!isCurrentCourseCompanyUser(companyUserId)) {
+			return R.error("非法操作");
+		}
+		return null;
+	}
+
+	protected boolean isCurrentCourseCompanyUser(Long companyUserId) {
+		if (companyUserId == null) {
+			return false;
+		}
+		try {
+			return companyUserId.equals(Long.parseLong(getCompanyUserCourseId()));
+		} catch (CustomException e) {
+			return false;
+		}
+	}
+
 }

+ 58 - 0
fs-user-app/src/main/java/com/fs/app/controller/app/AppQwStatisticsController.java

@@ -0,0 +1,58 @@
+package com.fs.app.controller.app;
+
+import com.fs.app.annotation.Login;
+import com.fs.app.controller.AppBaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qwApi.param.QwExternalContactHParam;
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
+import com.fs.statistics.service.IStatisticsService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * app客户个人侧边栏-企微统计数据
+ */
+@RestController
+@RequestMapping("/app/qw/statistics")
+public class AppQwStatisticsController extends AppBaseController {
+    @Autowired
+    private IStatisticsService statisticsService;
+
+    @Autowired
+    private IQwExternalContactService iQwExternalContactService;
+
+    @Login
+    @PostMapping("/course/watch")
+    @ApiOperation("会员看课详情")
+    public R queryCourseWatchStatistics(@RequestParam(value = "userId", required = false) String userId,
+                                        @RequestParam(value = "corpId", required = false) String corpId,
+                                        @RequestParam(value = "fsUserId", required = false) Long fsUserId,
+                                        @RequestParam(value = "type", required = false) Integer type) {
+        R denied = denyIfCannotAccessFsUser(fsUserId);
+        if (denied != null) {
+            return denied;
+        }
+        QwExternalContactHParam qwExternalContactHParam = new QwExternalContactHParam();
+        qwExternalContactHParam.setUserId(userId);
+        qwExternalContactHParam.setCorpId(corpId);
+        qwExternalContactHParam.setFsUserId(fsUserId);
+        QwExternalContact qwExternalContact = iQwExternalContactService.getQwExternalContactDetail(qwExternalContactHParam);
+        if (qwExternalContact == null || qwExternalContact.getId() == null) {
+            throw new CustomException("未查询到对应的外部联系人");
+        }
+        WatchCourseStatisticsParam param = new WatchCourseStatisticsParam();
+        param.setType(type);
+        param.setQwExternalContactId(qwExternalContact.getId());
+        WatchCourseStatisticsDTO watchCourseStatisticsDTO = statisticsService.queryWatchCourse(param);
+        return R.ok().put("data", watchCourseStatisticsDTO);
+    }
+
+}

+ 158 - 0
fs-user-app/src/main/java/com/fs/app/controller/app/AppQwUserController.java

@@ -0,0 +1,158 @@
+package com.fs.app.controller.app;
+
+import com.fs.app.annotation.Login;
+import com.fs.app.controller.AppBaseController;
+import com.fs.common.BeanCopyUtils;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.company.service.ICompanyUserUserService;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwExternalContactInfo;
+import com.fs.qw.domain.QwTagGroup;
+import com.fs.qw.param.sidebar.TagGroupListParam;
+import com.fs.qw.param.sidebar.TagGroupUpdateParam;
+import com.fs.qw.service.IQwExternalContactInfoService;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwTagGroupService;
+import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwTagGroupListVO;
+import com.fs.qw.vo.QwUserVO;
+import com.fs.qw.vo.sidebar.ExternalContactInfoVO;
+import com.fs.qw.vo.sidebar.ExternalContactTagVO;
+import com.fs.qwApi.param.QwExternalContactHParam;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+* app的客户个人侧边栏
+*/
+@RestController
+@RequestMapping("/app/qw/user")
+public class AppQwUserController extends AppBaseController {
+
+    @Autowired
+    private IQwUserService qwUserService;
+    @Autowired
+    private IQwExternalContactInfoService qwExternalContactInfoService;
+    @Autowired
+    private IQwExternalContactService iQwExternalContactService;
+    @Autowired
+    private IQwTagGroupService qwTagGroupService;
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private ICompanyUserUserService companyUserUserService;
+
+    @Login
+    @PostMapping("/list")
+    @ApiOperation("获取企微用户对应的主体")
+    public R getQwUserList(@RequestParam(value = "companyUserId", required = false) Long companyUserId,
+                           @RequestParam(value = "fsUserId", required = false) Long fsUserId) {
+        if (companyUserId != null) {
+            R denied = denyIfNotCurrentCourseCompanyUser(companyUserId);
+            if (denied != null) {
+                return denied;
+            }
+        }
+        if (fsUserId == null) {
+            return  R.error("客户id不能为空");
+        }
+        List<QwUserVO> qwUsers = qwUserService.selectQwUserListByCompanyUserIdAndFsUserId(companyUserId, fsUserId);
+        return R.ok().put("data", qwUsers);
+    }
+
+    @Login
+    @GetMapping("/getQwUserInfo")
+    @ApiOperation("获取企微用户ai信息")
+    public R getQwUserInfo(@RequestParam(value = "userId", required = false) String userId,
+                           @RequestParam(value = "corpId", required = false) String corpId,
+                           @RequestParam(value = "fsUserId", required = false) Long fsUserId) {
+        R denied = denyIfCannotAccessFsUser(fsUserId);
+        if (denied != null) {
+            return denied;
+        }
+        QwExternalContactHParam qwExternalContactHParam = new QwExternalContactHParam();
+        qwExternalContactHParam.setUserId(userId);
+        qwExternalContactHParam.setCorpId(corpId);
+        qwExternalContactHParam.setFsUserId(fsUserId);
+        QwExternalContact qwExternalContact = iQwExternalContactService.getQwExternalContactDetail(qwExternalContactHParam);
+        if (qwExternalContact == null) {
+            return R.ok().put("data", qwExternalContact);
+        }
+        if (qwExternalContact.getId() == null) {
+            throw new CustomException("企微外部联系人id不能为空!");
+        }
+
+        QwExternalContactInfo contactInfo = qwExternalContactInfoService.selectQwExternalContactInfoByExternalContactId(qwExternalContact.getId());
+        if (contactInfo == null) {
+            contactInfo = new QwExternalContactInfo();
+            contactInfo.setExternalContactId(qwExternalContact.getId());
+            qwExternalContactInfoService.insertQwExternalContactInfo(contactInfo);
+        }
+        return R.ok().put("data", contactInfo);
+    }
+
+    @Login
+    @PostMapping("/UpdateQwUserInfo")
+    @ApiOperation("修改企微用户信息")
+    public R updateQwUserInfo(@RequestBody QwExternalContactInfo qwExternalContact) {
+        if (qwExternalContact.getExternalContactId() != null) {
+            QwExternalContact contact = iQwExternalContactService.selectQwExternalContactById(qwExternalContact.getExternalContactId());
+            if (contact != null && contact.getFsUserId() != null) {
+                R denied = denyIfCannotAccessFsUser(contact.getFsUserId());
+                if (denied != null) {
+                    return denied;
+                }
+            }
+        }
+        qwExternalContactInfoService.updateQwExternalContactInfo(qwExternalContact);
+        return R.ok();
+    }
+
+
+    @GetMapping("/tagGroupList")
+    @ApiOperation("获取所有标签组和其下标签")
+    public R getTagGroupList(TagGroupListParam param) {
+        QwTagGroup qwTagGroup = new QwTagGroup();
+        BeanCopyUtils.copy(param, qwTagGroup);
+        qwTagGroup.setName(param.getTagName());
+
+        PageHelper.startPage(qwTagGroup.getPageNum(), qwTagGroup.getPageSize());
+        List<QwTagGroupListVO> list = qwTagGroupService.selectQwGroupTagList(qwTagGroup);
+
+        PageInfo<QwTagGroupListVO> result = new PageInfo<>(list);
+        return R.ok().put("data", result);
+    }
+
+    @PutMapping("/externalContact/tag")
+    @ApiOperation("编辑标签")
+    public R updateExternalContactTag(@RequestBody TagGroupUpdateParam param) {
+        int i = qwExternalContactService.updateExternalContactTag(param);
+        if (i > 0) {
+            return R.ok();
+        }
+        return R.error();
+    }
+
+    @GetMapping("/externalContact")
+    @ApiOperation("获取侧边栏外部联系人信息")
+    public R getExternalContactInfo(@RequestParam(value = "qwExternalContactId") Long qwExternalContactId) {
+        ExternalContactInfoVO externalContactInfo = qwExternalContactService.getExternalContactInfo(qwExternalContactId);
+        return R.ok().put("data", externalContactInfo);
+    }
+
+    @GetMapping("/externalContact/getTag")
+    @ApiOperation("获取侧边栏外部联系人标签")
+    public R getExternalContactTag(@RequestParam(value = "qwExternalContactId") Long qwExternalContactId) {
+        List<ExternalContactTagVO> tagList = qwExternalContactService.getExternalContactTag(qwExternalContactId);
+        return R.ok().put("data", tagList);
+    }
+
+}

+ 26 - 0
fs-user-app/src/main/java/com/fs/app/controller/live/LiveWatchUserController.java

@@ -4,6 +4,7 @@ package com.fs.app.controller.live;
 import com.fs.app.annotation.Login;
 import com.fs.app.controller.AppBaseController;
 import com.fs.app.facade.LiveFacadeService;
+import com.fs.course.vo.FsCourseWatchCommentVO;
 import com.fs.live.param.LiveIsAddKfParam;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -12,10 +13,16 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.live.domain.LiveWatchUser;
+import com.fs.live.param.LiveWatchUserDetailParam;
 import com.fs.live.service.ILiveWatchUserService;
+import com.fs.live.vo.LiveWatchUserDetailVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * 直播间观看用户Controller
  *
@@ -98,4 +105,23 @@ public class LiveWatchUserController extends AppBaseController
         return liveWatchUserService.liveIsAddKf(param);
     }
 
+    /**
+     * 获取用户的直播看课记录详细信息
+     */
+    @Login
+    @PostMapping(value = "/getLiveWatchUserDetail")
+    public R getLiveWatchUserDetail(@RequestBody LiveWatchUserDetailParam param)
+    {
+        R denied = denyIfNotCurrentCourseCompanyUser(param.getCompanyUserId());
+        if (denied != null) {
+            return denied;
+        }
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<LiveWatchUserDetailVO> list = liveWatchUserService.getLiveWatchUserDetail(param.getUserId());
+        PageInfo<LiveWatchUserDetailVO> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data", pageInfo);
+
+    }
+
 }