Browse Source

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

caoliqin 1 day ago
parent
commit
7e7efaf525
46 changed files with 695 additions and 803 deletions
  1. 9 0
      fs-admin/src/main/java/com/fs/live/controller/LiveController.java
  2. 2 6
      fs-admin/src/main/java/com/fs/live/controller/LiveVideoController.java
  3. 10 0
      fs-admin/src/main/java/com/fs/qw/controller/QwFriendWelcomeController.java
  4. 9 0
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  5. 2 38
      fs-live-app/src/main/java/com/fs/live/task/LiveCompletionPointsTask.java
  6. 32 11
      fs-live-app/src/main/java/com/fs/live/task/Task.java
  7. 75 2
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  8. 3 0
      fs-service/src/main/java/com/fs/company/domain/Company.java
  9. 3 0
      fs-service/src/main/java/com/fs/company/vo/CompanyVO.java
  10. 3 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  11. 0 2
      fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java
  12. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  13. 47 37
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  14. 12 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  15. 46 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  16. 3 0
      fs-service/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java
  17. 7 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralCartMapper.java
  18. 7 0
      fs-service/src/main/java/com/fs/his/service/impl/FsCouponServiceImpl.java
  19. 11 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralGoodsServiceImpl.java
  20. 51 19
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  21. 1 1
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  22. 7 0
      fs-service/src/main/java/com/fs/live/mapper/LiveWatchLogMapper.java
  23. 1 1
      fs-service/src/main/java/com/fs/live/service/ILiveAfterSalesService.java
  24. 7 0
      fs-service/src/main/java/com/fs/live/service/ILiveService.java
  25. 14 0
      fs-service/src/main/java/com/fs/live/service/ILiveWatchLogService.java
  26. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveWatchUserService.java
  27. 9 15
      fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java
  28. 10 15
      fs-service/src/main/java/com/fs/live/service/impl/LiveCompletionPointsRecordServiceImpl.java
  29. 85 63
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  30. 23 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  31. 17 8
      fs-service/src/main/java/com/fs/live/service/impl/LiveVideoServiceImpl.java
  32. 66 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveWatchLogServiceImpl.java
  33. 8 1
      fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java
  34. 2 2
      fs-service/src/main/resources/application-config-druid-heyantang.yml
  35. 2 2
      fs-service/src/main/resources/application-config-druid-nmgyt.yml
  36. 1 0
      fs-service/src/main/resources/application-config-druid-sczy.yml
  37. 1 1
      fs-service/src/main/resources/application-config-zkzh.yml
  38. 3 0
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  39. 2 1
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  40. 2 0
      fs-service/src/main/resources/mapper/course/FsUserCoursePeriodMapper.xml
  41. 5 0
      fs-service/src/main/resources/mapper/his/FsIntegralCartMapper.xml
  42. 91 0
      fs-service/src/main/resources/mapper/live/LiveWatchLogMapper.xml
  43. 0 5
      fs-user-app/src/main/java/com/fs/app/controller/course/CourseTransferController.java
  44. 2 0
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java
  45. 0 246
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java
  46. 0 322
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

+ 9 - 0
fs-admin/src/main/java/com/fs/live/controller/LiveController.java

@@ -221,4 +221,13 @@ public class LiveController extends BaseController {
         return getDataTable(list);
     }
 
+    /**
+     * 清除直播间缓存
+     */
+    @Log(title = "直播", businessType = BusinessType.UPDATE)
+    @PostMapping("/clearCache/{liveId}")
+    public R clearCache(@PathVariable("liveId") Long liveId) {
+        return liveService.clearLiveCache(liveId);
+    }
+
 }

+ 2 - 6
fs-admin/src/main/java/com/fs/live/controller/LiveVideoController.java

@@ -29,8 +29,7 @@ public class LiveVideoController extends BaseController
 {
     @Autowired
     private ILiveVideoService liveVideoService;
-    @Autowired
-    private CloudHostProper cloudHostProper;
+
     /**
      * 查询直播视频列表
      */
@@ -93,10 +92,7 @@ public class LiveVideoController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody LiveVideo liveVideo)
     {
-        if (LiveEnum.contains(cloudHostProper.getCompanyName())) {
-            liveVideo.setVideoUrl(liveVideo.getLineOne());
-            liveVideo.setFinishStatus(1);
-        }
+
         return toAjax(liveVideoService.insertLiveVideo(liveVideo));
     }
 

+ 10 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwFriendWelcomeController.java

@@ -1,6 +1,7 @@
 package com.fs.qw.controller;
 
 import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.qw.param.QwFriendWelcomeParam;
 import com.fs.qw.service.IQwFriendWelcomeService;
@@ -8,6 +9,7 @@ import com.fs.qw.vo.QwFriendWelcomeVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -30,4 +32,12 @@ public class QwFriendWelcomeController extends BaseController {
         List<QwFriendWelcomeVO> list = qwFriendWelcomeService.selectQwFriendWelcomeList(qwFriendWelcomeParam);
         return getDataTable(list);
     }
+
+    /**
+     * 获取好友欢迎语详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public R getInfo(@PathVariable("id") Long id) {
+        return R.ok().put("row", qwFriendWelcomeService.selectQwFriendWelcomeById(id));
+    }
 }

+ 9 - 0
fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java

@@ -195,6 +195,15 @@ public class FsUserCoursePeriodController extends BaseController {
 
     }
 
+    @PreAuthorize("@ss.hasPermi('course:period:edit')")
+    @Log(title = "会员营期", businessType = BusinessType.UPDATE)
+    @PutMapping("/updatePeriodIsOpenRestReminder")
+    public AjaxResult updatePeriodIsOpenRestReminder(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
+    {
+        return toAjax(fsUserCoursePeriodService.updatePeriod(fsUserCoursePeriod));
+
+    }
+
     /**
      * 删除会员营期
      */

+ 2 - 38
fs-live-app/src/main/java/com/fs/live/task/LiveCompletionPointsTask.java

@@ -39,7 +39,7 @@ public class LiveCompletionPointsTask {
     private ILiveService liveService;
 
     /**
-     * 定时检查观看时长并创建完课记录
+     * 定时检查观看时长并创建完课记录(兜底机制)
      * 每分钟执行一次
      * 优化:防重复推送 + 只查询开启了完课积分的直播间
      */
@@ -53,8 +53,6 @@ public class LiveCompletionPointsTask {
                 log.debug("当前没有开启完课积分的直播间");
                 return;
             }
-            
-            log.info("开始检查完课状态, 开启完课积分的直播间数量: {}", activeLives.size());
 
             for (Live live : activeLives) {
                 try {
@@ -65,14 +63,9 @@ public class LiveCompletionPointsTask {
                     Map<Object, Object> userDurations = redisCache.hashEntries(hashKey);
                     
                     if (userDurations == null || userDurations.isEmpty()) {
-                        log.warn("直播间没有观看时长数据, liveId={}, liveName={}, Redis Key: {}, userDurations={}", 
-                                liveId, live.getLiveName(), hashKey, userDurations);
+
                         continue;
                     }
-                    
-                    log.info("直播间有观看数据, liveId={}, liveName={}, 用户数: {}", 
-                            liveId, live.getLiveName(), userDurations.size());
-                    
                     // 3. 逐个用户处理
                     for (Map.Entry<Object, Object> entry : userDurations.entrySet()) {
                         try {
@@ -81,9 +74,6 @@ public class LiveCompletionPointsTask {
                             
                             completionPointsRecordService.checkAndCreateCompletionRecord(liveId, userId, duration);
 
-                            // 5. 检查是否有新的完课记录待领取,推送弹窗消息(防重复)
-                            sendCompletionNotificationOnce(liveId, userId);
-
                         } catch (Exception e) {
                             log.error("处理用户完课状态失败, liveId={}, userId={}", liveId, entry.getKey(), e);
                         }
@@ -98,30 +88,4 @@ public class LiveCompletionPointsTask {
             log.error("检查完课状态定时任务执行失败", e);
         }
     }
-
-   private void sendCompletionNotificationOnce(Long liveId, Long userId) {
-    try {
-        // 查询未领取的完课记录
-        List<LiveCompletionPointsRecord> unreceivedRecords = 
-            completionPointsRecordService.getUserUnreceivedRecords(liveId, userId);
-        
-        if (unreceivedRecords == null || unreceivedRecords.isEmpty()) {
-            return;
-        }
-
-        SendMsgVo sendMsgVo = new SendMsgVo();
-        sendMsgVo.setLiveId(liveId);
-        sendMsgVo.setUserId(userId);
-        sendMsgVo.setCmd("completionPoints");
-        sendMsgVo.setMsg("完成任务!");
-        sendMsgVo.setData(JSONObject.toJSONString(unreceivedRecords.get(0)));
-        
-        webSocketServer.sendCompletionPointsMessage(liveId, userId, sendMsgVo);
-        
-        log.info("发送完课积分弹窗通知, liveId={}, userId={}, points={}", 
-                liveId, userId, unreceivedRecords.get(0).getPointsAwarded());
-        } catch (Exception e) {
-        log.error("发送完课通知失败", e);
-        }
-    }
 }

+ 32 - 11
fs-live-app/src/main/java/com/fs/live/task/Task.java

@@ -169,7 +169,10 @@ public class Task {
                         redisCache.expire(key+live.getLiveId(), 1, TimeUnit.DAYS);
                     });
                 }
-                
+                // 清理小程序缓存 和 直播标签缓存
+                String cacheKey = String.format(LiveKeysConstant.LIVE_DATA_CACHE, live.getLiveId());
+                redisCache.setCacheObject(cacheKey,live,1,TimeUnit.HOURS);
+                liveWatchUserService.clearLiveFlagCache(live.getLiveId());
                 // 将开启的直播间信息写入Redis缓存,用于打标签定时任务
                 try {
                     // 获取视频时长
@@ -216,8 +219,10 @@ public class Task {
                         redisCache.redisTemplate.opsForZSet().remove(key + live.getLiveId(), JSON.toJSONString(liveAutoTask),liveAutoTask.getAbsValue().getTime());
                     });
                 }
+                String cacheKey = String.format(LiveKeysConstant.LIVE_DATA_CACHE, live.getLiveId());
+                redisCache.deleteObject(cacheKey);
                 webSocketServer.removeLikeCountCache(live.getLiveId());
-                
+
                 // 删除打标签缓存
                 try {
                     String tagMarkKey = String.format(LiveKeysConstant.LIVE_TAG_MARK_CACHE, live.getLiveId());
@@ -411,8 +416,12 @@ public class Task {
             String configJson = openRewardLive.getConfigJson();
             LiveWatchConfig config = JSON.parseObject(configJson, LiveWatchConfig.class);
             if (config.getEnabled()) {
+                List<LiveWatchUser> liveWatchUsers = liveWatchUserService.checkOnlineNoRewardUser(openRewardLive.getLiveId(), now);
+                if (liveWatchUsers == null || liveWatchUsers.isEmpty()) {
+                    continue;
+                }
                 // 3.检查当前直播间的在线用户(可以传入一个时间,然后查出来当天没领取奖励的用户)
-                List<LiveWatchUser> onlineUser = liveWatchUserService.checkOnlineNoRewardUser(openRewardLive.getLiveId(), now)
+                List<LiveWatchUser> onlineUser = liveWatchUsers
                         .stream().filter(user -> (now.getTime() - user.getUpdateTime().getTime() + ( user.getOnlineSeconds() == null ? 0L : user.getOnlineSeconds())) > config.getWatchDuration() * 60 * 1000)
                         .collect(Collectors.toList());
                 if(onlineUser.isEmpty()) continue;
@@ -679,7 +688,8 @@ public class Task {
                         queryUser.setLiveId(liveId);
                         queryUser.setLiveFlag(1);
                         queryUser.setReplayFlag(0);
-                        List<LiveWatchUser> liveUsers = liveWatchUserService.selectLiveWatchUserList(queryUser);
+                        queryUser.setOnline(0);
+                        List<LiveWatchUser> liveUsers = liveWatchUserService.selectAllWatchUser(queryUser);
 
                         if (liveUsers != null && !liveUsers.isEmpty()) {
 
@@ -725,6 +735,7 @@ public class Task {
                                 // 更新直播用户的在线时长
                                 liveUser.setOnlineSeconds(totalOnlineSeconds);
                                 liveUser.setUpdateTime(nowDate);
+                                liveUser.setOnline(1);
                                 updateLiveUsers.add(liveUser);
 
                                 // 2. 生成回放用户数据(liveFlag = 0, replayFlag = 1),在线时长从0开始
@@ -732,7 +743,7 @@ public class Task {
                                 replayUser.setLiveId(liveUser.getLiveId());
                                 replayUser.setUserId(liveUser.getUserId());
                                 replayUser.setMsgStatus(liveUser.getMsgStatus());
-                                replayUser.setOnline(liveUser.getOnline());
+                                replayUser.setOnline(0);
                                 replayUser.setOnlineSeconds(0L); // 回放观看时长从0开始,重新计时
                                 replayUser.setGlobalVisible(liveUser.getGlobalVisible());
                                 replayUser.setSingleVisible(liveUser.getSingleVisible());
@@ -742,6 +753,7 @@ public class Task {
                                 replayUser.setCreateTime(nowDate);
                                 replayUser.setUpdateTime(nowDate);
                                 replayUsers.add(replayUser);
+                                redisCache.setCacheObject(entryTimeKey,now);
                             }
 
                             // 批量更新直播用户的在线时长
@@ -824,8 +836,7 @@ public class Task {
                     queryUser.setLiveId(liveId);
                     queryUser.setLiveFlag(1);
                     queryUser.setReplayFlag(0);
-                    queryUser.setOnline(0); // 在线用户
-                    List<LiveWatchUser> onlineUsers = liveWatchUserService.selectLiveWatchUserList(queryUser);
+                    List<LiveWatchUser> onlineUsers = liveWatchUserService.selectAllWatchUser(queryUser);
                     if (onlineUsers == null || onlineUsers.isEmpty()) {
                         continue;
                     }
@@ -840,6 +851,7 @@ public class Task {
                     }
 
                     // 处理每个在线用户
+                    List<LiveWatchLog> updateLog = new ArrayList<>();
                     for (LiveWatchUser user : onlineUsers) {
                         try {
                             Long userId = user.getUserId();
@@ -869,13 +881,22 @@ public class Task {
 
                             // 使用 updateLiveWatchLogTypeByDuration 的逻辑更新观看记录状态
                             updateLiveWatchLogTypeByDuration(liveId, userId, qwUserId, externalContactId,
-                                    onlineSeconds, totalVideoDuration);
+                                    onlineSeconds, totalVideoDuration, updateLog);
                             
                         } catch (Exception e) {
                             log.error("处理用户观看记录状态异常: liveId={}, userId={}, error={}",
                                     liveId, user.getUserId(), e.getMessage(), e);
                         }
                     }
+                    // 批量插入回放用户数据
+                    if (!updateLog.isEmpty()) {
+                        int batchSize = 500;
+                        for (int i = 0; i < updateLog.size(); i += batchSize) {
+                            int end = Math.min(i + batchSize, updateLog.size());
+                            List<LiveWatchLog> batch = updateLog.subList(i, end);
+                            liveWatchLogService.batchUpdateLiveWatchLog(batch);
+                        }
+                    }
                     
                 } catch (Exception e) {
                     log.error("处理直播间观看记录状态异常: liveId={}, error={}",
@@ -897,7 +918,7 @@ public class Task {
      * @param totalVideoDuration 视频总时长(秒)
      */
     private void updateLiveWatchLogTypeByDuration(Long liveId, Long userId, Long qwUserId,
-                                                   Long exId, Long onlineSeconds, long totalVideoDuration) {
+                                                   Long exId, Long onlineSeconds, long totalVideoDuration, List<LiveWatchLog> updateLog) {
         try {
             // 查询 LiveWatchLog
             LiveWatchLog queryLog = new LiveWatchLog();
@@ -906,7 +927,7 @@ public class Task {
             queryLog.setQwUserId(String.valueOf(qwUserId));
             queryLog.setExternalContactId(exId);
 
-            List<LiveWatchLog> logs = liveWatchLogService.selectLiveWatchLogList(queryLog);
+            List<LiveWatchLog> logs = liveWatchLogService.selectLiveWatchLogByLogIdWithCache(queryLog);
             if (logs == null || logs.isEmpty()) {
                 return;
             }
@@ -940,7 +961,7 @@ public class Task {
                 // 如果 logType 已经是 2(完课),不再更新
                 if (needUpdate) {
                     log.setLogType(newLogType);
-                    liveWatchLogService.updateLiveWatchLog(log);
+                    updateLog.add(log);
                 }
             }
         } catch (Exception e) {

+ 75 - 2
fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -36,6 +36,7 @@ import javax.websocket.*;
 import javax.websocket.server.ServerEndpoint;
 import java.io.EOFException;
 import java.io.IOException;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.Lock;
@@ -80,6 +81,7 @@ public class WebSocketServer {
     private final LiveCouponMapper liveCouponMapper = SpringUtils.getBean(LiveCouponMapper.class);
     private final ILiveWatchLogService liveWatchLogService = SpringUtils.getBean(ILiveWatchLogService.class);
     private final ILiveVideoService liveVideoService = SpringUtils.getBean(ILiveVideoService.class);
+    private final ILiveCompletionPointsRecordService completionPointsRecordService = SpringUtils.getBean(ILiveCompletionPointsRecordService.class);
     private static Random random = new Random();
     
     // Redis key 前缀:用户进入直播间时间
@@ -126,7 +128,7 @@ public class WebSocketServer {
 
         // 记录连接信息 管理员不记录
         if (userType == 0) {
-            FsUserScrm fsUser = fsUserService.selectFsUserByUserId(userId);
+            FsUserScrm fsUser = fsUserService.selectFsUserById(userId);
             if (Objects.isNull(fsUser)) {
                 throw new BaseException("用户信息错误");
             }
@@ -273,7 +275,7 @@ public class WebSocketServer {
         ConcurrentHashMap<Long, Session> room = getRoom(liveId);
         List<Session> adminRoom = getAdminRoom(liveId);
         if (userType == 0) {
-            FsUserScrm fsUser = fsUserService.selectFsUserByUserId(userId);
+            FsUserScrm fsUser = fsUserService.selectFsUserById(userId);
             if (Objects.isNull(fsUser)) {
                 throw new BaseException("用户信息错误");
             }
@@ -349,6 +351,32 @@ public class WebSocketServer {
                     if (msg.getData() != null && !msg.getData().isEmpty()) {
                         try {
                             Long currentDuration = Long.parseLong(msg.getData());
+
+                            Live currentLive = liveService.selectLiveByLiveId(liveId);
+                            if (currentLive == null) {
+                                break;
+                            }
+                            
+                            // 判断直播是否已开始:status=2(直播中) 或 当前时间 >= 开播时间
+                            boolean isLiveStarted = false;
+                            if (currentLive.getStatus() != null && currentLive.getStatus() == 2) {
+                                // status=2 表示直播中
+                                isLiveStarted = true;
+                            } else if (currentLive.getStartTime() != null) {
+                                // 判断当前时间是否已超过开播时间
+                                LocalDateTime now = java.time.LocalDateTime.now();
+                                isLiveStarted = now.isAfter(currentLive.getStartTime()) || now.isEqual(currentLive.getStartTime());
+                            }
+                            
+                            if (!isLiveStarted) {
+                                log.debug("[心跳-观看时长] 直播未开始(开播倒计时中),不统计观看时长, liveId={}, status={}, startTime={}", 
+                                        liveId, currentLive.getStatus(), currentLive.getStartTime());
+                                break;
+                            }
+                            
+                            log.debug("[心跳-观看时长] 直播已开始,统计观看时长, liveId={}, userId={}, duration={}秒", 
+                                    liveId, watchUserId, currentDuration);
+                            
                             // 使用Hash结构存储:一个直播间一个Hash,包含所有用户的时长
                             String hashKey = "live:watch:duration:hash:" + liveId;
                             String userIdField = String.valueOf(watchUserId);
@@ -361,6 +389,8 @@ public class WebSocketServer {
                                 // 设置过期时间(2小时)
                                 redisCache.expire(hashKey, 2, TimeUnit.HOURS);
 
+                                checkAndSendCompletionPointsInRealTime(liveId, watchUserId, currentDuration);
+
                             }
                         } catch (Exception e) {
                             log.error("[心跳-观看时长] 更新失败, liveId={}, userId={}, data={}", 
@@ -1315,5 +1345,48 @@ public class WebSocketServer {
         }
     }
 
+    /**
+     * 实时检查并推送完课积分
+     * 在用户观看时长更新时立即检查是否达到完课条件,达到则立即推送
+     * @param liveId 直播间ID
+     * @param userId 用户ID
+     * @param duration 当前观看时长(秒)
+     */
+    private void checkAndSendCompletionPointsInRealTime(long liveId, long userId, Long duration) {
+        try {
+            log.debug("[实时完课检查] liveId={}, userId={}, duration={}秒", liveId, userId, duration);
+
+            // 1. 调用完课记录服务检查并创建完课记录
+            completionPointsRecordService.checkAndCreateCompletionRecord(liveId, userId, duration);
+
+            // 2. 查询是否有新的未领取完课记录
+            List<LiveCompletionPointsRecord> unreceivedRecords =
+                completionPointsRecordService.getUserUnreceivedRecords(liveId, userId);
+
+            if (unreceivedRecords == null || unreceivedRecords.isEmpty()) {
+                // 没有待领取的完课记录
+                return;
+            }
+
+            // 3. 构建推送消息
+            SendMsgVo sendMsgVo = new SendMsgVo();
+            sendMsgVo.setLiveId(liveId);
+            sendMsgVo.setUserId(userId);
+            sendMsgVo.setCmd("completionPoints");
+            sendMsgVo.setMsg("完成任务!");
+            sendMsgVo.setData(JSONObject.toJSONString(unreceivedRecords.get(0)));
+
+            // 4. 实时推送完课积分弹窗
+            sendCompletionPointsMessage(liveId, userId, sendMsgVo);
+
+            log.info("[实时完课推送] 发送完课积分弹窗通知, liveId={}, userId={}, points={}, duration={}秒",
+                    liveId, userId, unreceivedRecords.get(0).getPointsAwarded(), duration);
+
+        } catch (Exception e) {
+            log.error("[实时完课推送] 实时检查完课积分失败, liveId={}, userId={}, duration={}",
+                    liveId, userId, duration, e);
+        }
+    }
+
 }
 

+ 3 - 0
fs-service/src/main/java/com/fs/company/domain/Company.java

@@ -138,6 +138,9 @@ public class Company extends BaseEntity
 
     private BigDecimal redPackageMoney;
 
+    // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
+    private Integer isOpenRestReminder;
+
     @TableField(exist = false)
     private List<Long> ids;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyVO.java

@@ -104,4 +104,7 @@ public class CompanyVO implements Serializable
      * 新增展示商户号(分公司配置时有值)
      */
     private String mchId;
+
+    // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
+    private Integer isOpenRestReminder;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java

@@ -119,4 +119,7 @@ public class FsUserCoursePeriod
     private Date periodLine;
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
     private String isNeedRegisterMember;
+
+    // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
+    private Integer IsOpenRestReminder;
 }

+ 0 - 2
fs-service/src/main/java/com/fs/course/service/IFsCourseRedPacketLogService.java

@@ -89,6 +89,4 @@ public interface IFsCourseRedPacketLogService
     void queryRedPacketResult(String startTime, String endTime);
 
     R getBillsByTransferBillNo(String batchId);
-
-    R transferBatchesBatchId(String batchId);
 }

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

@@ -105,4 +105,6 @@ public interface IFsUserCoursePeriodService
     int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod,String s);
 
     List<SysDictData> selectFsUserCoursePeriodListLabel(FsUserCoursePeriod fsUserCoursePeriod);
+
+    int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod);
 }

+ 47 - 37
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -17,6 +17,7 @@ import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.company.mapper.CompanyMoneyLogsMapper;
+import com.fs.company.service.ICompanyConfigService;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.config.RedPacketConfig;
 import com.fs.course.domain.FsCourseWatchLog;
@@ -478,33 +479,8 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
                 company.getCompanyId(), moneyLog.getMoney());
     }
 
-    @Override
-    public R transferBatchesBatchId(String batchId) {
-        FsCourseRedPacketLog log = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByBatchId(batchId);
-        if (log ==null){
-            return R.error("未查询到红包记录!");
-        }
-        String json = configService.selectConfigByKey("redPacket.config");
-        RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
-        //创建微信订单
-        WxPayConfig payConfig = new WxPayConfig();
-        BeanUtils.copyProperties(config,payConfig);
-        WxPayService wxPayService = new WxPayServiceImpl();
-        wxPayService.setConfig(payConfig);
-        TransferService transferService=wxPayService.getTransferService();
-
-        QueryTransferBatchesRequest request = new QueryTransferBatchesRequest();
-        request.setBatchId(batchId);
-
-        try {
-            QueryTransferBatchesResult queryTransferBatchesResult = transferService.transferBatchesBatchId(request);
-            logger.info("FsCourseRedPacketLog-log_id:{},【红包处理】查询批次结果:{}",log.getLogId(),queryTransferBatchesResult);
-            return R.ok(queryTransferBatchesResult.toString());
-        } catch (WxPayException e) {
-            logger.error(e.getMessage());
-            return R.error(e.getMessage());
-        }
-    }
+    @Autowired
+    private ICompanyConfigService companyConfigService;
 
     @Override
     public R getBillsByTransferBillNo(String batchId) {
@@ -512,8 +488,29 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
         if (log ==null){
             return R.error("未查询到红包记录!");
         }
-        String json = configService.selectConfigByKey("redPacket.config");
-        RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
+        // 获取配置信息
+        CourseConfig courseConfig = JSONUtil.toBean(configService.selectConfigByKey("course.config"), CourseConfig.class);
+
+        String json;
+        RedPacketConfig config = new RedPacketConfig();
+        // 根据红包模式获取配置
+        switch (courseConfig.getRedPacketMode()){
+            case 1:
+                json = configService.selectConfigByKey("redPacket.config");
+                config = JSONUtil.toBean(json, RedPacketConfig.class);
+                break;
+            case 2:
+                json = companyConfigService.selectRedPacketConfigByKey(log.getCompanyId());
+                //如果分公司配置为空就走总后台的配置
+                if (StringUtils.isEmpty(json)){
+                    json = configService.selectConfigByKey("redPacket.config");
+                }
+                config = JSONUtil.toBean(json, RedPacketConfig.class);
+                break;
+            default:
+                throw new UnsupportedOperationException("当前红包模式不支持!");
+        }
+
         //创建微信订单
         WxPayConfig payConfig = new WxPayConfig();
         BeanUtils.copyProperties(config,payConfig);
@@ -521,15 +518,28 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
         wxPayService.setConfig(payConfig);
         TransferService transferService=wxPayService.getTransferService();
 
-        try {
-            TransferBillsGetResult queryRedPacketResult = transferService.getBillsByTransferBillNo(batchId);
-            logger.info("FsCourseRedPacketLog-log_id:{},【红包处理】查询批次结果:{}",log.getLogId(),queryRedPacketResult);
-            return R.ok(queryRedPacketResult.toString());
-        } catch (WxPayException e) {
-            logger.error(e.getMessage());
-            return R.error(e.getMessage());
+        if (config.getIsNew() != null && config.getIsNew() == 1) {
+            try {
+                TransferBillsGetResult queryRedPacketResult = transferService.getBillsByTransferBillNo(batchId);
+                logger.info("FsCourseRedPacketLog-log_id:{},【红包处理】查询批次结果:{}",log.getLogId(),queryRedPacketResult);
+                return R.ok(queryRedPacketResult.toString());
+            } catch (WxPayException e) {
+                logger.error(e.getMessage());
+                return R.error(e.getMessage());
+            }
+        } else {
+            QueryTransferBatchesRequest request = new QueryTransferBatchesRequest();
+            request.setBatchId(batchId);
+
+            try {
+                QueryTransferBatchesResult queryTransferBatchesResult = transferService.transferBatchesBatchId(request);
+                logger.info("FsCourseRedPacketLog-log_id:{},【红包处理】查询批次结果:{}",log.getLogId(),queryTransferBatchesResult);
+                return R.ok(queryTransferBatchesResult.toString());
+            } catch (WxPayException e) {
+                logger.error(e.getMessage());
+                return R.error(e.getMessage());
+            }
         }
 
-
     }
 }

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

@@ -343,4 +343,16 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     public List<SysDictData> selectFsUserCoursePeriodListLabel(FsUserCoursePeriod fsUserCoursePeriod) {
         return fsUserCoursePeriodMapper.selectFsUserCoursePeriodListLabel(fsUserCoursePeriod);
     }
+
+    /**
+     * @Description: 更新营期信息
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/12/19 10:52
+     */
+    @Override
+    public int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod) {
+        return fsUserCoursePeriodMapper.updateFsUserCoursePeriod(fsUserCoursePeriod);
+    }
 }

+ 46 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -2829,7 +2829,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         }
 
         // 2025-11-16 鹤颜堂 xgb 添加配置控制休息提示是否打开要暂停 默认打开 0-关闭 1-打开
-        if (config.getIsOpenRestReminder() == null || config.getIsOpenRestReminder() == 1) {
+        if(isOpenRestReminder(config,watchLog)){
             if (courseVideoDetails != null && courseVideoDetails.getDuration() != null) {
                 // 查询视频是否设置了红包,没有就不提示
                 Integer fsUserCourseVideoRedPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyCount(param.getVideoId(), null, param.getPeriodId());
@@ -2840,6 +2840,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             }
         }
 
+
         vo.setTipsTime(tipsTime);
         vo.setTipsTime2(tipsTime2);
         //判断是否完课
@@ -2909,6 +2910,50 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         return ResponseResult.ok(vo);
     }
 
+    /**
+     * @Description: 是否看课中断
+     * @Param:
+     * @Return:
+     * @Author xgb 默认 打开看课中断
+     * @Date 2025/12/18 17:33
+     */
+
+    private boolean isOpenRestReminder(CourseConfig config ,FsCourseWatchLog watchLog){
+        // 查询公司看课中断是否打开
+        boolean result= true;
+
+        if (config.getIsOpenRestReminder() != null && config.getIsOpenRestReminder() == 0) {
+            result=false;
+        }
+
+        if(watchLog!=null){
+            if(watchLog.getCompanyId()!=null){
+                Company company=companyMapper.selectCompanyById(watchLog.getCompanyId());
+                if(company!=null && company.getIsOpenRestReminder()!=null){
+                    if(company.getIsOpenRestReminder()==0){
+                        result=false;
+                    }else {
+                        result=true;
+                    }
+                }
+            }
+
+            if(watchLog.getPeriodId()!=null){
+                FsUserCoursePeriod period= fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(watchLog.getPeriodId());
+                if(period!=null && period.getIsOpenRestReminder()!=null){
+                    if(period.getIsOpenRestReminder()==0){
+                        result=false;
+                    }else {
+                        result=true;
+                    }
+                }
+            }
+        }
+
+
+        return result;
+    }
+
     @Override
     public R addWatchLogByLink(FsUserCourseAddCompanyUserParam param) {
 

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

@@ -90,4 +90,7 @@ public class FsUserCoursePeriodVO implements Serializable {
     private Date periodLine;
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
     private String isNeedRegisterMember;
+
+    // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
+    private Integer IsOpenRestReminder;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralCartMapper.java

@@ -28,4 +28,11 @@ public interface FsIntegralCartMapper extends BaseMapper<FsIntegralCart> {
      * @return  list
      */
     List<FsIntegralCartVO> getCartsByMap(@Param("params") Map<String, Object> params);
+
+    /**
+     * 根据商品ID删除购物车记录
+     * @param goodsId   商品ID
+     * @return  删除数量
+     */
+    int deleteCartByGoodsId(@Param("goodsId") Long goodsId);
 }

+ 7 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsCouponServiceImpl.java

@@ -141,6 +141,13 @@ public class FsCouponServiceImpl implements IFsCouponService
         if(fsUserCouponMapper.checkReceive(param.getUserId(),coupon.getCouponId())>0){
             return R.error("您已领取此券");
         }
+        //判断是否是私域优惠券
+        Integer couponType = coupon.getCouponType();
+        if(couponType!=null && couponType==5){
+            if (param.getCompanyId() == null || param.getCompanyUserId() == null) {
+                return R.error("您无法领取该优惠券");
+            }
+        }
         FsUserCoupon userCoupon=new FsUserCoupon();
         userCoupon.setUserId(param.getUserId());
         userCoupon.setStatus(0);

+ 11 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralGoodsServiceImpl.java

@@ -9,6 +9,7 @@ import com.fs.course.domain.FsCourseAnswerReward;
 import com.fs.his.domain.FsChineseMedicine;
 import com.fs.his.domain.FsIntegralGoods;
 import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsIntegralCartMapper;
 import com.fs.his.mapper.FsIntegralGoodsMapper;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.param.FsIntegralGoodsListUParam;
@@ -37,6 +38,8 @@ public class FsIntegralGoodsServiceImpl implements IFsIntegralGoodsService
     private FsIntegralGoodsMapper fsIntegralGoodsMapper;
     @Autowired
     private FsUserMapper fsUserMapper;
+    @Autowired
+    private FsIntegralCartMapper fsIntegralCartMapper;
 
     @Autowired
     private ISysConfigService configService;
@@ -99,6 +102,11 @@ public class FsIntegralGoodsServiceImpl implements IFsIntegralGoodsService
     @Override
     public int deleteFsIntegralGoodsByGoodsIds(Long[] goodsIds)
     {
+        // 先删除购物车中的相关记录
+        for (Long goodsId : goodsIds) {
+            fsIntegralCartMapper.deleteCartByGoodsId(goodsId);
+        }
+        // 再删除商品
         return fsIntegralGoodsMapper.deleteFsIntegralGoodsByGoodsIds(goodsIds);
     }
 
@@ -111,6 +119,9 @@ public class FsIntegralGoodsServiceImpl implements IFsIntegralGoodsService
     @Override
     public int deleteFsIntegralGoodsByGoodsId(Long goodsId)
     {
+        // 先删除购物车中的相关记录
+        fsIntegralCartMapper.deleteCartByGoodsId(goodsId);
+        // 再删除商品
         return fsIntegralGoodsMapper.deleteFsIntegralGoodsByGoodsId(goodsId);
     }
 

+ 51 - 19
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -43,6 +43,7 @@ import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.PhoneUtil;
+import com.fs.his.utils.RedisCacheUtil;
 import com.fs.his.vo.*;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwUserMapper;
@@ -161,6 +162,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
 
     @Autowired
     private IFsUserAddressService fsUserAddressService;
+
+    @Autowired
+    private RedisCacheUtil redisCacheUtil;
     /**
      * 查询积分商品订单
      *
@@ -312,6 +316,10 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             throw new CustomException("库存不足");
         }
 
+        // 清除商品缓存
+        redisCacheUtil.delSpringCacheKey("getIntegralGoodsById", integralGoods.getGoodsId());
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+
         integralGoods.setNum(1);
         List<FsIntegralGoods> goodsItem = new ArrayList<>();
         goodsItem.add(integralGoods);
@@ -467,6 +475,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
                 throw new CustomException("库存不足");
             }
 
+            // 清除商品缓存
+            redisCacheUtil.delSpringCacheKey("getIntegralGoodsById", integralGoods.getGoodsId());
+
             totalIntegral += integralGoods.getIntegral() * cart.getCartNum();
             totalCash = totalCash.add(integralGoods.getCash().multiply(BigDecimal.valueOf(cart.getCartNum())));
 
@@ -474,7 +485,17 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             goodsItem.add(integralGoods);
         }
 
-        return createOrder(user, address, totalIntegral, totalCash, goodsItem, null);
+        // 清除商品列表缓存
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+
+        // 创建订单
+        R result = createOrder(user, address, totalIntegral, totalCash, goodsItem, null);
+
+        // 订单创建成功后,删除购物车中已下单的商品
+        if (result.get("code").equals(200)) {
+            cartService.delCartByIds(user.getUserId(), param.getIds());
+        }
+        return result;
     }
 
     @Override
@@ -566,8 +587,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
     public R cannelOrder(Long orderId) {
         // 取消订单
         FsIntegralOrder order = fsIntegralOrderMapper.selectFsIntegralOrderByOrderId(orderId);
-        if (!order.getStatus().equals(4)){
-            return R.error("非法操作");
+        // 允许取消待支付(4)和待发货(1)的订单
+        if (!order.getStatus().equals(4) && !order.getStatus().equals(1)){
+            return R.error("非法操作,只能取消待支付或待发货的订单");
         }
 
         order.setStatus(5);
@@ -576,26 +598,36 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         // 还原库存
         if (order.getItemJson().startsWith("[") && order.getItemJson().endsWith("]")){
             List<FsIntegralGoods> goodsItem = JSONUtil.toBean(order.getItemJson(), new TypeReference<List<FsIntegralGoods>>(){}, true);
-            goodsItem.forEach(goods -> fsIntegralGoodsMapper.addStock(goods.getGoodsId(), Objects.isNull(goods.getNum()) ? 1 : goods.getNum()));
+            goodsItem.forEach(goods -> {
+                fsIntegralGoodsMapper.addStock(goods.getGoodsId(), Objects.isNull(goods.getNum()) ? 1 : goods.getNum());
+                // 清除商品缓存
+                redisCacheUtil.delSpringCacheKey("getIntegralGoodsById", goods.getGoodsId());
+            });
         } else {
             FsIntegralGoods integralGoods = JSONUtil.toBean(order.getItemJson(), FsIntegralGoods.class);
             fsIntegralGoodsMapper.addStock(integralGoods.getGoodsId(), Objects.isNull(integralGoods.getNum()) ? 1 : integralGoods.getNum());
+            // 清除商品缓存
+            redisCacheUtil.delSpringCacheKey("getIntegralGoodsById", integralGoods.getGoodsId());
+        }
+        // 清除商品列表缓存
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+
+        // 还原积分(只有当订单消耗了积分时才退还)
+        if (StringUtils.isNotEmpty(order.getIntegral()) && Long.parseLong(order.getIntegral()) > 0) {
+            FsUser user=fsUserMapper.selectFsUserByUserId(order.getUserId());
+            FsUser userMap=new FsUser();
+            userMap.setUserId(user.getUserId());
+            userMap.setIntegral(user.getIntegral() + Long.parseLong(order.getIntegral()));
+            fsUserMapper.updateFsUser(userMap);
+            FsUserIntegralLogs logs = new FsUserIntegralLogs();
+            logs.setIntegral(Long.parseLong(order.getIntegral()));
+            logs.setUserId(order.getUserId());
+            logs.setBalance(userMap.getIntegral());
+            logs.setLogType(5);
+            logs.setBusinessId(order.getOrderId().toString());
+            logs.setCreateTime(new Date());
+            fsUserIntegralLogsMapper.insertFsUserIntegralLogs(logs);
         }
-
-        // 还原积分
-        FsUser user=fsUserMapper.selectFsUserByUserId(order.getUserId());
-        FsUser userMap=new FsUser();
-        userMap.setUserId(user.getUserId());
-        userMap.setIntegral(user.getIntegral() + Long.parseLong(order.getIntegral()));
-        fsUserMapper.updateFsUser(userMap);
-        FsUserIntegralLogs logs = new FsUserIntegralLogs();
-        logs.setIntegral(Long.parseLong(order.getIntegral()));
-        logs.setUserId(order.getUserId());
-        logs.setBalance(userMap.getIntegral());
-        logs.setLogType(5);
-        logs.setBusinessId(order.getOrderId().toString());
-        logs.setCreateTime(new Date());
-        fsUserIntegralLogsMapper.insertFsUserIntegralLogs(logs);
 
         return R.ok();
     }

+ 1 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -1141,7 +1141,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         logger.info("zyp \n【收到转账回调V3::分公司】:{}",notifyData);
         try {
 //            String json = configService.selectConfigByKey("redPacket.config");
-            String json = companyConfigMapper.selectRedPacketConfigByKey(companyId);
+            String json = companyConfigService.selectRedPacketConfigByKey(companyId);
             RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
 
             //创建微信订单

+ 7 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveWatchLogMapper.java

@@ -74,4 +74,11 @@ public interface LiveWatchLogMapper extends BaseMapper<LiveWatchLog> {
 
     List<LiveWatchLogListVO> selectLiveWatchLogListInfo(LiveWatchLog liveWatchLog);
 
+    /**
+     * 批量更新直播看课记录
+     * @param liveWatchLogs 需要更新的直播看课记录列表
+     * @return 更新的记录数
+     */
+    int batchUpdateLiveWatchLog(@Param("list") List<LiveWatchLog> liveWatchLogs);
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/live/service/ILiveAfterSalesService.java

@@ -84,7 +84,7 @@ public interface ILiveAfterSalesService {
 
     R refundMoney(LiveAfterSalesRefundParam param);
 
-    R cancel(LiveAfterSalesCancelParam param);
+    R cancel(LiveAfterSalesCancelParam param)  throws ParseException;
 
     R applyForAfterSales(String userId, LiveAfterSalesParam param);
 

+ 7 - 0
fs-service/src/main/java/com/fs/live/service/ILiveService.java

@@ -187,6 +187,13 @@ public interface ILiveService
      */
     LiveConfigVo asyncToCacheLiveConfig(Long liveId);
 
+    /**
+     * 清除直播间数据缓存
+     * @param liveId 直播间ID
+     * @return 结果
+     */
+    R clearLiveCache(Long liveId);
+
     List<Live> liveCompanyList(Long companyId);
 
     R subNotifyLive(LiveNotifyParam liveNotifyParam);

+ 14 - 0
fs-service/src/main/java/com/fs/live/service/ILiveWatchLogService.java

@@ -66,4 +66,18 @@ public interface ILiveWatchLogService extends IService<LiveWatchLog>{
      * @return
      */
     List<LiveWatchLogListVO> selectLiveWatchLogListInfo(LiveWatchLog liveWatchLog);
+
+    /**
+     * 批量更新直播看课记录
+     * @param liveWatchLogs 需要更新的直播看课记录列表
+     * @return 更新的记录数
+     */
+    int batchUpdateLiveWatchLog(List<LiveWatchLog> liveWatchLogs);
+
+    /**
+     * 查询直播看课记录并缓存1小时
+     * @param logId 直播看课记录主键
+     * @return 直播看课记录
+     */
+    List<LiveWatchLog> selectLiveWatchLogByLogIdWithCache(LiveWatchLog logId);
 }

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

@@ -177,4 +177,6 @@ public interface ILiveWatchUserService {
      * @param liveId 直播间ID
      */
     void clearLiveFlagCache(Long liveId);
+
+    List<LiveWatchUser> selectAllWatchUser(LiveWatchUser queryUser);
 }

+ 9 - 15
fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java

@@ -280,8 +280,8 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
-    public R cancel(LiveAfterSalesCancelParam param) {
+    @Transactional
+    public R cancel(LiveAfterSalesCancelParam param)  throws ParseException{
         LiveAfterSales storeAfterSales = baseMapper.selectLiveAfterSalesById(param.getSalesId());
         if (storeAfterSales == null) {
             throw new CustomException("未查询到售后订单信息");
@@ -322,13 +322,8 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
                     orderMap.setStatus(order.getStatus());
                     liveOrderService.updateLiveOrder(orderMap);
                     liveOrderItemMapper.updateFsStoreOrderCode(order.getOrderId(),orderSn);
-                    try {
-                        //生成新的订单
-                        liveOrderService.createOmsOrder(order.getOrderId());
-                    } catch (Exception e) {
-                        log.error("撤销售后,生成oms订单异常",e);
-                    }
-
+                    //生成新的订单
+                    liveOrderService.createOmsOrder(order.getOrderId());
                 }
             }
         }
@@ -431,7 +426,6 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
         storeAfterSales.setIsDel(0);
         storeAfterSales.setOrderStatus(orderStatus);
         storeAfterSales.setUserId(Long.valueOf(userId));
-        storeAfterSales.setOrderStatus(orderStatus);
         storeAfterSales.setCompanyId(order.getCompanyId());
         storeAfterSales.setCompanyUserId(order.getCompanyUserId());
         liveAfterSalesService.insertLiveAfterSales(storeAfterSales);
@@ -557,6 +551,9 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
         if(ObjectUtil.isNull(liveAfterSales)) {
             throw new IllegalArgumentException("售后单不存在!");
         }
+        if (!liveAfterSales.getStatus().equals(AfterStatusEnum.STATUS_3.getValue())) {
+            throw new CustomException("非法操作");
+        }
         return liveOrderService.refundOrderMoney(liveAfterSales.getOrderId(),liveAfterSales);
     }
 
@@ -638,6 +635,7 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
         if (!liveAfterSales.getStatus().equals(AfterStatusEnum.STATUS_0.getValue())) {
             throw new CustomException("非法操作");
         }
+        //仅退款
         if(liveAfterSales.getRefundType().equals(0)){
             //仅退款未发货处理
             if(liveAfterSales.getOrderStatus().equals(OrderInfoEnum.STATUS_1.getValue())){
@@ -645,14 +643,11 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
                 liveAfterSales.setStatus(3);
                 baseMapper.updateLiveAfterSales(liveAfterSales);
             }
-            //待收货直接退款
+            //仅退款待收货处理
             else if(liveAfterSales.getOrderStatus().equals(OrderInfoEnum.STATUS_2.getValue())){
                 liveAfterSales.setStatus(2);
                 baseMapper.updateLiveAfterSales(liveAfterSales);
             //已完成 退货退款
-            } else if(liveAfterSales.getOrderStatus().equals(4)) {
-                liveAfterSales.setStatus(1);
-                baseMapper.updateLiveAfterSales(liveAfterSales);
             }
             LiveAfterSalesLogs salesLogs = new LiveAfterSalesLogs();
             salesLogs.setStoreAfterSalesId(liveAfterSales.getId());
@@ -897,7 +892,6 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
         LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(storeAfterSales.getOrderId()));
         order.setStatus(storeAfterSales.getOrderStatus());
         order.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue().toString());
-        order.setIsAfterSales(0);
         liveOrderService.updateLiveOrder(order);
         //操作记录
         LiveAfterSalesLogs logs = new LiveAfterSalesLogs();

+ 10 - 15
fs-service/src/main/java/com/fs/live/service/impl/LiveCompletionPointsRecordServiceImpl.java

@@ -62,7 +62,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
             // 1. 获取直播信息和配置
             Live live = liveService.selectLiveByLiveId(liveId);
             if (live == null) {
-                log.warn("直播间不存在, liveId={}", liveId);
+
                 return;
             }
 
@@ -71,7 +71,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
             
             // 检查是否开启完课积分功能
             if (!config.isEnabled()) {
-                log.debug("直播间未开启完课积分功能, liveId={}", liveId);
+
                 return;
             }
             
@@ -80,8 +80,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
             int[] pointsConfig = config.getPointsConfig();
             
             if (completionRate == null || pointsConfig == null || pointsConfig.length == 0) {
-                log.warn("完课积分配置不完整, liveId={}, completionRate={}, pointsConfig={}", 
-                        liveId, completionRate, pointsConfig);
+
                 return;
             }
 
@@ -90,19 +89,18 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
             if (actualWatchDuration == null) {
                 // 自动累加直播和回放的观看时长
                 actualWatchDuration = liveWatchUserService.getTotalWatchDuration(liveId, userId);
-                log.debug("自动累计观看时长: liveId={}, userId={}, totalDuration={}",
-                        liveId, userId, actualWatchDuration);
+
             }
 
             if (actualWatchDuration == null || actualWatchDuration <= 0) {
-                log.debug("观看时长为0, liveId={}, userId={}", liveId, userId);
+
                 return;
             }
 
             // 4. 获取视频总时长(秒)
             Long videoDuration = live.getDuration();
             if (videoDuration == null || videoDuration <= 0) {
-                log.warn("直播间视频时长无效, liveId={}, duration={}", liveId, videoDuration);
+
                 return;
             }
 
@@ -118,8 +116,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
 
             // 6. 判断是否达到完课标准
             if (watchRate.compareTo(BigDecimal.valueOf(completionRate)) < 0) {
-                log.debug("观看时长未达到完课标准, liveId={}, userId={}, watchDuration={}, videoDuration={}, watchRate={}%, required={}%",
-                        liveId, userId, actualWatchDuration, videoDuration, watchRate, completionRate);
+
                 return;
             }
 
@@ -129,7 +126,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
 
             LiveCompletionPointsRecord todayRecord = recordMapper.selectByUserAndDate(liveId, userId, currentDate);
             if (todayRecord != null) {
-                log.debug("今天已有完课记录, liveId={}, userId={}", liveId, userId);
+
                 return;
             }
 
@@ -145,8 +142,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
 
                 if (daysBetween == 0) {
                     continuousDays = latestRecord.getContinuousDays();
-                    log.debug("今天已有其他直播间完课记录,继承连续天数, liveId={}, userId={}, continuousDays={}", 
-                            liveId, userId, continuousDays);
+
                 } else if (daysBetween == 1) {
                     // 昨天完课了,连续天数+1
                     continuousDays = latestRecord.getContinuousDays() + 1;
@@ -177,8 +173,7 @@ public class LiveCompletionPointsRecordServiceImpl implements ILiveCompletionPoi
 
             recordMapper.insertRecord(record);
 
-            log.info("创建完课记录成功, liveId={}, userId={}, watchDuration={}, videoDuration={}, watchRate={}%, continuousDays={}, points={}",
-                    liveId, userId, actualWatchDuration, videoDuration, watchRate, continuousDays, points);
+
 
         } catch (Exception e) {
             log.error("检查并创建完课记录失败, liveId={}, userId={}", liveId, userId, e);

+ 85 - 63
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.live.service.impl;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
+import java.text.DecimalFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
@@ -689,7 +690,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     }
 
     @Override
-    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
+    @Transactional
     public String payConfirm(Integer type,Long orderId,String payCode,String tradeNo,String bankTransactionId,String bankSerialNo) {
         Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
         try {
@@ -709,7 +710,12 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         liveOrderPaymentMapper.updateLiveOrderPayment(paymentMap);
                         order = baseMapper.selectFsUserVipOrderByOrderCode(storePayment.getBusinessCode());
                         if(order==null || !order.getStatus().equals(OrderInfoEnum.STATUS_0.getValue())){
-                            throw new CustomException("当前订单未找到或者订单状态不为待支付! paycode:"+payCode);
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return "";
+                        }
+                        if (order != null && !order.getIsPay().equals(0)) {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return "";
                         }
                     }
                 }
@@ -1389,6 +1395,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public R refundOrderMoney(Long orderId, LiveAfterSales liveAfterSales) {
+        BigDecimal refundAmount = liveAfterSales.getRefundAmount();
         IErpOrderService erpOrderService = getErpService();
         FsErpConfig erpConfig = configUtil.generateStructConfigByKey("his.config", FsErpConfig.class);
         LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(orderId));
@@ -1407,43 +1414,49 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 && !CloudHostUtils.hasCloudHostName("康年堂")) {
             return R.error("暂未推送至erp,请稍后再试!");
         }
-        liveAfterSales.setRefundAmount(order.getPayPrice());
+        if (Objects.isNull(refundAmount)) {
+            throw new CustomException("退款金额不能为空");
+        }
+        if (order.getPayMoney().compareTo(refundAmount) < 0) {
+            throw new CustomException("退款金额不能大于支付金额");
+        }
+        liveAfterSales.setRefundAmount(liveAfterSales.getRefundAmount());
         liveAfterSales.setStatus(4);
         liveAfterSales.setSalesStatus(3);
         liveAfterSalesService.updateLiveAfterSales(liveAfterSales);
-        if (StringUtils.isNotEmpty(order.getExtendOrderId())) {
-            ErpRefundUpdateRequest request = new ErpRefundUpdateRequest();
-            request.setTid(order.getOrderCode());
-            request.setOid(order.getOrderCode());
-            request.setRefund_state(1);
-            request.setOrderStatus(order.getStatus());
-            if (ObjectUtils.equals(order.getStatus(), 2)) {
-                LiveAfterSalesParam param = new LiveAfterSalesParam();
-                param.setOrderCode(order.getOrderCode());
-                param.setRefundAmount(order.getPayMoney());
-                param.setServiceType(1);
-                param.setReasons("后台手动退款流程");
-                param.setExplainImg(null);
-                List<FsStoreAfterSalesProductParam> productParams = new ArrayList<>();
-                List <LiveOrderItem> items = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
-                for (LiveOrderItem item : items){
-                    FsStoreAfterSalesProductParam param1 = new FsStoreAfterSalesProductParam();
-                    param1.setProductId(item.getProductId());
-                    param1.setNum(Math.toIntExact(item.getNum()));
-                    productParams.add(param1);
-                }
-                return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
-            } else {
-                ErpOrderQueryRequert queryRequest = new ErpOrderQueryRequert();
-                queryRequest.setCode(order.getExtendOrderId());
-                ErpOrderQueryResponse response = erpOrderService.getLiveOrder(queryRequest);
-                if (response.getOrders() != null && response.getOrders().size() > 0) {
-                    if (response.getOrders().get(0).getCancle() != null && !response.getOrders().get(0).getCancle()) {
-                        jSTOrderService.refundUpdateLive(request);
-                    }
-                }
-            }
-        }
+//        if (StringUtils.isNotEmpty(order.getExtendOrderId())) {
+//            ErpRefundUpdateRequest request = new ErpRefundUpdateRequest();
+//            request.setTid(order.getOrderCode());
+//            request.setOid(order.getOrderCode());
+//            request.setRefund_state(1);
+//            request.setOrderStatus(order.getStatus());
+//            if (ObjectUtils.equals(order.getStatus(), 2)) {
+//                LiveAfterSalesParam param = new LiveAfterSalesParam();
+//                param.setOrderCode(order.getOrderCode());
+//                param.setRefundAmount(order.getPayMoney());
+//                param.setServiceType(1);
+//                param.setReasons("后台手动退款流程");
+//                param.setExplainImg(null);
+//                List<FsStoreAfterSalesProductParam> productParams = new ArrayList<>();
+//                List <LiveOrderItem> items = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+//                for (LiveOrderItem item : items){
+//                    FsStoreAfterSalesProductParam param1 = new FsStoreAfterSalesProductParam();
+//                    param1.setProductId(item.getProductId());
+//                    param1.setNum(Math.toIntExact(item.getNum()));
+//                    productParams.add(param1);
+//                }
+//                return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
+//            } else {
+//                ErpOrderQueryRequert queryRequest = new ErpOrderQueryRequert();
+//                queryRequest.setCode(order.getExtendOrderId());
+//                ErpOrderQueryResponse response = erpOrderService.getLiveOrder(queryRequest);
+//                if (response.getOrders() != null && response.getOrders().size() > 0) {
+//                    if (response.getOrders().get(0).getCancle() != null && !response.getOrders().get(0).getCancle()) {
+//                        jSTOrderService.refundUpdateLive(request);
+//                    }
+//                }
+//            }
+//        }
         order.setStatus(OrderInfoEnum.STATUS_NE2.getValue());
         order.setRefundMoney(order.getPayMoney());
         order.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue()));
@@ -1494,7 +1507,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         refundRequest.setOutTradeNo("live-" + payment.getPayCode());
                         refundRequest.setOutRefundNo("live-" + payment.getPayCode());
                         refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
-                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(refundAmount.toString()));
                         try {
                             WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
                             WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
@@ -1503,14 +1516,12 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                                 paymentMap.setPaymentId(payment.getPaymentId());
                                 paymentMap.setStatus(-1);
                                 paymentMap.setRefundTime(DateUtils.getNowDate());
-                                paymentMap.setRefundMoney(payment.getPayMoney());
+                                paymentMap.setRefundMoney(refundAmount);
                                 liveOrderPaymentMapper.updateLiveOrderPayment(paymentMap);
                             } else {
-                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                 return R.error("退款请求失败" + (refundQueryResult != null ? refundQueryResult.getErrCodeDes() : ""));
                             }
                         } catch (WxPayException e) {
-                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                             return R.error("退款请求失败" + e.getErrCodeDes());
                         }
                     } else if (payment.getPayMode() != null && "hf".equals(payment.getPayMode())) {
@@ -1518,25 +1529,26 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
                         if (payment.getAppId() != null) {
                             FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
-                            if (fsHfpayConfig != null) {
+                            if (fsHfpayConfig == null){
+                                huifuId = fsPayConfig.getHuifuId();
+                            }else {
                                 huifuId = fsHfpayConfig.getHuifuId();
                             }
                         } else {
                             CloudHostProper cloudHostProper = SpringUtils.getBean(CloudHostProper.class);
                             if ("益善缘".equals(cloudHostProper.getCompanyName())) {
                                 FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
-                                if (fsPayConfig2 != null) {
-                                    huifuId = fsPayConfig2.getHuifuId();
-                                }
+                                huifuId = fsPayConfig2.getHuifuId();
                             } else {
                                 huifuId = fsPayConfig.getHuifuId();
                             }
                         }
 
                         V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                        DecimalFormat df = new DecimalFormat("0.00");
                         request.setOrgHfSeqId(payment.getTradeNo());
                         request.setHuifuId(huifuId);
-                        request.setOrdAmt(payment.getPayMoney().toString());
+                        request.setOrdAmt(df.format(refundAmount));
                         request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                         request.setReqSeqId("refund-" + payment.getPayCode());
                         Map<String, Object> extendInfoMap = new HashMap<>();
@@ -3118,6 +3130,17 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                     if (amount != null){
                         payMoney=amount;
                     }
+                    //运费
+                    BigDecimal payPostage = order.getPayPostage();
+                    if (payPostage == null || payPostage.compareTo(BigDecimal.ZERO) <= 0){
+                        payPostage = storeConfig.getPayPostage();
+                        if (payPostage == null){
+                            payPostage = BigDecimal.ZERO;
+                        }
+                        order.setPayPrice(order.getPayPrice().add(payPostage));
+                    }
+                    order.setPayPostage(payPostage);
+                    payMoney = payMoney.add(payPostage);
                     order.setPayMoney(payMoney);
                     order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
 //                    order.setPayMoney(BigDecimal.ZERO);
@@ -3131,8 +3154,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             String payCode = OrderCodeUtils.getOrderSn();
 //            order.setOrderCode(orderCode);
 //            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
-            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-                LiveOrderPayment storePayment=new LiveOrderPayment();
+            if ((order.getPayType().equals("1") || order.getPayType().equals("2") || order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0)) > 0) {
+                LiveOrderPayment storePayment = new LiveOrderPayment();
                 storePayment.setCompanyId(order.getCompanyId());
                 storePayment.setCompanyUserId(order.getCompanyUserId());
                 storePayment.setPayMode(fsPayConfig.getType());
@@ -3149,35 +3172,35 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 storePayment.setAppId(param.getAppId());
                 liveOrderPaymentMapper.insertLiveOrderPayment(storePayment);
 
-                if (fsPayConfig.getType().equals("hf")){
+                if (fsPayConfig.getType().equals("hf")) {
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
                     o.setTradeType("T_MINIAPP");
                     o.setOpenid(storePayment.getOpenId());
-                    o.setReqSeqId("live-"+storePayment.getPayCode());
+                    o.setReqSeqId("live-" + storePayment.getPayCode());
                     o.setTransAmt(storePayment.getPayMoney().toString());
                     o.setGoodsDesc("直播订单支付");
                     if (StringUtils.isNotBlank(param.getAppId())) {
                         o.setAppId(param.getAppId());
                     }
                     HuifuCreateOrderResult result = huiFuService.createOrder(o);
-                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
-                        LiveOrderPayment mt=new LiveOrderPayment();
+                    if (result.getResp_code() != null && (result.getResp_code().equals("00000000") || result.getResp_code().equals("00000100"))) {
+                        LiveOrderPayment mt = new LiveOrderPayment();
                         mt.setPaymentId(storePayment.getPaymentId());
                         mt.setTradeNo(result.getHf_seq_id());
                         mt.setAppId(param.getAppId());
                         mt.setBusinessCode(order.getOrderCode());
                         liveOrderPaymentMapper.updateLiveOrderPayment(mt);
-                        redisCache.setCacheObject("isPaying:"+order.getOrderId(),order.getOrderId().toString(),1, TimeUnit.MINUTES);
+                        redisCache.setCacheObject("isPaying:" + order.getOrderId(), order.getOrderId().toString(), 1, TimeUnit.MINUTES);
                         log.info("汇付支付");
-                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
+                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {
+                        });
                         String s = (String) resultMap.get("package");
-                        resultMap.put("packageValue",s);
-                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
-                    }
-                    else{
+                        resultMap.put("packageValue", s);
+                        return R.ok().put("payType", param.getPayType()).put("result", resultMap);
+                    } else {
                         return R.error(result.getResp_desc());
                     }
-                }else  if (fsPayConfig.getType().equals("wx")){
+                } else if (fsPayConfig.getType().equals("wx")) {
                     WxPayConfig payConfig = new WxPayConfig();
                     payConfig.setAppId(fsPayConfig.getAppId());
                     payConfig.setMchId(fsPayConfig.getWxMchId());
@@ -3198,7 +3221,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                     //调用统一下单接口,获取"预支付交易会话标识"
                     try {
                         WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
-                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
+                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType", param.getPayType());
                     } catch (WxPayException e) {
                         e.printStackTrace();
                         throw new CustomException("支付失败" + e.getMessage());
@@ -3206,10 +3229,10 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 }
             }
 //            else if(order.getPayType().equals("3")){
-            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
+            else if (order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0)) <= 0) {
                 //货到付款
-                this.payConfirm(2,order.getOrderId(),null,null,null,null);
-                return R.ok().put("payType",param.getPayType());
+                this.payConfirm(2, order.getOrderId(), null, null, null, null);
+                return R.ok().put("payType", param.getPayType());
             }
             return R.error();
         }
@@ -3661,7 +3684,6 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         liveOrder.setStatus(OrderInfoEnum.STATUS_0.getValue());
         liveOrder.setPayType("1");
         liveOrder.setTotalPrice(payPrice);
-        liveOrder.setPayMoney(BigDecimal.ZERO);
         liveOrder.setPayPrice(payPrice.subtract(liveOrder.getDiscountMoney()));
         try {
             if (baseMapper.insertLiveOrder(liveOrder) > 0) {

+ 23 - 4
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -940,9 +940,18 @@ public class LiveServiceImpl implements ILiveService
         }
 
         SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("living.config");
+        if (sysConfig == null || StringUtils.isEmpty(sysConfig.getConfigValue())) {
+            log.error("直播配置不存在或为空, liveId: {}", live.getLiveId());
+            return R.error("直播配置不存在,请联系管理员配置");
+        }
         Map<String, String> livingConfigMap = JSON.parseObject(sysConfig.getConfigValue(), Map.class);
         if (livingConfigMap == null || livingConfigMap.isEmpty()) {
-            return R.error("缺失直播配置");
+            log.error("直播配置解析失败, liveId: {}, configValue: {}", live.getLiveId(), sysConfig.getConfigValue());
+            return R.error("直播配置解析失败");
+        }
+        if (StringUtils.isEmpty(livingConfigMap.get("domain")) || StringUtils.isEmpty(livingConfigMap.get("app"))) {
+            log.error("直播配置缺少必要参数, liveId: {}, configMap: {}", live.getLiveId(), livingConfigMap);
+            return R.error("直播配置缺少必要参数(domain/app)");
         }
         String rtmpPushUrl = generateRtmpPushUrl(livingConfigMap.get("domain"), livingConfigMap.get("app"), exist.getLiveId().toString());
         String hlvPlayUrl = generateHlvPlayUrl(livingConfigMap.get("http"), livingConfigMap.get("app"), exist.getLiveId().toString());
@@ -1339,15 +1348,25 @@ public class LiveServiceImpl implements ILiveService
         return jsonObject.getLong(key);
     }
 
+
     /**
-     * 清除直播间数据缓存
+     * 清除直播间数据缓存(公开方法)
      * @param liveId 直播间ID
+     * @return 结果
      */
-    private void clearLiveCache(Long liveId) {
-        if (liveId != null) {
+    @Override
+    public R clearLiveCache(Long liveId) {
+        if (liveId == null) {
+            return R.error("直播间ID不能为空");
+        }
+        try {
             String cacheKey = String.format(LiveKeysConstant.LIVE_DATA_CACHE, liveId);
             redisCache.deleteObject(cacheKey);
             log.debug("清除直播间缓存: liveId={}", liveId);
+            return R.ok("缓存清理成功");
+        } catch (Exception e) {
+            log.error("清除直播间缓存失败: liveId={}", liveId, e);
+            return R.error("缓存清理失败: " + e.getMessage());
         }
     }
 

+ 17 - 8
fs-service/src/main/java/com/fs/live/service/impl/LiveVideoServiceImpl.java

@@ -3,6 +3,8 @@ package com.fs.live.service.impl;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.config.cloud.CloudHostProper;
+import com.fs.hisStore.enums.LiveEnum;
 import com.fs.live.domain.LiveVideo;
 import com.fs.live.mapper.LiveVideoMapper;
 import com.fs.live.service.ILiveVideoService;
@@ -31,10 +33,11 @@ public class LiveVideoServiceImpl implements ILiveVideoService
 {
     @Autowired
     private LiveVideoMapper liveVideoMapper;
-    
+
     @Autowired
     private RedisCache redisCache;
-
+    @Autowired
+    private CloudHostProper cloudHostProper;
     /**
      * 查询直播视频
      *
@@ -81,8 +84,14 @@ public class LiveVideoServiceImpl implements ILiveVideoService
     @Override
     public int insertLiveVideo(LiveVideo liveVideo)
     {
-        // 直播ID为-1,则新增 直播视频库
-        liveVideo.setFinishStatus(0);
+        if (LiveEnum.contains(cloudHostProper.getCompanyName())) {
+            liveVideo.setVideoUrl(liveVideo.getLineOne());
+            liveVideo.setFinishStatus(1);
+        }else {
+            // 直播ID为-1,则新增 直播视频库
+            liveVideo.setFinishStatus(0);
+        }
+
         if (liveVideo.getLiveId() == -1) {
             liveVideo.setCreateTime(DateUtils.getNowDate());
             return liveVideoMapper.insertLiveVideo(liveVideo);
@@ -189,21 +198,21 @@ public class LiveVideoServiceImpl implements ILiveVideoService
     public List<LiveVideo> listByLiveIdWithCache(Long liveId, Integer type) {
         // Redis缓存键
         String cacheKey = "live:video:list:" + liveId + ":" + type;
-        
+
         // 先从缓存中获取
         List<LiveVideo> cachedVideos = redisCache.getCacheObject(cacheKey);
         if (cachedVideos != null && !cachedVideos.isEmpty()) {
             return cachedVideos;
         }
-        
+
         // 缓存未命中,从数据库查询
         List<LiveVideo> videos = liveVideoMapper.selectByIdAndType(liveId, type);
-        
+
         // 将查询结果存入缓存,缓存时间1小时
         if (videos != null) {
             redisCache.setCacheObject(cacheKey, videos, 1, TimeUnit.HOURS);
         }
-        
+
         return videos;
     }
 

+ 66 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveWatchLogServiceImpl.java

@@ -1,7 +1,11 @@
 package com.fs.live.service.impl;
 
+import java.util.Date;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.spring.SpringUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.live.vo.LiveWatchLogListVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -21,6 +25,10 @@ public class LiveWatchLogServiceImpl extends ServiceImpl<LiveWatchLogMapper, Liv
 
     @Autowired
     private LiveWatchLogMapper liveWatchLogMapper;
+    
+    private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+    
+    private static final String LIVE_WATCH_LOG_CACHE_KEY = "live:watch:log:cache:%s"; // logId
 
     /**
      * 查询直播看课记录
@@ -101,4 +109,62 @@ public class LiveWatchLogServiceImpl extends ServiceImpl<LiveWatchLogMapper, Liv
     {
         return baseMapper.deleteLiveWatchLogByLogId(logId);
     }
+
+    /**
+     * 批量更新直播看课记录
+     * @param liveWatchLogs 需要更新的直播看课记录列表
+     * @return 更新的记录数
+     */
+    @Override
+    public int batchUpdateLiveWatchLog(List<LiveWatchLog> liveWatchLogs) {
+        if (liveWatchLogs == null || liveWatchLogs.isEmpty()) {
+            return 0;
+        }
+        Date now = DateUtils.getNowDate();
+        // 设置统一的更新时间
+        for (LiveWatchLog log : liveWatchLogs) {
+            if (log.getUpdateTime() == null) {
+                log.setUpdateTime(now);
+            }
+        }
+        int result = baseMapper.batchUpdateLiveWatchLog(liveWatchLogs);
+        
+        // 更新后清除相关缓存
+        for (LiveWatchLog log : liveWatchLogs) {
+            if (log.getLogId() != null) {
+                String cacheKey = String.format(LIVE_WATCH_LOG_CACHE_KEY, log.getLogId());
+                redisCache.deleteObject(cacheKey);
+            }
+        }
+        
+        return result;
+    }
+
+    /**
+     * 查询直播看课记录并缓存1小时
+     * @param logId 直播看课记录主键
+     * @return 直播看课记录
+     */
+    @Override
+    public List<LiveWatchLog> selectLiveWatchLogByLogIdWithCache(LiveWatchLog logId) {
+        if (logId == null) {
+            return null;
+        }
+        
+        // 先从缓存中获取
+        String cacheKey = String.format(LIVE_WATCH_LOG_CACHE_KEY, logId);
+        List<LiveWatchLog> cachedLog = redisCache.getCacheObject(cacheKey);
+        if (cachedLog != null) {
+            return cachedLog;
+        }
+        
+        // 缓存中没有,从数据库查询
+        List<LiveWatchLog> log = baseMapper.selectLiveWatchLogList(logId);
+        if (log != null) {
+            // 将查询结果缓存1小时
+            redisCache.setCacheObject(cacheKey, log, 1, TimeUnit.HOURS);
+        }
+        
+        return log;
+    }
 }

+ 8 - 1
fs-service/src/main/java/com/fs/live/service/impl/LiveWatchUserServiceImpl.java

@@ -220,6 +220,11 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
         redisCache.deleteObject(cacheKey);
     }
 
+    @Override
+    public List<LiveWatchUser> selectAllWatchUser(LiveWatchUser queryUser) {
+        return baseMapper.selectLiveWatchUserList(queryUser);
+    }
+
     /**
      * 批量删除直播间观看用户
      *
@@ -854,9 +859,10 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
     @Override
     @Async
     public void qwTagMarkByLiveWatchLog(Long liveId) {
+        log.info("处理直播间打标签: liveId={}", liveId);
         //查询直播间的标签配置
         List<LiveTagItemVO> liveTagConfig = liveTagConfigMapper.getLiveTagListByliveId(liveId);
-
+        log.info("处理直播间打标签: liveTagConfig={}", liveTagConfig);
         /**
          * 8	回放已下单
          * 7	直播已下单
@@ -921,6 +927,7 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
                 default:
                     break;
             }
+            addItem.setTags(tags);
             if (null != liveLog.getLiveBuy() && liveLog.getLiveBuy().equals(1)) {
                 liveTagItemVO = liveTagMp.get(7);
                 if (null != liveTagItemVO) {

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

@@ -80,8 +80,8 @@ tencent_cloud_config:
 cloud_host:
   company_name: 鹤颜堂
   projectCode: CDHYT
-  spaceName:
-  volcengineUrl:
+  spaceName: cdhyt-2114522511
+  volcengineUrl: https://cdhytvolcengine.ylrztop.com
 headerImg:
   imgUrl: https
 ipad:

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

@@ -86,8 +86,8 @@ tencent_cloud_config:
 cloud_host:
   company_name: 内蒙古一贴
   projectCode: NMGYT
-  spaceName:
-  volcengineUrl:
+  spaceName: nmgmyt-2114522511
+  volcengineUrl: https://nmgmytvolcengine.ylrztop.com
 headerImg:
   imgUrl: https
 ipad:

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

@@ -95,6 +95,7 @@ cloud_host:
   company_name: 四川致医
   projectCode: SCZY
   spaceName:
+  volcengineUrl:
 headerImg:
   imgUrl: https://jiuzhouzaixian.obs.cn-southwest-2.myhuaweicloud.com/fs/20250623/1750665141214.png
 ipad:

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

@@ -116,7 +116,7 @@ cloud_host:
   company_name: 中康
   projectCode: ZKZH
   spaceName: sxzk-2114522511
-  volcengineUrl:
+  volcengineUrl: https://sxzkvolcengine.ylrztop.com
 headerImg:
   imgUrl: https://zkzh-2025.oss-cn-beijing.aliyuncs.com/fs/20250619/e31b5e051a474a7a9b4ad02575b46196.png
 

+ 3 - 0
fs-service/src/main/resources/mapper/company/CompanyMapper.xml

@@ -122,6 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="groupName != null">group_name,</if>
             <if test="maxPadNum != null">max_pad_num,</if>
             <if test="deptId != null">dept_id,</if>
+            <if test="isOpenRestReminder != null">is_open_rest_reminder,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyName != null">#{companyName},</if>
@@ -158,6 +159,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="groupName != null">#{groupName},</if>
             <if test="maxPadNum != null">#{maxPadNum},</if>
             <if test="deptId != null">#{deptId},</if>
+            <if test="isOpenRestReminder != null">is_open_rest_reminder = #{isOpenRestReminder},</if>
          </trim>
     </insert>
 
@@ -201,6 +203,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maxPadNum != null">max_pad_num = #{maxPadNum},</if>
             <if test="deptId != null">dept_id = #{deptId},</if>
             <if test="redPackageMoney != null">red_package_money = #{redPackageMoney},</if>
+            <if test="isOpenRestReminder != null">is_open_rest_reminder = #{isOpenRestReminder},</if>
         </trim>
         where company_id = #{companyId}
     </update>

+ 2 - 1
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -489,7 +489,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     sop_id,
                     finish_time,
                     send_finish_msg,
-                    camp_period_time
+                    camp_period_time,
+                    period_id
                 FROM
                     fs_course_watch_log
                 WHERE

+ 2 - 0
fs-service/src/main/resources/mapper/course/FsUserCoursePeriodMapper.xml

@@ -56,6 +56,7 @@
         fs_user_course_period.update_time,
         fs_user_course_period.period_status,
         fs_user_course_period.max_view_num,
+        fs_user_course_period.is_open_rest_reminder,
         course_style,
         live_room_style,
         red_packet_grant_method,
@@ -166,6 +167,7 @@
             <if test="courseLogo != null and courseLogo !=''">course_logo = #{courseLogo},</if>
             <if test="openCommentStatus != null">open_comment_status = #{openCommentStatus},</if>
             <if test="periodLine != null">period_line = #{periodLine},</if>
+            <if test="isOpenRestReminder != null">is_open_rest_reminder = #{isOpenRestReminder},</if>
         </trim>
         where period_id = #{periodId}
     </update>

+ 5 - 0
fs-service/src/main/resources/mapper/his/FsIntegralCartMapper.xml

@@ -41,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select
             ifnull(sum(ic.cart_num), 0)
         from fs_integral_cart ic
+        inner join fs_integral_goods ig on ig.goods_id = ic.goods_id
         <where>
             <if test="params.userId != null">
                 ic.user_id = #{params.userId}
@@ -79,4 +80,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
         </where>
     </select>
+
+    <delete id="deleteCartByGoodsId">
+        delete from fs_integral_cart where goods_id = #{goodsId}
+    </delete>
 </mapper>

+ 91 - 0
fs-service/src/main/resources/mapper/live/LiveWatchLogMapper.xml

@@ -245,4 +245,95 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="replayBuy != null">and t1.replay_buy = #{replayBuy} </if>
         </where>
     </select>
+
+    <!-- 批量更新直播看课记录 -->
+    <update id="batchUpdateLiveWatchLog" parameterType="java.util.List">
+        UPDATE live_watch_log
+        <set>
+            <if test="list != null and list.size() > 0 and list[0].logType != null">
+                log_type = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.logType}
+                </foreach>
+                ELSE log_type
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].updateTime != null">
+                update_time = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.updateTime}
+                </foreach>
+                ELSE update_time
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].finishTime != null">
+                finish_time = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.finishTime}
+                </foreach>
+                ELSE finish_time
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].sopCreateTime != null">
+                sop_create_time = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.sopCreateTime}
+                </foreach>
+                ELSE sop_create_time
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].sendAppId != null">
+                send_app_id = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.sendAppId}
+                </foreach>
+                ELSE send_app_id
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].logSource != null">
+                log_source = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.logSource}
+                </foreach>
+                ELSE log_source
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].watchType != null">
+                watch_type = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.watchType}
+                </foreach>
+                ELSE watch_type
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].corpId != null">
+                corp_id = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.corpId}
+                </foreach>
+                ELSE corp_id
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].liveBuy != null">
+                live_buy = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.liveBuy}
+                </foreach>
+                ELSE live_buy
+                END,
+            </if>
+            <if test="list != null and list.size() > 0 and list[0].replayBuy != null">
+                replay_buy = CASE log_id
+                <foreach collection="list" item="item">
+                    WHEN #{item.logId} THEN #{item.replayBuy}
+                </foreach>
+                ELSE replay_buy
+                END
+            </if>
+        </set>
+        WHERE log_id IN
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item.logId}
+        </foreach>
+    </update>
 </mapper>

+ 0 - 5
fs-user-app/src/main/java/com/fs/app/controller/course/CourseTransferController.java

@@ -94,9 +94,4 @@ public class CourseTransferController {
         return fsCourseRedPacketLogService.getBillsByTransferBillNo(transferBillNo);
     }
 
-    @GetMapping("/transferBatchesBatchId")
-    public R transferBatchesBatchId(String batchId){
-        return fsCourseRedPacketLogService.transferBatchesBatchId(batchId);
-    }
-
 }

+ 2 - 0
fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java

@@ -1,6 +1,7 @@
 package com.fs.app.controller.live;
 
 import com.fs.app.controller.AppBaseController;
+import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
@@ -30,6 +31,7 @@ public class LiveCompletionPointsController extends AppBaseController {
      * 领取完课积分
      */
     @PostMapping("/receive")
+    @RepeatSubmit
     public R receive(@RequestParam Long recordId) {
         Long userId = Long.parseLong(getUserId());
         LiveCompletionPointsRecord record = completionPointsRecordService.receiveCompletionPoints(recordId, userId);

+ 0 - 246
fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java

@@ -91,252 +91,6 @@ public class LiveController extends AppBaseController {
     @Autowired
     private com.fs.live.mapper.LiveOrderMapper liveOrderMapper;
 
-
-	@GetMapping("/test/{liveId}")
-	public void test(@PathVariable("liveId") Long liveId) {
-		Live live = liveService.selectLiveDbByLiveId(liveId);
-		List<LiveVideo> liveVideos = liveVideoMapper.selectByIdAndType(liveId, 1);
-		Long duration = liveVideos.get(0).getDuration();
-		List<LiveWatchUser> liveWatchUsers = liveWatchUserService.selectLiveWatchUserListByLiveId(live.getLiveId());
-		List<LiveWatchUser> online = liveWatchUsers.stream().filter(liveWatchUser -> 1 == liveWatchUser.getLiveFlag()).collect(Collectors.toList());
-		List<LiveWatchUser> offline = liveWatchUsers.stream().filter(liveWatchUser -> 1 == liveWatchUser.getReplayFlag()).collect(Collectors.toList());
-		this.adjustWatchDuration(liveId,liveWatchUsers,online,offline,liveWatchUsers.size(),duration);
-	}
-
-	/**
-	 * 调整观看时长以满足统计要求
-	 * 按照每个分公司学员人数,随机50%的人,添加看课时长
-	 * 40%的人看课是30min-40min随机,其中一定包含购买商品用户
-	 * 10%的人看课是20min-29min随机,其中一定包含购买商品用户
-	 * 剩余50%看课是0-19min随机
-	 * 回放规则同上
-	 */
-	private void adjustWatchDuration(Long liveId, List<LiveWatchUser> allUsers,
-									 List<LiveWatchUser> liveUsers, List<LiveWatchUser> replayUsers,
-									 long totalViewers, Long videoDuration) {
-
-		// 查询购买商品的用户(is_pay = '1')
-		com.fs.live.domain.LiveOrder orderQuery = new com.fs.live.domain.LiveOrder();
-		orderQuery.setLiveId(liveId);
-		List<com.fs.live.domain.LiveOrder> orders = liveOrderMapper.selectLiveOrderList(orderQuery);
-		Set<Long> paidUserIds = orders.stream()
-				.filter(o -> "1".equals(o.getIsPay()) && o.getUserId() != null && !o.getUserId().isEmpty())
-				.map(o -> {
-					try {
-						return Long.parseLong(o.getUserId());
-					} catch (NumberFormatException e) {
-						return null;
-					}
-				})
-				.filter(java.util.Objects::nonNull)
-				.collect(Collectors.toSet());
-
-		// 查询每个分公司的学员(通过 live_user_first_entry 表)
-		com.fs.live.domain.LiveUserFirstEntry firstEntryQuery = new com.fs.live.domain.LiveUserFirstEntry();
-		firstEntryQuery.setLiveId(liveId);
-		List<com.fs.live.domain.LiveUserFirstEntry> firstEntries = liveUserFirstEntryMapper.selectLiveUserFirstEntryList(firstEntryQuery);
-		
-		// 按分公司分组用户
-		Map<Long, List<Long>> companyUserMap = new HashMap<>();
-		Map<Long, Long> userCompanyMap = new HashMap<>(); // 用户ID -> 分公司ID
-		Set<Long> usersWithCompany = new HashSet<>(); // 有分公司的用户
-		
-		for (com.fs.live.domain.LiveUserFirstEntry entry : firstEntries) {
-			if (entry.getCompanyId() != null && entry.getUserId() != null) {
-				companyUserMap.computeIfAbsent(entry.getCompanyId(), k -> new ArrayList<>()).add(entry.getUserId());
-				userCompanyMap.put(entry.getUserId(), entry.getCompanyId());
-				usersWithCompany.add(entry.getUserId());
-			}
-		}
-		
-		// 处理没有分公司的用户(归到一个虚拟分公司,companyId = null 或 0)
-		Long noCompanyId = 0L;
-		for (LiveWatchUser user : allUsers) {
-			Long userId = user.getUserId();
-			if (userId != null && !usersWithCompany.contains(userId)) {
-				companyUserMap.computeIfAbsent(noCompanyId, k -> new ArrayList<>()).add(userId);
-				userCompanyMap.put(userId, noCompanyId);
-			}
-		}
-
-		// 按用户ID分组,合并同一用户的观看时长(把观看时间平分到各个用户身上)
-		Map<Long, List<LiveWatchUser>> allUserMap = new HashMap<>();
-		Map<Long, LiveWatchUser> liveUserMap = new HashMap<>();
-		Map<Long, LiveWatchUser> replayUserMap = new HashMap<>();
-
-		for (LiveWatchUser user : allUsers) {
-			Long userId = user.getUserId();
-			if (userId == null) continue;
-
-			allUserMap.computeIfAbsent(userId, k -> new ArrayList<>()).add(user);
-
-			if (user.getLiveFlag() != null && user.getLiveFlag() == 1 && (user.getReplayFlag() == null || user.getReplayFlag() == 0)) {
-				LiveWatchUser existing = liveUserMap.get(userId);
-				if (existing == null) {
-					liveUserMap.put(userId, user);
-				} else {
-					// 合并观看时长:把观看时间平分到各个用户身上
-					long totalSeconds = (existing.getOnlineSeconds() != null ? existing.getOnlineSeconds() : 0L) +
-							(user.getOnlineSeconds() != null ? user.getOnlineSeconds() : 0L);
-					existing.setOnlineSeconds(totalSeconds);
-				}
-			} else if (user.getReplayFlag() != null && user.getReplayFlag() == 1 && (user.getLiveFlag() == null || user.getLiveFlag() == 0)) {
-				LiveWatchUser existing = replayUserMap.get(userId);
-				if (existing == null) {
-					replayUserMap.put(userId, user);
-				} else {
-					// 合并观看时长:把观看时间平分到各个用户身上
-					long totalSeconds = (existing.getOnlineSeconds() != null ? existing.getOnlineSeconds() : 0L) +
-							(user.getOnlineSeconds() != null ? user.getOnlineSeconds() : 0L);
-					existing.setOnlineSeconds(totalSeconds);
-				}
-			}
-		}
-
-		// 按分公司处理直播用户观看时长
-		adjustWatchDurationByCompany(liveUserMap, companyUserMap, userCompanyMap, paidUserIds, true);
-		
-		// 按分公司处理回放用户观看时长(规则同上)
-		adjustWatchDurationByCompany(replayUserMap, companyUserMap, userCompanyMap, paidUserIds, false);
-
-		// 更新数据库
-		Date now = new Date();
-		int batchSize = 500;
-		for (int i = 0; i < allUsers.size(); i += batchSize) {
-			int end = Math.min(i + batchSize, allUsers.size());
-			List<LiveWatchUser> batch = allUsers.subList(i, end);
-			for (LiveWatchUser user : batch) {
-				user.setUpdateTime(now);
-			}
-			liveWatchUserService.batchUpdateLiveWatchUser(batch);
-		}
-
-		log.info("直播间 {} 观看时长调整完成:总观看人数={}, 视频时长={}秒",
-				liveId, totalViewers, videoDuration);
-	}
-
-	/**
-	 * 按分公司调整观看时长
-	 * @param userMap 用户观看记录Map(userId -> LiveWatchUser)
-	 * @param companyUserMap 分公司用户Map(companyId -> List<userId>)
-	 * @param userCompanyMap 用户分公司Map(userId -> companyId)
-	 * @param paidUserIds 购买商品的用户ID集合
-	 * @param isLive 是否为直播(true=直播,false=回放)
-	 */
-	private void adjustWatchDurationByCompany(Map<Long, LiveWatchUser> userMap,
-											   Map<Long, List<Long>> companyUserMap,
-											   Map<Long, Long> userCompanyMap,
-											   Set<Long> paidUserIds,
-											   boolean isLive) {
-		
-		// 遍历每个分公司
-		for (Map.Entry<Long, List<Long>> companyEntry : companyUserMap.entrySet()) {
-			Long companyId = companyEntry.getKey();
-			List<Long> companyUserIds = companyEntry.getValue();
-			
-			// 筛选出该分公司有观看记录的用户
-			List<Long> companyWatchUserIds = companyUserIds.stream()
-					.filter(userId -> userMap.containsKey(userId))
-					.collect(Collectors.toList());
-			
-			if (companyWatchUserIds.isEmpty()) {
-				continue;
-			}
-			
-			// 随机选择50%的人添加看课时长
-			Collections.shuffle(companyWatchUserIds);
-			int selectedCount = (int) Math.round(companyWatchUserIds.size() * 0.5);
-			List<Long> selectedUserIds = companyWatchUserIds.subList(0, Math.min(selectedCount, companyWatchUserIds.size()));
-			
-			// 分离购买商品的用户和未购买商品的用户
-			List<Long> paidUsers = selectedUserIds.stream()
-					.filter(paidUserIds::contains)
-					.collect(Collectors.toList());
-			List<Long> unpaidUsers = selectedUserIds.stream()
-					.filter(userId -> !paidUserIds.contains(userId))
-					.collect(Collectors.toList());
-			
-			// 计算各区间人数
-			// 40%的人(即总人数的20%)看课30-40分钟,必须包含购买商品用户
-			// 10%的人(即总人数的5%)看课20-29分钟,必须包含购买商品用户
-			// 剩余50%的人(即总人数的25%)看课0-19分钟
-			int count30to40 = (int) Math.round(selectedUserIds.size() * 0.4);
-			int count20to29 = (int) Math.round(selectedUserIds.size() * 0.1);
-			int count0to19 = selectedUserIds.size() - count30to40 - count20to29;
-			
-			// 确保购买商品的用户被包含在30-40分钟或20-29分钟组中
-			List<Long> users30to40 = new ArrayList<>();
-			List<Long> users20to29 = new ArrayList<>();
-			List<Long> users0to19 = new ArrayList<>();
-			
-			// 优先将购买商品的用户分配到30-40分钟组
-			int paidIndex = 0;
-			for (int i = 0; i < count30to40 && paidIndex < paidUsers.size(); i++) {
-				users30to40.add(paidUsers.get(paidIndex++));
-			}
-			
-			// 如果30-40分钟组还有空位,从购买商品用户中继续分配
-			for (int i = users30to40.size(); i < count30to40 && paidIndex < paidUsers.size(); i++) {
-				users30to40.add(paidUsers.get(paidIndex++));
-			}
-			
-			// 如果还有购买商品的用户,分配到20-29分钟组
-			for (int i = 0; i < count20to29 && paidIndex < paidUsers.size(); i++) {
-				users20to29.add(paidUsers.get(paidIndex++));
-			}
-			
-			// 剩余的购买商品用户分配到0-19分钟组
-			while (paidIndex < paidUsers.size()) {
-				users0to19.add(paidUsers.get(paidIndex++));
-			}
-			
-			// 填充30-40分钟组(从未购买用户中随机选择)
-			Collections.shuffle(unpaidUsers);
-			int unpaidIndex = 0;
-			for (int i = users30to40.size(); i < count30to40 && unpaidIndex < unpaidUsers.size(); i++) {
-				users30to40.add(unpaidUsers.get(unpaidIndex++));
-			}
-			
-			// 填充20-29分钟组(从未购买用户中随机选择)
-			for (int i = users20to29.size(); i < count20to29 && unpaidIndex < unpaidUsers.size(); i++) {
-				users20to29.add(unpaidUsers.get(unpaidIndex++));
-			}
-			
-			// 剩余用户分配到0-19分钟组
-			while (unpaidIndex < unpaidUsers.size()) {
-				users0to19.add(unpaidUsers.get(unpaidIndex++));
-			}
-			
-			// 设置30-40分钟的用户观看时长(1800-2400秒)
-			for (Long userId : users30to40) {
-				LiveWatchUser user = userMap.get(userId);
-				if (user != null) {
-					user.setOnlineSeconds(1800L + (long)(Math.random() * 600)); // 30-40分钟
-				}
-			}
-			
-			// 设置20-29分钟的用户观看时长(1200-1740秒)
-			for (Long userId : users20to29) {
-				LiveWatchUser user = userMap.get(userId);
-				if (user != null) {
-					user.setOnlineSeconds(1200L + (long)(Math.random() * 540)); // 20-29分钟
-				}
-			}
-			
-			// 设置0-19分钟的用户观看时长(0-1140秒)
-			for (Long userId : users0to19) {
-				LiveWatchUser user = userMap.get(userId);
-				if (user != null) {
-					user.setOnlineSeconds((long)(Math.random() * 1140)); // 0-19分钟
-				}
-			}
-			
-			log.debug("分公司 {} {}用户观看时长调整:总人数={}, 选中人数={}, 30-40分钟={}, 20-29分钟={}, 0-19分钟={}, 购买用户数={}",
-					companyId, isLive ? "直播" : "回放", companyWatchUserIds.size(), selectedUserIds.size(),
-					users30to40.size(), users20to29.size(), users0to19.size(), paidUsers.size());
-		}
-	}
-
 	/**
 	 * 查询未结束直播间(销售专用)
 	 */

+ 0 - 322
fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

@@ -323,328 +323,6 @@ public class LiveOrderController extends AppBaseController
         return orderService.createLiveOrder(param);
     }
 
-//    @Login
-//    @ApiOperation("支付")
-//    @PostMapping("/pay")
-//    @Transactional
-//    //@Synchronized
-//    public R pay(HttpServletRequest request, @Validated @RequestBody LiveOrderPayParam param)
-//    {
-//        LiveOrder order=orderService.selectLiveOrderByOrderId(String.valueOf(param.getOrderId()));
-//        if(order==null){
-//            return R.error("订单不存在");
-//        }
-//        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
-//            return R.error("订单状态不正确");
-//        }
-//        String orderId=redisCache.getCacheObject("isPaying:"+order.getOrderId());
-//        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getOrderId().toString())){
-//            return R.error("正在支付中...");
-//        }
-//
-//        FsUserScrm user=userService.selectFsUserById(Long.valueOf(order.getUserId()));
-//        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
-//            //已改价处理
-//            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
-//                //改过价不做处理
-//
-//            }
-//            else{
-//                String config=configService.selectConfigByKey("his.store");
-//                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
-//                if(param.getPayType().equals(1)){
-//                    order.setPayType("1");
-//                    order.setPayMoney(order.getPayPrice());
-//                    order.setPayDelivery(BigDecimal.ZERO);
-//                }
-//                else if(param.getPayType().equals(2)){
-//                    order.setPayType("2");
-//                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
-//                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
-//                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
-//                    order.setPayMoney(payMoney);
-//                }
-//                else if(param.getPayType().equals(3)){
-//                    //货到付款
-//                    order.setPayType("3");
-//                    BigDecimal amount=redisCache.getCacheObject("orderAmount:"+order.getOrderId());
-//                    BigDecimal payMoney = BigDecimal.ZERO;
-//                    if (amount != null){
-//                        payMoney=amount;
-//                    }
-//                    order.setPayMoney(payMoney);
-//                    order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
-////                    order.setPayMoney(BigDecimal.ZERO);
-//                }
-//                orderService.updateLiveOrder(order);
-//            }
-//            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
-////            order.setOrderCode(orderCode);
-////            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
-//            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-//                String json = configService.selectConfigByKey("his.pay");
-//                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
-//                LiveOrderPayment storePayment=new LiveOrderPayment();
-//                storePayment.setCompanyId(order.getCompanyId());
-//                storePayment.setCompanyUserId(order.getCompanyUserId());
-//                storePayment.setPayMode(fsPayConfig.getType());
-//                storePayment.setStatus(0);
-//                storePayment.setPayCode(payCode);
-//                storePayment.setPayMoney(order.getPayMoney());
-//                storePayment.setCreateTime(new Date());
-//                storePayment.setPayTypeCode("weixin");
-//                storePayment.setBusinessType(2);
-//                storePayment.setRemark("直播订单支付");
-//                storePayment.setOpenId(user.getRealName());
-//                storePayment.setUserId(user.getUserId());
-//                storePayment.setBusinessId(String.valueOf(order.getOrderId()));
-//                liveOrderPaymentMapper.insertLiveOrderPayment(storePayment);
-//
-//                if (fsPayConfig.getType().equals("hf")){
-//                    HuiFuCreateOrder o = new HuiFuCreateOrder();
-//                    o.setTradeType("T_MINIAPP");
-//                    o.setOpenid(user.getMaOpenId());
-//                    o.setReqSeqId("live-"+storePayment.getPayCode());
-//                    o.setTransAmt(storePayment.getPayMoney().toString());
-//                    o.setGoodsDesc("直播订单支付");
-//                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
-//                        o.setAppId(param.getAppId());
-//                    }
-//                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
-//                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
-//                        LiveOrderPayment mt=new LiveOrderPayment();
-//                        mt.setPaymentId(storePayment.getPaymentId());
-//                        mt.setTradeNo(result.getHf_seq_id());
-//                        liveOrderPaymentMapper.updateLiveOrderPayment(mt);
-//                        redisCache.setCacheObject("isPaying:"+order.getOrderId(),order.getOrderId().toString(),1, TimeUnit.MINUTES);
-//                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
-//                        String s = (String) resultMap.get("package");
-//                        resultMap.put("packageValue",s);
-//                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
-//                    }
-//                    else{
-//                        return R.error(result.getResp_desc());
-//                    }
-//                }else  if (fsPayConfig.getType().equals("wx")){
-//                    WxPayConfig payConfig = new WxPayConfig();
-//                    payConfig.setAppId(fsPayConfig.getAppId());
-//                    payConfig.setMchId(fsPayConfig.getWxMchId());
-//                    payConfig.setMchKey(fsPayConfig.getWxMchKey());
-//                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-//                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-//                    payConfig.setKeyPath(fsPayConfig.getKeyPath());
-//                    payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
-//                    wxPayService.setConfig(payConfig);
-//                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-//                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
-//                    orderRequest.setBody("直播订单支付");
-//                    orderRequest.setOutTradeNo("live-" + storePayment.getPayCode());
-//                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
-//                    //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
-//                    orderRequest.setTradeType("JSAPI");
-//                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
-//                    //调用统一下单接口,获取"预支付交易会话标识"
-//                    try {
-//                        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
-//                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
-//                    } catch (WxPayException e) {
-//                        e.printStackTrace();
-//                        throw new CustomException("支付失败" + e.getMessage());
-//                    }
-//                }
-//            }
-////            else if(order.getPayType().equals("3")){
-//            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
-//                //货到付款
-//                orderService.payConfirm(2,order.getOrderId(),null,null,null,null);
-//                return R.ok().put("payType",param.getPayType());
-//            }
-//            return R.error();
-//        }
-//        else{
-//            return R.error("用户OPENID不存在");
-//        }
-//
-//    }
-
-    /*
-    @Login
-    @ApiOperation("支付")
-    @PostMapping("/pay")
-    @Transactional
-    //@Synchronized
-    public R pay(HttpServletRequest request, @Validated @RequestBody LiveOrderPayParam param)
-    {
-        Long orderId = param.getOrderId();
-        logger.info("开始处理支付请求, 订单号: {}, 支付类型: {}", orderId, param.getPayType());
-
-        RLock lock = redissonClient.getLock(String.format(LOCK_KEY_PAY,orderId));
-        R result = null;
-
-        try {
-            boolean locked = lock.tryLock(100, 30000, TimeUnit.MILLISECONDS);
-
-            if (!locked) {
-                logger.warn("订单正在处理中,获取锁失败, 订单号: {}", orderId);
-                return R.error("订单正在处理中,请勿重复提交");
-            }
-
-            result = orderService.pay(param);
-
-        } catch (InterruptedException e) {
-            logger.error("获取支付锁的过程被中断, 订单号: {}", orderId, e);
-            Thread.currentThread().interrupt();
-            return R.error("支付处理被中断,请稍后重试");
-        } catch (Throwable e) {
-            logger.error("支付过程中发生异常, 订单号: {}", orderId, e);
-            throw e;
-        } finally {
-            if (lock.isHeldByCurrentThread()) {
-                lock.unlock();
-                logger.debug("支付锁已释放, 订单号: {}", orderId);
-            }
-        }
-
-        return result;
-        LiveOrder order=orderService.selectLiveOrderByOrderId(String.valueOf(param.getOrderId()));
-        if(order==null){
-            return R.error("订单不存在");
-        }
-        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
-            return R.error("订单状态不正确");
-        }
-        String orderId=redisCache.getCacheObject("isPaying:"+order.getOrderId());
-        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getOrderId().toString())){
-            return R.error("正在支付中...");
-        }
-
-        FsUserScrm user=userService.selectFsUserById(Long.valueOf(order.getUserId()));
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
-            //已改价处理
-            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
-                //改过价不做处理
-
-            }
-            else{
-                String config=configService.selectConfigByKey("his.store");
-                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
-                if(param.getPayType().equals(1)){
-                    order.setPayType("1");
-                    order.setPayMoney(order.getPayPrice());
-                    order.setPayDelivery(BigDecimal.ZERO);
-                }
-                else if(param.getPayType().equals(2)){
-                    order.setPayType("2");
-                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
-                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
-                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
-                    order.setPayMoney(payMoney);
-                }
-                else if(param.getPayType().equals(3)){
-                    //货到付款
-                    order.setPayType("3");
-                    BigDecimal amount=redisCache.getCacheObject("orderAmount:"+order.getOrderId());
-                    BigDecimal payMoney = BigDecimal.ZERO;
-                    if (amount != null){
-                        payMoney=amount;
-                    }
-                    order.setPayMoney(payMoney);
-                    order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
-//                    order.setPayMoney(BigDecimal.ZERO);
-                }
-                orderService.updateLiveOrder(order);
-            }
-            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
-//            order.setOrderCode(orderCode);
-//            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
-            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-                String json = configService.selectConfigByKey("his.pay");
-                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
-                LiveOrderPayment storePayment=new LiveOrderPayment();
-                storePayment.setCompanyId(order.getCompanyId());
-                storePayment.setCompanyUserId(order.getCompanyUserId());
-                storePayment.setPayMode(fsPayConfig.getType());
-                storePayment.setStatus(0);
-                storePayment.setPayCode(payCode);
-                storePayment.setPayMoney(order.getPayMoney());
-                storePayment.setCreateTime(new Date());
-                storePayment.setPayTypeCode("weixin");
-                storePayment.setBusinessType(2);
-                storePayment.setRemark("直播订单支付");
-                storePayment.setOpenId(user.getRealName());
-                storePayment.setUserId(user.getUserId());
-                storePayment.setBusinessId(String.valueOf(order.getOrderId()));
-                liveOrderPaymentMapper.insertLiveOrderPayment(storePayment);
-
-                if (fsPayConfig.getType().equals("hf")){
-                    HuiFuCreateOrder o = new HuiFuCreateOrder();
-                    o.setTradeType("T_MINIAPP");
-                    o.setOpenid(user.getMaOpenId());
-                    o.setReqSeqId("live-"+storePayment.getPayCode());
-                    o.setTransAmt(storePayment.getPayMoney().toString());
-                    o.setGoodsDesc("直播订单支付");
-                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
-                        o.setAppId(param.getAppId());
-                    }
-                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
-                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
-                        LiveOrderPayment mt=new LiveOrderPayment();
-                        mt.setPaymentId(storePayment.getPaymentId());
-                        mt.setTradeNo(result.getHf_seq_id());
-                        liveOrderPaymentMapper.updateLiveOrderPayment(mt);
-                        redisCache.setCacheObject("isPaying:"+order.getOrderId(),order.getOrderId().toString(),1, TimeUnit.MINUTES);
-                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
-                        String s = (String) resultMap.get("package");
-                        resultMap.put("packageValue",s);
-                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
-                    }
-                    else{
-                        return R.error(result.getResp_desc());
-                    }
-                }else  if (fsPayConfig.getType().equals("wx")){
-                    WxPayConfig payConfig = new WxPayConfig();
-                    payConfig.setAppId(fsPayConfig.getAppId());
-                    payConfig.setMchId(fsPayConfig.getWxMchId());
-                    payConfig.setMchKey(fsPayConfig.getWxMchKey());
-                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-                    payConfig.setKeyPath(fsPayConfig.getKeyPath());
-                    payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
-                    wxPayService.setConfig(payConfig);
-                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
-                    orderRequest.setBody("直播订单支付");
-                    orderRequest.setOutTradeNo("live-" + storePayment.getPayCode());
-                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
-                    //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
-                    orderRequest.setTradeType("JSAPI");
-                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
-                    //调用统一下单接口,获取"预支付交易会话标识"
-                    try {
-                        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
-                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
-                    } catch (WxPayException e) {
-                        e.printStackTrace();
-                        throw new CustomException("支付失败" + e.getMessage());
-                    }
-                }
-            }
-//            else if(order.getPayType().equals("3")){
-            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
-                //货到付款
-                orderService.payConfirm(2,order.getOrderId(),null,null,null,null);
-                return R.ok().put("payType",param.getPayType());
-            }
-            return R.error();
-        }
-        else{
-            return R.error("用户OPENID不存在");
-        }
-
-    }
-        /**
-     * 获取订单详细信息
-     */
     @Login
     @GetMapping(value = "/info/{orderId}")
     public AjaxResult getInfo(@PathVariable("orderId") String orderId)