26 Commits f8c910a174 ... b54a35c441

Autore SHA1 Messaggio Data
  yfh b54a35c441 Merge remote-tracking branch 'refs/remotes/origin/master' into Payment-Configuration 1 giorno fa
  yfh b283320d49 增加看课权限 1 giorno fa
  yfh dce2dff85a Merge remote-tracking branch 'origin/master' 1 giorno fa
  zyp 3029d6c500 zyp 1 giorno fa
  lmx 236babc2bb sop发送直播间 1 giorno fa
  yuhongqi 3cd7a38756 关联状态 使用订单id 1 giorno fa
  yfh fd210295ac Merge remote-tracking branch 'origin/master' 1 giorno fa
  yfh dade05b88f 调整下单收货地址不要的调整 1 giorno fa
  yuhongqi 9e712ad180 Merge remote-tracking branch 'origin/master' 1 giorno fa
  yuhongqi 50eed55c01 取消状态订单关闭 1 giorno fa
  xgb f3cb09ee32 Merge remote-tracking branch 'origin/master' 1 giorno fa
  xgb f5349a2010 看课休息暂定 区分公司 1 giorno fa
  吴树波 222f893df9 Merge remote-tracking branch 'origin/master' 1 giorno fa
  吴树波 8bd33d329f 修改发群类型 1 giorno fa
  yuhongqi 307e681879 切换小程序 1 giorno fa
  yuhongqi 350f360f71 直播间订阅 1 giorno fa
  yuhongqi 53971f4081 Merge remote-tracking branch 'origin/master' 1 giorno fa
  yuhongqi be3772fa23 非直播不进行弹窗 1 giorno fa
  luolinsong 4007ad8da0 在职继承,离职继承增加员工账号模糊查询 1 giorno fa
  zhangqin 1ec945a91c Merge branch 'new_adv_2.0' 1 giorno fa
  zhangqin a3ed19746c coding:微信配置 1 giorno fa
  yuhongqi 2f11c6afd0 Merge remote-tracking branch 'origin/master' 2 giorni fa
  yuhongqi 94a6e6271b 导出上限 2 giorni fa
  caoliqin 6b44b27141 Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java 2 giorni fa
  caoliqin 78c2060e63 feat:套餐包制单-代收金额添加。 2 giorni fa
  yfh b8486677ad 调整下单收货地址不能为空 2 giorni fa
31 ha cambiato i file con 515 aggiunte e 66 eliminazioni
  1. 2 1
      fs-ad-new-api/src/main/java/com/fs/app/controller/WeChatController.java
  2. 9 3
      fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeServiceImpl.java
  3. 1 1
      fs-ad-new-api/src/main/java/com/fs/app/task/ConversionRetryTask.java
  4. 1 1
      fs-ad-new-api/src/main/java/com/fs/app/task/DataSyncTask.java
  5. 110 0
      fs-ad-new-api/src/main/java/com/fs/framework/aspectj/ControllerLogAspect.java
  6. 3 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  7. 1 1
      fs-admin/src/main/java/com/fs/live/controller/OrderController.java
  8. 13 1
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  9. 1 1
      fs-company/src/main/java/com/fs/company/controller/live/OrderController.java
  10. 5 4
      fs-company/src/main/java/com/fs/company/controller/qw/QwCustomerLinkController.java
  11. 3 6
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  12. 6 0
      fs-qw-api/Dockerfile
  13. 91 9
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  14. 2 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  15. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  16. 21 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  17. 9 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  18. 2 0
      fs-service/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java
  19. 161 5
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  20. 1 1
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderCreateParam.java
  21. 38 12
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  22. 4 1
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  23. 5 0
      fs-service/src/main/java/com/fs/qw/param/QwGroupChatParam.java
  24. 4 0
      fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java
  25. 8 3
      fs-service/src/main/resources/application-config-druid-bjzm-test.yml
  26. 2 2
      fs-service/src/main/resources/application-config-druid-bjzm.yml
  27. 2 2
      fs-service/src/main/resources/application-config-druid-ylrz.yml
  28. 2 2
      fs-service/src/main/resources/mapper/course/FsUserCoursePeriodMapper.xml
  29. 3 3
      fs-service/src/main/resources/mapper/hisStore/MergedOrderMapper.xml
  30. 3 0
      fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml
  31. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/store/WxUserScrmController.java

+ 2 - 1
fs-ad-new-api/src/main/java/com/fs/app/controller/WeChatController.java

@@ -60,11 +60,12 @@ public class WeChatController {
                     JSONObject obj = JSONObject.parseObject(execute2.body());
                     access_token = obj.getString("access_token");
                     advMiniConfig.setAccessToken(access_token);
+                    advMiniConfig.setExpiresIn(LocalDateTime.now().plusSeconds(obj.getLong("expires_in")));
                     advMiniConfigService.updateById(advMiniConfig);
                 }
                 Map<String, Object> map = new HashMap<>();
                 Map<String, Object> map2 = new HashMap<>();
-                map2.put("path", "pages/home/productList");
+                map2.put("path", "/pages/shopping/productDetails");
                 map2.put("query", "traceId=" + traceId);
                 map2.put("env_version", "trial");
                 map.put("jump_wxa", map2);

+ 9 - 3
fs-ad-new-api/src/main/java/com/fs/app/facade/CallbackProcessingFacadeServiceImpl.java

@@ -153,7 +153,7 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
             }
         }
         // 模板缓存
-        Object ca = redisUtil.get(TEMPLATE_DATA + traceId);
+/*        Object ca = redisUtil.get(TEMPLATE_DATA + traceId);
         String templateData;
         if (ca != null) {
             templateData = String.valueOf(ca);
@@ -164,8 +164,14 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
             // 替换二维码链接
             updateQrCodeInTemplate(jsonObject, traceId, byId, byTraceId);
             templateData = JSONUtil.toJsonStr(jsonObject);
-        }
+        }*/
 
+        // 查询模板数据
+        LandingPageTemplate landingPageTemplate = landingPageTemplateService.getById(byId.getLaunchPageId());
+        JSONObject jsonObject = JSONUtil.parseObj(landingPageTemplate.getTemplateData());
+        // 替换二维码链接
+        updateQrCodeInTemplate(jsonObject, traceId, byId, byTraceId);
+        String templateData = JSONUtil.toJsonStr(jsonObject);
 
         // 保存或更新 线索信息
         LocalDateTime now = LocalDateTime.now();
@@ -221,7 +227,7 @@ public class CallbackProcessingFacadeServiceImpl implements CallbackProcessingFa
                                                Integer allocationRule,
                                                Long allocationRuleId,
                                                Lead byTraceId) {
-
+        log.info("开始获取广告二维码: {} {} {} {}", launchType, allocationRule, allocationRuleId ,byTraceId);
         // 二维码
         String qrCode = "";
         if (allocationRule == 1) {

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/task/ConversionRetryTask.java

@@ -37,7 +37,7 @@ public class ConversionRetryTask {
      * 转化回传重试任务
      * cron: 每10分钟执行
      */
-    @Scheduled(cron = "0 */5 * * * ?")
+    // @Scheduled(cron = "0 */5 * * * ?")
     @DistributeLock(scene = "task", key = "conversion_retry", waitTime = 0, errorMsg = "conversion_retry任务已执行")
     public void execute() {
         // 查询待重试的转化记录

+ 1 - 1
fs-ad-new-api/src/main/java/com/fs/app/task/DataSyncTask.java

@@ -59,7 +59,7 @@ public class DataSyncTask {
      * 数据同步任务->当日数据
      * cron: 每1小时统计站点数据
      */
-    @Scheduled(cron = "0 0/1 * * * ?")
+    @Scheduled(cron = "0 0 0/1 * * ?")
     @DistributeLock(scene = "task", key = "sync_today_data", waitTime = 0, errorMsg = "sync_today_data任务已执行")
     public void syncTodayData() throws InterruptedException {
         String batchNo = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd");

+ 110 - 0
fs-ad-new-api/src/main/java/com/fs/framework/aspectj/ControllerLogAspect.java

@@ -0,0 +1,110 @@
+
+package com.fs.framework.aspectj;
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+@Slf4j
+@Aspect
+@Component
+public class ControllerLogAspect {
+
+    @Pointcut("execution(* com.fs.app.controller..*.*(..))")
+    public void controllerPointcut() {
+    }
+
+    @Around("controllerPointcut()")
+    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
+        long startTime = System.currentTimeMillis();
+
+        String className = joinPoint.getTarget().getClass().getName();
+        String methodName = joinPoint.getSignature().getName();
+        String fullMethodName = className + "." + methodName;
+
+        Object[] args = joinPoint.getArgs();
+        String requestParams = getRequestParams(args);
+
+        log.info("========== 接口调用开始 ==========");
+        log.info("接口方法: {}", fullMethodName);
+        log.info("请求参数: {}", requestParams);
+
+        Object result = null;
+        try {
+            result = joinPoint.proceed();
+
+            long endTime = System.currentTimeMillis();
+            long costTime = endTime - startTime;
+
+            log.info("返回结果: {}", JSON.toJSONString(result));
+            log.info("接口耗时: {} ms", costTime);
+            log.info("========== 接口调用结束 ==========");
+
+            return result;
+        } catch (Throwable e) {
+            long endTime = System.currentTimeMillis();
+            long costTime = endTime - startTime;
+
+            log.error("接口异常: {}", e.getMessage());
+            log.error("接口耗时: {} ms", costTime);
+            log.error("========== 接口调用异常 ==========");
+
+            throw e;
+        }
+    }
+
+    private String getRequestParams(Object[] args) {
+        if (args == null || args.length == 0) {
+            return "无参数";
+        }
+
+        StringBuilder params = new StringBuilder();
+        for (int i = 0; i < args.length; i++) {
+            if (args[i] != null && !isFilterObject(args[i])) {
+                try {
+                    Object jsonObj = JSON.toJSON(args[i]);
+                    params.append(jsonObj.toString());
+                    if (i < args.length - 1) {
+                        params.append(", ");
+                    }
+                } catch (Exception e) {
+                    params.append(args[i].getClass().getSimpleName());
+                }
+            }
+        }
+
+        return params.length() > 0 ? params.toString() : "无参数";
+    }
+
+    private boolean isFilterObject(final Object o) {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray()) {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        } else if (Collection.class.isAssignableFrom(clazz)) {
+            Collection collection = (Collection) o;
+            for (Iterator iter = collection.iterator(); iter.hasNext();) {
+                return iter.next() instanceof MultipartFile;
+            }
+        } else if (Map.class.isAssignableFrom(clazz)) {
+            Map map = (Map) o;
+            for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
+                Map.Entry entry = (Map.Entry) iter.next();
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+                || o instanceof BindingResult;
+    }
+}

+ 3 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java

@@ -106,8 +106,10 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         if (list != null) {
             LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderVO vo : list) {
-                if(vo.getPhone()!=null){
+                if(StringUtils.isNotEmpty(vo.getPhone())){
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                }
+                if (StringUtils.isNotEmpty(vo.getUserPhone())){
                     vo.setUserPhone(vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                 }
                 if (CloudHostUtils.hasCloudHostName("康年堂")){

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

@@ -51,7 +51,7 @@ public class OrderController extends BaseController
     @Autowired
     private IMergedOrderService mergedOrderService;
     // 设置最大导出数量限制为20000条
-    private static final int maxExportCount = 20000;
+    private static final int maxExportCount = 50000;
 
 
     @Autowired

+ 13 - 1
fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java

@@ -31,6 +31,8 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import com.hc.openapi.tool.fastjson.JSON;
+import com.hc.openapi.tool.fastjson.JSONObject;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -115,6 +117,15 @@ public class FsUserCoursePeriodController extends BaseController {
             } else {
                 vo.setIsNeedRegisterMember("0");
             }
+
+            // 看课休息判断
+            if(StringUtils.isNotBlank(vo.getIsOpenRestFlag())){
+                JSONObject  jsonObject= JSON.parseObject(vo.getIsOpenRestFlag());
+                vo.setIsOpenRestReminder(Integer.parseInt(jsonObject.get(currentCompanyId.toString()).toString()));
+            }else {
+                vo.setIsOpenRestReminder(null);
+            }
+
         }
         PageInfo<FsUserCoursePeriodVO> pageInfo = new PageInfo<>(list);
         Map<String, Object> result = new HashMap<>();
@@ -200,7 +211,8 @@ public class FsUserCoursePeriodController extends BaseController {
     @PutMapping("/updatePeriodIsOpenRestReminder")
     public AjaxResult updatePeriodIsOpenRestReminder(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
-        return toAjax(fsUserCoursePeriodService.updatePeriod(fsUserCoursePeriod));
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        return toAjax(fsUserCoursePeriodService.updatePeriod(fsUserCoursePeriod,loginUser.getCompany().getCompanyId()));
 
     }
 

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/live/OrderController.java

@@ -52,7 +52,7 @@ public class OrderController extends BaseController
     @Autowired
     private IMergedOrderService mergedOrderService;
     // 设置最大导出数量限制为20000条
-    private static final int maxExportCount = 20000;
+    private static final int maxExportCount = 50000;
 
 
 

+ 5 - 4
fs-company/src/main/java/com/fs/company/controller/qw/QwCustomerLinkController.java

@@ -17,6 +17,7 @@ import com.fs.qw.dto.QwCustomerLinkUserDto;
 import com.fs.qw.service.IQwCustomerLinkChannelService;
 import com.fs.qw.service.IQwCustomerLinkService;
 import com.fs.qw.service.IQwCustomerLinkUserService;
+import com.fs.qwApi.domain.QwLinkCreateResult;
 import com.fs.qwApi.param.QwLinkCreateParam;
 import com.fs.qwApi.service.QwApiService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -110,11 +111,11 @@ public class QwCustomerLinkController {
             // qwApiService.linkUpdate(qwLinkCreateParam, qwGroupLiveCode.getCorpId());
             success = qwCustomerLinkService.updateById(bean);
         } else {
-/*            QwLinkCreateResult qwLinkCreateResult = qwApiService.linkCreate(qwLinkCreateParam, qwGroupLiveCode.getCorpId());
+            QwLinkCreateResult qwLinkCreateResult = qwApiService.linkCreate(qwLinkCreateParam, qwGroupLiveCode.getCorpId());
             bean.setLinkId(qwLinkCreateResult.getLinkId());
-            bean.setUrl(qwLinkCreateResult.getUrl());*/
-            bean.setLinkId(IdUtil.randomUUID());
-            bean.setUrl("https://work.weixin.qq.com/ca/" + IdUtil.randomUUID());
+            bean.setUrl(qwLinkCreateResult.getUrl());
+/*            bean.setLinkId(IdUtil.randomUUID());
+            bean.setUrl("https://work.weixin.qq.com/ca/" + IdUtil.randomUUID())*/;
             success = qwCustomerLinkService.save(bean);
         }
 

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

@@ -362,7 +362,8 @@ public class WebSocketServer {
                             if (currentLive == null) {
                                 break;
                             }
-                            
+
+
                             // 判断直播是否已开始:status=2(直播中) 或 当前时间 >= 开播时间
                             boolean isLiveStarted = false;
                             if (currentLive.getStatus() != null && currentLive.getStatus() == 2) {
@@ -375,13 +376,9 @@ public class WebSocketServer {
                             }
                             
                             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;

+ 6 - 0
fs-qw-api/Dockerfile

@@ -0,0 +1,6 @@
+FROM openjdk:8-jre
+# java版本,最好使用openjdk,而不是类似于Java:1.8
+COPY ./target/fs-qw-api.jar fs-qw-api.jar
+# 向外暴露的接口,最好与项目yml文件中的端口一致
+ENTRYPOINT ["java","-jar","fs-qw-api.jar"]
+# 执行启动命令java -jar

+ 91 - 9
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -694,6 +694,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         int type = content.getType();
         Long courseId = content.getCourseId();
         Long videoId = content.getVideoId();
+        Long liveId = content.getLiveId();
         Integer isOfficial = content.getIsOfficial() != null ? Integer.valueOf(content.getIsOfficial()) : 0;
 
 
@@ -746,13 +747,13 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
         if (StringUtils.isNotEmpty(logVo.getChatId())) {
             QwGroupChat groupChat = groupChatMap.get(logVo.getChatId());
-            ruleTimeVO.setSendType(6);
-            ruleTimeVO.setType(2);
             if (groupChat.getChatUserList() != null && !groupChat.getChatUserList().isEmpty()) {
                 QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null,null);
+                ruleTimeVO.setSendType(6);
+                ruleTimeVO.setType(2);
                 handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                         type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText, qwUserName,
-                        null, true, miniAppId, groupChat,config, miniMap, null, sendMsgType,companies);
+                        null, true, miniAppId, groupChat,config, miniMap, null, sendMsgType,companies,liveId);
             }
 //            if (content.getIndex() == 0) {
 //                QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null);
@@ -782,7 +783,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId, isOfficial, contactId.getExternalId(),contactId.getIsDaysNotStudy());
                     handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
                             type, qwUserId, companyUserId, companyId, externalId, welcomeText, qwUserName, fsUserId, false, miniAppId,
-                            null,config, miniMap, grade, sendMsgType,companies);
+                            null,config, miniMap, grade, sendMsgType,companies,liveId);
                 } catch (Exception e) {
                     log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
                 }
@@ -898,7 +899,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                                       String qwUserName, Long fsUserId, boolean isGroupChat, String miniAppId,
                                       QwGroupChat groupChat,CourseConfig config,
                                       Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
-                                      Integer grade, Integer sendMsgType ,List<Company> companies ) {
+                                      Integer grade, Integer sendMsgType ,List<Company> companies ,Long liveId) {
         switch (type) {
             case 1:
                 handleNormalMessage(sopLogs, content,companyUserId,companyId,isGroupChat,qwUserId,groupChat,externalId,logVo);
@@ -920,6 +921,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             case 7:
                 handleVoiceMessage(sopLogs, content, companyUserId);
                 break;
+            //直播间发送类型
+            case 20:
+                handleLiveMessage(sopLogs, content,companyUserId,companyId,isGroupChat,qwUserId,groupChat,externalId,logVo,liveId);
             default:
                 log.error("未知的消息类型 {},跳过处理。", type);
                 break;
@@ -1003,6 +1007,83 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         enqueueQwSopLogs(sopLogs);
     }
 
+    /**
+     * 处理直播消息
+     */
+    public void handleLiveMessage(QwSopLogs sopLogs,QwSopTempSetting.Content content, String companyUserId, String companyId,
+                                  boolean isGroupChat,String qwUserId,QwGroupChat groupChat,String externalId,SopUserLogsVo logVo,Long liveId){
+        // 深拷贝 Content 对象,避免使用 JSON
+        QwSopTempSetting.Content clonedContent = deepCopyContent(content);
+        if (clonedContent == null) {
+            log.error("Failed to clone content, skipping handleCourseMessage.");
+            return;
+        }
+        clonedContent.setLiveId(liveId);
+        List<QwSopTempSetting.Content.Setting> settings = clonedContent.getSetting();
+        if (settings == null || settings.isEmpty()) {
+            log.error("Cloned content settings are empty, skipping.");
+            return;
+        }
+
+        //直播发送类型
+        sopLogs.setSendType(20);
+
+        // 顺序处理每个 Setting,避免过多的并行导致线程开销
+        for (QwSopTempSetting.Content.Setting setting : settings) {
+            switch (setting.getContentType()) {
+                //直播小程序单独
+                case "12":
+                    clonedContent.setLiveId(setting.getLiveId());
+                    String sortLiveLink;
+                    sortLiveLink = "/pages_course/living.html?companyId=" + companyId + "&companyUserId=" + companyUserId + "&liveId=" + setting.getLiveId() + "&corpId=" + logVo.getCorpId()+"&qwUserId=" + qwUserId;
+                    String json = configService.selectConfigByKey("his.config");
+                    FSSysConfig sysConfig = JSON.parseObject(json, FSSysConfig.class);
+                    if (isGroupChat) {
+                        try {
+                            groupChat.getChatUserList().stream().filter(e -> e.getUserList() != null && !e.getUserList().isEmpty()).forEach(e -> {
+                                Map<String, GroupUserExternalVo> userMap = PubFun.listToMapByGroupObject(e.getUserList(), GroupUserExternalVo::getUserId);
+                                GroupUserExternalVo vo = userMap.get(groupChat.getOwner());
+                                if (vo != null && vo.getId() != null) {
+                                    sopLogs.setFsUserId(vo.getFsUserId());
+                                    //写入直播待看课记录
+                                    createLiveWatchLogAndEnQueue(companyId, companyUserId, vo.getId().toString(), setting.getLiveId(), sysConfig.getAppId(), 2, qwUserId,logVo.getCorpId());
+                                }
+                            });
+                            sortLiveLink += "&chatId=" + groupChat.getChatId();
+                        } catch (Exception e) {
+                            log.error("直播小程序群聊新增报错,{}", e.getMessage(), e);
+                        }
+                    } else {
+                        try {
+                            createLiveWatchLogAndEnQueue(companyId, companyUserId, externalId, setting.getLiveId(), sysConfig.getAppId(), 1, qwUserId,logVo.getCorpId());
+                            sortLiveLink += "&externalId=" + externalId;
+                        } catch (Exception e) {
+                            log.error("直播小程序个人新增报错,{}", e.getMessage(), e);
+                        }
+                    }
+
+                    String miniprogramLiveTitle = setting.getMiniprogramTitle();
+                    int maxLiveLength = 17;
+                    setting.setMiniprogramTitle(miniprogramLiveTitle.length() > maxLiveLength ? miniprogramLiveTitle.substring(0, maxLiveLength) + "..." : miniprogramLiveTitle);
+                    setting.setMiniprogramAppid(sysConfig.getAppId());
+                    setting.setMiniprogramPage(sortLiveLink);
+                    setting.setContentType("4");
+                    try {
+                        setting.setMiniprogramPicUrl(StringUtil.strIsNullOrEmpty(setting.getMiniprogramPicUrl()) ? "https://cos.his.cdwjyyh.com/fs/20250331/ec2b4e73be8048afbd526124a655ad56.png" : setting.getMiniprogramPicUrl());
+                    } catch (Exception e) {
+                        log.error("赋值-小程序封面地址失败-" + e);
+                    }
+
+                    break;
+                default:
+                    break;
+            }
+        }
+        sopLogs.setContentJson(JSON.toJSONString(clonedContent));
+
+        enqueueQwSopLogs(sopLogs);
+    }
+
     private void handleAIMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content) {
         sopLogs.setContentJson(JSON.toJSONString(content));
         sopLogs.setSort(3);
@@ -1988,17 +2069,18 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
     )
     public void batchInsertLiveWatchLog(List<LiveWatchLog> liveWatchLogToInsert) {
         try {
-            List<LiveWatchLog> lastInsertList = new ArrayList<>();
+            //更改为set 避免同一批生成的消息里面有重复数据 插入会报错
+            Set<LiveWatchLog> lastInsertSet = new HashSet<>();
             //判断是否存在数据 liveId + his_qw_external_contact_id + qwUserId 唯一
             for (LiveWatchLog liveWatchLog : liveWatchLogToInsert) {
                 //判断是否存在数据 存在的数据直接更新发送时间
                 if(liveWatchLogMapper.updateLiveWatchLogCondition(liveWatchLog) > 0){
                     continue;
                 }
-                lastInsertList.add(liveWatchLog);
+                lastInsertSet.add(liveWatchLog);
             }
-            if(!lastInsertList.isEmpty()){
-                liveWatchLogMapper.insertLiveWatchLogBatch(lastInsertList);
+            if(!lastInsertSet.isEmpty()){
+                liveWatchLogMapper.insertLiveWatchLogBatch(new ArrayList<>(lastInsertSet));
             }
 //            log.info("批量插入 LiveWatchLog 完成,共插入 {} 条记录。", liveWatchLogToInsert.size());
         } catch (Exception e) {

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

@@ -122,4 +122,6 @@ public class FsUserCoursePeriod
 
     // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
     private Integer IsOpenRestReminder;
+    //  控制休息提示是否打开要暂停  0-关闭 1-打开 Json串 key值为companyId
+    private String isOpenRestFlag;
 }

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

@@ -106,5 +106,5 @@ public interface IFsUserCoursePeriodService
 
     List<SysDictData> selectFsUserCoursePeriodListLabel(FsUserCoursePeriod fsUserCoursePeriod);
 
-    int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod);
+    int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod, Long companyId);
 }

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

@@ -16,7 +16,10 @@ import com.fs.course.param.PeriodStatisticCountParam;
 import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsCourseStaticsCountVO;
 import com.fs.course.vo.FsUserCoursePeriodVO;
+import com.hc.openapi.tool.fastjson.JSON;
+import com.hc.openapi.tool.fastjson.JSONObject;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -352,7 +355,24 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
      * @Date 2025/12/19 10:52
      */
     @Override
-    public int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod) {
+    public int updatePeriod(FsUserCoursePeriod fsUserCoursePeriod, Long companyId) {
+        Integer flag=fsUserCoursePeriod.getIsOpenRestReminder(); // 0-关闭 1-打开
+        FsUserCoursePeriod period=fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(fsUserCoursePeriod.getPeriodId());
+        if (period==null){
+            return 0;
+        }
+
+        JSONObject jsonObject;
+        if (StringUtils.isNotBlank(period.getIsOpenRestFlag())){
+            jsonObject= JSON.parseObject(period.getIsOpenRestFlag());
+            jsonObject.put(companyId.toString(),flag);
+        }else {
+            jsonObject=new JSONObject();
+            jsonObject.put(companyId.toString(),flag);
+        }
+
+        fsUserCoursePeriod.setIsOpenRestFlag(jsonObject.toJSONString());
+
         return fsUserCoursePeriodMapper.updateFsUserCoursePeriod(fsUserCoursePeriod);
     }
 }

+ 9 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -2531,6 +2531,9 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
         if (fsUser == null) {
             return ResponseResult.fail(401, "当前用户信息不存在");
         }
+        if (fsUser.getStatus() == 0) {
+            return ResponseResult.fail(503, "会员被停用,无权限,请联系客服!");
+        }
         //公开课
         if (param.getIsOpenCourse() != null && param.getIsOpenCourse() == 1) {
             FsCourseWatchLog watchCourseVideo = courseWatchLogMapper.getCourseWatchLogByUser(param.getUserId(), param.getVideoId(), null);
@@ -2943,17 +2946,20 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
 
             if(watchLog.getPeriodId()!=null){
                 FsUserCoursePeriod period= fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(watchLog.getPeriodId());
-                if(period!=null && period.getIsOpenRestReminder()!=null){
-                    if(period.getIsOpenRestReminder()==0){
+                if(period!=null && watchLog.getCompanyId()!=null && StringUtils.isNotBlank(period.getIsOpenRestFlag()) ){
+                    //  Json 字符串  key值公司id value值  0-关闭 1-打开 没有获取到不管
+                    JSONObject jsonObject= JSON.parseObject(period.getIsOpenRestFlag());
+                    Integer flag=(Integer) jsonObject.get(watchLog.getCompanyId().toString());
+                    if(flag==0){
                         result=false;
                     }else {
                         result=true;
                     }
+
                 }
             }
         }
 
-
         return result;
     }
 

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

@@ -93,4 +93,6 @@ public class FsUserCoursePeriodVO implements Serializable {
 
     // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
     private Integer IsOpenRestReminder;
+
+    private String IsOpenRestFlag;
 }

+ 161 - 5
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -555,8 +555,6 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             List<ErpOrderQuery> erpOrders = query.getOrders().stream()
                     .map(this::convertToErpOrderQueryScrm)
                     .collect(Collectors.toList());
-            if ("Cancelled".equals(query.getOrders().get(0).getStatus()))
-                fsStoreOrderScrmService.cancelOrderByCode(query.getOrders().get(0).getOuterPayId());
             response.setOrders(erpOrders);
         } else {
             response.setOrders(Collections.emptyList());
@@ -603,9 +601,9 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             List<ErpOrderQuery> erpOrders = query.getOrders().stream()
                     .map(this::convertToErpOrderQueryLive)
                     .collect(Collectors.toList());
-            if ("Cancelled".equals(query.getOrders().get(0).getStatus())) {
-                liveOrderMapper.cancelOrderByCode(query.getOrders().get(0).getOuterPayId());
-            }
+//            if ("Split".equals(query.getOrders().get(0).getStatus())) {
+//                this.splitLiveOrder(query.getOrders().get(0));
+//            }
             response.setOrders(erpOrders);
         } else {
             response.setOrders(Collections.emptyList());
@@ -614,6 +612,164 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return response;
     }
 
+    private void splitLiveOrder(OrderQueryResponseDTO.Order order) {
+        // ① 首先查询原来的订单
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(order.getSoId());
+        if (liveOrder == null) {
+            log.error("直播拆分订单:未查询到数据,{}", order.getSoId());
+            return;
+        }
+
+        try {
+            // ② 重新组装请求,使用 OrderQueryRequestDTO 查询拆分订单
+            OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
+            requestDTO.setOrderItemFlds(Arrays.asList("status"));
+            requestDTO.setSoIds(Collections.singletonList(order.getSoId()));
+
+            // 调用ERP服务查询拆分订单
+            OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
+
+            if (query == null || query.getOrders() == null || query.getOrders().isEmpty()) {
+                log.error("直播拆分订单:查询拆分订单失败, orderCode={}", order.getSoId());
+                return;
+            }
+
+            // ③ 把原来的订单状态修改为 6(被拆分)
+            liveOrder.setStatus(6);
+            liveOrderMapper.updateLiveOrder(liveOrder);
+            log.info("直播拆分订单:原订单状态已更新为被拆分, orderCode={}, orderId={}", order.getSoId(), liveOrder.getOrderId());
+
+            // ④ 查询出来的订单里面,除了原来的订单,将查询出来的订单新增到数据库里面
+            for (OrderQueryResponseDTO.Order splitOrder : query.getOrders()) {
+                // 跳过原来的订单(状态为 Split 的订单)
+                if ("Split".equals(splitOrder.getStatus())) {
+                    continue;
+                }
+
+                // 检查是否已经存在该拆分订单
+                LiveOrder existingOrder = liveOrderMapper.selectLiveOrderByOrderCode(splitOrder.getSoId());
+                if (existingOrder != null) {
+                    log.info("直播拆分订单:拆分订单已存在,跳过, orderCode={}", splitOrder.getSoId());
+                    continue;
+                }
+
+                // 创建新的拆分订单
+                LiveOrder newOrder = new LiveOrder();
+                // 复制原订单的基本信息
+                newOrder.setLiveId(liveOrder.getLiveId());
+                newOrder.setStoreId(liveOrder.getStoreId());
+                newOrder.setOrderCode(splitOrder.getSoId()); // 保存订单ID(soId)
+                newOrder.setUserId(liveOrder.getUserId()); // buyerId -> userId
+                newOrder.setUserName(liveOrder.getUserName());
+                newOrder.setRealName(liveOrder.getRealName());
+                newOrder.setUserPhone(liveOrder.getUserPhone());
+                newOrder.setUserAddress(liveOrder.getUserAddress());
+                newOrder.setCompanyId(liveOrder.getCompanyId());
+                newOrder.setCompanyUserId(liveOrder.getCompanyUserId());
+
+                // 设置支付金额
+                if (splitOrder.getPayAmount() != null) {
+                    newOrder.setPayMoney(splitOrder.getPayAmount());
+                    newOrder.setPayPrice(splitOrder.getPayAmount());
+                }
+
+                // 根据订单状态枚举设置状态
+                ErpQueryOrderStatusEnum statusEnum = ErpQueryOrderStatusEnum.getByCode(splitOrder.getStatus());
+                if (statusEnum != null) {
+                    // 根据状态类型设置订单状态
+                    // WaitPay -> 1 (待支付)
+                    // Sent -> 3 (待收货)
+                    // Cancelled -> 0 (已取消)
+                    // 其他状态根据业务需求设置
+                    if ("WaitPay".equals(splitOrder.getStatus())) {
+                        newOrder.setStatus(1); // 待支付
+                    } else if ("Sent".equals(splitOrder.getStatus())) {
+                        newOrder.setStatus(3); // 待收货
+                    } else if ("Cancelled".equals(splitOrder.getStatus())) {
+//                        newOrder.setStatus(0); // 已取消
+                    } else {
+                        newOrder.setStatus(2); // 默认待发货
+                    }
+                } else {
+                    newOrder.setStatus(2); // 默认待发货
+                }
+
+                // 设置物流信息
+                if (StringUtils.isNotEmpty(splitOrder.getLogisticsCompany())) {
+                    newOrder.setDeliveryName(splitOrder.getLogisticsCompany());
+                }
+                if (StringUtils.isNotEmpty(splitOrder.getLId())) {
+                    newOrder.setDeliverySn(splitOrder.getLId());
+                }
+                if (StringUtils.isNotEmpty(splitOrder.getLcId())) {
+                    newOrder.setDeliveryCode(splitOrder.getLcId());
+                }
+
+                // 设置发货时间
+                if (StringUtils.isNotEmpty(splitOrder.getSendDate())) {
+                    try {
+                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                        Date sendDate = formatter.parse(splitOrder.getSendDate());
+                        newOrder.setDeliverySendTime(sendDate);
+                        newOrder.setDeliveryTime(splitOrder.getSendDate());
+                    } catch (Exception e) {
+                        log.error("解析发货时间失败: {}", splitOrder.getSendDate(), e);
+                    }
+                }
+
+                // 设置支付时间
+                if (StringUtils.isNotEmpty(splitOrder.getPayDate())) {
+                    try {
+                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                        Date payDate = formatter.parse(splitOrder.getPayDate());
+                        newOrder.setPayTime(payDate.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
+                    } catch (Exception e) {
+                        log.error("解析支付时间失败: {}", splitOrder.getPayDate(), e);
+                    }
+                }
+
+                // 设置扩展订单ID
+                newOrder.setExtendOrderId(String.valueOf(splitOrder.getOId()));
+
+                // 计算订单总数量
+                if (splitOrder.getItems() != null && !splitOrder.getItems().isEmpty()) {
+                    int totalQty = splitOrder.getItems().stream()
+                            .mapToInt(OrderQueryResponseDTO.OrderItem::getQty)
+                            .sum();
+                    newOrder.setTotalNum(String.valueOf(totalQty));
+                }
+
+                // 设置订单总价
+                if (splitOrder.getAmount() != null) {
+                    newOrder.setTotalPrice(splitOrder.getAmount());
+                }
+
+                // 设置创建时间和更新时间
+                newOrder.setCreateTime(new Date());
+                newOrder.setUpdateTime(new Date());
+
+                // 插入订单
+                liveOrderMapper.insertLiveOrder(newOrder);
+
+                // 保存订单项(SKU)
+                if (splitOrder.getItems() != null && !splitOrder.getItems().isEmpty()) {
+                    for (OrderQueryResponseDTO.OrderItem item : splitOrder.getItems()) {
+                        LiveOrderItem orderItem = new LiveOrderItem();
+                        orderItem.setOrderId(newOrder.getOrderId());
+                        orderItem.setOrderCode(splitOrder.getSoId());
+                        orderItem.setNum(item.getQty() != null ? item.getQty().longValue() : 0L);
+                        // 可以根据需要设置其他字段,如 productId, goodsId 等
+                        // 这里需要根据业务逻辑从 item 中获取或从原订单项中复制
+                        liveOrderItemMapper.insertLiveOrderItem(orderItem);
+                    }
+                }
+            }
+
+        } catch (Exception e) {
+            log.error("直播拆分订单处理异常, orderCode={}", order.getSoId(), e);
+        }
+    }
+
     /**
      * 将OrderQueryResponseDTO.Order转换为ErpOrderQuery
      *

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderCreateParam.java

@@ -19,7 +19,7 @@ public class FsStoreOrderCreateParam implements Serializable
     @NotNull(message = "orderKey不能为空")
     private String orderKey;
     @ApiModelProperty(value = "地址ID")
-    @NotNull(message = "地址不能为空")
+//    @NotNull(message = "地址不能为空")
     private Long addressId;
 
     @ApiModelProperty(value = "来源")

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

@@ -634,8 +634,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public List<FsStoreOrderVO> selectFsStoreOrderListVO(FsStoreOrderParam param) {
         List<FsStoreOrderVO> list = fsStoreOrderMapper.selectFsStoreOrderListVO(param);
         for (FsStoreOrderVO vo : list) {
-            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
-            vo.setNickname(nickName);
+            if (StringUtils.isNotEmpty(vo.getUserPhone())){
+                String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
+                vo.setNickname(nickName);
+            }
+
             if (StringUtils.isNotEmpty(vo.getItemJson())) {
                 JSONArray jsonArray = JSONUtil.parseArray(vo.getItemJson());
                 List<FsStoreOrderItemVO> items = JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
@@ -653,8 +656,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public List<FsStoreOrderVO> selectFsStoreOrderAllListVO(FsStoreOrderParam param) {
         List<FsStoreOrderVO> list = fsStoreOrderMapper.selectFsStoreOrderAllListVO(param);
         for (FsStoreOrderVO vo : list) {
-            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
-            vo.setNickname(nickName);
+            if (StringUtils.isNotEmpty(vo.getUserPhone())){
+                String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
+                vo.setNickname(nickName);
+            }
+
             if (StringUtils.isNotEmpty(vo.getItemJson())) {
                 JSONArray jsonArray = JSONUtil.parseArray(vo.getItemJson());
                 List<FsStoreOrderItemVO> items = JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
@@ -834,6 +840,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     @Override
     @Transactional
     public R createOrder(long userId, FsStoreOrderCreateParam param) {
+        if (!CloudHostUtils.hasCloudHostName("鹤颜堂")){
+            log.error("进入到数据");
+            if (ObjectUtil.isEmpty(param.getAddressId())){
+                return R.error("地址不能为空!");
+            }
+        }
         FsStoreOrderComputedParam computedParam = new FsStoreOrderComputedParam();
         BeanUtils.copyProperties(param, computedParam);
         //计算金额
@@ -907,10 +919,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
             storeOrder.setUserId(userId);
             storeOrder.setOrderCode(orderSn);
-            storeOrder.setRealName(address.getRealName());
-            storeOrder.setUserPhone(address.getPhone());
-            storeOrder.setUserAddress(address.getProvince() + " " + address.getCity() +
-                    " " + address.getDistrict() + " " + address.getDetail().trim());
+            if (ObjectUtil.isNotEmpty(address)){
+                storeOrder.setRealName(address.getRealName());
+                storeOrder.setUserPhone(address.getPhone());
+                storeOrder.setUserAddress(address.getProvince() + " " + address.getCity() +
+                        " " + address.getDistrict() + " " + address.getDetail().trim());
+            }
             storeOrder.setCartId(cartIds);
             storeOrder.setTotalNum(Long.parseLong(String.valueOf(carts.size())));
             storeOrder.setTotalPrice(dto.getTotalPrice());
@@ -978,6 +992,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if (param.getPayType().equals("1")) {
                 //全款支付
                 storeOrder.setStatus(0);
+                if("广州郑多燕".equals(cloudHostProper.getCompanyName())){
+                    BigDecimal amount = redisCache.getCacheObject("createOrderAmount:" + param.getCreateOrderKey());
+                    storeOrder.setPayDelivery(amount != null ? amount : BigDecimal.ZERO);
+                }
             } else if (param.getPayType().equals("2")) {
                 //物流代收
                 storeOrder.setStatus(1);
@@ -1753,6 +1771,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             storeOrder.setOrderCreateType(2);
             storeOrder.setPayType(storeProductPackage.getPayType().toString());
             storeOrder.setPayPrice(totalMoney);
+            if("广州郑多燕".equals(cloudHostProper.getCompanyName())){
+                BigDecimal amount = redisCache.getCacheObject("createOrderAmount:" + param.getOrderKey());
+                storeOrder.setPayDelivery(amount != null ? amount : BigDecimal.ZERO);
+            }
             storeOrder.setIsPackage(1);
             FsStoreProductPackageScrm productPackage = new FsStoreProductPackageScrm();
             productPackage.setTitle(storeProductPackage.getTitle());
@@ -2775,8 +2797,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 totalMoney = totalMoney.add(vo.getPrice().multiply(new BigDecimal(vo.getCartNum().toString())));
             }
         } else {
-            //套餐制单
-            totalMoney = carts.get(0).getPrice();
+            //套餐制单,这个金额是套餐的金额
+            totalMoney = redisCache.getCacheObject("createOrderMoney:" + createOrderKey);
         }
         if (money.compareTo(totalMoney) == 1) {
             throw new CustomException("价格不能大于商品总价", 501);
@@ -4221,7 +4243,9 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 if(param.getPayType().equals(1)){
                     order.setPayType("1");
                     order.setPayMoney(order.getPayPrice());
-                    order.setPayDelivery(BigDecimal.ZERO);
+                    if(!"广州郑多燕".equals(cloudHostProper.getCompanyName())){
+                        order.setPayDelivery(BigDecimal.ZERO);
+                    }
                 }
                 else if(param.getPayType().equals(2)){
                     order.setPayType("2");
@@ -4778,7 +4802,9 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 if(param.getPayType().equals(1)){
                     order.setPayType("1");
                     order.setPayMoney(order.getPayPrice());
-                    order.setPayDelivery(BigDecimal.ZERO);
+                    if(!"广州郑多燕".equals(cloudHostProper.getCompanyName())){
+                        order.setPayDelivery(BigDecimal.ZERO);
+                    }
                 }
                 else if(param.getPayType().equals(2)){
                     // 物流代收

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

@@ -319,6 +319,9 @@ public class LiveServiceImpl implements ILiveService
 
     @Override
     public R subNotifyLive(LiveNotifyParam param) {
+        if (StringUtils.isEmpty(param.getAppId())) {
+            return R.error("小程序订阅失败:appId为空!");
+        }
         LiveMiniprogramSubNotifyTask notifyTask = new LiveMiniprogramSubNotifyTask();
         notifyTask.setPage("pages_course/living?liveId=" + param.getLiveId());
         notifyTask.setTaskName("直播间预约提醒");
@@ -326,7 +329,7 @@ public class LiveServiceImpl implements ILiveService
         Long userId = param.getUserId();
         Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                 .eq(FsUserWx::getFsUserId, userId)
-                .eq(FsUserWx::getAppId, StringUtils.isEmpty(param.getAppId()) ? "wx44beed5640bcb1ba" : param.getAppId()); // 卓美小程序
+                .eq(FsUserWx::getAppId, StringUtils.isEmpty(param.getAppId()) ? "wxd791d5933ed42218" : param.getAppId()); // 卓美小程序
         FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
         String maOpenId = "";
         if (fsUserWx == null) {

+ 5 - 0
fs-service/src/main/java/com/fs/qw/param/QwGroupChatParam.java

@@ -60,4 +60,9 @@ public class QwGroupChatParam {
      */
     private String userType;
 
+    /**
+     * 员工账号
+     */
+    private String userName;
+
 }

+ 4 - 0
fs-service/src/main/java/com/fs/sop/domain/QwSopTempRules.java

@@ -86,4 +86,8 @@ public class QwSopTempRules{
     
      /**是否@所有人  1是0否**/
     private Integer isAtAll;
+    /**
+     * 直播间id
+     */
+    private Long liveId;
 }

+ 8 - 3
fs-service/src/main/resources/application-config-druid-bjzm-test.yml

@@ -4,14 +4,19 @@ baidu:
 #配置
 logging:
   level:
+    com:
+      fs:
+        hisStore:
+            mapper: debug
+    com.fs.live: debug
     org.springframework.web: INFO
     com.github.binarywang.demo.wx.cp: DEBUG
     me.chanjar.weixin: DEBUG
 wx:
   miniapp:
     configs:
-      - appid: wx44beed5640bcb1ba   #北京卓美
-        secret: 1bfcfa420f741801575a74d94752d014 #北京卓美
+      - appid: wxd791d5933ed42218   #北京卓美
+        secret: 3d2e220de33d67aeb2140edeec692b73 #北京卓美
         token: cbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON
@@ -61,7 +66,7 @@ fs :
     # token有效时长,7天,单位秒
     expire: 31536000
     header: AppToken
-  commonApi: http://172.16.16.6:7771
+  commonApi: http://127.0.0.1:7771
   h5CommonApi: http://172.16.16.6:7771
 nuonuo:
   key: 10924508

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

@@ -10,8 +10,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: wx44beed5640bcb1ba   #北京卓美
-        secret: 1bfcfa420f741801575a74d94752d014 #北京卓美
+      - appid: wxd791d5933ed42218   #北京卓美
+        secret: 3d2e220de33d67aeb2140edeec692b73 #北京卓美
         token: cbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON

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

@@ -80,8 +80,8 @@ tencent_cloud_config:
 cloud_host:
   company_name: 云联融智
   projectCode: YLRZ
-  spaceName:
-  volcengineUrl: https://myhkvolcengine.ylrztop.com
+  spaceName: ylrz-2114522511
+  volcengineUrl: https://ylrzvolcengine.ylrztop.com
 headerImg:
   imgUrl:
 

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

@@ -56,7 +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,
+        fs_user_course_period.is_open_rest_flag,
         course_style,
         live_room_style,
         red_packet_grant_method,
@@ -167,7 +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>
+            <if test="isOpenRestFlag != null">is_open_rest_flag = #{isOpenRestFlag},</if>
         </trim>
         where period_id = #{periodId}
     </update>

+ 3 - 3
fs-service/src/main/resources/mapper/hisStore/MergedOrderMapper.xml

@@ -75,7 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
       LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
         LEFT JOIN company c ON c.company_id = cu.company_id
-      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_code = o.order_code
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_order_id ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_order_id = o.id
       AND sp_latest.rn = 1
       LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
           WHERE  o.company_id IS NOT NULL
@@ -217,7 +217,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
       LEFT JOIN company_user cu ON cu.user_id = o.company_user_id
         LEFT JOIN company c ON c.company_id = cu.company_id
-      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_code = o.order_code
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_order_id ORDER BY sp.create_time DESC ) AS rn FROM fs_store_payment_scrm sp ) sp_latest ON sp_latest.business_order_id = o.id
       AND sp_latest.rn = 1
       LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
           WHERE  o.company_id is null
@@ -362,7 +362,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN company c ON c.company_id = cu.company_id
       LEFT JOIN ( SELECT t.*, ROW_NUMBER() OVER ( PARTITION BY t.order_id ORDER BY t.create_time DESC ) AS rn FROM live_after_sales t ) a ON o.order_id = a.order_id
       AND a.rn = 1
-      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_code ORDER BY sp.create_time DESC ) AS rn FROM live_order_payment sp ) sp_latest ON sp_latest.business_code = o.order_code
+      LEFT JOIN ( SELECT sp.*, ROW_NUMBER() OVER ( PARTITION BY sp.business_id ORDER BY sp.create_time DESC ) AS rn FROM live_order_payment sp ) sp_latest ON sp_latest.business_id = o.order_id
       AND sp_latest.rn = 1
       LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
           WHERE o.is_del = 0

+ 3 - 0
fs-service/src/main/resources/mapper/qw/QwGroupChatMapper.xml

@@ -63,6 +63,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         left join qw_user qu on qu.qw_user_id = gc.owner and qu.is_del = 0 and qu.corp_id = gc.corp_id
         left join company_user cu on cu.user_id = qu.company_user_id
         <where>
+            <if test="userName != null and userName != ''">
+                and cu.user_name like concat('%', #{userName}, '%')
+            </if>
             <if test="corpId != null and corpId != ''">
                 and gc.corp_id = #{corpId}
             </if>

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/store/WxUserScrmController.java

@@ -371,7 +371,7 @@ public class WxUserScrmController extends AppBaseController {
             userService.handleFsUserWx(user,loginMaWxParam,session);
             String token = jwtUtils.generateToken(user.getUserId());
             // 广告线索
-            leadService.weChatAuthorizationLead(param.getTraceId(), user.getUnionId(),user.getMaOpenId(),user.getPhone());
+            leadService.weChatAuthorizationLead(param.getTraceId(), session.getUnionid(),session.getOpenid(),user.getPhone());
             return R.ok("登录成功").put("token",token).put("user", user);
         } catch (WxErrorException e) {
             //this.logger.error(e.getMessage(), e);