|  | @@ -8,10 +8,13 @@ import com.fs.common.core.domain.R;
 | 
	
		
			
				|  |  |  import com.fs.common.exception.base.BaseException;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.PubFun;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.StringUtils;
 | 
	
		
			
				|  |  | +import com.fs.company.domain.Company;
 | 
	
		
			
				|  |  |  import com.fs.company.domain.CompanyMiniapp;
 | 
	
		
			
				|  |  |  import com.fs.company.domain.CompanyUser;
 | 
	
		
			
				|  |  | +import com.fs.company.mapper.CompanyMapper;
 | 
	
		
			
				|  |  |  import com.fs.company.service.ICompanyMiniappService;
 | 
	
		
			
				|  |  |  import com.fs.company.service.ICompanyUserService;
 | 
	
		
			
				|  |  | +import com.fs.config.cloud.CloudHostProper;
 | 
	
		
			
				|  |  |  import com.fs.course.config.CourseConfig;
 | 
	
		
			
				|  |  |  import com.fs.course.domain.*;
 | 
	
		
			
				|  |  |  import com.fs.course.mapper.*;
 | 
	
	
		
			
				|  | @@ -136,6 +139,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |      private IQwSopTempContentService qwSopTempContentService;
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private IQwSopTempVoiceService qwSopTempVoiceService;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private CloudHostProper cloudHostProper;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Blocking queues with bounded capacity to implement backpressure
 | 
	
		
			
				|  |  |      private final BlockingQueue<QwSopLogs> qwSopLogsQueue = new LinkedBlockingQueue<>(20000);
 | 
	
	
		
			
				|  | @@ -165,6 +170,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private IQwCompanyService iQwCompanyService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private CompanyMapper companyMapper;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @PostConstruct
 | 
	
		
			
				|  |  |      public void init() {
 | 
	
	
		
			
				|  | @@ -312,6 +319,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap = miniList.stream().collect(Collectors.groupingBy(CompanyMiniapp::getCompanyId, Collectors.groupingBy(CompanyMiniapp::getType)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<Company> companies = companyMapper.selectCompanyAllList();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          log.info("共分组 {} 个 SOP ID 进行处理。", sopLogsGroupedById.size());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          CountDownLatch sopGroupLatch = new CountDownLatch(sopLogsGroupedById.size());
 | 
	
	
		
			
				|  | @@ -319,7 +329,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |          for (Map.Entry<String, List<SopUserLogsVo>> entry : sopLogsGroupedById.entrySet()) {
 | 
	
		
			
				|  |  |              String sopId = entry.getKey();
 | 
	
		
			
				|  |  |              List<SopUserLogsVo> userLogsVos = entry.getValue();
 | 
	
		
			
				|  |  | -            processSopGroupAsync(sopId, userLogsVos, sopGroupLatch,currentTime, groupChatMap,config,miniMap);
 | 
	
		
			
				|  |  | +            processSopGroupAsync(sopId, userLogsVos, sopGroupLatch,currentTime, groupChatMap,config,miniMap,companies);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // 等待所有 SOP 分组处理完成
 | 
	
	
		
			
				|  | @@ -340,9 +350,10 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |              backoff = @Backoff(delay = 2000)
 | 
	
		
			
				|  |  |      )
 | 
	
		
			
				|  |  |      public void processSopGroupAsync(String sopId, List<SopUserLogsVo> userLogsVos, CountDownLatch latch ,LocalDateTime currentTime,
 | 
	
		
			
				|  |  | -                                     Map<String, QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap) {
 | 
	
		
			
				|  |  | +                                     Map<String, QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
 | 
	
		
			
				|  |  | +                                     List<Company> companies) {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  | -            processSopGroup(sopId, userLogsVos,currentTime, groupChatMap, config,miniMap);
 | 
	
		
			
				|  |  | +            processSopGroup(sopId, userLogsVos,currentTime, groupChatMap, config,miniMap,companies);
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  |              log.error("处理 SOP ID {} 时发生异常: {}", sopId, e.getMessage(), e);
 | 
	
		
			
				|  |  |          } finally {
 | 
	
	
		
			
				|  | @@ -352,7 +363,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private void processSopGroup(String sopId, List<SopUserLogsVo> userLogsVos,LocalDateTime currentTime, Map<String,
 | 
	
		
			
				|  |  | -            QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap) throws Exception {
 | 
	
		
			
				|  |  | +            QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
 | 
	
		
			
				|  |  | +                                 List<Company> companies) throws Exception {
 | 
	
		
			
				|  |  |          QwSopRuleTimeVO ruleTimeVO = sopMapper.selectQwSopByClickHouseId(sopId);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (ruleTimeVO == null) {
 | 
	
	
		
			
				|  | @@ -394,7 +406,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          CountDownLatch userLogsLatch = new CountDownLatch(userLogsVos.size());
 | 
	
		
			
				|  |  |          for (SopUserLogsVo logVo : userLogsVos) {
 | 
	
		
			
				|  |  | -            processUserLogAsync(logVo, ruleTimeVO, rulesList, userLogsLatch, currentTime, groupChatMap,qwCompany.getMiniAppId(), config,miniMap);
 | 
	
		
			
				|  |  | +            processUserLogAsync(logVo, ruleTimeVO, rulesList, userLogsLatch, currentTime, groupChatMap,qwCompany.getMiniAppId(),
 | 
	
		
			
				|  |  | +                    config,miniMap,companies);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // 等待所有用户日志处理完成
 | 
	
	
		
			
				|  | @@ -415,9 +428,10 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |      )
 | 
	
		
			
				|  |  |      public void processUserLogAsync(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings,
 | 
	
		
			
				|  |  |                                      CountDownLatch latch, LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap,
 | 
	
		
			
				|  |  | -                                    String miniAppId,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap) {
 | 
	
		
			
				|  |  | +                                    String miniAppId,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
 | 
	
		
			
				|  |  | +                                    List<Company> companies) {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  | -            processUserLog(logVo, ruleTimeVO, tempSettings,currentTime, groupChatMap, miniAppId, config,miniMap);
 | 
	
		
			
				|  |  | +            processUserLog(logVo, ruleTimeVO, tempSettings,currentTime, groupChatMap, miniAppId, config,miniMap,companies);
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  |              log.error("处理用户日志 {} 时发生异常: {}", logVo.getId(), e.getMessage(), e);
 | 
	
		
			
				|  |  |          } finally {
 | 
	
	
		
			
				|  | @@ -428,7 +442,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private void processUserLog(SopUserLogsVo logVo, QwSopRuleTimeVO ruleTimeVO, List<QwSopTempRules> tempSettings,
 | 
	
		
			
				|  |  |                                  LocalDateTime currentTime, Map<String, QwGroupChat> groupChatMap,String miniAppId,
 | 
	
		
			
				|  |  | -                                CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap) {
 | 
	
		
			
				|  |  | +                                CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
 | 
	
		
			
				|  |  | +                                List<Company> companies) {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              LocalDate startDate = LocalDate.parse(logVo.getStartTime(), DATE_FORMATTER);
 | 
	
	
		
			
				|  | @@ -596,7 +611,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                          insertSopUserLogs(sopUserLogsInfos, logVo, sendTime, ruleTimeVO, content, qwUserId,
 | 
	
		
			
				|  |  |                                  companyUserId, companyId, qwUserByRedis.getWelcomeText(),qwUserByRedis.getQwUserName(),
 | 
	
		
			
				|  |  | -                                groupChatMap, miniAppId,config,miniMap, sendMsgType);
 | 
	
		
			
				|  |  | +                                groupChatMap, miniAppId,config,miniMap, sendMsgType,companies);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  } catch (Exception e) {
 | 
	
	
		
			
				|  | @@ -640,7 +655,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                                     QwSopRuleTimeVO ruleTimeVO, QwSopTempSetting.Content content,
 | 
	
		
			
				|  |  |                                     String qwUserId,String companyUserId,String companyId,String welcomeText,String qwUserName,
 | 
	
		
			
				|  |  |                                     Map<String, QwGroupChat> groupChatMap,String miniAppId,CourseConfig config,
 | 
	
		
			
				|  |  | -                                   Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap, Integer sendMsgType) {
 | 
	
		
			
				|  |  | +                                   Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap, Integer sendMsgType,
 | 
	
		
			
				|  |  | +                                   List<Company> companies) {
 | 
	
		
			
				|  |  |          String formattedSendTime = sendTime.toInstant()
 | 
	
		
			
				|  |  |                  .atZone(ZoneId.systemDefault())
 | 
	
		
			
				|  |  |                  .format(DATE_TIME_FORMATTER);
 | 
	
	
		
			
				|  | @@ -667,7 +683,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                  QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, groupChat.getChatId(), groupChat.getName(), null, isOfficial, null);
 | 
	
		
			
				|  |  |                  handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
 | 
	
		
			
				|  |  |                          type, qwUserId, companyUserId, companyId, groupChat.getChatId(), welcomeText, qwUserName,
 | 
	
		
			
				|  |  | -                        null, true, miniAppId, groupChat,config, miniMap, null, sendMsgType);
 | 
	
		
			
				|  |  | +                        null, true, miniAppId, groupChat,config, miniMap, null, sendMsgType,companies);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  |                  if(groupChat.getChatUserList() != null && !groupChat.getChatUserList().isEmpty()){
 | 
	
		
			
				|  |  |                      groupChat.getChatUserList().forEach(user -> {
 | 
	
	
		
			
				|  | @@ -676,7 +692,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                          QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, user.getUserId(), user.getName(), null, isOfficial, null);
 | 
	
		
			
				|  |  |                          handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
 | 
	
		
			
				|  |  |                                  type, qwUserId, companyUserId, companyId, user.getId().toString(), welcomeText, qwUserName,
 | 
	
		
			
				|  |  | -                                null, false, miniAppId, groupChat,config, miniMap, null, sendMsgType);
 | 
	
		
			
				|  |  | +                                null, false, miniAppId, groupChat,config, miniMap, null, sendMsgType,companies);
 | 
	
		
			
				|  |  |                      });
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -691,7 +707,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                      QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, contactId.getExternalContactId(), externalUserName, fsUserId, isOfficial, contactId.getExternalId());
 | 
	
		
			
				|  |  |                      handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
 | 
	
		
			
				|  |  |                              type, qwUserId, companyUserId, companyId, externalId, welcomeText, qwUserName, fsUserId, false, miniAppId,
 | 
	
		
			
				|  |  | -                            null,config, miniMap, grade, sendMsgType);
 | 
	
		
			
				|  |  | +                            null,config, miniMap, grade, sendMsgType,companies);
 | 
	
		
			
				|  |  |                  } catch (Exception e) {
 | 
	
		
			
				|  |  |                      log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
 | 
	
		
			
				|  |  |                  }
 | 
	
	
		
			
				|  | @@ -800,7 +816,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  ) {
 | 
	
		
			
				|  |  | +                                      Integer grade, Integer sendMsgType ,List<Company> companies ) {
 | 
	
		
			
				|  |  |          switch (type) {
 | 
	
		
			
				|  |  |              case 1:
 | 
	
		
			
				|  |  |                  handleNormalMessage(sopLogs, content,companyUserId);
 | 
	
	
		
			
				|  | @@ -808,7 +824,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |              case 2:
 | 
	
		
			
				|  |  |                  handleCourseMessage(sopLogs, content, logVo, sendTime, courseId, videoId,
 | 
	
		
			
				|  |  |                          qwUserId, companyUserId, companyId, externalId, welcomeText,qwUserName, fsUserId,
 | 
	
		
			
				|  |  | -                        isGroupChat, miniAppId, groupChat,config,miniMap, grade, sendMsgType);
 | 
	
		
			
				|  |  | +                        isGroupChat, miniAppId, groupChat,config,miniMap, grade, sendMsgType,companies);
 | 
	
		
			
				|  |  |                  break;
 | 
	
		
			
				|  |  |              case 3:
 | 
	
		
			
				|  |  |                  handleOrderMessage(sopLogs, content);
 | 
	
	
		
			
				|  | @@ -841,7 +857,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                                       SopUserLogsVo logVo, Date sendTime, Long courseId, Long videoId, String qwUserId, String companyUserId,
 | 
	
		
			
				|  |  |                                       String companyId, String externalId, String welcomeText, String qwUserName,
 | 
	
		
			
				|  |  |                                       Long fsUserId, boolean isGroupChat, String miniAppId, QwGroupChat groupChat,CourseConfig config,Map<Long,
 | 
	
		
			
				|  |  | -                                     Map<Integer, List<CompanyMiniapp>>> miniMap,Integer grade, Integer sendMsgType) {
 | 
	
		
			
				|  |  | +                                     Map<Integer, List<CompanyMiniapp>>> miniMap,Integer grade, Integer sendMsgType,
 | 
	
		
			
				|  |  | +                                     List<Company> companies) {
 | 
	
		
			
				|  |  |          // 深拷贝 Content 对象,避免使用 JSON
 | 
	
		
			
				|  |  |          QwSopTempSetting.Content clonedContent = deepCopyContent(content);
 | 
	
		
			
				|  |  |          if (clonedContent == null) {
 | 
	
	
		
			
				|  | @@ -967,6 +984,28 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |                      setting.setLinkUrl(linkByApp.getSortLink().replaceAll("^[\\s\\u2005]+", ""));
 | 
	
		
			
				|  |  |                      setting.setAppLinkUrl(linkByApp.getAppMsgLink().replaceAll("^[\\s\\u2005]+", ""));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                //自定义小程序
 | 
	
		
			
				|  |  | +                case "10":
 | 
	
		
			
				|  |  | +                    addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    Optional<Company> matchedCompany = companies.stream()
 | 
	
		
			
				|  |  | +                            .filter(company -> String.valueOf(company.getCompanyId()).equals(companyId))
 | 
	
		
			
				|  |  | +                            .findFirst();
 | 
	
		
			
				|  |  | +                    if (matchedCompany.isPresent()) {
 | 
	
		
			
				|  |  | +                        Company company = matchedCompany.get();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        String customMiniAppId = company.getCustomMiniAppId();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        if (customMiniAppId != null && !customMiniAppId.trim().isEmpty()) {
 | 
	
		
			
				|  |  | +                            setting.setMiniprogramAppid(customMiniAppId);
 | 
	
		
			
				|  |  | +                        } else {
 | 
	
		
			
				|  |  | +                            setting.setMiniprogramAppid("该公司未配置自定义小程序:"+companyId);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    } else {
 | 
	
		
			
				|  |  | +                        setting.setMiniprogramAppid("未找到匹配的公司的自定义小程序:"+companyId);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                      break;
 | 
	
		
			
				|  |  |                  default:
 | 
	
		
			
				|  |  |                      break;
 | 
	
	
		
			
				|  | @@ -1261,6 +1300,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 | 
	
		
			
				|  |  |          link.setCorpId(logVo.getCorpId());
 | 
	
		
			
				|  |  |          link.setCourseId(courseId.longValue());
 | 
	
		
			
				|  |  |          link.setQwExternalId(Long.parseLong(externalId));
 | 
	
		
			
				|  |  | +        link.setProjectCode(cloudHostProper.getProjectCode());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (StringUtil.strIsNullOrEmpty(isOfficial)){
 | 
	
		
			
				|  |  |              link.setLinkType(3);
 |