Parcourir la source

还原251119 当天提交代码

yuhongqi il y a 1 jour
Parent
commit
9ac9d3d135
24 fichiers modifiés avec 196 ajouts et 283 suppressions
  1. 5 23
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  2. 5 3
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  3. 0 49
      fs-service/src/main/java/com/fs/course/domain/FsProjectAddressConfig.java
  4. 2 4
      fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  5. 0 14
      fs-service/src/main/java/com/fs/course/mapper/FsProjectAddressConfigMapper.java
  6. 0 12
      fs-service/src/main/java/com/fs/course/service/IFsProjectAddressConfigService.java
  7. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  8. 0 23
      fs-service/src/main/java/com/fs/course/service/impl/FsProjectAddressConfigServiceImpl.java
  9. 1 24
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  10. 18 45
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  11. 1 1
      fs-service/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java
  12. 1 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java
  13. 11 0
      fs-service/src/main/java/com/fs/live/mapper/LiveWatchUserMapper.java
  14. 50 33
      fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java
  15. 1 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java
  16. 1 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java
  17. 1 1
      fs-service/src/main/resources/application-config-druid-kyt.yml
  18. 1 1
      fs-service/src/main/resources/application-config-druid-nmgyt.yml
  19. 1 1
      fs-service/src/main/resources/application-config-druid-qdtst.yml
  20. 1 1
      fs-service/src/main/resources/application-druid-nmgyt.yml
  21. 0 8
      fs-service/src/main/resources/mapper/course/FsProjectAddressConfigMapper.xml
  22. 53 11
      fs-service/src/main/resources/mapper/live/LiveDataMapper.xml
  23. 42 1
      fs-service/src/main/resources/mapper/live/LiveWatchUserMapper.xml
  24. 0 26
      fs-user-app/src/main/java/com/fs/app/controller/CommonController.java

+ 5 - 23
fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java

@@ -10,7 +10,6 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
@@ -38,7 +37,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDate;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -102,20 +104,6 @@ public class FsUserCoursePeriodController extends BaseController {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserCoursePeriod.setCompanyIdList(Collections.singletonList(loginUser.getCompany().getCompanyId()));
         List<FsUserCoursePeriodVO> list = fsUserCoursePeriodService.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
-        // 使用Stream API的简洁写法
-        Long currentCompanyId = loginUser.getCompany().getCompanyId();
-        for (FsUserCoursePeriodVO vo : list) {
-            String isNeedRegisterMember = vo.getIsNeedRegisterMember();
-
-            if (StringUtils.isNotEmpty(isNeedRegisterMember)) {
-                boolean containsCurrentCompany = Arrays.stream(isNeedRegisterMember.split(","))
-                        .map(String::trim)
-                        .anyMatch(id -> id.equals(String.valueOf(currentCompanyId)));
-                vo.setIsNeedRegisterMember(containsCurrentCompany ? "1" : "0");
-            } else {
-                vo.setIsNeedRegisterMember("0");
-            }
-        }
         PageInfo<FsUserCoursePeriodVO> pageInfo = new PageInfo<>(list);
         Map<String, Object> result = new HashMap<>();
         result.put("rows", pageInfo.getList());
@@ -185,13 +173,7 @@ public class FsUserCoursePeriodController extends BaseController {
     @PutMapping("/editIsNeedRegisterMember")
     public AjaxResult editIsNeedRegisterMember(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
-        FsUserCoursePeriod fsUserCoursePeriod1 = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsUserCoursePeriod.getPeriodId());
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if (ObjectUtil.isEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())){
-            throw new CustomException("修改失败!");
-        }
-
-        return toAjax(fsUserCoursePeriodService.editIsNeedRegisterMember(fsUserCoursePeriod,loginUser.getCompany().getCompanyId().toString()));
+        return toAjax(fsUserCoursePeriodService.editIsNeedRegisterMember(fsUserCoursePeriod));
     }
 
     /**

+ 5 - 3
fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -7,6 +7,8 @@ import com.fs.common.constant.LiveKeysConstant;
 import com.fs.common.exception.base.BaseException;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
+import com.fs.hisStore.domain.FsUserScrm;
+import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.live.config.ProductionWordFilter;
 import com.fs.live.mapper.LiveCouponMapper;
 import com.fs.live.websocket.auth.WebSocketConfigurator;
@@ -51,7 +53,7 @@ public class WebSocketServer {
     private final ILiveMsgService liveMsgService = SpringUtils.getBean(ILiveMsgService.class);
     private final ILiveService liveService = SpringUtils.getBean(ILiveService.class);
     private final ILiveWatchUserService liveWatchUserService = SpringUtils.getBean(ILiveWatchUserService.class);
-    private final IFsUserService fsUserService = SpringUtils.getBean(IFsUserService.class);
+    private final IFsUserScrmService fsUserService = SpringUtils.getBean(IFsUserScrmService.class);
     private final ILiveDataService liveDataService = SpringUtils.getBean(ILiveDataService.class);
     private final ProductionWordFilter productionWordFilter = SpringUtils.getBean(ProductionWordFilter.class);
     private final ILiveRedConfService liveRedConfService =  SpringUtils.getBean(ILiveRedConfService.class);
@@ -94,7 +96,7 @@ public class WebSocketServer {
 
         // 记录连接信息 管理员不记录
         if (userType == 0) {
-            FsUser fsUser = fsUserService.selectFsUserByUserId(userId);
+            FsUserScrm fsUser = fsUserService.selectFsUserByUserId(userId);
             if (Objects.isNull(fsUser)) {
                 throw new BaseException("用户信息错误");
             }
@@ -193,7 +195,7 @@ public class WebSocketServer {
         ConcurrentHashMap<Long, Session> room = getRoom(liveId);
         List<Session> adminRoom = getAdminRoom(liveId);
         if (userType == 0) {
-            FsUser fsUser = fsUserService.selectFsUserByUserId(userId);
+            FsUserScrm fsUser = fsUserService.selectFsUserByUserId(userId);
             if (Objects.isNull(fsUser)) {
                 throw new BaseException("用户信息错误");
             }

+ 0 - 49
fs-service/src/main/java/com/fs/course/domain/FsProjectAddressConfig.java

@@ -1,49 +0,0 @@
-package com.fs.course.domain;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-public class FsProjectAddressConfig {
-
-    /**
-     * 主键ID
-     */
-    private Long id;
-
-    /**
-     * 项目名称
-     */
-    private String name;
-
-    /**
-     * 唯一编码
-     */
-    private String code;
-
-    /**
-     * api接口地址
-     */
-    private String addressUrl;
-
-    /**
-     * 存储桶地址
-     */
-    private String bucketPath;
-
-    /**
-     * 创建时间
-     */
-    private LocalDateTime createTime;
-
-    /**
-     * 修改时间
-     */
-    private LocalDateTime updateTime;
-
-    /**
-     * 发送类型 1个微 2企微
-     */
-    private Integer sendType;
-}

+ 2 - 4
fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java

@@ -117,8 +117,6 @@ public class FsUserCoursePeriod
      * 营期线,即营期首次播放课程的日期
      */
     private Date periodLine;
-    /**
-     * 是否单独注册会员的绑定公司,存在就是开启,不存在就是关闭
-     */
-    private String isNeedRegisterMember;
+    /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
+    private Integer isNeedRegisterMember;
 }

+ 0 - 14
fs-service/src/main/java/com/fs/course/mapper/FsProjectAddressConfigMapper.java

@@ -1,14 +0,0 @@
-package com.fs.course.mapper;
-
-import com.fs.course.domain.FsProjectAddressConfig;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
-
-public interface FsProjectAddressConfigMapper {
-
-    /**
-     * 根据code查询url
-     */
-    @Select("select * from fs_project_address_config where code = #{code}")
-    FsProjectAddressConfig selectDomainByCode(@Param("code") String code);
-}

+ 0 - 12
fs-service/src/main/java/com/fs/course/service/IFsProjectAddressConfigService.java

@@ -1,12 +0,0 @@
-package com.fs.course.service;
-
-
-import com.fs.course.domain.FsProjectAddressConfig;
-
-public interface IFsProjectAddressConfigService {
-
-    /**
-     * 根据code查询url
-     */
-    FsProjectAddressConfig selectDomainByCode(String code);
-}

+ 1 - 1
fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java

@@ -102,7 +102,7 @@ public interface IFsUserCoursePeriodService
 
     List<Long> selectFsUserCoursePeriodListByPeriodId(List<Long> periodIds,Long companyId);
 
-    int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod, String s);
+    int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod);
 
     List<SysDictData> selectFsUserCoursePeriodListLabel(FsUserCoursePeriod fsUserCoursePeriod);
 }

+ 0 - 23
fs-service/src/main/java/com/fs/course/service/impl/FsProjectAddressConfigServiceImpl.java

@@ -1,23 +0,0 @@
-package com.fs.course.service.impl;
-
-import com.fs.course.domain.FsProjectAddressConfig;
-import com.fs.course.mapper.FsProjectAddressConfigMapper;
-import com.fs.course.service.IFsProjectAddressConfigService;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-
-@Service
-public class FsProjectAddressConfigServiceImpl implements IFsProjectAddressConfigService {
-
-    @Resource
-    private FsProjectAddressConfigMapper fsProjectAddressConfigMapper;
-
-    /**
-     * 根据code查询url
-     */
-    @Override
-    public FsProjectAddressConfig selectDomainByCode(String code) {
-        return fsProjectAddressConfigMapper.selectDomainByCode(code);
-    }
-}

+ 1 - 24
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java

@@ -313,30 +313,7 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     }
 
     @Override
-    public int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod, String companyId) {
-        String currentValue = fsUserCoursePeriod.getIsNeedRegisterMember();
-
-        if (currentValue.equals("0")) {
-            // 移除指定的 companyId
-            String updatedValue = Arrays.stream(currentValue.split(","))
-                    .map(String::trim)
-                    .filter(id -> !id.equals(companyId))
-                    .collect(Collectors.joining(","));
-            fsUserCoursePeriod.setIsNeedRegisterMember(updatedValue);
-        } else {
-            // 添加 companyId,并过滤掉 "0"
-            String updatedValue = Arrays.stream(currentValue.split(","))
-                    .map(String::trim)
-                    .filter(id -> !id.equals("0")) // 清除 "0"
-                    .collect(Collectors.collectingAndThen(
-                            Collectors.toCollection(LinkedHashSet::new),
-                            set -> {
-                                set.add(companyId);
-                                return String.join(",", set);
-                            }
-                    ));
-            fsUserCoursePeriod.setIsNeedRegisterMember(updatedValue);
-        }
+    public int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod) {
         return fsUserCoursePeriodMapper.updateFsUserCoursePeriod(fsUserCoursePeriod);
     }
 

+ 18 - 45
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -604,49 +604,26 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if(qwGroupChatUsers == null || qwGroupChatUsers.isEmpty()){
             return R.error("群参数异常");
         }
-        //群聊寻找用户新逻辑
-        QwExternalContact qwExternalContact = null;
-        if( null != param.getUserId() && null == qwExternalContact){
-            try {
-                qwExternalContact =  qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+        QwExternalContact qwExternalContact =
+                qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
                         .eq("user_id", qwGroupChat.getOwner())
                         .eq("fs_user_id", param.getUserId())
                         .eq("corp_id", param.getCorpId())
                         .eq("status",0));
-            } catch (Exception e){
-                log.error("群聊用户id匹配异常,参数user_id:{},fs_user_id:{},corp_id:{}",qwGroupChat.getOwner(),param.getUserId(),param.getCorpId(),e);
-            }
-        }
-        //找当前群中的用户匹配
-        if(StringUtils.isNotBlank(param.getChatId()) && null == qwExternalContact){
-            List<QwExternalContact> groupChatUserByChatIdAndUserName = qwExternalContactMapper.getGroupChatUserByChatIdAndUserName(qwGroupChat.getOwner(), user.getNickName(), param.getCorpId(), param.getChatId());
-            //没找到用户 || 找到的用户数量大于1 使用userid查询匹配
-            if(null == groupChatUserByChatIdAndUserName || groupChatUserByChatIdAndUserName.isEmpty() || groupChatUserByChatIdAndUserName.size() > 1){
-                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{},chatId:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),param.getChatId());
-            } else {
-                qwExternalContact =  groupChatUserByChatIdAndUserName.get(0);
+        if(null == qwExternalContact){
+            try{
+                //修改成通过昵称匹配
+                qwExternalContact =
+                        qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+                                .eq("user_id", qwGroupChat.getOwner())
+                                .eq("name", user.getNickName())
+                                .eq("corp_id", param.getCorpId())
+                                .eq("status",0));
+            } catch(Exception e){
+                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),e);
             }
+
         }
-//        QwExternalContact qwExternalContact =  qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
-//                            .eq("user_id", qwGroupChat.getOwner())
-//                            .eq("fs_user_id", param.getUserId())
-//                            .eq("corp_id", param.getCorpId())
-//                            .eq("status",0));
-//
-//        if(null == qwExternalContact){
-//            try{
-//                //修改成通过昵称匹配
-//                qwExternalContact =
-//                        qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
-//                                .eq("user_id", qwGroupChat.getOwner())
-//                                .eq("name", user.getNickName())
-//                                .eq("corp_id", param.getCorpId())
-//                                .eq("status",0));
-//            } catch(Exception e){
-//                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),e);
-//            }
-//
-//        }
         if(qwExternalContact==null){
             return addCustomerService(param.getQwUserId(),msg);
         }
@@ -2193,15 +2170,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 if((companyUser.getIsAllowedAllRegister() !=null && companyUser.getIsAllowedAllRegister() != 1)){
                     return ResponseResult.fail(504,"当前销售禁止绑定会员,请联系销售!");
                 }
-                // 使用 Stream API 检查是否包含 companyId
-                // 修正类型转换问题
                 if (companyUser.getIsNeedRegisterMember() == null || companyUser.getIsNeedRegisterMember() == 1
-                        || (ObjectUtils.isNotEmpty(fsUserCoursePeriod)
-                        && ObjectUtils.isNotEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())
-                        && Arrays.stream(fsUserCoursePeriod.getIsNeedRegisterMember().split(","))
-                        .map(String::trim)
-                        .anyMatch(id -> id.equals(String.valueOf(company.getCompanyId()))))) {
-                    return ResponseResult.fail(504, "请联系销售发送邀请链接成为会员!");
+                        ||(ObjectUtils.isNotEmpty(fsUserCoursePeriod)
+                        &&ObjectUtils.isNotEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())
+                        &&fsUserCoursePeriod.getIsNeedRegisterMember().equals(1))){
+                    return ResponseResult.fail(504,"请联系销售发送邀请链接成为会员!");
                 }
                 int defaultStatus = (company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1;
                 userCompanyUser = userCompanyUserService.bindRelationship(param.getUserId(), courseProject, companyUser.getCompanyId(), companyUser.getUserId(), defaultStatus);

+ 1 - 1
fs-service/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java

@@ -89,5 +89,5 @@ public class FsUserCoursePeriodVO implements Serializable {
     @Excel(name = "营期线", width = 31, dateFormat = "yyyy-MM-dd")
     private Date periodLine;
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
-    private String isNeedRegisterMember;
+    private Integer isNeedRegisterMember;
 }

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java

@@ -788,7 +788,7 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             }
         }
         return R.ok();
-        }
+    }
 
 
     @Override

+ 11 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveWatchUserMapper.java

@@ -107,6 +107,17 @@ public interface LiveWatchUserMapper {
     @Select("select * from live_watch_user where live_id = #{liveId} and user_id = #{userId}")
     LiveWatchUser selectUserByLiveIdAndUserId(@Param("liveId") long liveId,@Param("userId")  long userId);
 
+    /**
+     * 根据唯一索引查询:live_id, user_id, live_flag, replay_flag
+     */
+    LiveWatchUser selectByUniqueIndex(@Param("liveId") Long liveId, @Param("userId") Long userId, 
+                                      @Param("liveFlag") Integer liveFlag, @Param("replayFlag") Integer replayFlag);
+
+    /**
+     * 根据唯一索引更新或插入(ON DUPLICATE KEY UPDATE)
+     */
+    int insertOrUpdateByUniqueIndex(LiveWatchUser liveWatchUser);
+
     @Select("SELECT " +
             "    SUM(CASE WHEN lwu.online = 0 and lwu.msg_status = 0 THEN 1 ELSE 0 END) AS online, " +
             "    SUM(CASE WHEN lwu.online = 1 and lwu.msg_status = 0 THEN 1 ELSE 0 END) AS offline, " +

+ 50 - 33
fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java

@@ -12,6 +12,8 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.his.domain.FsUser;
 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.LiveWatchUser;
@@ -43,7 +45,7 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
     @Autowired
     private RedisCache redisCache;
     @Autowired
-    private IFsUserService fsUserService;
+    private IFsUserScrmService fsUserService;
     @Autowired
     private LiveWatchUserMapper baseMapper;
     @Autowired
@@ -153,38 +155,60 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
 
     @Override
     public LiveWatchUser join(long liveId, long userId, String location) {
-        LiveWatchUser liveWatchUser = getByLiveIdAndUserId(liveId, userId);
-        FsUser fsUserVO = fsUserService.selectFsUserByUserId(userId);
+        FsUserScrm fsUserVO = fsUserService.selectFsUserByUserId(userId);
         Date now = DateUtils.getNowDate();
 
         // 查询直播间信息
         Live live = liveMapper.selectLiveByLiveId(liveId);
+        if (live == null) {
+            throw new RuntimeException("直播间不存在");
+        }
 
-        // 判断用户进入时间:如果进入时间大于直播结束时间,说明是回放
-        boolean isReplay = false;
-        if (live != null && live.getFinishTime() != null) {
-            Date finishTime = java.sql.Timestamp.valueOf(live.getFinishTime());
-            isReplay = now.after(finishTime);
+        // 查询直播间录播视频时长(video_type IN (1, 2))
+        List<LiveVideo> videos = liveVideoMapper.selectByLiveIdAndType(liveId,1);
+        long totalDuration = 0L;
+        if (videos != null && !videos.isEmpty()) {
+            totalDuration = videos.stream()
+                    .filter(v -> v.getVideoType() != null && (v.getVideoType() == 1 || v.getVideoType() == 2))
+                    .filter(v -> v.getDuration() != null)
+                    .mapToLong(LiveVideo::getDuration)
+                    .sum();
         }
 
-        if(liveWatchUser != null) {
-            liveWatchUser.setUpdateTime(now);
-            liveWatchUser.setOnline(0);
+        // 判断是直播还是回放:开播时间 + 视频时长
+        Integer liveFlag = 0;
+        Integer replayFlag = 0;
 
-            // 更新location
-            if (StringUtils.isNotEmpty(location)) {
-                liveWatchUser.setLocation(location);
-            }
+        if (live.getStartTime() != null) {
+            // 将 LocalDateTime 转换为 Date
+            Date startTime = java.sql.Timestamp.valueOf(live.getStartTime());
+            // 计算结束时间:开播时间 + 视频时长(秒)
+            Date endTime = new Date(startTime.getTime() + totalDuration * 1000);
 
-            // 更新进入标记
-            if (isReplay) {
-                liveWatchUser.setReplayFlag(1);
+            if (now.before(endTime)) {
+                // 当前时间 < 开播时间 + 视频时长,说明是直播
+                liveFlag = 1;
+                replayFlag = 0;
             } else {
-                liveWatchUser.setLiveFlag(1);
+                // 当前时间 >= 开播时间 + 视频时长,说明是回放
+                liveFlag = 0;
+                replayFlag = 1;
             }
+        }
+
+        // 使用唯一索引查询:live_id, user_id, live_flag, replay_flag
+        LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
 
+        if (liveWatchUser != null) {
+            // 存在则更新
+            liveWatchUser.setUpdateTime(now);
+            liveWatchUser.setOnline(0);
+            if (StringUtils.isNotEmpty(location)) {
+                liveWatchUser.setLocation(location);
+            }
             baseMapper.updateLiveWatchUser(liveWatchUser);
-        }else{
+        } else {
+            // 不存在则插入
             liveWatchUser = new LiveWatchUser();
             liveWatchUser.setLiveId(liveId);
             liveWatchUser.setUserId(userId);
@@ -192,23 +216,16 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
             liveWatchUser.setMsgStatus(0);
             liveWatchUser.setOnline(0);
             liveWatchUser.setLocation(location);
-
-            // 设置进入标记
-            if (isReplay) {
-                liveWatchUser.setReplayFlag(1);
-                liveWatchUser.setLiveFlag(0);
-            } else {
-                liveWatchUser.setLiveFlag(1);
-                liveWatchUser.setReplayFlag(0);
-            }
-
+            liveWatchUser.setLiveFlag(liveFlag);
+            liveWatchUser.setReplayFlag(replayFlag);
             liveWatchUser.setCreateTime(now);
             liveWatchUser.setUpdateTime(now);
             baseMapper.insertLiveWatchUser(liveWatchUser);
         }
+
         liveWatchUser.setAvatar(fsUserVO.getAvatar());
         liveWatchUser.setNickName(fsUserVO.getNickname());
-        String hashKey  = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
+        String hashKey = String.format(LiveKeysConstant.LIVE_WATCH_USERS, liveId);
         redisCache.hashPut(hashKey, String.valueOf(userId), JSON.toJSONString(liveWatchUser));
         return liveWatchUser;
     }
@@ -216,7 +233,7 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
     @Override
     public LiveWatchUser joinWithoutLocation(long liveId, long userId) {
         LiveWatchUser liveWatchUser = getByLiveIdAndUserId(liveId, userId);
-        FsUser fsUserVO = fsUserService.selectFsUserByUserId(userId);
+        FsUserScrm fsUserVO = fsUserService.selectFsUserByUserId(userId);
         Date now = DateUtils.getNowDate();
 
         // 查询直播间信息
@@ -337,7 +354,7 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
 
     @Override
     public int blockUser(Long userId) {
-        FsUser fsUser = new FsUser();
+        FsUserScrm fsUser = new FsUserScrm();
         fsUser.setUserId(userId);
         fsUser.setStatus(0);
         return fsUserService.updateFsUser(fsUser);

+ 1 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java

@@ -95,6 +95,7 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
     private QwExternalContactServiceImpl qwExternalContactService;
 
     @Autowired
+    @Lazy
     private IFsCourseWatchLogService watchLogService;
 
     @Autowired

+ 1 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopServiceImpl.java

@@ -137,6 +137,7 @@ public class QwSopServiceImpl implements IQwSopService
     private IFsUserService fsUserService;
 
     @Autowired
+    @Lazy
     private IFsCourseWatchLogService fsCourseWatchLogService;
 
     @Autowired

+ 1 - 1
fs-service/src/main/resources/application-config-druid-kyt.yml

@@ -64,7 +64,7 @@ fs :
   h5CommonApi: http://172.17.0.10:8010
   jwt:
     # 加密秘钥
-    secret: f4e2e52034348f86b67cde581c0f9eb5
+    secret: f4k2y52034348t86b67cde581c0f9eb5
     # token有效时长,7天,单位秒
     expire: 31536000
     header: AppToken

+ 1 - 1
fs-service/src/main/resources/application-config-druid-nmgyt.yml

@@ -96,6 +96,6 @@ ipad:
 wx_miniapp_temp:
   pay_order_temp_id: V
   inquiry_temp_id: 9
-enableRedPackAccount: 0
+enableRedPackAccount: 1
 
 

+ 1 - 1
fs-service/src/main/resources/application-config-druid-qdtst.yml

@@ -64,7 +64,7 @@ fs :
   h5CommonApi: http://10.206.0.16:8010
   jwt:
     # 加密秘钥
-    secret: f4q2d52034348t86b678s1581c0f9eb5
+    secret: f4e2e52034348f86b67cde581c0f9eb5
     # token有效时长,7天,单位秒
     expire: 31536000
     header: AppToken

+ 1 - 1
fs-service/src/main/resources/application-druid-nmgyt.yml

@@ -156,4 +156,4 @@ openIM:
 im:
     type: NONE
 #是否为新商户,新商户不走mpOpenId
-isNewWxMerchant: true
+isNewWxMerchant: false

+ 0 - 8
fs-service/src/main/resources/mapper/course/FsProjectAddressConfigMapper.xml

@@ -1,8 +0,0 @@
-<?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.FsProjectAddressConfigMapper">
-
-
-</mapper>

+ 53 - 11
fs-service/src/main/resources/mapper/live/LiveDataMapper.xml

@@ -300,10 +300,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 WHEN l.live_type = 3 AND lwu.online_seconds >= COALESCE(video_duration.total_duration, 0) AND video_duration.total_duration > 0 
                 THEN lwu.user_id 
             END) AS playbackCompletedCourses,
-            COALESCE(SUM(lo.pay_price), 0) AS gmv,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.user_id END) AS paidUsers,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.order_id END) AS paidOrders,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.order_id END) AS salesCount
+            COALESCE((
+                SELECT SUM(pay_price) 
+                FROM live_order 
+                WHERE live_id IN 
+                <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
+                    #{liveId}
+                </foreach>
+                AND is_pay = '1'
+            ), 0) AS gmv,
+            COALESCE((
+                SELECT COUNT(DISTINCT user_id) 
+                FROM live_order 
+                WHERE live_id IN 
+                <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
+                    #{liveId}
+                </foreach>
+                AND is_pay = '1'
+            ), 0) AS paidUsers,
+            COALESCE((
+                SELECT COUNT(DISTINCT order_id) 
+                FROM live_order 
+                WHERE live_id IN 
+                <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
+                    #{liveId}
+                </foreach>
+                AND is_pay = '1'
+            ), 0) AS paidOrders,
+            COALESCE((
+                SELECT COUNT(DISTINCT order_id) 
+                FROM live_order 
+                WHERE live_id IN 
+                <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
+                    #{liveId}
+                </foreach>
+                AND is_pay = '1'
+            ), 0) AS salesCount
         FROM live l
         LEFT JOIN live_watch_user lwu ON l.live_id = lwu.live_id
         LEFT JOIN (
@@ -312,7 +344,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             WHERE video_type IN (1, 2)
             GROUP BY live_id
         ) video_duration ON l.live_id = video_duration.live_id
-        LEFT JOIN live_order lo ON l.live_id = lo.live_id
         WHERE l.live_id IN
         <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
             #{liveId}
@@ -345,10 +376,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 WHEN l.live_type = 3 AND lwu.online_seconds >= COALESCE(video_duration.total_duration, 0) AND video_duration.total_duration > 0 
                 THEN lwu.user_id 
             END) AS playbackCompletedCourses,
-            COALESCE(SUM(lo.pay_price), 0) AS gmv,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.user_id END) AS paidUsers,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.order_id END) AS paidOrders,
-            COUNT(DISTINCT CASE WHEN lo.is_pay = '1' THEN lo.order_id END) AS salesCount
+            COALESCE(order_stats.gmv, 0) AS gmv,
+            COALESCE(order_stats.paidUsers, 0) AS paidUsers,
+            COALESCE(order_stats.paidOrders, 0) AS paidOrders,
+            COALESCE(order_stats.salesCount, 0) AS salesCount
         FROM live l
         LEFT JOIN live_watch_user lwu ON l.live_id = lwu.live_id
         LEFT JOIN (
@@ -357,12 +388,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             WHERE video_type IN (1, 2)
             GROUP BY live_id
         ) video_duration ON l.live_id = video_duration.live_id
-        LEFT JOIN live_order lo ON l.live_id = lo.live_id
+        LEFT JOIN (
+            SELECT 
+                live_id,
+                SUM(pay_price) AS gmv,
+                COUNT(DISTINCT user_id) AS paidUsers,
+                COUNT(DISTINCT order_id) AS paidOrders,
+                COUNT(DISTINCT order_id) AS salesCount
+            FROM live_order
+            WHERE is_pay = '1'
+            GROUP BY live_id
+        ) order_stats ON l.live_id = order_stats.live_id
         WHERE l.live_id IN
         <foreach collection="liveIds" item="liveId" open="(" separator="," close=")">
             #{liveId}
         </foreach>
-        GROUP BY l.live_id, l.live_name, l.live_type, l.status, l.start_time, l.finish_time
+        GROUP BY l.live_id, l.live_name, l.live_type, l.status, l.start_time, l.finish_time, 
+                 order_stats.gmv, order_stats.paidUsers, order_stats.paidOrders, order_stats.salesCount
         ORDER BY l.start_time DESC
     </select>
 </mapper>

+ 42 - 1
fs-service/src/main/resources/mapper/live/LiveWatchUserMapper.xml

@@ -18,10 +18,13 @@
         <result property="onlineSeconds"    column="online_seconds"    />
         <result property="globalVisible"    column="global_visible"    />
         <result property="singleVisible"    column="single_visible"    />
+        <result property="liveFlag"    column="live_flag"    />
+        <result property="replayFlag"    column="replay_flag"    />
+        <result property="location"    column="location"    />
     </resultMap>
 
     <sql id="selectLiveWatchUserVo">
-        select id, live_id,user_id, msg_status, online, create_time, create_by, update_by, update_time, remark,online_seconds,global_visible,single_visible from live_watch_user
+        select id, live_id,user_id, msg_status, online, create_time, create_by, update_by, update_time, remark,online_seconds,global_visible,single_visible,live_flag,replay_flag,location from live_watch_user
     </sql>
 
     <select id="selectLiveWatchUserList" parameterType="LiveWatchUser" resultMap="LiveWatchUserResult">
@@ -125,6 +128,9 @@
             <if test="onlineSeconds != null">online_seconds,</if>
             <if test="globalVisible != null">global_visible,</if>
             <if test="singleVisible != null">single_visible,</if>
+            <if test="liveFlag != null">live_flag,</if>
+            <if test="replayFlag != null">replay_flag,</if>
+            <if test="location != null">location,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="liveId != null">#{liveId},</if>
@@ -139,6 +145,9 @@
             <if test="onlineSeconds != null">#{onlineSeconds},</if>
             <if test="globalVisible != null">#{globalVisible},</if>
             <if test="singleVisible != null">#{singleVisible},</if>
+            <if test="liveFlag != null">#{liveFlag},</if>
+            <if test="replayFlag != null">#{replayFlag},</if>
+            <if test="location != null">#{location},</if>
         </trim>
     </insert>
 
@@ -157,6 +166,9 @@
             <if test="onlineSeconds != null">online_seconds = #{onlineSeconds},</if>
             <if test="globalVisible != null">global_visible = #{globalVisible},</if>
             <if test="singleVisible != null">single_visible = #{singleVisible},</if>
+            <if test="liveFlag != null">live_flag = #{liveFlag},</if>
+            <if test="replayFlag != null">replay_flag = #{replayFlag},</if>
+            <if test="location != null">location = #{location},</if>
         </trim>
         where id = #{id}
     </update>
@@ -186,4 +198,33 @@
               AND DATE(lrr.create_time) = DATE(#{now})
         )
     </select>
+
+    <!-- 根据唯一索引查询:live_id, user_id, live_flag, replay_flag -->
+    <select id="selectByUniqueIndex" resultMap="LiveWatchUserResult">
+        <include refid="selectLiveWatchUserVo"/>
+        WHERE live_id = #{liveId}
+          AND user_id = #{userId}
+          AND live_flag = #{liveFlag}
+          AND replay_flag = #{replayFlag}
+        LIMIT 1
+    </select>
+
+    <!-- 根据唯一索引插入或更新(ON DUPLICATE KEY UPDATE) -->
+    <insert id="insertOrUpdateByUniqueIndex" parameterType="LiveWatchUser">
+        INSERT INTO live_watch_user (
+            live_id, user_id, live_flag, replay_flag,
+             msg_status, online, location,
+            create_time, update_time
+        ) VALUES (
+            #{liveId}, #{userId}, #{liveFlag}, #{replayFlag},
+             #{msgStatus}, #{online}, #{location},
+            #{createTime}, #{updateTime}
+        )
+        ON DUPLICATE KEY UPDATE
+
+            msg_status = VALUES(msg_status),
+            online = VALUES(online),
+            location = VALUES(location),
+            update_time = VALUES(update_time)
+    </insert>
 </mapper>

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

@@ -33,8 +33,6 @@ import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.service.ICompanyMoneyLogsService;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.config.CourseConfig;
-import com.fs.course.domain.FsProjectAddressConfig;
-import com.fs.course.service.IFsProjectAddressConfigService;
 import com.fs.course.service.IHuaweiVodService;
 import com.fs.event.TemplateBean;
 import com.fs.event.TemplateEvent;
@@ -80,7 +78,6 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.*;
 import java.math.BigDecimal;
 import java.util.*;
-import java.util.concurrent.TimeUnit;
 
 import static com.fs.common.utils.SecurityUtils.getUserId;
 
@@ -137,8 +134,6 @@ public class CommonController {
 
 	@Autowired
 	private IQwAppContactWayService qwAppContactWayService;
-	@Autowired
-	private IFsProjectAddressConfigService projectAddressConfigService;
 
 //	@Autowired
 //	private RocketMQTemplate rocketMQTemplate;
@@ -641,25 +636,4 @@ public class CommonController {
 		return ResponseResult.ok(config.getIsOpenIM());
 	}
 
-	@ApiOperation("获取项目对应api请求域名地址")
-	@GetMapping("/getDomain")
-	public R getDomain(@RequestParam String projectCode) {
-		String redisKey = "projectCode:" + projectCode;
-		FsProjectAddressConfig config = redisCache.getCacheObject(redisKey);
-		if (Objects.isNull(config)) {
-			config = projectAddressConfigService.selectDomainByCode(projectCode);
-			redisCache.setCacheObject(redisKey, config, 5, TimeUnit.MINUTES);
-		}
-		String addressUrl = "";
-		String imgPath = "";
-		Integer sendType = null;
-
-		if (Objects.nonNull(config)) {
-			addressUrl = config.getAddressUrl();
-			imgPath = config.getBucketPath();
-			sendType = config.getSendType();
-		}
-
-		return R.ok().put("addressUrl", addressUrl).put("imgpath", imgPath).put("sendType", sendType);
-	}
 }