Przeglądaj źródła

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

caoliqin 3 dni temu
rodzic
commit
e494a3f71a
26 zmienionych plików z 511 dodań i 92 usunięć
  1. 21 0
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  2. 8 0
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  3. 18 1
      fs-admin/src/main/java/com/fs/live/controller/LiveController.java
  4. 2 2
      fs-admin/src/main/resources/application.yml
  5. 1 1
      fs-live-app/src/main/java/com/fs/framework/aspectj/RateLimiterAspect.java
  6. 3 5
      fs-live-app/src/main/java/com/fs/live/websocket/handle/LiveChatHandler.java
  7. 52 65
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  8. 16 2
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  9. 3 2
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  10. 39 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserCompanyPackageScrm.java
  11. 2 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java
  12. 61 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsUserCompanyPackageScrmMapper.java
  13. 21 0
      fs-service/src/main/java/com/fs/hisStore/param/FsUsePackageScrmSendParam.java
  14. 5 1
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreProductPackageScrmService.java
  15. 12 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  16. 32 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductPackageScrmServiceImpl.java
  17. 4 0
      fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java
  18. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveService.java
  19. 49 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  20. 27 5
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  21. 13 0
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  22. 79 0
      fs-service/src/main/resources/mapper/hisStore/FsUserCompanyPackageScrmMapper.xml
  23. 3 1
      fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml
  24. 5 1
      fs-user-app/src/main/java/com/fs/app/controller/UserController.java
  25. 10 1
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java
  26. 23 4
      fs-user-app/src/main/java/com/fs/app/controller/store/StoreProductPackageScrmController.java

+ 21 - 0
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -47,6 +47,7 @@ import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysRoleService;
 import com.github.pagehelper.PageHelper;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -73,6 +74,7 @@ import static com.fs.his.utils.PhoneUtil.*;
  */
 @RestController
 @RequestMapping("/his/storeOrder")
+@Slf4j
 public class FsStoreOrderController extends BaseController
 {
     @Autowired
@@ -421,6 +423,14 @@ public class FsStoreOrderController extends BaseController
             tuiMoneyLogs=moneyLogsService.selectCompanyStoreOrderMoneyLogsList(moneyLogsMap);
         }
         if ((CloudHostUtils.hasCloudHostName("金牛明医"))){
+            if (order.getStatus() == 2 ){
+                FsUserInfoCollectionAndStoreOrderVo infoVo = fsPackageOrderService.selectInformationCollectionByStoreOrderId(orderId);
+                if (infoVo!=null) {
+                    if (infoVo.getDoctorType2Confirm() == null || infoVo.getDoctorType2Confirm()!=1) {
+                        order.setStatus(7);
+                    }
+                }
+            }
             return R.ok().put("data",order).put("tuiMoneyLogs",tuiMoneyLogs).put("isUpdateRefund",1).put("isUpdatePayRemain",1);
         } else {
             return R.ok().put("data",order).put("tuiMoneyLogs",tuiMoneyLogs).put("isUpdateRefund",0).put("isUpdatePayRemain",0);
@@ -482,6 +492,17 @@ public class FsStoreOrderController extends BaseController
     {
         AjaxResult error = moneyCheck(fsStoreOrder);
         if (error != null) return error;
+        try {
+            FsUserInfoCollectionAndStoreOrderVo infoVo = fsPackageOrderService.selectInformationCollectionByStoreOrderId(fsStoreOrder.getOrderId());
+            if (infoVo != null) {
+                Integer doctorType2Confirm = infoVo.getDoctorType2Confirm();
+                if (doctorType2Confirm == null || doctorType2Confirm != 1) {
+                    return AjaxResult.error("信息采集订单药师未确认,不能修改状态!");
+                }
+            }
+        } catch (Exception e) {
+            log.error("信息采集查询错误,orderId: " + fsStoreOrder.getOrderId() + ",信息:{}"+ e);
+        }
         return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
     }
 

+ 8 - 0
fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java

@@ -4,6 +4,7 @@ package com.fs.hisStore.task;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.DateUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.vo.RedPacketMoneyVO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
@@ -32,6 +33,7 @@ import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
 import com.fs.hisStore.mapper.FsStoreProductAttrValueScrmMapper;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
+import com.fs.live.domain.LiveOrder;
 import com.fs.pay.pay.dto.OrderQueryDTO;
 import com.fs.pay.service.IPayService;
 import com.fs.store.config.StoreConfig;
@@ -49,6 +51,7 @@ import java.math.BigDecimal;
 import java.text.ParseException;
 import java.time.LocalTime;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
@@ -217,6 +220,11 @@ public class MallStoreTask
         if (list != null && list.size() > 50) {
             list = list.subList(0, 50);
         }
+        Date nowDate = DateUtils.getNowDate();
+        for (FsStoreOrderScrm order : list) {
+            order.setUpdateTime(nowDate);
+        }
+        fsStoreOrderMapper.batchUpdateTime(list);
         for (FsStoreOrderScrm order : list){
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();
             request.setCode(order.getExtendOrderId());

+ 18 - 1
fs-admin/src/main/java/com/fs/live/controller/LiveController.java

@@ -4,14 +4,19 @@ import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.framework.web.service.TokenService;
 import com.fs.hisStore.task.LiveTask;
 import com.fs.hisStore.task.MallStoreTask;
 import com.fs.live.domain.Live;
 import com.fs.live.service.ILiveService;
 import com.fs.live.vo.LiveListVo;
+import com.hc.openapi.tool.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -28,10 +33,14 @@ import java.util.Map;
  */
 @RestController
 @RequestMapping("/live/live")
+@Slf4j
 public class LiveController extends BaseController {
     @Autowired
     private ILiveService liveService;
 
+    @Autowired
+    private TokenService tokenService;
+
 
     /**
      * 查询直播列表
@@ -63,7 +72,7 @@ public class LiveController extends BaseController {
     @PreAuthorize("@ss.hasPermi('live:live:query')")
     @GetMapping(value = "/{liveId}")
     public AjaxResult getInfo(@PathVariable("liveId") Long liveId) {
-        return AjaxResult.success(liveService.selectLiveByLiveId(liveId));
+        return AjaxResult.success(liveService.selectLiveDbByLiveId(liveId));
     }
 
     /**
@@ -83,6 +92,8 @@ public class LiveController extends BaseController {
     @Log(title = "直播", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody Live live) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        log.warn("loginUser:{},update:{}", loginUser.getUserId(), JSON.toJSONString( live));
         return toAjax(liveService.updateLive(live));
     }
 
@@ -93,6 +104,8 @@ public class LiveController extends BaseController {
     @Log(title = "直播", businessType = BusinessType.DELETE)
     @DeleteMapping("/{liveIds}")
     public AjaxResult remove(@PathVariable Long[] liveIds) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        log.warn("loginUser:{},update:{}", loginUser.getUserId(), JSON.toJSONString( liveIds));
         return toAjax(liveService.deleteLiveByLiveIds(liveIds, new Live()));
     }
 
@@ -116,6 +129,8 @@ public class LiveController extends BaseController {
     @PreAuthorize("@ss.hasPermi('live:live:edit')")
     @PostMapping("/handleShelfOrUn")
     public R handleShelfOrUn(@RequestBody LiveListVo listVo) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        log.warn("loginUser:{},update:{}", loginUser.getUserId(), JSON.toJSONString( listVo));
         return liveService.handleShelfOrUnAdmin(listVo);
     }
 
@@ -125,6 +140,8 @@ public class LiveController extends BaseController {
     @PreAuthorize("@ss.hasPermi('live:live:edit')")
     @PostMapping("/handleDeleteSelected")
     public R handleDeleteSelected(@RequestBody LiveListVo listVo) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        log.warn("loginUser:{},update:{}", loginUser.getUserId(), JSON.toJSONString( listVo));
         return liveService.handleDeleteSelectedAdmin(listVo);
     }
     /**

+ 2 - 2
fs-admin/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 server:
-  # 服务器的HTTP端口,默认为8080 8004
-  port: 7772
+  # 服务器的HTTP端口,默认为8080
+  port: 8004
 # Spring配置
 spring:
   profiles:

+ 1 - 1
fs-live-app/src/main/java/com/fs/framework/aspectj/RateLimiterAspect.java

@@ -73,7 +73,7 @@ public class RateLimiterAspect
             {
                 throw new ServiceException("访问过于频繁,请稍后再试");
             }
-            log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key);
+
         }
         catch (ServiceException e)
         {

+ 3 - 5
fs-live-app/src/main/java/com/fs/live/websocket/handle/LiveChatHandler.java

@@ -53,7 +53,7 @@ public class LiveChatHandler extends SimpleChannelInboundHandler<TextWebSocketFr
      */
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
-        log.debug("事件");
+
         // 处理 WebSocket 握手完成事件
         if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
             Long userId = ctx.channel().attr(AttrConstant.ATTR_USER_ID).get();
@@ -100,7 +100,6 @@ public class LiveChatHandler extends SimpleChannelInboundHandler<TextWebSocketFr
                 adminRoom.add(ctx.channel());
             }
 
-            log.debug("加入webSocket liveId: {}, userId: {}, 直播间人数: {}", liveId, userId, room.size());
         }
     }
 
@@ -157,7 +156,7 @@ public class LiveChatHandler extends SimpleChannelInboundHandler<TextWebSocketFr
      */
     @Override
     protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
-        log.debug("接收到消息 data: {}", textWebSocketFrame.text());
+
         Long liveId = channelHandlerContext.channel().attr(AttrConstant.ATTR_LIVE_ID).get();
         Long userType = channelHandlerContext.channel().attr(AttrConstant.ATTR_USER_TYPE).get();
 
@@ -207,7 +206,7 @@ public class LiveChatHandler extends SimpleChannelInboundHandler<TextWebSocketFr
      */
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        log.debug("断开连接");
+
         Long userId = ctx.channel().attr(AttrConstant.ATTR_USER_ID).get();
         Long liveId = ctx.channel().attr(AttrConstant.ATTR_LIVE_ID).get();
         Long userType = ctx.channel().attr(AttrConstant.ATTR_USER_TYPE).get();
@@ -254,7 +253,6 @@ public class LiveChatHandler extends SimpleChannelInboundHandler<TextWebSocketFr
             roomGroups.remove(liveId);
         }
 
-        log.debug("断开webSocket liveId: {}, userId: {}, 直播间人数: {}", liveId, userId, room.size());
 
     }
 

+ 52 - 65
fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -49,7 +49,7 @@ public class WebSocketServer {
     private final static ConcurrentHashMap<Long, ConcurrentHashMap<Long, Session>> rooms = new ConcurrentHashMap<>();
     // 管理端连接
     private final static ConcurrentHashMap<Long, CopyOnWriteArrayList<Session>> adminRooms = new ConcurrentHashMap<>();
-    
+
     // Session发送锁,避免同一会话并发发送消息
     private final static ConcurrentHashMap<String, Lock> sessionLocks = new ConcurrentHashMap<>();
     // 心跳超时缓存:key=sessionId,value=最后心跳时间戳
@@ -58,7 +58,7 @@ public class WebSocketServer {
     private final static long HEARTBEAT_TIMEOUT = 3 * 60 * 1000;
     // admin房间消息发送线程池(单线程,保证串行化)
     private final static ConcurrentHashMap<Long, ExecutorService> adminExecutors = new ConcurrentHashMap<>();
-    
+
     private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
     private final ILiveMsgService liveMsgService = SpringUtils.getBean(ILiveMsgService.class);
     private final ILiveService liveService = SpringUtils.getBean(ILiveService.class);
@@ -72,6 +72,7 @@ public class WebSocketServer {
     private final ILiveUserFirstEntryService liveUserFirstEntryService =  SpringUtils.getBean(ILiveUserFirstEntryService.class);
     private final ILiveCouponIssueService liveCouponIssueService =  SpringUtils.getBean(ILiveCouponIssueService.class);
     private final LiveCouponMapper liveCouponMapper = SpringUtils.getBean(LiveCouponMapper.class);
+    private static Random random = new Random();
 
     // 直播间在线用户缓存
 //    private static final ConcurrentHashMap<Long, Integer> liveOnlineUsers = new ConcurrentHashMap<>();
@@ -145,17 +146,19 @@ public class WebSocketServer {
                 redisCache.incr(UNIQUE_VIEWERS_KEY + liveId, 1);
             }
             liveWatchUserVO.setMsgStatus(liveWatchUserVO.getMsgStatus());
-            SendMsgVo sendMsgVo = new SendMsgVo();
-            sendMsgVo.setLiveId(liveId);
-            sendMsgVo.setUserId(userId);
-            sendMsgVo.setUserType(userType);
-            sendMsgVo.setCmd("entry");
-            sendMsgVo.setMsg("用户进入");
-            sendMsgVo.setData(JSONObject.toJSONString(liveWatchUserVO));
-            sendMsgVo.setNickName(fsUser.getNickname());
-            sendMsgVo.setAvatar(fsUser.getAvatar());
-            // 广播连接消息
-            broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
+            if (1 == random.nextInt(4)) {
+                SendMsgVo sendMsgVo = new SendMsgVo();
+                sendMsgVo.setLiveId(liveId);
+                sendMsgVo.setUserId(userId);
+                sendMsgVo.setUserType(userType);
+                sendMsgVo.setCmd("entry");
+                sendMsgVo.setMsg("用户进入");
+                sendMsgVo.setData(JSONObject.toJSONString(liveWatchUserVO));
+                sendMsgVo.setNickName(fsUser.getNickname());
+                sendMsgVo.setAvatar(fsUser.getAvatar());
+                // 广播连接消息
+                broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
+            }
 
             LiveUserFirstEntry liveUserFirstEntry = liveUserFirstEntryService.selectEntityByLiveIdUserId(liveId, userId);
             if (liveUserFirstEntry != null) {
@@ -190,13 +193,12 @@ public class WebSocketServer {
             // 为admin房间创建单线程执行器,保证串行化发送
             adminExecutors.computeIfAbsent(liveId, k -> Executors.newSingleThreadExecutor());
         }
-        
+
         // 初始化Session锁
         sessionLocks.putIfAbsent(session.getId(), new ReentrantLock());
         // 初始化心跳时间
         heartbeatCache.put(session.getId(), System.currentTimeMillis());
 
-        log.debug("加入webSocket liveId: {}, userId: {}, 直播间人数: {}, 管理端人数: {}", liveId, userId, room.size(), adminRoom.size());
     }
 
     //关闭连接时调用
@@ -227,18 +229,22 @@ public class WebSocketServer {
             String onlineUsersSetKey = ONLINE_USERS_SET_KEY + liveId;
             redisCache.redisTemplate.opsForSet().remove(onlineUsersSetKey, String.valueOf(userId));
             LiveWatchUser liveWatchUserVO = liveWatchUserService.close(fsUser,liveId, userId);
-            SendMsgVo sendMsgVo = new SendMsgVo();
-            sendMsgVo.setLiveId(liveId);
-            sendMsgVo.setUserId(userId);
-            sendMsgVo.setUserType(userType);
-            sendMsgVo.setCmd("out");
-            sendMsgVo.setMsg("用户离开");
-            sendMsgVo.setData(JSONObject.toJSONString(liveWatchUserVO));
-            sendMsgVo.setNickName(fsUser.getNickname());
-            sendMsgVo.setAvatar(fsUser.getAvatar());
-
-            // 广播离开消息
-            broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
+
+
+            // 广播离开消息 添加一个概率问题 摇塞子,1-4 当为1的时候广播消息
+            if (1 == new Random().nextInt(4)) {
+                SendMsgVo sendMsgVo = new SendMsgVo();
+                sendMsgVo.setLiveId(liveId);
+                sendMsgVo.setUserId(userId);
+                sendMsgVo.setUserType(userType);
+                sendMsgVo.setCmd("out");
+                sendMsgVo.setMsg("用户离开");
+                sendMsgVo.setData(JSONObject.toJSONString(liveWatchUserVO));
+                sendMsgVo.setNickName(fsUser.getNickname());
+                sendMsgVo.setAvatar(fsUser.getAvatar());
+                broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
+            }
+
         } else {
             adminRoom.remove(session);
             // 如果admin房间为空,关闭并清理执行器
@@ -250,12 +256,10 @@ public class WebSocketServer {
                 adminRooms.remove(liveId);
             }
         }
-        
+
         // 清理Session相关资源
         heartbeatCache.remove(session.getId());
         sessionLocks.remove(session.getId());
-
-        log.debug("离开webSocket liveId: {}, userId: {}, 直播间人数: {}, 管理端人数: {}", liveId, userId, room.size(), adminRoom.size());
     }
 
     //收到客户端信息
@@ -467,7 +471,6 @@ public class WebSocketServer {
      * 处理红包变动消息
      */
     private void processRed(Long liveId, SendMsgVo msg) {
-        log.debug("redData: {}", msg);
         JSONObject jsonObject = JSON.parseObject(msg.getData());
         Integer status = jsonObject.getInteger("status");
         msg.setStatus( status);
@@ -483,7 +486,6 @@ public class WebSocketServer {
      * 处理抽奖变动消息
      */
     private void processLottery(Long liveId, SendMsgVo msg) {
-        log.debug("lotteryData: {}", msg);
         JSONObject jsonObject = JSON.parseObject(msg.getData());
         Integer status = jsonObject.getInteger("status");
         msg.setStatus( status);
@@ -502,12 +504,7 @@ public class WebSocketServer {
         try {
             this.onClose(session);
         } catch (Exception e) {
-            log.error("webSocket 错误 onError", e);
-        }
-        if (throwable instanceof EOFException) {
-            log.info("WebSocket连接被客户端正常关闭(EOF),sessionId: {}", session.getId());
-        } else {
-            log.error("WebSocket连接错误", throwable);
+            log.error("webSocket 错误处理失败", e);
         }
     }
 
@@ -532,17 +529,16 @@ public class WebSocketServer {
     //发送消息(带锁机制,避免并发发送)
     public void sendMessage(Session session, String message) throws IOException {
         if (session == null || !session.isOpen()) {
-            log.warn("WebSocket 会话已关闭,跳过发送");
             return;
         }
-        
+
         // 获取Session锁
         Lock lock = sessionLocks.get(session.getId());
         if (lock == null) {
             // 如果锁不存在,创建一个新锁
             lock = sessionLocks.computeIfAbsent(session.getId(), k -> new ReentrantLock());
         }
-        
+
         // 使用锁保证同一Session的消息串行发送
         lock.lock();
         try {
@@ -558,7 +554,6 @@ public class WebSocketServer {
         ConcurrentHashMap<Long, Session> room = getRoom(liveId);
         Session session = room.get(userId);
         if (session == null || !session.isOpen()) {
-            log.warn("WebSocket 会话已关闭,跳过发送");
             return;
         }
         SendMsgVo sendMsgVo = new SendMsgVo();
@@ -578,7 +573,6 @@ public class WebSocketServer {
         ConcurrentHashMap<Long, Session> room = getRoom(liveId);
         Session session = room.get(userId);
         if (session == null || !session.isOpen()) {
-            log.warn("WebSocket 会话已关闭,跳过发送");
             return;
         }
 
@@ -609,7 +603,7 @@ public class WebSocketServer {
                 sendWithRetry(v,message,1);
             }
         });
-        
+
         // admin房间:串行发送,使用单线程执行器
         if (!adminRoom.isEmpty()) {
             ExecutorService executor = adminExecutors.get(liveId);
@@ -649,7 +643,6 @@ public class WebSocketServer {
                 String valueStr = cacheObject.toString().trim();
                 current = Integer.parseInt(valueStr);
             } catch (NumberFormatException e) {
-                log.error("点赞数格式错误,liveId: {}, value: {}", liveId, cacheObject, e);
                 continue;
             }
             Integer last = lastLikeCountCache.getOrDefault(liveId, 0);
@@ -684,8 +677,6 @@ public class WebSocketServer {
 
             // 广播当前直播间的在线人数
             broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
-
-            log.debug("广播直播间在线人数: liveId={}, onlineCount={}", liveId, onlineCount);
         }
     }
 
@@ -697,66 +688,64 @@ public class WebSocketServer {
     public void cleanInactiveSessions() {
         long currentTime = System.currentTimeMillis();
         int cleanedCount = 0;
-        
+
         // 遍历所有直播间
         for (Map.Entry<Long, ConcurrentHashMap<Long, Session>> roomEntry : rooms.entrySet()) {
             Long liveId = roomEntry.getKey();
             ConcurrentHashMap<Long, Session> room = roomEntry.getValue();
-            
+
             // 检查普通用户会话
             List<Long> toRemove = new ArrayList<>();
             room.forEach((userId, session) -> {
                 Long lastHeartbeat = heartbeatCache.get(session.getId());
                 if (lastHeartbeat != null && (currentTime - lastHeartbeat) > HEARTBEAT_TIMEOUT) {
-                    log.warn("会话心跳超时,即将关闭: sessionId={}, liveId={}, userId={}, 超时时长={}ms", 
-                            session.getId(), liveId, userId, currentTime - lastHeartbeat);
                     toRemove.add(userId);
                     try {
                         if (session.isOpen()) {
                             session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "心跳超时"));
                         }
                     } catch (Exception e) {
-                        log.error("关闭超时会话失败: sessionId={}, liveId={}, userId={}", 
+                        log.error("关闭超时会话失败: sessionId={}, liveId={}, userId={}",
                                 session.getId(), liveId, userId, e);
                     }
                 }
             });
-            
+
             // 移除超时的会话
             toRemove.forEach(room::remove);
             cleanedCount += toRemove.size();
         }
-        
+
         // 检查admin房间
         for (Map.Entry<Long, CopyOnWriteArrayList<Session>> adminEntry : adminRooms.entrySet()) {
             Long liveId = adminEntry.getKey();
             CopyOnWriteArrayList<Session> adminRoom = adminEntry.getValue();
-            
+
             List<Session> toRemoveAdmin = new ArrayList<>();
             for (Session session : adminRoom) {
                 Long lastHeartbeat = heartbeatCache.get(session.getId());
                 if (lastHeartbeat != null && (currentTime - lastHeartbeat) > HEARTBEAT_TIMEOUT) {
-                    log.warn("admin会话心跳超时,即将关闭: sessionId={}, liveId={}, 超时时长={}ms", 
-                            session.getId(), liveId, currentTime - lastHeartbeat);
                     toRemoveAdmin.add(session);
                     try {
                         if (session.isOpen()) {
                             session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "心跳超时"));
                         }
                     } catch (Exception e) {
-                        log.error("关闭admin超时会话失败: sessionId={}, liveId={}", 
+                        log.error("关闭admin超时会话失败: sessionId={}, liveId={}",
                                 session.getId(), liveId, e);
                     }
                 }
             }
-            
+
             // 移除超时的admin会话
             toRemoveAdmin.forEach(adminRoom::remove);
             cleanedCount += toRemoveAdmin.size();
         }
-        
+
         if (cleanedCount > 0) {
-            log.info("清理无效会话完成,共清理 {} 个超时会话", cleanedCount);
+            if (random.nextInt(10) == 1) {
+                log.info("已清理 {} 个无效会话", cleanedCount);
+            }
         }
     }
 
@@ -777,10 +766,9 @@ public class WebSocketServer {
 
     private void sendWithRetry(Session session, String message, int maxRetries) {
         if (session == null || !session.isOpen()) {
-            log.warn("WebSocket 会话已关闭,跳过发送");
             return;
         }
-        
+
         int attempts = 0;
         while (attempts < maxRetries) {
             try {
@@ -790,7 +778,6 @@ public class WebSocketServer {
             } catch (Exception e) {
                 if (e.getMessage() != null && e.getMessage().contains("TEXT_FULL_WRITING")) {
                     attempts++;
-                    log.warn("发送消息遇到TEXT_FULL_WRITING错误,第{}次重试, sessionId={}", attempts, session.getId());
                     try {
                         TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(5, 100));
                     } catch (InterruptedException ie) {
@@ -803,7 +790,7 @@ public class WebSocketServer {
                 }
             }
         }
-        
+
         if (attempts >= maxRetries) {
             log.warn("超过重试次数({}),放弃发送消息: sessionId={}", maxRetries, session.getId());
         }

+ 16 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -1206,10 +1206,17 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
                 return R.error("公司不存在");
             }
 
+            // 实际流量传输消耗是大于文件的,添加倍数计算流量消耗 配置 course.data.usage.multiple
+            BigDecimal multiple = new BigDecimal("1"); // 默认一倍
+            String config=configService.selectConfigByKey("course.data.usage.multiple");
+            if(StringUtils.isNotEmpty(config)){
+                multiple=new BigDecimal(config);
+            }
+
             // 计算流量
             BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
             BigDecimal longAsBigDecimal = BigDecimal.valueOf(video.getFileSize());
-            long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
+            long roundedResult = result.multiply(longAsBigDecimal).multiply(multiple).setScale(0, RoundingMode.HALF_UP).longValue();
             trafficLog.setInternetTraffic(roundedResult);
             // 获取课程所属项目id
             FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
@@ -3469,10 +3476,17 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
                 return R.error("视频不存在");
             }
 
+            // 实际流量传输消耗是大于文件的,添加倍数计算流量消耗 配置 course.data.usage.multiple
+            BigDecimal multiple = new BigDecimal("1"); // 默认一倍
+            String config=configService.selectConfigByKey("course.data.usage.multiple");
+            if(config!= null){
+                multiple=new BigDecimal(config);
+            }
+
             // 计算流量
             BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
             BigDecimal longAsBigDecimal = BigDecimal.valueOf(video.getFileSize());
-            long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
+            long roundedResult = result.multiply(longAsBigDecimal).multiply(multiple).setScale(0, RoundingMode.HALF_UP).longValue();
             trafficLog.setInternetTraffic(roundedResult);
 
             //扣除流量

+ 3 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -638,14 +638,15 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         if (param.getIsUserInformation()!=null && param.getIsUserInformation() == 1){
             FsUserInformationCollection fsUserInformationCollection = fsUserInformationCollectionService.selectFsUserInformationCollectionById(param.getUserInformationId());
             if (fsUserInformationCollection != null) {
-                fsUserInformationCollection.setPackageOrderCode(order.getOrderSn());
+                String orderSn = "info" + order.getOrderSn();
+                fsUserInformationCollection.setPackageOrderCode(orderSn);
                 fsUserInformationCollection.setPackageOrderId(order.getOrderId());
                 fsUserInformationCollectionService.updatePackageOrderCode(fsUserInformationCollection);
                 //更新订单表
                 FsPackageOrder temp = new FsPackageOrder();
                 temp.setOrderId(order.getOrderId());
                 //添加前缀 区分信息采集订单
-                temp.setOrderSn("info"+ order.getOrderSn());
+                temp.setOrderSn(orderSn);
                 fsPackageOrderMapper.updateFsPackageOrder(temp);
             }
         }

+ 39 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsUserCompanyPackageScrm.java

@@ -0,0 +1,39 @@
+package com.fs.hisStore.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 销售套餐用户绑定对象 fs_user_company_package_scrm
+ *
+ * @author fs
+ * @date 2025-12-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserCompanyPackageScrm extends BaseEntity{
+
+    @TableId
+    private Long id;
+
+    /** 销售公司id */
+    @Excel(name = "销售公司id")
+    private Long companyId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 套餐id */
+    @Excel(name = "套餐id")
+    private Long packageId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+
+}

+ 2 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java

@@ -1029,7 +1029,7 @@ public interface FsStoreOrderScrmMapper
     @Select("select id from fs_store_order_scrm WHERE `status`= 1  and  extend_order_id is null ")
     List<Long> selectFsStoreOrderNoCreateOms();
 
-    @Select("select * from fs_store_order_scrm where status = 1 and extend_order_id is not null and extend_order_id != '' and delivery_id is null ")
+    @Select("select * from fs_store_order_scrm where status = 1 and extend_order_id is not null and extend_order_id != '' and delivery_id is null order by update_time")
     List<FsStoreOrderScrm> selectUpdateExpress();
 
     @Select("select fso.id from fs_store_order_scrm fso inner join fs_store_order_audit_scrm fsoa on fsoa.order_id = fso.id where fso.`status`= 1 and fso.extend_order_id is null and fsoa.audit_status = 4")
@@ -1395,4 +1395,5 @@ public interface FsStoreOrderScrmMapper
      * **/
     List<FsStoreOrderScrm> getUnsettledOrder();
 
+    void batchUpdateTime(@Param("list") List<FsStoreOrderScrm> list);
 }

+ 61 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsUserCompanyPackageScrmMapper.java

@@ -0,0 +1,61 @@
+package com.fs.hisStore.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.hisStore.domain.FsUserCompanyPackageScrm;
+
+/**
+ * 销售套餐用户绑定Mapper接口
+ * 
+ * @author fs
+ * @date 2025-12-04
+ */
+public interface FsUserCompanyPackageScrmMapper extends BaseMapper<FsUserCompanyPackageScrm>{
+    /**
+     * 查询销售套餐用户绑定
+     * 
+     * @param id 销售套餐用户绑定主键
+     * @return 销售套餐用户绑定
+     */
+    FsUserCompanyPackageScrm selectFsUserCompanyPackageScrmById(Long id);
+
+    /**
+     * 查询销售套餐用户绑定列表
+     * 
+     * @param fsUserCompanyPackageScrm 销售套餐用户绑定
+     * @return 销售套餐用户绑定集合
+     */
+    List<FsUserCompanyPackageScrm> selectFsUserCompanyPackageScrmList(FsUserCompanyPackageScrm fsUserCompanyPackageScrm);
+
+    /**
+     * 新增销售套餐用户绑定
+     * 
+     * @param fsUserCompanyPackageScrm 销售套餐用户绑定
+     * @return 结果
+     */
+    int insertFsUserCompanyPackageScrm(FsUserCompanyPackageScrm fsUserCompanyPackageScrm);
+
+    /**
+     * 修改销售套餐用户绑定
+     * 
+     * @param fsUserCompanyPackageScrm 销售套餐用户绑定
+     * @return 结果
+     */
+    int updateFsUserCompanyPackageScrm(FsUserCompanyPackageScrm fsUserCompanyPackageScrm);
+
+    /**
+     * 删除销售套餐用户绑定
+     * 
+     * @param id 销售套餐用户绑定主键
+     * @return 结果
+     */
+    int deleteFsUserCompanyPackageScrmById(Long id);
+
+    /**
+     * 批量删除销售套餐用户绑定
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserCompanyPackageScrmByIds(Long[] ids);
+}

+ 21 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsUsePackageScrmSendParam.java

@@ -0,0 +1,21 @@
+package com.fs.hisStore.param;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class FsUsePackageScrmSendParam {
+
+    /** 优惠劵id */
+    @Excel(name = "套餐id")
+    private Long packageId;
+
+    @Excel(name = "会员ID")
+    private Long userId;
+
+    //发送销售id
+    private Long companyUserId;
+
+    //发送销售公司id
+    private Long companyId;
+}

+ 5 - 1
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreProductPackageScrmService.java

@@ -1,8 +1,11 @@
 package com.fs.hisStore.service;
 
 import java.util.List;
+
+import com.fs.common.core.domain.R;
 import com.fs.hisStore.domain.FsStoreProductPackageScrm;
 import com.fs.hisStore.param.FsStoreProductPackageQueryParam;
+import com.fs.hisStore.param.FsUsePackageScrmSendParam;
 import com.fs.hisStore.vo.FsStoreProductPacketVO;
 
 /**
@@ -68,9 +71,10 @@ public interface IFsStoreProductPackageScrmService
     /**
      * 批量修改商品组合套餐
      *
-     * @param packageIds 需要修改的数据ID
+     * @param orderIds 需要修改的数据ID
      * @return 结果
      */
     public int updateFsStoreProductPackages(Long[] orderIds,Long status,Long companyId);
 
+    R sendPackage(FsUsePackageScrmSendParam param);
 }

+ 12 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -390,6 +390,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     private IFsUserIntegralLogsService userIntegralLogsService;
     @Autowired
     private FsStoreProductPackageScrmMapper fsStoreProductPackageMapper;
+    @Autowired
+    private FsUserCompanyPackageScrmMapper fsUserCompanyPackageScrmMapper;
 
     @PostConstruct
     public void initErpServiceMap() {
@@ -1606,6 +1608,16 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if (storeProductPackage.getStatus().equals(0)) {
                 return R.error("此套餐已下架");
             }
+            //只允许销售分享下单
+            if (CloudHostUtils.hasCloudHostName("康年堂")){
+                FsUserCompanyPackageScrm fsUserCompanyPackageScrm = new FsUserCompanyPackageScrm();
+                fsUserCompanyPackageScrm.setUserId(uid);
+                fsUserCompanyPackageScrm.setPackageId(param.getPackageId());
+                List<FsUserCompanyPackageScrm> fsUserCompanyPackageList = fsUserCompanyPackageScrmMapper.selectFsUserCompanyPackageScrmList(fsUserCompanyPackageScrm);
+                if (fsUserCompanyPackageList == null || fsUserCompanyPackageList.isEmpty()) {
+                    return R.error("商品链接无效");
+                }
+            }
             //限购处理
             if (storeProductPackage.getLimitCount() != null && storeProductPackage.getLimitCount() > 0) {
                 //查看是否已购买

+ 32 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductPackageScrmServiceImpl.java

@@ -1,17 +1,24 @@
 package com.fs.hisStore.service.impl;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
+import com.fs.common.core.domain.R;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.domain.FsStoreProductAttrValueScrm;
+import com.fs.hisStore.domain.FsUserCompanyPackageScrm;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
 import com.fs.hisStore.dto.StorePackageProductDTO;
 import com.fs.hisStore.mapper.FsStoreProductAttrValueScrmMapper;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
+import com.fs.hisStore.mapper.FsUserCompanyPackageScrmMapper;
 import com.fs.hisStore.param.FsStoreProductPackageQueryParam;
+import com.fs.hisStore.param.FsUsePackageScrmSendParam;
 import com.fs.hisStore.vo.FsStoreProductPacketVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -34,6 +41,10 @@ public class FsStoreProductPackageScrmServiceImpl implements IFsStoreProductPack
     private FsStoreProductAttrValueScrmMapper fsStoreProductAttrValueMapper;
     @Autowired
     private FsStoreProductScrmMapper fsStoreProductMapper;
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+    @Autowired
+    private FsUserCompanyPackageScrmMapper fsUserCompanyPackageScrmMapper;
     /**
      * 查询商品组合套餐
      *
@@ -152,4 +163,25 @@ public class FsStoreProductPackageScrmServiceImpl implements IFsStoreProductPack
         return fsStoreProductPackageMapper.updateFsStoreProductPackages(orderIds,status,companyId);
     }
 
+    @Override
+    public R sendPackage(FsUsePackageScrmSendParam param) {
+        Long companyUserId = param.getCompanyUserId();
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);
+        if (companyUser.getCompanyId()==null){
+            return R.error("销售信息错误");
+        }
+        FsUserCompanyPackageScrm fsUserCompanyPackageScrm = new FsUserCompanyPackageScrm();
+        fsUserCompanyPackageScrm.setCompanyId(companyUser.getCompanyId());
+        fsUserCompanyPackageScrm.setCompanyUserId(param.getCompanyUserId());
+        fsUserCompanyPackageScrm.setUserId(param.getUserId());
+        fsUserCompanyPackageScrm.setPackageId(param.getPackageId());
+        List<FsUserCompanyPackageScrm> fsUserCompanyPackageScrms = fsUserCompanyPackageScrmMapper.selectFsUserCompanyPackageScrmList(fsUserCompanyPackageScrm);
+        if (fsUserCompanyPackageScrms == null || fsUserCompanyPackageScrms.isEmpty()){
+            fsUserCompanyPackageScrm.setCreateTime(new Date());
+            fsUserCompanyPackageScrmMapper.insertFsUserCompanyPackageScrm(fsUserCompanyPackageScrm);
+        }
+        return R.ok();
+
+    }
+
 }

+ 4 - 0
fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java

@@ -266,4 +266,8 @@ public interface ILiveOrderService {
     void batchUpdateTime(List<LiveOrder> list);
 
     void batchUpdateTimeIds(List<Long> ids);
+
+    Long isExistPayedRecord(Long orderId);
+
+    void payConfirmPayment(Long existPayedRecordId);
 }

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

@@ -195,4 +195,6 @@ public interface ILiveService
     R liveListAll(PageRequest pageRequest);
 
     List<Live> listToLiveNoEnd(Live live);
+
+    Live selectLiveDbByLiveId(Long liveId);
 }

+ 49 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -82,8 +82,10 @@ import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
 import com.fs.hisStore.vo.*;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
+import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
 import com.fs.live.domain.*;
@@ -98,8 +100,13 @@ import com.fs.live.service.*;
 import com.fs.live.vo.*;
 import com.fs.store.domain.*;
 import com.fs.system.service.ISysConfigService;
+import com.fs.tzBankPay.doman.QueryOrderResult;
+import com.fs.tzBankPay.doman.TzBankResult;
+import com.fs.tzBankPay.doman.payQueryOrder;
 import com.fs.wx.order.domain.FsWxExpressTask;
 import com.fs.wx.order.mapper.FsWxExpressTaskMapper;
+import com.fs.ybPay.domain.OrderResult;
+import com.fs.ybPay.dto.OrderQueryDTO;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
 import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
@@ -3395,6 +3402,48 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         baseMapper.batchUpdateTimeIds(ids);
     }
 
+    @Override
+    public Long isExistPayedRecord(Long orderId) {
+        LiveOrder liveOrder = baseMapper.selectLiveOrderByOrderId(String.valueOf(orderId));
+        if (liveOrder != null) {
+            List<LiveOrderPayment> paymentList = liveOrderPaymentMapper.selectLiveOrderPaymentByOrderId(orderId);
+            if (null != paymentList && !paymentList.isEmpty()) {
+                for (LiveOrderPayment payment : paymentList) {
+                    V2TradePaymentScanpayQueryRequest request = new V2TradePaymentScanpayQueryRequest();
+                    request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                    request.setOrgHfSeqId(payment.getTradeNo());
+                    HuiFuQueryOrderResult queryOrderResult = null;
+                    try {
+                        queryOrderResult = huiFuService.queryOrder(request);
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                    if ("00000000".equals(queryOrderResult.getResp_code())) {
+                        if (queryOrderResult.getTrans_stat().equals("S")) {
+                            return payment.getPaymentId();
+                        }
+                    }
+                }
+            }
+
+        } else {
+            throw new RuntimeException("直播订单不存在");
+        }
+        return null;
+    }
+
+    @Override
+    @Transactional
+    public void payConfirmPayment(Long existPayedRecordId) {
+        LiveOrderPayment payment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentId(existPayedRecordId);
+        if (payment == null) {
+            log.error("支付单不存在");
+            return;
+        }
+        log.info("手动查询单号:" + existPayedRecordId + ":" + payment);
+        this.payConfirm(1, null, payment.getPayCode(), payment.getTradeNo(), payment.getBankSerialNo(), payment.getBankSerialNo());
+    }
+
 
     @Override
     @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)

+ 27 - 5
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -128,6 +128,28 @@ public class LiveServiceImpl implements ILiveService
     private static volatile Integer version = 0;
 
 
+    @Override
+    public Live selectLiveDbByLiveId(Long liveId) {
+        // 缓存中没有,从数据库查询
+        Live byId = baseMapper.selectLiveByLiveId(liveId);
+        if (byId == null) {
+            return null;
+        }
+
+        List<LiveVideo> videos = liveVideoService.listByLiveId(liveId, 1);
+        if(!videos.isEmpty()){
+            LiveVideo liveVideo = videos.get(0);
+            byId.setVideoUrl(liveVideo.getVideoUrl());
+            byId.setDuration(liveVideo.getDuration());
+            byId.setVideoId(liveVideo.getVideoId());
+            byId.setVideoType(liveVideo.getVideoType());
+            byId.setVideoFileSize(liveVideo.getFileSize());
+            byId.setVideoDuration(liveVideo.getDuration());
+        }
+
+        return byId;
+    }
+
 
     /**
      * 查询直播
@@ -143,13 +165,13 @@ public class LiveServiceImpl implements ILiveService
         if (cachedLive != null) {
             return cachedLive;
         }
-        
+
         // 缓存中没有,从数据库查询
         Live byId = baseMapper.selectLiveByLiveId(liveId);
         if (byId == null) {
             return null;
         }
-        
+
         List<LiveVideo> videos = liveVideoService.listByLiveId(liveId, 1);
         if(!videos.isEmpty()){
             LiveVideo liveVideo = videos.get(0);
@@ -160,10 +182,10 @@ public class LiveServiceImpl implements ILiveService
             byId.setVideoFileSize(liveVideo.getFileSize());
             byId.setVideoDuration(liveVideo.getDuration());
         }
-        
+
         // 将结果存入缓存
         redisCache.setCacheObject(cacheKey, byId, LiveKeysConstant.LIVE_DATA_CACHE_EXPIRE, TimeUnit.SECONDS);
-        
+
         return byId;
     }
 
@@ -551,7 +573,7 @@ public class LiveServiceImpl implements ILiveService
         log.error("updateLive:" + live.getLiveId());
         int result = baseMapper.updateLive(live);
         liveAutoTaskService.recalcLiveAutoTask(live);
-        
+
         // 清除缓存
         clearLiveCache(live.getLiveId());
 

+ 13 - 0
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -2082,4 +2082,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
               ) >= 3
     </select>
 
+    <update id="batchUpdateTime">
+        UPDATE fs_store_order_scrm
+        SET update_time = CASE
+        <foreach collection="list" item="item" separator="">
+            WHEN id = #{item.id} THEN #{item.updateTime}
+        </foreach>
+        END
+        WHERE id IN
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item.id}
+        </foreach>
+    </update>
+
 </mapper>

+ 79 - 0
fs-service/src/main/resources/mapper/hisStore/FsUserCompanyPackageScrmMapper.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.hisStore.mapper.FsUserCompanyPackageScrmMapper">
+    
+    <resultMap type="FsUserCompanyPackageScrm" id="FsUserCompanyPackageScrmResult">
+        <result property="id"    column="id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="packageId"    column="package_id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectFsUserCompanyPackageScrmVo">
+        select id, company_id, company_user_id, package_id, user_id, create_time, update_time from fs_user_company_package_scrm
+    </sql>
+
+    <select id="selectFsUserCompanyPackageScrmList" parameterType="FsUserCompanyPackageScrm" resultMap="FsUserCompanyPackageScrmResult">
+        <include refid="selectFsUserCompanyPackageScrmVo"/>
+        <where>  
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="companyUserId != null "> and company_user_id = #{companyUserId}</if>
+            <if test="packageId != null "> and package_id = #{packageId}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+        </where>
+    </select>
+    
+    <select id="selectFsUserCompanyPackageScrmById" parameterType="Long" resultMap="FsUserCompanyPackageScrmResult">
+        <include refid="selectFsUserCompanyPackageScrmVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertFsUserCompanyPackageScrm" parameterType="FsUserCompanyPackageScrm" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_user_company_package_scrm
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">company_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="packageId != null">package_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="companyId != null">#{companyId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="packageId != null">#{packageId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateFsUserCompanyPackageScrm" parameterType="FsUserCompanyPackageScrm">
+        update fs_user_company_package_scrm
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="packageId != null">package_id = #{packageId},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsUserCompanyPackageScrmById" parameterType="Long">
+        delete from fs_user_company_package_scrm where id = #{id}
+    </delete>
+
+    <delete id="deleteFsUserCompanyPackageScrmByIds" parameterType="String">
+        delete from fs_user_company_package_scrm where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 3 - 1
fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml

@@ -1120,7 +1120,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             t1.delivery_code as deliverySn,
             t3.company_name as companyName,
             t4.nick_name as companyUserNickName,
-            lop.bank_transaction_id as  bankTransactionId
+            lop.bank_transaction_id as  bankTransactionId,
+            t1.pay_money,
+            t1.pay_delivery as payPostage
         from
             live_order t1
                 left join live_order_item t2 on t1.order_id = t2.order_id

+ 5 - 1
fs-user-app/src/main/java/com/fs/app/controller/UserController.java

@@ -26,6 +26,8 @@ import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsUserCouponCountUVO;
 import com.fs.his.vo.FsUserCouponListUVO;
 import com.fs.his.vo.UserVo;
+import com.fs.hisStore.domain.FsUserScrm;
+import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.qw.service.IQwAppContactWayService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
@@ -77,6 +79,8 @@ public class UserController extends  AppBaseController {
     private IQwAppContactWayService qwAppContactWayService;
     @Autowired
     private IFsUserCourseVideoService courseVideoService;
+    @Autowired
+    private IFsUserScrmService fsUserScrmService;
 
 
     @Autowired
@@ -116,7 +120,7 @@ public class UserController extends  AppBaseController {
     @GetMapping("/getUserInfo")
     public R getUserInfo(HttpServletRequest request){
         try {
-            FsUser user=userService.selectFsUserByUserId(Long.parseLong(getUserId()));
+            FsUserScrm user=fsUserScrmService.selectFsUserByUserId(Long.parseLong(getUserId()));
             if (user.getPhone()!=null&&user.getPhone().length()>11&&!user.getPhone().matches("\\d+")){
                 user.setPhone(decryptPhoneMk(user.getPhone()));
             }

+ 10 - 1
fs-user-app/src/main/java/com/fs/app/controller/live/LiveOrderController.java

@@ -644,13 +644,22 @@ public class LiveOrderController extends AppBaseController
     {
         Long orderId = param.getOrderId();
         logger.info("开始处理支付请求, 订单号: {}, 支付类型: {}", orderId, param.getPayType());
+        try{
+            Long existPayedRecordId = orderService.isExistPayedRecord(param.getOrderId());
+            if (null != existPayedRecordId) {
+                orderService.payConfirmPayment(existPayedRecordId);
+                return R.error("当前订单已支付");
+            }
+        } catch(Exception ex){
+            log.error("校验当前订单是否存在已经支付的支付记录异常,param:{}",param,ex);
+        }
+
 
         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("订单正在处理中,请勿重复提交");

+ 23 - 4
fs-user-app/src/main/java/com/fs/app/controller/store/StoreProductPackageScrmController.java

@@ -12,6 +12,7 @@ import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
 import com.fs.hisStore.dto.StorePackageProductDTO;
 import com.fs.hisStore.param.FsStoreProductPackageQueryParam;
+import com.fs.hisStore.param.FsUsePackageScrmSendParam;
 import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
 import com.fs.hisStore.service.IFsStoreProductPackageScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
@@ -21,10 +22,7 @@ import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
@@ -83,4 +81,25 @@ public class StoreProductPackageScrmController extends AppBaseController {
         return R.ok().put("data",storeProductPackage);
     }
 
+    /**
+     * 销售分享套餐
+     */
+    @Login
+    @ApiOperation("销售分享套餐")
+    @PostMapping("/sendPackage")
+    public R sendPackage(@RequestBody FsUsePackageScrmSendParam param)
+    {
+        Long companyUserId = getCompanyUserId();
+        if(companyUserId==null){
+            return R.error("销售未登录!");
+        }
+        Long userId = param.getUserId();
+        if (userId == null) {
+            return R.error("未选择分享用户!");
+        }
+        param.setCompanyUserId(companyUserId);
+        return productPackageService.sendPackage(param);
+    }
+
+
 }