Quellcode durchsuchen

商城移植controller[0,1]

chenguo vor 1 Woche
Ursprung
Commit
274df9598d
100 geänderte Dateien mit 4394 neuen und 476 gelöschten Zeilen
  1. 45 0
      fs-service/src/main/java/com/fs/company/domain/CompanyCompanyFsuser.java
  2. 68 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyCompanyFsuserMapper.java
  3. 2 1
      fs-service/src/main/java/com/fs/company/mapper/CompanyTcmScheduleMapper.java
  4. 11 0
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  5. 110 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  6. 1 1
      fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java
  7. 2 0
      fs-service/src/main/java/com/fs/event/TemplateBean.java
  8. 2 1
      fs-service/src/main/java/com/fs/event/TemplateListenEnum.java
  9. 1 1
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptChatReplaceWords.java
  10. 23 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptEventLog.java
  11. 23 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptEventTokenLog.java
  12. 21 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptExpressInfo.java
  13. 12 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeyword.java
  14. 19 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeywordArtificial.java
  15. 55 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeywordSend.java
  16. 77 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastgptChatArtificialWords.java
  17. 56 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastgptEventLogTotal.java
  18. 8 0
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatKeywordMapper.java
  19. 14 6
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatMsgMapper.java
  20. 2 4
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatReplaceWordsMapper.java
  21. 3 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatSessionMapper.java
  22. 73 0
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptKeywordSendMapper.java
  23. 13 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptRoleMapper.java
  24. 2 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptRoleTagMapper.java
  25. 62 0
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptChatArtificialWordsMapper.java
  26. 2 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptChatVoiceHomoMapper.java
  27. 74 0
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptEventLogTotalMapper.java
  28. 2 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptTagGroupMapper.java
  29. 2 1
      fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptTagMapper.java
  30. 5 0
      fs-service/src/main/java/com/fs/fastGpt/param/FastGptChatSessionParam.java
  31. 76 0
      fs-service/src/main/java/com/fs/fastGpt/param/FastgptEventLogTotalParam.java
  32. 14 0
      fs-service/src/main/java/com/fs/fastGpt/param/SendHookParam.java
  33. 4 0
      fs-service/src/main/java/com/fs/fastGpt/service/AiHookService.java
  34. 7 0
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatKeywordService.java
  35. 11 2
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatMsgService.java
  36. 2 1
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatReplaceWordsService.java
  37. 5 2
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatSessionService.java
  38. 72 0
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptKeywordSendService.java
  39. 13 2
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptRoleService.java
  40. 2 1
      fs-service/src/main/java/com/fs/fastGpt/service/IFastGptRoleTagService.java
  41. 62 0
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptChatArtificialWordsService.java
  42. 2 1
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptChatVoiceHomoService.java
  43. 76 0
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptEventLogTotalService.java
  44. 2 1
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptTagGroupService.java
  45. 2 1
      fs-service/src/main/java/com/fs/fastGpt/service/IFastgptTagService.java
  46. 412 238
      fs-service/src/main/java/com/fs/fastGpt/service/impl/AiHookServiceImpl.java
  47. 39 42
      fs-service/src/main/java/com/fs/fastGpt/service/impl/AiNewServiceImpl.java
  48. 22 20
      fs-service/src/main/java/com/fs/fastGpt/service/impl/AiServiceImpl.java
  49. 16 0
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatKeywordServiceImpl.java
  50. 33 9
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatMsgServiceImpl.java
  51. 4 4
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatReplaceWordsServiceImpl.java
  52. 162 95
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatSessionServiceImpl.java
  53. 115 0
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptKeywordSendServiceImpl.java
  54. 99 8
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptRoleServiceImpl.java
  55. 5 5
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptRoleTagServiceImpl.java
  56. 106 0
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptChatArtificialWordsServiceImpl.java
  57. 5 4
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptChatVoiceHomoServiceImpl.java
  58. 265 0
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptEventLogTotalServiceImpl.java
  59. 5 4
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptTagGroupServiceImpl.java
  60. 5 4
      fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptTagServiceImpl.java
  61. 4 0
      fs-service/src/main/java/com/fs/fastGpt/vo/FastGptChatSessionListCVO.java
  62. 78 0
      fs-service/src/main/java/com/fs/fastGpt/vo/FastGptChatSessionVo.java
  63. 46 0
      fs-service/src/main/java/com/fs/fastGpt/vo/FastGptKeywordSendVo.java
  64. 19 0
      fs-service/src/main/java/com/fs/fastGpt/vo/FastGptRoleDataVO.java
  65. 65 0
      fs-service/src/main/java/com/fs/fastGpt/vo/FastgptEventLogTotalVo.java
  66. 83 0
      fs-service/src/main/java/com/fs/gtPush/domain/UniPushLog.java
  67. 1 0
      fs-service/src/main/java/com/fs/gtPush/service/uniPush2Service.java
  68. 2 0
      fs-service/src/main/java/com/fs/his/config/FsSysConfig.java
  69. 8 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java
  70. 3 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java
  71. 3 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserIntegralLogsMapper.java
  72. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  73. 2 0
      fs-service/src/main/java/com/fs/his/param/FsUserCouponUParam.java
  74. 2 0
      fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java
  75. 1 1
      fs-service/src/main/java/com/fs/his/service/IFsPrescribeService.java
  76. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsUserIntegralLogsService.java
  77. 2 2
      fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java
  78. 3 3
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  79. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java
  80. 29 0
      fs-service/src/main/java/com/fs/im/config/IMConfig.java
  81. 0 1
      fs-service/src/main/java/com/fs/im/dto/InquiryOrderMsgDTO.java
  82. 0 1
      fs-service/src/main/java/com/fs/im/dto/MsgCustomDTO.java
  83. 0 1
      fs-service/src/main/java/com/fs/im/dto/MsgDTO.java
  84. 0 1
      fs-service/src/main/java/com/fs/im/dto/MsgResponseDTO.java
  85. 15 0
      fs-service/src/main/java/com/fs/im/dto/OpenImConversationDTO.java
  86. 11 0
      fs-service/src/main/java/com/fs/im/dto/OpenImEditConversationDTO.java
  87. 12 0
      fs-service/src/main/java/com/fs/im/dto/OpenImMsgCallBackResponse.java
  88. 45 0
      fs-service/src/main/java/com/fs/im/dto/OpenImMsgDTO.java
  89. 13 0
      fs-service/src/main/java/com/fs/im/dto/OpenImResponseDTO.java
  90. 11 0
      fs-service/src/main/java/com/fs/im/dto/OpenImResponseDataDTO.java
  91. 34 0
      fs-service/src/main/java/com/fs/im/service/OpenIMService.java
  92. 0 2
      fs-service/src/main/java/com/fs/im/service/impl/ImServiceImpl.java
  93. 882 0
      fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java
  94. 28 0
      fs-service/src/main/java/com/fs/im/vo/OpenImMsgCallBackVO.java
  95. 18 0
      fs-service/src/main/java/com/fs/im/vo/OpenImResponseDTOTest.java
  96. 44 0
      fs-service/src/main/java/com/fs/store/domain/FsInquiryOrderMsgScrm.java
  97. 159 0
      fs-service/src/main/java/com/fs/store/domain/FsPackageOrderScrm.java
  98. 41 0
      fs-service/src/main/java/com/fs/store/domain/FsStoreAfterSalesItemScrm.java
  99. 133 0
      fs-service/src/main/java/com/fs/store/domain/FsStoreAfterSalesLogsScrm.java
  100. 154 0
      fs-service/src/main/java/com/fs/store/domain/FsStoreOrderBillLogScrm.java

+ 45 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyCompanyFsuser.java

@@ -0,0 +1,45 @@
+package com.fs.company.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 销售绑定用户(一个用户绑定唯一一个销售)对象 company_company_fsuser
+ *
+ * @author fs
+ * @date 2025-04-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CompanyCompanyFsuser extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 会员id */
+    @Excel(name = "会员id")
+    private Long userId;
+
+    @Excel(name = "企微外部联系人id")
+    private Long qwContactId;
+
+
+    /** 状态 0:禁用 1:正常 */
+    @Excel(name = "状态 0:禁用 1:正常")
+    private Integer status;
+
+    /** 绑定类型 0:链接二维码 1:看课 */
+    private Integer bindType;
+
+
+}

+ 68 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyCompanyFsuserMapper.java

@@ -0,0 +1,68 @@
+package com.fs.company.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.domain.CompanyCompanyFsuser;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 销售绑定用户Mapper接口
+ *
+ * @author fs
+ * @date 2025-04-09
+ */
+public interface CompanyCompanyFsuserMapper extends BaseMapper<CompanyCompanyFsuser>{
+    /**
+     * 查询销售绑定用户
+     *
+     * @param id 销售绑定用户主键
+     * @return 销售绑定用户
+     */
+    CompanyCompanyFsuser selectCompanyCompanyUserById(Long id);
+
+    /**
+     * 查询销售绑定用户列表
+     *
+     * @param companyCompanyUser 销售绑定用户
+     * @return 销售绑定用户集合
+     */
+    List<CompanyCompanyFsuser> selectCompanyCompanyUserList(CompanyCompanyFsuser companyCompanyUser);
+
+    /**
+     * 新增销售绑定用户
+     *
+     * @param companyCompanyUser 销售绑定用户
+     * @return 结果
+     */
+    int insertCompanyCompanyUser(CompanyCompanyFsuser companyCompanyUser);
+
+    /**
+     * 修改销售绑定用户
+     *
+     * @param companyCompanyUser 销售绑定用户
+     * @return 结果
+     */
+    int updateCompanyCompanyUser(CompanyCompanyFsuser companyCompanyUser);
+
+    /**
+     * 删除销售绑定用户
+     *
+     * @param id 销售绑定用户主键
+     * @return 结果
+     */
+    int deleteCompanyCompanyUserById(Long id);
+
+    /**
+     * 批量删除销售绑定用户
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteCompanyCompanyUserByIds(Long[] ids);
+
+    CompanyCompanyFsuser getInfoByUserId(@Param("userId") String userId);
+
+    List<CompanyCompanyFsuser> selectNoHistoryApp(@Param("limit") Integer limit);
+
+}

+ 2 - 1
fs-service/src/main/java/com/fs/company/mapper/CompanyTcmScheduleMapper.java

@@ -1,6 +1,7 @@
 package com.fs.company.mapper;
 
 import com.fs.company.domain.CompanyTcmSchedule;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
@@ -67,5 +68,5 @@ public interface CompanyTcmScheduleMapper
             "</script>"})
     List<CompanyTcmSchedule> selectUseableScheduleList();
 
-
+    List<CompanyTcmSchedule> selectCompanyTcmScheduleByIds(@Param("scheduleIds") List<Long> scheduleIds);
 }

+ 11 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyService.java

@@ -14,6 +14,8 @@ import com.fs.his.domain.FsInquiryOrder;
 import com.fs.his.domain.FsStoreOrder;
 import com.fs.his.domain.FsStorePayment;
 import com.fs.his.vo.OptionsVO;
+import com.fs.store.domain.FsStoreOrderScrm;
+import org.springframework.transaction.annotation.Transactional;
 
 
 /**
@@ -87,6 +89,9 @@ public interface ICompanyService
 
     void addCompanyMoney(FsStoreOrder order);
 
+    @Transactional
+    void addCompanyMoney(FsStoreOrderScrm order);
+
     void subCompanyMoney(FsStoreOrder order);
 
     Company selectCompanyByAppId(String appId);
@@ -107,9 +112,15 @@ public interface ICompanyService
 
     void subtractCompanyMoney(FsStoreOrder order);
 
+    @Transactional
+    void subtractCompanyMoney(FsStoreOrderScrm order);
+
     void inquirySubtractCompanyMoney(FsInquiryOrder order);
     void refundCompanyMoney(FsStoreOrder order);
 
+    @Transactional
+    void refundCompanyMoney(FsStoreOrderScrm order);
+
     Company selectCompanyByIdForUpdate(Long companyId);
 
     public void subtractCompanyMoney(BigDecimal money, Long companyId);

+ 110 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -27,6 +27,8 @@ import com.fs.his.dto.InquiryConfigDTO;
 import com.fs.his.mapper.FsStoreOrderMapper;
 import com.fs.his.vo.OptionsVO;
 import com.fs.store.config.CompanyMenuConfig;
+import com.fs.store.domain.FsStoreOrderScrm;
+import com.fs.store.mapper.FsStoreOrderScrmMapper;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysConfigService;
@@ -74,6 +76,8 @@ public class CompanyServiceImpl implements ICompanyService
     @Autowired
     private FsStoreOrderMapper storeOrderMapper;
     @Autowired
+    private FsStoreOrderScrmMapper storeOrderScrmMapper;
+    @Autowired
     private ICompanyProfitService companyProfitService;
     @Autowired
     private SysConfigMapper sysConfigMapper;
@@ -351,6 +355,36 @@ public class CompanyServiceImpl implements ICompanyService
         }
     }
 
+    @Override
+    @Transactional
+    public void addCompanyMoney(FsStoreOrderScrm order) {
+        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                FsStoreOrderScrm orderMap=new FsStoreOrderScrm();
+                orderMap.setOrderId(order.getOrderId());
+                orderMap.setTuiMoneyStatus(1);
+                storeOrderScrmMapper.updateFsStoreOrder(orderMap);
+                BigDecimal money = order.getPayMoney().add(order.getPayRemain());
+                company.setMoney(company.getMoney().add(money));
+                companyMapper.updateCompany(company);
+                CompanyMoneyLogs log=new CompanyMoneyLogs();
+                log.setCompanyId(company.getCompanyId());
+                log.setRemark("佣金入账");
+                log.setMoney(money);
+                log.setLogsType(3);
+                log.setBalance(company.getMoney());
+                log.setCreateTime(new Date());
+                log.setBusinessId(order.getOrderId().toString());
+                moneyLogsMapper.insertCompanyMoneyLogs(log);
+                FsStoreOrderScrm fsStoreOrder = new FsStoreOrderScrm();
+                fsStoreOrder.setOrderId(order.getOrderId());
+                fsStoreOrder.setTuiMoneyStatus(1);
+                storeOrderScrmMapper.updateFsStoreOrder(fsStoreOrder);
+            }
+        }
+    }
+
     @Override
     @Transactional
     public void subCompanyMoney(FsStoreOrder order) {
@@ -530,6 +564,36 @@ public class CompanyServiceImpl implements ICompanyService
         }
     }
 
+    @Override
+    @Transactional
+    public void subtractCompanyMoney(FsStoreOrderScrm order) {
+
+        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
+                StoreConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), StoreConfig.class);
+                Integer DeductMoneyRate = fsPayConfig.getDeductMoneyRate();
+                BigDecimal money = BigDecimal.ZERO;
+                if (DeductMoneyRate != null && DeductMoneyRate > 0) {
+                    money = order.getPrescribePrice().multiply(new BigDecimal(DeductMoneyRate).multiply(new BigDecimal("0.01")));
+                }
+                logger.info("扣除成本:"+order.getOrderCode()+":"+money);
+                company.setMoney(company.getMoney().subtract(money));
+                companyMapper.updateCompany(company);
+                CompanyMoneyLogs log=new CompanyMoneyLogs();
+                log.setCompanyId(company.getCompanyId());
+                log.setRemark("发货扣除成本");
+                log.setMoney(money.multiply(new BigDecimal(-1)));
+                log.setLogsType(5);
+                log.setBalance(company.getMoney());
+                log.setCreateTime(new Date());
+                log.setBusinessId(order.getOrderId().toString());
+                moneyLogsMapper.insertCompanyMoneyLogs(log);
+            }
+        }
+    }
+
     @Override
     @Transactional
     public void inquirySubtractCompanyMoney(FsInquiryOrder order) {
@@ -1056,6 +1120,52 @@ public class CompanyServiceImpl implements ICompanyService
         }
     }
 
+    @Override
+    @Transactional
+    public void refundCompanyMoney(FsStoreOrderScrm order) {
+        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                List<CompanyMoneyLogs> companyMoneyLogs = moneyLogsMapper.selectCompanyMoneyByOrderId(order.getOrderId());
+                for (CompanyMoneyLogs logs : companyMoneyLogs) {
+                    if (logs.getLogsType()==3){
+                        if (order.getTuiMoneyStatus()!=null&&order.getTuiMoneyStatus()==0){
+                            continue;
+                        }
+                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
+                        logger.info("退款佣金扣除:"+company.getCompanyId()+":"+money);
+                        company.setMoney(company.getMoney().subtract(logs.getMoney()));
+                        companyMapper.updateCompany(company);
+                        CompanyMoneyLogs log=new CompanyMoneyLogs();
+                        log.setCompanyId(company.getCompanyId());
+                        log.setRemark("退款佣金扣除");
+                        log.setMoney(money);
+                        log.setLogsType(4);
+                        log.setBalance(company.getMoney());
+                        log.setCreateTime(new Date());
+                        log.setBusinessId(order.getOrderId().toString());
+                        moneyLogsMapper.insertCompanyMoneyLogs(log);
+                    }else if(logs.getLogsType()==5){
+                        BigDecimal money = logs.getMoney().multiply(new BigDecimal(-1));
+                        logger.info("退款成本返还:"+company.getCompanyId()+":"+money);
+                        company.setMoney(company.getMoney().add(money));
+                        companyMapper.updateCompany(company);
+                        CompanyMoneyLogs log=new CompanyMoneyLogs();
+                        log.setCompanyId(company.getCompanyId());
+                        log.setRemark("退款成本返还");
+                        log.setMoney(money);
+                        log.setLogsType(6);
+                        log.setBalance(company.getMoney());
+                        log.setCreateTime(new Date());
+                        log.setBusinessId(order.getOrderId().toString());
+                        moneyLogsMapper.insertCompanyMoneyLogs(log);
+                    }
+                }
+
+            }
+        }
+    }
+
     @Override
     public Company selectCompanyByIdForUpdate(Long companyId) {
         return companyMapper.selectCompanyByIdForUpdate(companyId);

+ 1 - 1
fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java

@@ -165,7 +165,7 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
     private JSONObject buildHzOMSOrder(String orderCode) {
         //通过订单号查询更多订单信息
         FsStoreOrder fsOrder = fsStoreOrderService.selectFsStoreOrderByOrderCode(orderCode);
-        FsStore fsStore = fsStoreService.selectFsStoreByStoreId(fsOrder.getStoreId());
+        FsStoreScrm fsStore = fsStoreService.selectFsStoreByStoreId(fsOrder.getStoreId());
 
         JSONObject obj = new JSONObject();
         String iordertype = "";

+ 2 - 0
fs-service/src/main/java/com/fs/event/TemplateBean.java

@@ -19,5 +19,7 @@ public class TemplateBean {
     private String title;
     private String remark;
     private Date time;
+    private String deliverySn; //快递单号
+    private String deliveryName; //快递名称
 
 }

+ 2 - 1
fs-service/src/main/java/com/fs/event/TemplateListenEnum.java

@@ -17,7 +17,8 @@ public enum TemplateListenEnum {
     TYPE_2("2","接单通知"),
     TYPE_3("3","待支付推送套餐包"),
     TYPE_4("4","随访创建咨询"),
-    TYPE_5("5","医生回复咨询");
+    TYPE_5("5","医生回复咨询"),
+    TYPE_6("6","订单发货通知");
     private String value;
     private String desc;
 

+ 1 - 1
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptChatReplaceWords.java

@@ -1,8 +1,8 @@
 package com.fs.fastGpt.domain;
 
 import com.fs.common.annotation.Excel;
-import lombok.Data;
 import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 /**

+ 23 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptEventLog.java

@@ -0,0 +1,23 @@
+package com.fs.fastGpt.domain;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FastGptEventLog {
+    private Long id;
+    private Long senderId;
+    private Long roleId;
+    private String eventName;
+    private Long count;
+    /**
+     * 事件类型(1互动 1总对话 3转人工 4AI无法回复转人工 5AI回复不合适转人工 6完课回复 7物流事件 8图片回复 9自定义事件回复 10用户未回复AI再次提醒)
+     */
+    private Integer type;
+    private Long companyId;
+    private Long companyUserId;
+    private Long qwUserId;
+    private Date createTime;
+
+}

+ 23 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptEventTokenLog.java

@@ -0,0 +1,23 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FastGptEventTokenLog extends BaseEntity {
+
+    private Long id;
+    private Long senderId;
+    private Long roleId;
+    private String eventName;
+    private Integer eventType;
+    private Long tokenCount;
+    private Integer tokenType;
+    private Long companyId;
+    private Long companyUserId;
+    private Long qwUserId;
+    private String statTime;
+    private Date createTime;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptExpressInfo.java

@@ -0,0 +1,21 @@
+package com.fs.fastGpt.domain;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FastGptExpressInfo {
+    //id
+    private Long id;
+
+    //订单ID(fs_store_order)
+    private Long orderId;
+
+    //订单物流是否通知  0未通知   1已通知
+    private Integer status;
+
+    //创建时间
+    private Date createTime;
+
+}

+ 12 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeyword.java

@@ -0,0 +1,12 @@
+package com.fs.fastGpt.domain;
+
+import lombok.Data;
+
+@Data
+public class FastGptKeyword {
+    private Long id;
+    //关键字
+    private String keyword;
+    //关键字类型
+    private Integer keywordType;
+}

+ 19 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeywordArtificial.java

@@ -0,0 +1,19 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FastGptKeywordArtificial extends BaseEntity {
+
+    private Long id;
+    private String userId;
+    private Long companyId;
+    private Long companyUserId;
+    private Long keywordSendId;
+    private String keywordSendContent;
+    private Date createTime;
+
+}

+ 55 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptKeywordSend.java

@@ -0,0 +1,55 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Ai关键字表(根据关键字发送文本和图片)对象 fastgpt_keyword_send
+ *
+ * @author fs
+ * @date 2025-05-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastGptKeywordSend extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 营销关键字 */
+    @Excel(name = "营销关键字")
+    private String keyword;
+
+    @Excel(name = "营销关键字类型 0客服端  1总后台")
+    private Long keywordType;
+
+    /** 发送文字内容 */
+    @Excel(name = "发送文字内容")
+    private String content;
+
+    /** 内容类型 */
+    @Excel(name = "内容类型")
+    private Integer contentType;
+
+    /** 图片访问地址 */
+    @Excel(name = "图片访问地址")
+    private String imgUrl;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Integer status;
+
+    /** Ai角色id*/
+    @Excel(name = "Ai角色id")
+    private String roleIds;
+
+    private Long cropId;
+
+    private Long companyId;
+
+    private Long companyUserId;
+
+
+}

+ 77 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastgptChatArtificialWords.java

@@ -0,0 +1,77 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 转人工提示词对象 fastgpt_chat_artificial_words
+ *
+ * @author fs
+ * @date 2025-05-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastgptChatArtificialWords extends BaseEntity{
+
+    /** id */
+    private Long id;
+
+    /** 类型 1报错 2关键词 */
+    @Excel(name = "类型 1报错 2关键词")
+    private Long type;
+
+    /** 文本 */
+    @Excel(name = "文本")
+    private String content;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Long status;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Long sort;
+
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getType() {
+        return type;
+    }
+
+    public void setType(Long type) {
+        this.type = type;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Long getStatus() {
+        return status;
+    }
+
+    public void setStatus(Long status) {
+        this.status = status;
+    }
+
+    public Long getSort() {
+        return sort;
+    }
+
+    public void setSort(Long sort) {
+        this.sort = sort;
+    }
+}

+ 56 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastgptEventLogTotal.java

@@ -0,0 +1,56 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * ai事件埋点统计对象 fastgpt_event_log_total
+ *
+ * @author fs
+ * @date 2025-06-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastgptEventLogTotal extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 角色id */
+    @Excel(name = "角色id")
+    private Long roleId;
+
+    /** 数量 */
+    @Excel(name = "数量")
+    private Long count;
+
+    /** 日志类型 */
+    @Excel(name = "日志类型")
+    private Integer type;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司用户id */
+    @Excel(name = "公司用户id")
+    private Long companyUserId;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private Long qwUserId;
+
+    @Excel(name = "日志生成时间")
+    private String statTime;
+
+    private Long senderCount;
+
+    private String qwUserIds;
+
+    private List<String> userIds;
+
+}

+ 8 - 0
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatKeywordMapper.java

@@ -1,6 +1,7 @@
 package com.fs.fastGpt.mapper;
 
 import com.fs.fastGpt.domain.FastGptChatKeyword;
+import com.fs.fastGpt.domain.FastGptExpressInfo;
 
 import java.util.List;
 
@@ -59,4 +60,11 @@ public interface FastGptChatKeywordMapper
      * @return 结果
      */
     public int deleteFastGptChatKeywordByKeywordIds(Long[] keywordIds);
+
+    List<FastGptExpressInfo> selectFastGptExpressInfoList(FastGptExpressInfo fastGptExpressInfo);
+
+    void insertFastGptChatExpressInfo(FastGptExpressInfo expressInfo);
+
+    void updateFastGptExpressInfo(FastGptExpressInfo info);
+
 }

+ 14 - 6
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatMsgMapper.java

@@ -1,11 +1,10 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
-
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.fastGpt.domain.FastGptChatMsg;
-import com.fs.fastGpt.domain.FastGptChatSession;
+import com.fs.fastGpt.domain.FastGptEventLog;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
 import com.fs.fastGpt.param.FastGptChatMsgListCParam;
 import com.fs.fastGpt.vo.FastGptChatMsgCVO;
 import com.fs.fastGpt.vo.FastGptChatMsgListCVO;
@@ -13,6 +12,8 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * 聊天记录Mapper接口
  *
@@ -74,8 +75,8 @@ public interface FastGptChatMsgMapper
      */
     public int deleteFastGptChatMsgByMsgIds(Long[] msgIds);
 
-    @Select("select m.*  from fastgpt_chat_msg m  where m.session_id=#{sessionId} and msg_type=2 order by m.msg_id desc")
-    public List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(@Param("sessionId")Long sessionId);
+
+    public List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(@Param("sessionId")Long sessionId,@Param("userId") String userId);
 
 
     @Select({"<script> " +
@@ -111,8 +112,15 @@ public interface FastGptChatMsgMapper
 
     @Select("select content from fastgpt_chat_msg where msg_id < #{msgId} and user_id = #{userId} and role_id = #{roleId} and send_type = 1  ORDER BY msg_id desc limit 1")
     String selectUserContent(@Param("msgId") Long msgId,@Param("userId") String userId,@Param("roleId") Long roleId);
-    @Select("select * from fastgpt_chat_msg where  session_id =#{sessionId} and msg_type=1 ORDER BY msg_id DESC  limit 20 ")
+    //@Select("select * from fastgpt_chat_msg where  session_id =#{sessionId} and msg_type=1 ORDER BY msg_id DESC  limit 10 ")
     List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionId(Long sessionId);
 
 
+    List<FastGptChatMsg> selectFastGptChatMsgUserList(List<Long> list);
+
+    void insertFastGptEventLog(FastGptEventLog fastGptEventLog);
+
+    void insertFastGptEventTokenLog(FastGptEventTokenLog fastGptEventTokenLog);
+
+    List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionIdAndExtId(@Param("sessionId") Long sessionId,@Param("extId") String extId);
 }

+ 2 - 4
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatReplaceWordsMapper.java

@@ -1,13 +1,11 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.fs.common.annotation.DataSource;
-import com.fs.common.enums.DataSourceType;
 import com.fs.fastGpt.domain.FastGptChatReplaceWords;
-import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
 import org.apache.ibatis.annotations.Select;
 
+import java.util.List;
+
 /**
  * 违规词语Mapper接口
  *

+ 3 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptChatSessionMapper.java

@@ -117,7 +117,7 @@ public interface FastGptChatSessionMapper
 
     @Select("select * from fastgpt_chat_session where user_id=#{userId} and qw_user_id=#{qwUserId} and status=1 order by session_id desc limit 1 ")
     FastGptChatSession selectFastGptChatSessionByUserIdAndKfId(@Param("userId") String userId, @Param("qwUserId")Long qwUserId);
-    @Select("select * from fastgpt_chat_session where remind_status=1 and remind_time < NOW() ")
+    @Select("select * from fastgpt_chat_session where remind_status=1 and user_id is not null and remind_time < NOW() ")
     List<FastGptChatSession> selectFastGptChatSessionByRemind();
     @Select("select * from fastgpt_chat_session where qw_ext_id=#{extId} and qw_user_id=#{qwUser} and status=1 limit 1")
     FastGptChatSession selectFastGptChatSessionByQwExternalContactsAndUserId(@Param("extId") Long extId,@Param("qwUser")  Long qwUser);
@@ -125,4 +125,6 @@ public interface FastGptChatSessionMapper
     @Update("UPDATE fastgpt_chat_session  SET is_artificial = 0 WHERE is_artificial = 1  AND TIMESTAMPDIFF(MINUTE, last_time, NOW()) > 10;")
     void updateFastGptChatSessionByIsReply();
 
+
+
 }

+ 73 - 0
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptKeywordSendMapper.java

@@ -0,0 +1,73 @@
+package com.fs.fastGpt.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.fastGpt.domain.FastGptKeyword;
+import com.fs.fastGpt.domain.FastGptKeywordArtificial;
+import com.fs.fastGpt.domain.FastGptKeywordSend;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * Ai关键字表(根据关键字发送文本和图片)Mapper接口
+ * 
+ * @author fs
+ * @date 2025-05-12
+ */
+public interface FastGptKeywordSendMapper extends BaseMapper<FastGptKeywordSend>{
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return Ai关键字表(根据关键字发送文本和图片)
+     */
+    FastGptKeywordSend selectFastGptKeywordSendById(@Param("id") Long id,@Param("keywordType") Long keywordType);
+
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)列表
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return Ai关键字表(根据关键字发送文本和图片)集合
+     */
+    List<FastGptKeywordSend> selectFastGptKeywordSendList(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 新增Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    int insertFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 修改Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    int updateFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 删除Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return 结果
+     */
+    int deleteFastGptKeywordSendById(Long id);
+
+    /**
+     * 批量删除Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFastGptKeywordSendByIds(Long[] ids);
+
+    List<FastGptKeywordSend> selectFastGptKeywordSendByRoleId(@Param("roleIds") Long roleId);
+
+    List<FastGptKeywordArtificial> selectFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial);
+
+    int insertFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial);
+
+    List<FastGptKeyword> selectFastGptKeywordList(int type);
+}

+ 13 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptRoleMapper.java

@@ -1,12 +1,15 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastGptRole;
 import com.fs.fastGpt.vo.FastGptRoleVO;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
 import com.fs.his.vo.OptionsVO;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
+import java.util.List;
+
 /**
  * 应用Mapper接口
  *
@@ -88,4 +91,13 @@ public interface FastGptRoleMapper
     List<OptionsVO> selectFastGptRoleType();
     @Select("select r.role_id, r.role_name,t.contact_info,r.company_id, r.create_time, r.update_time, r.role_type, r.mode_config_json, r.mode, r.kf_id, r.kf_url, r.avatar, r.kf_media_id,r.reminder_words, r.bind_corp_id from fastgpt_role r LEFT JOIN fastgpt_role_type t on t.id =r.role_type where role_id = #{roleId}")
     FastGptRole selectFastGptRoleTypeByRoleId(Long roleId);
+
+    List<FastGptRole> selectFastGptRoleByRoleIds(@Param("roleIds") List<Long> roleIds);
+
+    List<String> selectFastGptRoleRoleIdsByAppKey(@Param("appKey") String appKey);
+
+    List<OptionsVO> selectFastGptRoleRoleIdsByLikeAppKey(@Param("appKey") String appKey);
+
+    List<FastgptEventLogTotalVo> selectFastGptRoleAppKeyList();
+
 }

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastGptRoleTagMapper.java

@@ -1,9 +1,10 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastGptRoleTag;
 import org.apache.ibatis.annotations.Select;
 
+import java.util.List;
+
 /**
  * AI的标签Mapper接口
  *

+ 62 - 0
fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptChatArtificialWordsMapper.java

@@ -0,0 +1,62 @@
+package com.fs.fastGpt.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.fastGpt.domain.FastgptChatArtificialWords;
+
+import java.util.List;
+
+/**
+ * 转人工提示词Mapper接口
+ * 
+ * @author fs
+ * @date 2025-05-07
+ */
+public interface FastgptChatArtificialWordsMapper extends BaseMapper<FastgptChatArtificialWords>{
+    /**
+     * 查询转人工提示词
+     * 
+     * @param id 转人工提示词主键
+     * @return 转人工提示词
+     */
+    FastgptChatArtificialWords selectFastgptChatArtificialWordsById(Long id);
+
+    /**
+     * 查询转人工提示词列表
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 转人工提示词集合
+     */
+    List<FastgptChatArtificialWords> selectFastgptChatArtificialWordsList(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 新增转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    int insertFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 修改转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    int updateFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 删除转人工提示词
+     * 
+     * @param id 转人工提示词主键
+     * @return 结果
+     */
+    int deleteFastgptChatArtificialWordsById(Long id);
+
+    /**
+     * 批量删除转人工提示词
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFastgptChatArtificialWordsByIds(Long[] ids);
+}

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptChatVoiceHomoMapper.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
 
+import java.util.List;
+
 /**
  * 多音字Mapper接口
  * 

+ 74 - 0
fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptEventLogTotalMapper.java

@@ -0,0 +1,74 @@
+package com.fs.fastGpt.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastgptEventLogTotal;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
+
+import java.util.List;
+
+/**
+ * ai事件埋点统计Mapper接口
+ * 
+ * @author fs
+ * @date 2025-06-26
+ */
+public interface FastgptEventLogTotalMapper extends BaseMapper<FastgptEventLogTotal>{
+    /**
+     * 查询ai事件埋点统计
+     * 
+     * @param id ai事件埋点统计主键
+     * @return ai事件埋点统计
+     */
+    FastgptEventLogTotal selectFastgptEventLogTotalById(Long id);
+
+    /**
+     * 查询ai事件埋点统计列表
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return ai事件埋点统计集合
+     */
+    List<FastgptEventLogTotal> selectFastgptEventLogTotalList(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 新增ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    int insertFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 修改ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    int updateFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 删除ai事件埋点统计
+     * 
+     * @param id ai事件埋点统计主键
+     * @return 结果
+     */
+    int deleteFastgptEventLogTotalById(Long id);
+
+    /**
+     * 批量删除ai事件埋点统计
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFastgptEventLogTotalByIds(Long[] ids);
+
+    List<FastgptEventLogTotal> selectFastgptEventLogTotalInfoList(FastgptEventLogTotal logTotal);
+
+    FastgptEventLogTotal selectFastgptEventLogTotalByRoleIdAndType(FastgptEventLogTotal total);
+
+    List<FastgptEventLogTotal> selectFastgptEventLogTotalVoInfoList(FastgptEventLogTotalVo fastgptEventLogTotal);
+
+    List<FastGptEventTokenLog> selectFastgptEventTokenLogTotalList(FastGptEventTokenLog fastGptEventTokenLog);
+
+    FastgptEventLogTotal selectFastgptEventTokenLogTotalByRoleIdAndType(FastGptEventTokenLog tokenLog);
+}

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptTagGroupMapper.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptTagGroup;
 
+import java.util.List;
+
 /**
  * ai标签组Mapper接口
  * 

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/mapper/FastgptTagMapper.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.mapper;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptTag;
 
+import java.util.List;
+
 /**
  * ai标签Mapper接口
  * 

+ 5 - 0
fs-service/src/main/java/com/fs/fastGpt/param/FastGptChatSessionParam.java

@@ -47,4 +47,9 @@ public class FastGptChatSessionParam  extends BaseEntity {
     private String qwUserName;
     private Integer isArtificial;
 
+    private Long qwExtId;
+    private String qwUserId;
+    private Integer overTime;
+    private String corpId;
+
 }

+ 76 - 0
fs-service/src/main/java/com/fs/fastGpt/param/FastgptEventLogTotalParam.java

@@ -0,0 +1,76 @@
+package com.fs.fastGpt.param;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * ai事件埋点统计对象 fastgpt_event_log_total
+ *
+ * @author fs
+ * @date 2025-06-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastgptEventLogTotalParam extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 角色id */
+    //@Excel(name = "角色id")
+    private Long roleId;
+
+    @Excel(name = "角色名称")
+    private Long roleName;
+
+    /** 数量 */
+    @Excel(name = "数量")
+    private Long count;
+
+    /** 日志类型 */
+    @Excel(name = "日志类型")
+    private Integer type;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司用户id */
+    @Excel(name = "公司用户id")
+    private Long companyUserId;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private Long qwUserId;
+
+    @Excel(name = "日志生成时间")
+    private String statTime;
+
+    /**
+     * 员工列表
+     */
+    private List<String> userIds;
+
+    private String qwUserIds;
+
+    private Date createTime;
+
+    private Integer pageNum;
+    private Integer pageSize;
+
+
+    private String beginTime;
+
+
+    private String endTime;
+
+    private String appKey;
+
+
+
+}

+ 14 - 0
fs-service/src/main/java/com/fs/fastGpt/param/SendHookParam.java

@@ -0,0 +1,14 @@
+package com.fs.fastGpt.param;
+
+import lombok.Data;
+
+
+@Data
+public class SendHookParam {
+
+    String key;  //key
+    String qwExtName;
+    String qwExtUserId; //外部联系人id
+    Integer msgType; //1 普通消息 2 图片 3 卡片链接  4 小程序
+    String msg;
+}

+ 4 - 0
fs-service/src/main/java/com/fs/fastGpt/service/AiHookService.java

@@ -1,6 +1,7 @@
 package com.fs.fastGpt.service;
 
 import com.fs.common.core.domain.R;
+import com.fs.im.vo.OpenImMsgCallBackVO;
 import com.fs.qwHookApi.vo.QwHookVO;
 import com.fs.wxwork.dto.WxWorkResponseDTO;
 
@@ -14,6 +15,9 @@ public interface AiHookService {
     /** 转人工 **/
     void artificial(QwHookVO vo);
 
+    /** ai自动回复 **/
+    R AiReply(OpenImMsgCallBackVO openImMsgDTO, Long companyId);
+
     R qwHookNotifyAddMsg(Long qwUserID, Long sender,String count,String uid);
 
     void expireAiMsg();

+ 7 - 0
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatKeywordService.java

@@ -1,6 +1,7 @@
 package com.fs.fastGpt.service;
 
 import com.fs.fastGpt.domain.FastGptChatKeyword;
+import com.fs.fastGpt.domain.FastGptExpressInfo;
 
 import java.util.List;
 
@@ -59,4 +60,10 @@ public interface IFastGptChatKeywordService
      * @return 结果
      */
     public int deleteFastGptChatKeywordByKeywordId(Long keywordId);
+
+    List<FastGptExpressInfo> selectFastGptExpressInfoList(FastGptExpressInfo fastGptExpressInfo);
+
+    void insertFastGptChatExpressInfo(FastGptExpressInfo expressInfo);
+
+    void updateFastGptExpressInfo(FastGptExpressInfo info);
 }

+ 11 - 2
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatMsgService.java

@@ -1,7 +1,8 @@
 package com.fs.fastGpt.service;
 
 import com.fs.fastGpt.domain.FastGptChatMsg;
-import com.fs.fastGpt.domain.FastGptChatSession;
+import com.fs.fastGpt.domain.FastGptEventLog;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
 import com.fs.fastGpt.param.FastGptChatMsgListCParam;
 import com.fs.fastGpt.vo.FastGptChatMsgCVO;
 import com.fs.fastGpt.vo.FastGptChatMsgListCVO;
@@ -64,7 +65,7 @@ public interface IFastGptChatMsgService
      */
     public int deleteFastGptChatMsgByMsgId(Long msgId);
 
-    List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(Long sessionId);
+    List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(Long sessionId,String userId);
 
     List<FastGptChatMsgListCVO> selectFastGptChatMsgListCVO(FastGptChatMsgListCParam param);
 
@@ -74,4 +75,12 @@ public interface IFastGptChatMsgService
 
 
     List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionId(Long sessionId);
+
+    List<FastGptChatMsg> selectFastGptChatMsgUserList(List<Long> list);
+
+    void insertFastGptEventLog(FastGptEventLog fastGptEventLog);
+
+    void insertFastGptEventTokenLog(FastGptEventTokenLog fastGptEventTokenLog);
+
+    List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionIdAndExtId(Long sessionId, Long extId);
 }

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatReplaceWordsService.java

@@ -1,9 +1,10 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.fastGpt.domain.FastGptChatReplaceWords;
 
+import java.util.List;
+
 /**
  * 违规词语Service接口
  * 

+ 5 - 2
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptChatSessionService.java

@@ -1,13 +1,12 @@
 package com.fs.fastGpt.service;
 
+import com.fs.common.core.domain.R;
 import com.fs.fastGpt.domain.FastGptChatSession;
 import com.fs.fastGpt.param.FastGptChatSessionParam;
 import com.fs.fastGpt.vo.FastGptChatSessionCVO;
 import com.fs.fastGpt.vo.FastGptChatSessionListCVO;
 import com.fs.qwHookApi.vo.QwHookMsgVO;
 import com.fs.sop.vo.QwSopLogsDoSendListTVO;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
 
@@ -78,4 +77,8 @@ public interface IFastGptChatSessionService
     void addAiMsgBySopByStatus(String id);
 
     void qwHookNotifyAddMsg(QwHookMsgVO msgVo);
+
+    R extendArtificialTime(FastGptChatSessionParam sessionParam);
+
+    Integer selectFastGptChatSessionArtificialType(FastGptChatSessionParam sessionParam);
 }

+ 72 - 0
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptKeywordSendService.java

@@ -0,0 +1,72 @@
+package com.fs.fastGpt.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.fastGpt.domain.FastGptKeyword;
+import com.fs.fastGpt.domain.FastGptKeywordArtificial;
+import com.fs.fastGpt.domain.FastGptKeywordSend;
+
+import java.util.List;
+
+/**
+ * Ai关键字表(根据关键字发送文本和图片)Service接口
+ * 
+ * @author fs
+ * @date 2025-05-12
+ */
+public interface IFastGptKeywordSendService extends IService<FastGptKeywordSend>{
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return Ai关键字表(根据关键字发送文本和图片)
+     */
+    FastGptKeywordSend selectFastGptKeywordSendById(Long id,Long keywordType);
+
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)列表
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return Ai关键字表(根据关键字发送文本和图片)集合
+     */
+    List<FastGptKeywordSend> selectFastGptKeywordSendList(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 新增Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    int insertFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 修改Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    int updateFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend);
+
+    /**
+     * 批量删除Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param ids 需要删除的Ai关键字表(根据关键字发送文本和图片)主键集合
+     * @return 结果
+     */
+    int deleteFastGptKeywordSendByIds(Long[] ids);
+
+    /**
+     * 删除Ai关键字表(根据关键字发送文本和图片)信息
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return 结果
+     */
+    int deleteFastGptKeywordSendById(Long id);
+
+    List<FastGptKeywordSend> selectFastGptKeywordSendByRoleId(Long roleId);
+
+    List<FastGptKeywordArtificial> selectFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial);
+
+    int insertFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial);
+
+    List<FastGptKeyword> selectFastGptKeywordList(int type);
+}

+ 13 - 2
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptRoleService.java

@@ -1,12 +1,13 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
-
 import com.fs.common.core.domain.R;
 import com.fs.fastGpt.domain.FastGptRole;
+import com.fs.fastGpt.vo.FastGptRoleDataVO;
 import com.fs.fastGpt.vo.FastGptRoleVO;
 import com.fs.his.vo.OptionsVO;
 
+import java.util.List;
+
 /**
  * 应用Service接口
  *
@@ -73,4 +74,14 @@ public interface IFastGptRoleService
     List<OptionsVO> selectFastGptRoleType();
 
     public FastGptRole selectFastGptRoleTypeByRoleId(Long roleId);
+
+    List<FastGptRole> selectFastGptRoleByRoleIds(List<Long> roleIds);
+
+    List<String> selectFastGptRoleRoleIdsByAppKey(String appKey);
+
+    List<OptionsVO> selectFastGptRoleRoleIdsByLikeAppKey(String appKey);
+
+    List<FastGptRoleDataVO> selectFastGptRoleAppKeyList();
+
+
 }

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/service/IFastGptRoleTagService.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastGptRoleTag;
 
+import java.util.List;
+
 /**
  * AI的标签Service接口
  *

+ 62 - 0
fs-service/src/main/java/com/fs/fastGpt/service/IFastgptChatArtificialWordsService.java

@@ -0,0 +1,62 @@
+package com.fs.fastGpt.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.fastGpt.domain.FastgptChatArtificialWords;
+
+import java.util.List;
+
+/**
+ * 转人工提示词Service接口
+ * 
+ * @author fs
+ * @date 2025-05-07
+ */
+public interface IFastgptChatArtificialWordsService extends IService<FastgptChatArtificialWords>{
+    /**
+     * 查询转人工提示词
+     * 
+     * @param id 转人工提示词主键
+     * @return 转人工提示词
+     */
+    FastgptChatArtificialWords selectFastgptChatArtificialWordsById(Long id);
+
+    /**
+     * 查询转人工提示词列表
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 转人工提示词集合
+     */
+    List<FastgptChatArtificialWords> selectFastgptChatArtificialWordsList(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 新增转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    int insertFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 修改转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    int updateFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords);
+
+    /**
+     * 批量删除转人工提示词
+     * 
+     * @param ids 需要删除的转人工提示词主键集合
+     * @return 结果
+     */
+    int deleteFastgptChatArtificialWordsByIds(Long[] ids);
+
+    /**
+     * 删除转人工提示词信息
+     * 
+     * @param id 转人工提示词主键
+     * @return 结果
+     */
+    int deleteFastgptChatArtificialWordsById(Long id);
+}

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/service/IFastgptChatVoiceHomoService.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
 
+import java.util.List;
+
 /**
  * 多音字Service接口
  * 

+ 76 - 0
fs-service/src/main/java/com/fs/fastGpt/service/IFastgptEventLogTotalService.java

@@ -0,0 +1,76 @@
+package com.fs.fastGpt.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastgptEventLogTotal;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
+
+import java.util.List;
+
+/**
+ * ai事件埋点统计Service接口
+ * 
+ * @author fs
+ * @date 2025-06-26
+ */
+public interface IFastgptEventLogTotalService extends IService<FastgptEventLogTotal>{
+    /**
+     * 查询ai事件埋点统计
+     * 
+     * @param id ai事件埋点统计主键
+     * @return ai事件埋点统计
+     */
+    FastgptEventLogTotal selectFastgptEventLogTotalById(Long id);
+
+    /**
+     * 查询ai事件埋点统计列表
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return ai事件埋点统计集合
+     */
+    List<FastgptEventLogTotal> selectFastgptEventLogTotalList(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 新增ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    int insertFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 修改ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    int updateFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal);
+
+    /**
+     * 批量删除ai事件埋点统计
+     * 
+     * @param ids 需要删除的ai事件埋点统计主键集合
+     * @return 结果
+     */
+    int deleteFastgptEventLogTotalByIds(Long[] ids);
+
+    /**
+     * 删除ai事件埋点统计信息
+     * 
+     * @param id ai事件埋点统计主键
+     * @return 结果
+     */
+    int deleteFastgptEventLogTotalById(Long id);
+
+    List<FastgptEventLogTotal> selectFastgptEventLogTotalInfoList(FastgptEventLogTotal logTotal);
+
+    FastgptEventLogTotal selectFastgptEventLogTotalByRoleIdAndType(FastgptEventLogTotal total);
+
+    List<FastgptEventLogTotalVo> selectFastgptEventLogTotalVoInfoList(FastgptEventLogTotalVo fastgptEventLogTotal);
+
+    List<FastGptEventTokenLog> selectFastgptEventTokenLogTotalList(FastGptEventTokenLog fastGptEventTokenLog);
+
+    FastgptEventLogTotal selectFastgptEventTokenLogTotalByRoleIdAndType(FastGptEventTokenLog tokenLog);
+
+    FastgptEventLogTotalVo totalFastgptEventLog(List<FastgptEventLogTotalVo> list);
+}

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/service/IFastgptTagGroupService.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptTagGroup;
 
+import java.util.List;
+
 /**
  * ai标签组Service接口
  * 

+ 2 - 1
fs-service/src/main/java/com/fs/fastGpt/service/IFastgptTagService.java

@@ -1,8 +1,9 @@
 package com.fs.fastGpt.service;
 
-import java.util.List;
 import com.fs.fastGpt.domain.FastgptTag;
 
+import java.util.List;
+
 /**
  * ai标签Service接口
  * 

Datei-Diff unterdrückt, da er zu groß ist
+ 412 - 238
fs-service/src/main/java/com/fs/fastGpt/service/impl/AiHookServiceImpl.java


+ 39 - 42
fs-service/src/main/java/com/fs/fastGpt/service/impl/AiNewServiceImpl.java

@@ -38,6 +38,7 @@ import com.fs.qwHookApi.vo.QwHookMsgVO;
 import com.fs.qwHookApi.vo.QwHookVO;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.mapper.QwSopLogsMapper;
+import com.vdurmont.emoji.EmojiParser;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -534,7 +535,7 @@ public class AiNewServiceImpl implements AiNewService {
             if (fsCourseWatchLogVO!=null){
                 FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                 param.setVideoId(fsCourseWatchLogVO.getVideoId());
-                param.setQwUserId(user.getId());
+                param.setQwUserId(String.valueOf(user.getId()));
                 param.setDays(1);
                 param.setCorpId(user.getCorpId());
                 param.setCourseId(fsCourseWatchLogVO.getCourseId());
@@ -565,7 +566,7 @@ public class AiNewServiceImpl implements AiNewService {
                     if (fsUserCourseVideo==null){
                         FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                         param.setVideoId(fsUserCourseVideo.getVideoId());
-                        param.setQwUserId(user.getId());
+                        param.setQwUserId(String.valueOf(user.getId()));
                         param.setDays(1);
                         param.setCorpId(user.getCorpId());
                         param.setCourseId(fsUserCourseVideo.getCourseId());
@@ -671,25 +672,13 @@ public class AiNewServiceImpl implements AiNewService {
     private void addPromptWord(List<ChatParam.Message> messageList,String count,Long extId,String words,String countInfo,Long sessionId){
 
         String  str="";
-        List<FastGptChatMsg> msgs=fastGptChatMsgService.selectFastGptChatMsgByMsgSessionId(sessionId);
-        if (!msgs.isEmpty()){
-            Collections.reverse(msgs);
-            str="【历史聊天内容:\n";
-            for (FastGptChatMsg msg : msgs) {
-                Integer sendType = msg.getSendType();
-                String content = msg.getContent();
-                str +=(sendType==1?"用户:":"AI:")+content+"\n";
-            }
-            str+="】\n";
-        }
-
         // 这里获取后台的提示词进行匹配
         QwExternalContactInfo info = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(extId);
         if(info==null){
             info=new QwExternalContactInfo();
         }
         if (info!=null){
-            str+="【用户状态信息\n";
+            str="【用户状态信息\n";
             Field[] fields = info.getClass().getDeclaredFields();
             for (Field field : fields) {
                 field.setAccessible(true);
@@ -719,13 +708,25 @@ public class AiNewServiceImpl implements AiNewService {
         if (words!=null&&!"".equals(words)){
             str+="【你的角色信息:以下内容为你的信息状态的补充而非用户信息,相当于放在角色任务里面,问到了需要知晓,但是如果无关的时候请无视此段内容 "+"\""+words+"\""+"】\n";
         }
+
+        List<FastGptChatMsg> msgs=fastGptChatMsgService.selectFastGptChatMsgByMsgSessionId(sessionId);
+        if (!msgs.isEmpty()){
+            Collections.reverse(msgs);
+            str+="【历史聊天内容:\n";
+            for (FastGptChatMsg msg : msgs) {
+                Integer sendType = msg.getSendType();
+                String content = msg.getContent();
+                str +=(sendType==1?"用户:":"AI:")+content+"\n";
+            }
+            str+="】\n";
+        }
+
         if (count!=null&&!"".equals(count)){
             str+="【用户说的话内容(之前的内容仅仅为背景,你知道即可,以下才是用户真实说的话的内容)\n" +
                     "\""+count+"\""+"\n" +
                     "】";
         }
 
-
         ChatParam.Message message1=new ChatParam.Message();
         message1.setRole("user");
         message1.setContent(str);
@@ -972,7 +973,8 @@ public class AiNewServiceImpl implements AiNewService {
 
         if(org.springframework.util.StringUtils.isEmpty(s)) return "";
         // 替换匹配到的内容
-        return s.replaceAll("\\[.*?]", "").trim();
+        String text = s.replaceAll("\\[.*?]", "");
+        return EmojiParser.removeAllEmojis(text);
     }
     /** 发送语音过滤 */
     private  String voiceHomo(String content){
@@ -1052,7 +1054,7 @@ public class AiNewServiceImpl implements AiNewService {
             if (fsCourseWatchLogVO!=null){
                 FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                 param.setVideoId(fsCourseWatchLogVO.getVideoId());
-                param.setQwUserId(user.getId());
+                param.setQwUserId(String.valueOf(user.getId()));
                 param.setDays(1);
                 param.setCorpId(user.getCorpId());
                 param.setCourseId(fsCourseWatchLogVO.getCourseId());
@@ -1083,7 +1085,7 @@ public class AiNewServiceImpl implements AiNewService {
                     System.out.println("课程:"+fsUserCourseVideo);
                     FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                     param.setVideoId(fsUserCourseVideo.getVideoId());
-                    param.setQwUserId(user.getId());
+                    param.setQwUserId(String.valueOf(user.getId()));
                     param.setDays(1);
                     param.setCorpId(user.getCorpId());
                     param.setCourseId(fsUserCourseVideo.getCourseId());
@@ -1177,29 +1179,24 @@ public class AiNewServiceImpl implements AiNewService {
 
     @Override
     public void expireAiMsg() {
+        List<QwSopLogs> qwSopLogs = qwSopLogsMapper.selectExpireAiMsg();
+        if (qwSopLogs==null|| qwSopLogs.isEmpty()){
+            System.out.println("无");
+            return;
+        }
+        qwSopLogsMapper.batchUpdateQwSopLogsById(qwSopLogs);
+        List<QwSopLogs> distinctList = new ArrayList<>(qwSopLogs.stream()
+                .collect(Collectors.toMap(
+                        QwSopLogs::getExternalId,  // 以 extId 作为 Key
+                        log -> log,            // Value 是对象本身
+                        (existing, replacement) -> existing  // 遇到重复时保留已有值(第一个)
+                ))
+                .values());
+        for (QwSopLogs logs : distinctList) {
+            log.info("转人工:"+logs.getCorpId());
+            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(logs.getCorpId());
+            sendQwAppMsg(logs.getCorpId(),Integer.parseInt(qwCompany.getServerAgentId().trim()),logs.getQwUserid(),"您的客户:"+logs.getExternalUserName()+"因  AI回复内容过期转人工,请及时登录插件确定定位配置准确");
+        }
 
     }
-
-//    @Override
-//    public void expireAiMsg() {
-//        List<QwSopLogs> qwSopLogs = qwSopLogsMapper.selectExpireAiMsg();
-//        if (qwSopLogs==null|| qwSopLogs.isEmpty()){
-//            System.out.println("无");
-//            return;
-//        }
-//        qwSopLogsMapper.batchUpdateQwSopLogsById(qwSopLogs);
-//        List<QwSopLogs> distinctList = new ArrayList<>(qwSopLogs.stream()
-//                .collect(Collectors.toMap(
-//                        QwSopLogs::getExternalId,  // 以 extId 作为 Key
-//                        log -> log,            // Value 是对象本身
-//                        (existing, replacement) -> existing  // 遇到重复时保留已有值(第一个)
-//                ))
-//                .values());
-//        for (QwSopLogs logs : distinctList) {
-//            log.info("转人工:"+logs.getCorpId());
-//            QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(logs.getCorpId());
-//            sendQwAppMsg(logs.getCorpId(),Integer.parseInt(qwCompany.getServerAgentId().trim()),logs.getQwUserid(),"您的客户:"+logs.getExternalUserName()+"因  AI回复内容过期转人工,请及时登录插件确定定位配置准确");
-//        }
-//
-//    }
 }

+ 22 - 20
fs-service/src/main/java/com/fs/fastGpt/service/impl/AiServiceImpl.java

@@ -36,6 +36,7 @@ import com.fs.qwApi.service.QwApiService;
 import com.fs.qwHookApi.param.QwHookSendMsgParam;
 import com.fs.qwHookApi.vo.QwHookMsgVO;
 import com.fs.qwHookApi.vo.QwHookVO;
+import com.vdurmont.emoji.EmojiParser;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -316,7 +317,7 @@ public class AiServiceImpl implements AiService {
                         List<String> countList = countString(content, !type.equals(104014));
                         for (String msg : countList) {
 //                          if (vo.getType().equals(104014)){
-//                            sendWebSocketVoiceMsg(msg,msgVo,user,session,user.getCompanyUserId());
+                            sendWebSocketVoiceMsg(msg,msgVo,user,session,user.getCompanyUserId());
 //                               }else {
                             sendWebSocketMsg(msg,msgVo,user,session);
 //                               }
@@ -511,7 +512,7 @@ public class AiServiceImpl implements AiService {
             if (fsCourseWatchLogVO!=null){
                 FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                 param.setVideoId(fsCourseWatchLogVO.getVideoId());
-                param.setQwUserId(user.getId());
+                param.setQwUserId(String.valueOf(user.getId()));
                 param.setDays(1);
                 param.setCorpId(user.getCorpId());
                 param.setCourseId(fsCourseWatchLogVO.getCourseId());
@@ -542,7 +543,7 @@ public class AiServiceImpl implements AiService {
                     if (fsUserCourseVideo==null){
                         FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                         param.setVideoId(fsUserCourseVideo.getVideoId());
-                        param.setQwUserId(user.getId());
+                        param.setQwUserId(String.valueOf(user.getId()));
                         param.setDays(1);
                         param.setCorpId(user.getCorpId());
                         param.setCourseId(fsUserCourseVideo.getCourseId());
@@ -648,25 +649,13 @@ public class AiServiceImpl implements AiService {
     private void addPromptWord(List<ChatParam.Message> messageList,String count,Long extId,String words,String countInfo,Long sessionId){
 
         String  str="";
-        List<FastGptChatMsg> msgs=fastGptChatMsgService.selectFastGptChatMsgByMsgSessionId(sessionId);
-        if (!msgs.isEmpty()){
-            Collections.reverse(msgs);
-            str="【历史聊天内容:\n";
-            for (FastGptChatMsg msg : msgs) {
-                Integer sendType = msg.getSendType();
-                String content = msg.getContent();
-                str +=(sendType==1?"用户:":"AI:")+content+"\n";
-            }
-            str+="】\n";
-        }
-
         // 这里获取后台的提示词进行匹配
         QwExternalContactInfo info = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(extId);
         if(info==null){
             info=new QwExternalContactInfo();
         }
         if (info!=null){
-            str+="【用户状态信息\n";
+            str="【用户状态信息\n";
             Field[] fields = info.getClass().getDeclaredFields();
             for (Field field : fields) {
                 field.setAccessible(true);
@@ -696,13 +685,25 @@ public class AiServiceImpl implements AiService {
         if (words!=null&&!"".equals(words)){
             str+="【你的角色信息:以下内容为你的信息状态的补充而非用户信息,相当于放在角色任务里面,问到了需要知晓,但是如果无关的时候请无视此段内容 "+"\""+words+"\""+"】\n";
         }
+
+        List<FastGptChatMsg> msgs=fastGptChatMsgService.selectFastGptChatMsgByMsgSessionId(sessionId);
+        if (!msgs.isEmpty()){
+            Collections.reverse(msgs);
+            str+="【历史聊天内容:\n";
+            for (FastGptChatMsg msg : msgs) {
+                Integer sendType = msg.getSendType();
+                String content = msg.getContent();
+                str +=(sendType==1?"用户:":"AI:")+content+"\n";
+            }
+            str+="】\n";
+        }
+
         if (count!=null&&!"".equals(count)){
             str+="【用户说的话内容(之前的内容仅仅为背景,你知道即可,以下才是用户真实说的话的内容)\n" +
                     "\""+count+"\""+"\n" +
                     "】";
         }
 
-
         ChatParam.Message message1=new ChatParam.Message();
         message1.setRole("user");
         message1.setContent(str);
@@ -949,7 +950,8 @@ public class AiServiceImpl implements AiService {
 
         if(org.springframework.util.StringUtils.isEmpty(s)) return "";
         // 替换匹配到的内容
-        return s.replaceAll("\\[.*?]", "").trim();
+        String text = s.replaceAll("\\[.*?]", "");
+        return EmojiParser.removeAllEmojis(text);
     }
     /** 发送语音过滤 */
     private  String voiceHomo(String content){
@@ -1029,7 +1031,7 @@ public class AiServiceImpl implements AiService {
             if (fsCourseWatchLogVO!=null){
                 FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                 param.setVideoId(fsCourseWatchLogVO.getVideoId());
-                param.setQwUserId(user.getId());
+                param.setQwUserId(String.valueOf(user.getId()));
                 param.setDays(1);
                 param.setCorpId(user.getCorpId());
                 param.setCourseId(fsCourseWatchLogVO.getCourseId());
@@ -1060,7 +1062,7 @@ public class AiServiceImpl implements AiService {
                     System.out.println("课程:"+fsUserCourseVideo);
                     FsCourseLinkCreateParam param = new FsCourseLinkCreateParam();
                     param.setVideoId(fsUserCourseVideo.getVideoId());
-                    param.setQwUserId(user.getId());
+                    param.setQwUserId(String.valueOf(user.getId()));
                     param.setDays(1);
                     param.setCorpId(user.getCorpId());
                     param.setCourseId(fsUserCourseVideo.getCourseId());

+ 16 - 0
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatKeywordServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.fastGpt.service.impl;
 
 import com.fs.common.utils.DateUtils;
 import com.fs.fastGpt.domain.FastGptChatKeyword;
+import com.fs.fastGpt.domain.FastGptExpressInfo;
 import com.fs.fastGpt.mapper.FastGptChatKeywordMapper;
 import com.fs.fastGpt.service.IFastGptChatKeywordService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -94,4 +95,19 @@ public class FastGptChatKeywordServiceImpl implements IFastGptChatKeywordService
     {
         return fastGptChatKeywordMapper.deleteFastGptChatKeywordByKeywordId(keywordId);
     }
+
+    @Override
+    public List<FastGptExpressInfo> selectFastGptExpressInfoList(FastGptExpressInfo fastGptExpressInfo) {
+        return fastGptChatKeywordMapper.selectFastGptExpressInfoList(fastGptExpressInfo);
+    }
+
+    @Override
+    public void insertFastGptChatExpressInfo(FastGptExpressInfo expressInfo) {
+        fastGptChatKeywordMapper.insertFastGptChatExpressInfo(expressInfo);
+    }
+
+    @Override
+    public void updateFastGptExpressInfo(FastGptExpressInfo info) {
+        fastGptChatKeywordMapper.updateFastGptExpressInfo(info);
+    }
 }

+ 33 - 9
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatMsgServiceImpl.java

@@ -1,19 +1,21 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.Collections;
-import java.util.List;
-
 import cn.hutool.core.lang.Snowflake;
+import com.fs.common.annotation.DataSource;
+import com.fs.common.enums.DataSourceType;
 import com.fs.common.utils.DateUtils;
-import com.fs.fastGpt.domain.FastGptChatSession;
+import com.fs.fastGpt.domain.FastGptChatMsg;
+import com.fs.fastGpt.domain.FastGptEventLog;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.mapper.FastGptChatMsgMapper;
 import com.fs.fastGpt.param.FastGptChatMsgListCParam;
+import com.fs.fastGpt.service.IFastGptChatMsgService;
 import com.fs.fastGpt.vo.FastGptChatMsgCVO;
 import com.fs.fastGpt.vo.FastGptChatMsgListCVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastGptChatMsgMapper;
-import com.fs.fastGpt.domain.FastGptChatMsg;
-import com.fs.fastGpt.service.IFastGptChatMsgService;
+
+import java.util.List;
 
 /**
  * 聊天记录Service业务层处理
@@ -102,8 +104,8 @@ public class FastGptChatMsgServiceImpl implements IFastGptChatMsgService
     }
 
     @Override
-    public List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(Long sessionId) {
-        return fastGptChatMsgMapper.selectFastGptChatMsgCVOBySessionId(sessionId);
+    public List<FastGptChatMsgCVO> selectFastGptChatMsgCVOBySessionId(Long sessionId,String userId) {
+        return fastGptChatMsgMapper.selectFastGptChatMsgCVOBySessionId(sessionId,userId);
     }
 
     @Override
@@ -128,4 +130,26 @@ public class FastGptChatMsgServiceImpl implements IFastGptChatMsgService
     public List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionId(Long sessionId) {
         return fastGptChatMsgMapper.selectFastGptChatMsgByMsgSessionId(sessionId);
     }
+
+    @Override
+    public List<FastGptChatMsg> selectFastGptChatMsgUserList(List<Long> list) {
+        return fastGptChatMsgMapper.selectFastGptChatMsgUserList(list);
+    }
+
+    @Override
+    @DataSource(DataSourceType.CLICKHOUSE)
+    public void insertFastGptEventLog(FastGptEventLog fastGptEventLog) {
+        fastGptChatMsgMapper.insertFastGptEventLog(fastGptEventLog);
+    }
+
+    @Override
+    @DataSource(DataSourceType.CLICKHOUSE)
+    public void insertFastGptEventTokenLog(FastGptEventTokenLog fastGptEventTokenLog) {
+        fastGptChatMsgMapper.insertFastGptEventTokenLog(fastGptEventTokenLog);
+    }
+
+    @Override
+    public List<FastGptChatMsg> selectFastGptChatMsgByMsgSessionIdAndExtId(Long sessionId, Long extId) {
+        return fastGptChatMsgMapper.selectFastGptChatMsgByMsgSessionIdAndExtId(sessionId,String.valueOf(extId));
+    }
 }

+ 4 - 4
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatReplaceWordsServiceImpl.java

@@ -1,13 +1,13 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.List;
-
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.utils.DateUtils;
-import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
 import com.fs.fastGpt.domain.FastGptChatReplaceWords;
+import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
 import com.fs.fastGpt.service.IFastGptChatReplaceWordsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 违规词语Service业务层处理

+ 162 - 95
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptChatSessionServiceImpl.java

@@ -1,17 +1,14 @@
 package com.fs.fastGpt.service.impl;
 
-import cn.hutool.http.HttpRequest;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.Excel;
-import com.fs.common.annotation.RateLimiter;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
-import com.fs.course.service.IFsCourseLinkService;
 import com.fs.fastGpt.config.ModeConfig;
 import com.fs.fastGpt.domain.FastGptChatMsg;
 import com.fs.fastGpt.domain.FastGptChatSession;
@@ -35,7 +32,7 @@ import com.fs.qw.mapper.QwCompanyMapper;
 import com.fs.qw.mapper.QwExternalContactInfoMapper;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
-import com.fs.qw.service.IQwContactWayService;
+import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qw.service.IQwJsApiService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qwApi.service.QwApiService;
@@ -44,9 +41,8 @@ import com.fs.qwHookApi.vo.QwHookMsgVO;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.service.IQwSopLogsService;
-import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.sop.vo.QwSopLogsDoSendListTVO;
-import org.apache.poi.ss.formula.functions.T;
+import com.vdurmont.emoji.EmojiParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,7 +51,6 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.lang.reflect.Field;
-import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -69,7 +64,7 @@ import java.util.regex.Pattern;
 @Service
 public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
 {
-   private static final Logger log = LoggerFactory.getLogger(FastGptChatSessionServiceImpl.class);
+   private static final Logger logger = LoggerFactory.getLogger(FastGptChatSessionServiceImpl.class);
     @Autowired
     private FastGptChatSessionMapper fastGptChatSessionMapper;
     @Autowired
@@ -111,6 +106,8 @@ public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
     RedisCache redisCache;
     @Autowired
     private IQwUserService qwUserService;
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
 
     /**
      * 查询对话关系
@@ -188,7 +185,26 @@ public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
 
     @Override
     public List<FastGptChatSessionListCVO> selectFastGptChatSessionListCVO(FastGptChatSessionParam param) {
-        return fastGptChatSessionMapper.selectFastGptChatSessionListCVO(param);
+        List<FastGptChatSessionListCVO> list = fastGptChatSessionMapper.selectFastGptChatSessionListCVO(param);
+        List<Long> sessionIdList = new ArrayList<>();
+        if(list != null && !list.isEmpty()){
+            list.forEach(m -> sessionIdList.add(m.getSessionId()));
+            if(!sessionIdList.isEmpty()){
+                List<FastGptChatMsg> msgList = fastGptChatMsgService.selectFastGptChatMsgUserList(sessionIdList);
+                msgList.forEach(m ->{
+                    list.forEach(n ->{
+                        if(m.getSessionId().equals(n.getSessionId())){
+                            if(m.getSendType().equals(1)){
+                                n.setQuestion(m.getContent()==null?"":m.getContent());
+                            }else if(m.getSendType().equals(2)){
+                                n.setAnswer(m.getContent()==null?"":m.getContent());
+                            }
+                        }
+                    });
+                });
+            }
+        }
+        return list;
     }
 
     @Override
@@ -203,97 +219,102 @@ public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
     @Async
     @Override
     public void sendAiTouch(QwSopLogsDoSendListTVO log,String CorpId) {
-        String externalUserId = log.getExternalUserId();
-        String qwUserid = log.getQwUserid();
-        QwUser user=qwUserMapper.selectQwUserByQwUseridAndCorpId(qwUserid,CorpId);
-        QwExternalContact qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByExternalUserIdAndQwUserId(externalUserId, CorpId,qwUserid);
-        if(user!=null&&qwExternalContacts!=null){
-            FastGptChatSession ss = fastGptChatSessionMapper.selectFastGptChatSessionByQwExternalContactsAndUserId(qwExternalContacts.getId(), user.getId());
-            QwExternalContactInfo info = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(qwExternalContacts.getId());
-            JSONObject jsonObject = JSON.parseObject(log.getContentJson());
-            String msg = (String)jsonObject.get("aiTouch");
-            if (info!=null){
-                QwExternalContactInfo extInfo = new QwExternalContactInfo();
-                extInfo.setTalk(msg);
-                extInfo.setId(info.getId());
-                qwExternalContactInfoMapper.updateQwExternalContactInfo(extInfo);
-            }else {
-                QwExternalContactInfo extInfo = new QwExternalContactInfo();
-                extInfo.setTalk(msg);
-                extInfo.setExternalContactId(qwExternalContacts.getId());
-                extInfo.setCreateTime(new Date());
-                qwExternalContactInfoMapper.insertQwExternalContactInfo(extInfo);
-            }
-            QwSopLogs qwSopLogs=new QwSopLogs();
-            qwSopLogs.setId(log.getId());
-            qwSopLogs.setSendStatus(1L);
-            qwSopLogsService.updateQwSopLogsSendType(qwSopLogs);
-            if (ss!=null){
-                if (msg!=null&&msg.contains("交流状态")){
-                    ChatParam param=new ChatParam();
-                    param.setChatId(ss.getChatId());
-                    param.setStream(false);
-                    param.setDetail(true);
-                    ChatParam.Variables variables=new ChatParam.Variables();
-                    variables.setUid(ss.getKfId().toString());
-                    variables.setName("test");
-                    param.setVariables(variables);
-                    List<ChatParam.Message> messageList=new ArrayList<ChatParam.Message>();
-                    param.setMessages(messageList);
-                    FastGptRole role=roleService.selectFastGptRoleByRoleId(Long.parseLong(ss.getKfId()) );
-                    String modeConfig=role.getModeConfigJson();
-                    ModeConfig config=JSONUtil.toBean(modeConfig,ModeConfig.class);
-                    addPromptWord(messageList,"用户触达了",ss.getQwExtId(),role.getReminderWords(), role.getContactInfo());
-                    R r = chatService.initiatingTakeChat(param,"http://154.8.194.176:3000/api",config.getAPPKey());
-                    if(r.get("code").equals(200)){
-                        ChatDetailTStreamFResult result=(ChatDetailTStreamFResult)r.get("data");
-                        String count = replace(result.getChoices().get(0).getMessage().getContent()).trim();
-                        QwHookSendMsgParam sendMsgParam=new QwHookSendMsgParam();
-                        QwHookSendMsgParam.QwHookSendMsgData sendMsgData=new QwHookSendMsgParam.QwHookSendMsgData();
-                        sendMsgParam.setType(101003);
-                        sendMsgData.setMsg(count);
-                        sendMsgData.setSendId(ss.getUserId());
-                        sendMsgData.setSyncKey("1");
-                        sendMsgParam.setData(sendMsgData);
-                        SendHookAIParam sendAIParam = new SendHookAIParam();
-                        sendAIParam.setCmd("aiReplyMsg");
-                        sendAIParam.setData(JSONUtil.toJsonStr(sendMsgParam));
-                        sendAIParam.setKey(user.getAppKey());
-                        redisTemplate.opsForList().leftPush("AiMsg:"+user.getAppKey(), JSON.toJSONString(sendAIParam));
-                        FastGptChatSession fastGptChatSession = new FastGptChatSession();
-                        fastGptChatSession.setSessionId(ss.getSessionId());
-                        fastGptChatSession.setRemindCount(0);
-                        fastGptChatSession.setRemindStatus(1);
-                        Calendar calendar = Calendar.getInstance(); // 获取当前时间
-                        calendar.add(Calendar.MINUTE, 30); // 增加30分钟
-                        fastGptChatSession.setRemindTime(calendar.getTime());
-                        fastGptChatSessionMapper.updateFastGptChatSession(fastGptChatSession);
-                        FastGptChatMsg fastGptChatMsg = new FastGptChatMsg();
-                        fastGptChatMsg.setContent(count);
-                        fastGptChatMsg.setSessionId(fastGptChatSession.getSessionId());
-                        fastGptChatMsg.setRoleId(role.getRoleId());
-                        fastGptChatMsg.setSendType(1);
-                        fastGptChatMsg.setCompanyId(user.getCompanyId());
-                        fastGptChatMsg.setCompanyUserId(user.getCompanyUserId());
-                        fastGptChatMsg.setUserType(1);
-                        fastGptChatMsg.setMsgType(1);
-                        fastGptChatMsg.setStatus(0);
-                        fastGptChatMsg.setUserId(qwExternalContacts.getId().toString());
-                        fastGptChatMsg.setAvatar(qwExternalContacts.getAvatar());
-                        fastGptChatMsg.setNickName(qwExternalContacts.getName());
-                        fastGptChatMsg.setCreateTime(new Date());
-                        fastGptChatMsg.setExtId(qwExternalContacts.getExternalUserId());
-                        fastGptChatMsgService.insertFastGptChatMsg(fastGptChatMsg);
-                        addUserInfo(result.getChoices().get(0).getMessage().getContent(), ss.getQwExtId(),ss);
-                    }
+        try {
+            String externalUserId = log.getExternalUserId();
+            String qwUserid = log.getQwUserid();
+            QwUser user=qwUserMapper.selectQwUserByQwUseridAndCorpId(qwUserid,CorpId);
+            QwExternalContact qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByExternalUserIdAndQwUserId(externalUserId, CorpId,qwUserid);
+            if(user!=null&&qwExternalContacts!=null){
+                FastGptChatSession ss = fastGptChatSessionMapper.selectFastGptChatSessionByQwExternalContactsAndUserId(qwExternalContacts.getId(), user.getId());
+                QwExternalContactInfo info = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(qwExternalContacts.getId());
+                JSONObject jsonObject = JSON.parseObject(log.getContentJson());
+                String msg = (String)jsonObject.get("aiTouch");
+                if (info!=null){
+                    QwExternalContactInfo extInfo = new QwExternalContactInfo();
+                    extInfo.setTalk(msg);
+                    extInfo.setId(info.getId());
+                    qwExternalContactInfoMapper.updateQwExternalContactInfo(extInfo);
+                }else {
+                    QwExternalContactInfo extInfo = new QwExternalContactInfo();
+                    extInfo.setTalk(msg);
+                    extInfo.setExternalContactId(qwExternalContacts.getId());
+                    extInfo.setCreateTime(new Date());
+                    qwExternalContactInfoMapper.insertQwExternalContactInfo(extInfo);
+                }
+                QwSopLogs qwSopLogs=new QwSopLogs();
+                qwSopLogs.setId(log.getId());
+                qwSopLogs.setSendStatus(1L);
+                qwSopLogsService.updateQwSopLogsSendType(qwSopLogs);
+                if (ss!=null){
+                    if (msg!=null&&msg.contains("交流状态")){
+                        ChatParam param=new ChatParam();
+                        param.setChatId(ss.getChatId());
+                        param.setStream(false);
+                        param.setDetail(true);
+                        ChatParam.Variables variables=new ChatParam.Variables();
+                        variables.setUid(ss.getKfId().toString());
+                        variables.setName("test");
+                        param.setVariables(variables);
+                        List<ChatParam.Message> messageList=new ArrayList<ChatParam.Message>();
+                        param.setMessages(messageList);
+                        FastGptRole role=roleService.selectFastGptRoleByRoleId(Long.parseLong(ss.getKfId()) );
+                        String modeConfig=role.getModeConfigJson();
+                        ModeConfig config=JSONUtil.toBean(modeConfig,ModeConfig.class);
+                        addPromptWord(messageList,"用户触达了",ss.getQwExtId(),role.getReminderWords(), role.getContactInfo());
+                        R r = chatService.initiatingTakeChat(param,"http://154.8.194.176:3000/api",config.getAPPKey());
+                        if(r.get("code").equals(200)){
+                            ChatDetailTStreamFResult result=(ChatDetailTStreamFResult)r.get("data");
+                            String count = replace(result.getChoices().get(0).getMessage().getContent()).trim();
+                            QwHookSendMsgParam sendMsgParam=new QwHookSendMsgParam();
+                            QwHookSendMsgParam.QwHookSendMsgData sendMsgData=new QwHookSendMsgParam.QwHookSendMsgData();
+                            sendMsgParam.setType(101003);
+                            sendMsgData.setMsg(count);
+                            sendMsgData.setSendId(ss.getUserId());
+                            sendMsgData.setSyncKey("1");
+                            sendMsgParam.setData(sendMsgData);
+                            SendHookAIParam sendAIParam = new SendHookAIParam();
+                            sendAIParam.setCmd("aiReplyMsg");
+                            sendAIParam.setData(JSONUtil.toJsonStr(sendMsgParam));
+                            sendAIParam.setKey(user.getAppKey());
+                            redisTemplate.opsForList().leftPush("AiMsg:"+user.getAppKey(), JSON.toJSONString(sendAIParam));
+                            FastGptChatSession fastGptChatSession = new FastGptChatSession();
+                            fastGptChatSession.setSessionId(ss.getSessionId());
+                            fastGptChatSession.setRemindCount(0);
+                            fastGptChatSession.setRemindStatus(1);
+                            Calendar calendar = Calendar.getInstance(); // 获取当前时间
+                            calendar.add(Calendar.MINUTE, 30); // 增加30分钟
+                            fastGptChatSession.setRemindTime(calendar.getTime());
+                            fastGptChatSessionMapper.updateFastGptChatSession(fastGptChatSession);
+                            FastGptChatMsg fastGptChatMsg = new FastGptChatMsg();
+                            fastGptChatMsg.setContent(count);
+                            fastGptChatMsg.setSessionId(fastGptChatSession.getSessionId());
+                            fastGptChatMsg.setRoleId(role.getRoleId());
+                            fastGptChatMsg.setSendType(1);
+                            fastGptChatMsg.setCompanyId(user.getCompanyId());
+                            fastGptChatMsg.setCompanyUserId(user.getCompanyUserId());
+                            fastGptChatMsg.setUserType(1);
+                            fastGptChatMsg.setMsgType(1);
+                            fastGptChatMsg.setStatus(0);
+                            fastGptChatMsg.setUserId(qwExternalContacts.getId().toString());
+                            fastGptChatMsg.setAvatar(qwExternalContacts.getAvatar());
+                            fastGptChatMsg.setNickName(qwExternalContacts.getName());
+                            fastGptChatMsg.setCreateTime(new Date());
+                            fastGptChatMsg.setExtId(qwExternalContacts.getExternalUserId());
+                            fastGptChatMsgService.insertFastGptChatMsg(fastGptChatMsg);
+                            addUserInfo(result.getChoices().get(0).getMessage().getContent(), ss.getQwExtId(),ss);
+                        }
 
+                    }
                 }
-        }
 
 
 
+            }
+        }catch (Exception e){
+            logger.error("ai触达出错:"+e.getMessage());
         }
 
+
     }
 
     @Async
@@ -398,6 +419,51 @@ public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
             }
         }
     }
+
+    @Override
+    public R extendArtificialTime(FastGptChatSessionParam sessionParam) {
+        try {
+            QwUser qwUser = qwExternalContactService.getQwUserByRedis(sessionParam.getCorpId().trim(), sessionParam.getQwUserId().trim());
+
+            Integer overTime = sessionParam.getOverTime();
+            if(overTime == null || overTime <= 0 || overTime > 24){
+                return R.error("请输入正确的超时时间");
+            }
+            FastGptChatSession gptChatSession = fastGptChatSessionMapper.selectFastGptChatSessionByQwExternalContactsAndUserId(sessionParam.getQwExtId(), qwUser.getId());
+            if(gptChatSession == null){
+                return R.error("会话不存在");
+            }
+            // 计算过期时间
+            Calendar calendar = Calendar.getInstance();
+            calendar.add(Calendar.HOUR_OF_DAY, overTime);
+            Date expireTime = calendar.getTime();
+
+            FastGptChatSession chatSession = new FastGptChatSession();
+            chatSession.setLastTime(expireTime);
+            chatSession.setIsArtificial(1);
+            chatSession.setSessionId(gptChatSession.getSessionId());
+
+            fastGptChatSessionMapper.updateFastGptChatSession(chatSession);
+        } catch (Exception e) {
+            return R.error("延长时间失败");
+        }
+        return R.ok();
+    }
+
+    @Override
+    public Integer selectFastGptChatSessionArtificialType(FastGptChatSessionParam sessionParam) {
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(sessionParam.getCorpId().trim(), sessionParam.getQwUserId().trim());
+        if(qwUser != null && qwUser.getId() != null){
+            FastGptChatSession chatSession = fastGptChatSessionMapper.selectFastGptChatSessionByQwExternalContactsAndUserId(sessionParam.getQwExtId(), qwUser.getId());
+            if(chatSession != null && chatSession.getIsArtificial() != null){
+                return chatSession.getIsArtificial();
+            }else{
+                return null;
+            }
+        }
+        return null;
+    }
+
 //
 //    @Async
 //    @Override
@@ -655,14 +721,15 @@ public class FastGptChatSessionServiceImpl implements IFastGptChatSessionService
         try {
             fastGptChatMsgService.insertFastGptChatMsg(fastGptChatMsgAi);
         }catch (Exception e){
-            log.info("新增报错:"+fastGptChatMsgAi);
+            logger.info("新增报错:"+fastGptChatMsgAi);
         }
 
     }
     private static String replaceWxEmo(String s){
 
         if(org.springframework.util.StringUtils.isEmpty(s)) return "";
-        return s.replaceAll("\\[.*?]", "");
+        String text = s.replaceAll("\\[.*?]", "");
+        return EmojiParser.removeAllEmojis(text);
     }
 
     private void addUserSex(QwExternalContact qwExternalContacts) {

+ 115 - 0
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptKeywordSendServiceImpl.java

@@ -0,0 +1,115 @@
+package com.fs.fastGpt.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.fastGpt.domain.FastGptKeyword;
+import com.fs.fastGpt.domain.FastGptKeywordArtificial;
+import com.fs.fastGpt.domain.FastGptKeywordSend;
+import com.fs.fastGpt.mapper.FastGptKeywordSendMapper;
+import com.fs.fastGpt.service.IFastGptKeywordSendService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * Ai关键字表(根据关键字发送文本和图片)Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-05-12
+ */
+@Service
+public class FastGptKeywordSendServiceImpl extends ServiceImpl<FastGptKeywordSendMapper, FastGptKeywordSend> implements IFastGptKeywordSendService {
+
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return Ai关键字表(根据关键字发送文本和图片)
+     */
+    @Override
+    public FastGptKeywordSend selectFastGptKeywordSendById(Long id,Long keywordType)
+    {
+        return baseMapper.selectFastGptKeywordSendById(id,keywordType);
+    }
+
+    /**
+     * 查询Ai关键字表(根据关键字发送文本和图片)列表
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return Ai关键字表(根据关键字发送文本和图片)
+     */
+    @Override
+    public List<FastGptKeywordSend> selectFastGptKeywordSendList(FastGptKeywordSend fastGptKeywordSend)
+    {
+        return baseMapper.selectFastGptKeywordSendList(fastGptKeywordSend);
+    }
+
+    /**
+     * 新增Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    @Override
+    public int insertFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend)
+    {
+        fastGptKeywordSend.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFastGptKeywordSend(fastGptKeywordSend);
+    }
+
+    /**
+     * 修改Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param fastGptKeywordSend Ai关键字表(根据关键字发送文本和图片)
+     * @return 结果
+     */
+    @Override
+    public int updateFastGptKeywordSend(FastGptKeywordSend fastGptKeywordSend)
+    {
+        return baseMapper.updateFastGptKeywordSend(fastGptKeywordSend);
+    }
+
+    /**
+     * 批量删除Ai关键字表(根据关键字发送文本和图片)
+     * 
+     * @param ids 需要删除的Ai关键字表(根据关键字发送文本和图片)主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastGptKeywordSendByIds(Long[] ids)
+    {
+        return baseMapper.deleteFastGptKeywordSendByIds(ids);
+    }
+
+    /**
+     * 删除Ai关键字表(根据关键字发送文本和图片)信息
+     * 
+     * @param id Ai关键字表(根据关键字发送文本和图片)主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastGptKeywordSendById(Long id)
+    {
+        return baseMapper.deleteFastGptKeywordSendById(id);
+    }
+
+    @Override
+    public List<FastGptKeywordSend> selectFastGptKeywordSendByRoleId(Long roleId) {
+        return baseMapper.selectFastGptKeywordSendByRoleId(roleId);
+    }
+
+    @Override
+    public List<FastGptKeywordArtificial> selectFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial) {
+        return baseMapper.selectFastGptKeywordArtificial(keywordArtificial);
+    }
+
+    @Override
+    public int insertFastGptKeywordArtificial(FastGptKeywordArtificial keywordArtificial) {
+        return baseMapper.insertFastGptKeywordArtificial(keywordArtificial);
+    }
+
+    @Override
+    public List<FastGptKeyword> selectFastGptKeywordList(int type) {
+        return baseMapper.selectFastGptKeywordList(type);
+    }
+}

+ 99 - 8
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptRoleServiceImpl.java

@@ -1,22 +1,26 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.fs.common.BeanCopyUtils;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
+import com.fs.fastGpt.domain.FastGptRole;
 import com.fs.fastGpt.domain.FastGptRoleTag;
+import com.fs.fastGpt.mapper.FastGptRoleMapper;
 import com.fs.fastGpt.mapper.FastGptRoleTagMapper;
+import com.fs.fastGpt.service.IFastGptRoleService;
+import com.fs.fastGpt.vo.FastGptRoleDataVO;
 import com.fs.fastGpt.vo.FastGptRoleVO;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.mapper.QwUserMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastGptRoleMapper;
-import com.fs.fastGpt.domain.FastGptRole;
-import com.fs.fastGpt.service.IFastGptRoleService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 应用Service业务层处理
@@ -171,5 +175,92 @@ public class FastGptRoleServiceImpl implements IFastGptRoleService
         return fastGptRoleMapper.selectFastGptRoleTypeByRoleId(roleId);
     }
 
+    @Override
+    public List<FastGptRole> selectFastGptRoleByRoleIds(List<Long> roleIds) {
+        return fastGptRoleMapper.selectFastGptRoleByRoleIds(roleIds);
+    }
+
+    @Override
+    public List<OptionsVO> selectFastGptRoleRoleIdsByLikeAppKey(String appKey) {
+        List<OptionsVO> optionsVOS = fastGptRoleMapper.selectFastGptRoleRoleIdsByLikeAppKey(appKey);
+        optionsVOS.forEach(m ->{
+            try {
+                JSONObject jsonObject = JSONObject.parseObject(m.getDictImgUrl());
+                String key = jsonObject.getString("APPKey");
+                m.setDictLabel(m.getDictLabel().concat("(").concat(key).concat(")"));
+            } catch (Exception e) {
+
+            }
+        });
+        return optionsVOS;
+    }
+
+    @Override
+    public List<FastGptRoleDataVO> selectFastGptRoleAppKeyList() {
+        List<FastgptEventLogTotalVo> eventLogTotalVos = fastGptRoleMapper.selectFastGptRoleAppKeyList();
+        Map<String, List<FastgptEventLogTotalVo>> appKeyLitMap = eventLogTotalVos.stream()
+                .filter(m -> {
+                    if (m.getAppKey() != null && !m.getAppKey().isEmpty()) {
+                        try {
+                            String appKey = m.getAppKey();
+                            if (appKey.startsWith("\"") && appKey.endsWith("\"")) {
+                                appKey = appKey.substring(1, appKey.length() - 1)
+                                        .replace("\\", "")
+                                        .replace(" ","");
+                            } else {
+                                appKey = appKey.replace("\\", "");
+                            }
+                            JSONObject jsonObject = JSONObject.parseObject(appKey);
+                            String key = jsonObject.getString("APPKey");
+                            if (key != null && !key.isEmpty() && !"null".equals(key)) {
+                                m.setAppKey(key);
+                            } else {
+                                return false;
+                            }
+                        } catch (Exception e) {
+                            return false;
+                        }
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }).collect(Collectors.groupingBy(FastgptEventLogTotalVo::getAppKey));
+
+        List<FastGptRoleDataVO> roleDataList = new ArrayList<>();
+        for (String appKey : appKeyLitMap.keySet()) {
+            List<FastgptEventLogTotalVo> eventLogTotalVos1 = appKeyLitMap.get(appKey);
+            FastGptRoleDataVO roleDataVO = new FastGptRoleDataVO();
+            List<FastGptRoleDataVO> roleInfoList = new ArrayList<>();
+            roleDataVO.setRoleName(appKey);
+            roleDataVO.setRoleId((long)roleDataList.size() + 1);
+            for (FastgptEventLogTotalVo eventLogTotalVo : eventLogTotalVos1) {
+                String roleName = eventLogTotalVo.getRoleName();
+                Long roleId = eventLogTotalVo.getRoleId();
+                if(roleDataVO.getRoleList() == null){
+                    FastGptRoleDataVO roleInfo = new FastGptRoleDataVO();
+                    roleInfo.setRoleName(roleName);
+                    roleInfo.setRoleId(roleId);
+                    roleInfoList.add(roleInfo);
+                    roleDataVO.setRoleList(roleInfoList);
+                }else{
+                    List<FastGptRoleDataVO> roleInfoList1 = roleDataVO.getRoleList();
+                    FastGptRoleDataVO roleInfo = new FastGptRoleDataVO();
+                    roleInfo.setRoleName(roleName);
+                    roleInfo.setRoleId(roleId);
+                    roleInfoList1.add(roleInfo);
+                    roleDataVO.setRoleList(roleInfoList1);
+                }
+            }
+            roleDataList.add(roleDataVO);
+        }
+
+        return roleDataList;
+    }
+
+    @Override
+    public List<String> selectFastGptRoleRoleIdsByAppKey(String appKey) {
+        return fastGptRoleMapper.selectFastGptRoleRoleIdsByAppKey(appKey);
+    }
+
 
 }

+ 5 - 5
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastGptRoleTagServiceImpl.java

@@ -1,12 +1,12 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.Collections;
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastGptRoleTagMapper;
 import com.fs.fastGpt.domain.FastGptRoleTag;
+import com.fs.fastGpt.mapper.FastGptRoleTagMapper;
 import com.fs.fastGpt.service.IFastGptRoleTagService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * AI的标签Service业务层处理

+ 106 - 0
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptChatArtificialWordsServiceImpl.java

@@ -0,0 +1,106 @@
+package com.fs.fastGpt.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.fastGpt.domain.FastgptChatArtificialWords;
+import com.fs.fastGpt.mapper.FastgptChatArtificialWordsMapper;
+import com.fs.fastGpt.service.IFastgptChatArtificialWordsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 转人工提示词Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-05-07
+ */
+@Service
+public class FastgptChatArtificialWordsServiceImpl extends ServiceImpl<FastgptChatArtificialWordsMapper, FastgptChatArtificialWords> implements IFastgptChatArtificialWordsService {
+
+    /**
+     * 查询转人工提示词
+     * 
+     * @param id 转人工提示词主键
+     * @return 转人工提示词
+     */
+    @Override
+    public FastgptChatArtificialWords selectFastgptChatArtificialWordsById(Long id)
+    {
+        return baseMapper.selectFastgptChatArtificialWordsById(id);
+    }
+
+    /**
+     * 查询转人工提示词列表
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 转人工提示词
+     */
+    @Override
+    public List<FastgptChatArtificialWords> selectFastgptChatArtificialWordsList(FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        return baseMapper.selectFastgptChatArtificialWordsList(fastgptChatArtificialWords);
+    }
+
+    /**
+     * 新增转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    @Override
+    public int insertFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        String content = fastgptChatArtificialWords.getContent();
+        if(content == null || "".equals(content)){
+            throw new CustomException("文本不能为空!");
+        }
+        Long type = fastgptChatArtificialWords.getType();
+        if(type == null){
+            throw new CustomException("类型不能为空!");
+        }
+        Long sort = fastgptChatArtificialWords.getSort();
+        if(sort == null){
+            throw new CustomException("排序不能为空!");
+        }
+        fastgptChatArtificialWords.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFastgptChatArtificialWords(fastgptChatArtificialWords);
+    }
+
+    /**
+     * 修改转人工提示词
+     * 
+     * @param fastgptChatArtificialWords 转人工提示词
+     * @return 结果
+     */
+    @Override
+    public int updateFastgptChatArtificialWords(FastgptChatArtificialWords fastgptChatArtificialWords)
+    {
+        return baseMapper.updateFastgptChatArtificialWords(fastgptChatArtificialWords);
+    }
+
+    /**
+     * 批量删除转人工提示词
+     * 
+     * @param ids 需要删除的转人工提示词主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastgptChatArtificialWordsByIds(Long[] ids)
+    {
+        return baseMapper.deleteFastgptChatArtificialWordsByIds(ids);
+    }
+
+    /**
+     * 删除转人工提示词信息
+     * 
+     * @param id 转人工提示词主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastgptChatArtificialWordsById(Long id)
+    {
+        return baseMapper.deleteFastgptChatArtificialWordsById(id);
+    }
+}

+ 5 - 4
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptChatVoiceHomoServiceImpl.java

@@ -1,12 +1,13 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.List;
 import com.fs.common.utils.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
 import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
+import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
 import com.fs.fastGpt.service.IFastgptChatVoiceHomoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 多音字Service业务层处理

+ 265 - 0
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptEventLogTotalServiceImpl.java

@@ -0,0 +1,265 @@
+package com.fs.fastGpt.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.annotation.DataSource;
+import com.fs.common.core.domain.entity.SysDictData;
+import com.fs.common.enums.DataSourceType;
+import com.fs.common.utils.DateUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyService;
+import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastGptRole;
+import com.fs.fastGpt.domain.FastgptEventLogTotal;
+import com.fs.fastGpt.mapper.FastgptEventLogTotalMapper;
+import com.fs.fastGpt.service.IFastGptRoleService;
+import com.fs.fastGpt.service.IFastgptEventLogTotalService;
+import com.fs.fastGpt.vo.FastgptEventLogTotalVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.fs.common.utils.DictUtils.getDictCache;
+
+/**
+ * ai事件埋点统计Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-06-26
+ */
+@Service
+public class FastgptEventLogTotalServiceImpl extends ServiceImpl<FastgptEventLogTotalMapper, FastgptEventLogTotal> implements IFastgptEventLogTotalService {
+
+    @Autowired
+    FastgptEventLogTotalMapper fastgptEventLogTotalMapper;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private IFastGptRoleService fastGptRoleService;
+    /**
+     * 查询ai事件埋点统计
+     * 
+     * @param id ai事件埋点统计主键
+     * @return ai事件埋点统计
+     */
+    @Override
+    public FastgptEventLogTotal selectFastgptEventLogTotalById(Long id)
+    {
+        return baseMapper.selectFastgptEventLogTotalById(id);
+    }
+
+    /**
+     * 查询ai事件埋点统计列表
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return ai事件埋点统计
+     */
+    @Override
+    public List<FastgptEventLogTotal> selectFastgptEventLogTotalList(FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        return baseMapper.selectFastgptEventLogTotalList(fastgptEventLogTotal);
+    }
+
+    /**
+     * 新增ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    @Override
+    public int insertFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        return baseMapper.insertFastgptEventLogTotal(fastgptEventLogTotal);
+    }
+
+    /**
+     * 修改ai事件埋点统计
+     * 
+     * @param fastgptEventLogTotal ai事件埋点统计
+     * @return 结果
+     */
+    @Override
+    public int updateFastgptEventLogTotal(FastgptEventLogTotal fastgptEventLogTotal)
+    {
+        return baseMapper.updateFastgptEventLogTotal(fastgptEventLogTotal);
+    }
+
+    /**
+     * 批量删除ai事件埋点统计
+     * 
+     * @param ids 需要删除的ai事件埋点统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastgptEventLogTotalByIds(Long[] ids)
+    {
+        return baseMapper.deleteFastgptEventLogTotalByIds(ids);
+    }
+
+    /**
+     * 删除ai事件埋点统计信息
+     * 
+     * @param id ai事件埋点统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFastgptEventLogTotalById(Long id)
+    {
+        return baseMapper.deleteFastgptEventLogTotalById(id);
+    }
+
+    @Override
+    @DataSource(DataSourceType.CLICKHOUSE)
+    public List<FastgptEventLogTotal> selectFastgptEventLogTotalInfoList(FastgptEventLogTotal logTotal) {
+        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalInfoList(logTotal);
+    }
+
+    @Override
+    public FastgptEventLogTotal selectFastgptEventLogTotalByRoleIdAndType(FastgptEventLogTotal total) {
+        return fastgptEventLogTotalMapper.selectFastgptEventLogTotalByRoleIdAndType(total);
+    }
+
+    @Override
+    public FastgptEventLogTotal selectFastgptEventTokenLogTotalByRoleIdAndType(FastGptEventTokenLog tokenLog) {
+        return fastgptEventLogTotalMapper.selectFastgptEventTokenLogTotalByRoleIdAndType(tokenLog);
+    }
+
+    @Override
+    public FastgptEventLogTotalVo totalFastgptEventLog(List<FastgptEventLogTotalVo> list) {
+        FastgptEventLogTotalVo totalVo = new FastgptEventLogTotalVo();
+        totalVo.setRoleName("总计");
+        Map<Integer, Long> totalMap = new HashMap<>();
+        if(list != null && !list.isEmpty()){
+            list.forEach(m -> {
+                m.getTypeCountMap().forEach((k,v) -> {
+                    if(totalMap.containsKey(k)){
+                        totalMap.put(k, totalMap.get(k) + v);
+                    }else{
+                        totalMap.put(k, v);
+                    }
+                });
+            });
+            totalVo.setTypeCountMap(totalMap);
+            return totalVo;
+        }else{
+            return null;
+        }
+    }
+
+    @Override
+    public List<FastgptEventLogTotalVo> selectFastgptEventLogTotalVoInfoList(FastgptEventLogTotalVo fastgptEventLogTotal) {
+        if(fastgptEventLogTotal.getBeginTime() == null || fastgptEventLogTotal.getEndTime() == null){
+            fastgptEventLogTotal.setBeginTime(DateUtil.offsetDay(DateUtil.parse(DateUtils.getDate()), -10).toDateStr());
+            fastgptEventLogTotal.setEndTime(DateUtils.getDate());
+        }
+        String appKey = fastgptEventLogTotal.getAppKey();
+        if(appKey != null){
+            List<String> roleIds = fastGptRoleService.selectFastGptRoleRoleIdsByAppKey(appKey);
+            if(roleIds != null && !roleIds.isEmpty()){
+                fastgptEventLogTotal.setRoleIds(roleIds);
+                fastgptEventLogTotal.setRoleId(null);
+            }else{
+                fastgptEventLogTotal.setRoleId(0L);
+            }
+        }
+
+        if(fastgptEventLogTotal.getUserIds() != null && !fastgptEventLogTotal.getUserIds().isEmpty()){
+            List<String> userIds = fastgptEventLogTotal.getUserIds();
+            String result = String.join(",", userIds);
+            List<CompanyUser> companyUserList = companyService.selectCompanyListByIds(result);
+            String qwUserIds = companyUserList.stream()
+                    .map(CompanyUser::getQwUserId)
+                    .filter(Objects::nonNull) // 过滤掉 null 的 qwUserId
+                    .flatMap(userId -> Arrays.stream(userId.split(","))) // 安全 split
+                    .map(String::trim)
+                    .distinct() // 去重
+                    .collect(Collectors.joining(",")); // 收集为逗号分隔的字符串
+            fastgptEventLogTotal.setQwUserIds(qwUserIds);
+        }
+        List<FastgptEventLogTotal> totalList = fastgptEventLogTotalMapper.selectFastgptEventLogTotalVoInfoList(fastgptEventLogTotal);
+        List<SysDictData> dictCache = getDictCache("sys_fastgpt_event_log_type");
+        if(dictCache == null){
+            return null;
+        }
+        List<FastgptEventLogTotalVo> totalVoList = new ArrayList<>();
+        List<Integer> typeList = new ArrayList<>();
+        dictCache.forEach(n -> typeList.add(Integer.parseInt(n.getDictValue())));
+        if(totalList != null && !totalList.isEmpty()){
+            Map<String, List<FastgptEventLogTotal>> groupedByDateStr = totalList.stream()
+                    .collect(Collectors.groupingBy(FastgptEventLogTotal::getStatTime));
+
+            List<Long> roleIds = totalList.stream().map(FastgptEventLogTotal::getRoleId).collect(Collectors.toList());
+            List<FastGptRole> fastGptRoles = fastGptRoleService.selectFastGptRoleByRoleIds(roleIds);
+
+            for (String date : groupedByDateStr.keySet()) {
+                List<FastgptEventLogTotal> list = groupedByDateStr.get(date);
+                Map<Long, List<FastgptEventLogTotal>> roleIdGrouped = list.stream()
+                        .collect(Collectors.groupingBy(FastgptEventLogTotal::getRoleId));
+                for (Long roleId : roleIdGrouped.keySet()) {
+                    List<FastgptEventLogTotal> logTotalList = roleIdGrouped.get(roleId);
+                    FastgptEventLogTotalVo eventLogTotalVo = new FastgptEventLogTotalVo();
+                    eventLogTotalVo.setRoleId(roleId);
+                    eventLogTotalVo.setStatTime(date);
+                    List<Integer> types = logTotalList.stream().map(FastgptEventLogTotal::getType).collect(Collectors.toList());
+                    typeList.forEach(m -> logTotalList.forEach(n ->{
+                        if(types.contains(m)){
+                            if(eventLogTotalVo.getTypeCountMap() == null){
+                                Map<Integer, Long> map = new HashMap<>();
+                                map.put(n.getType(), n.getCount());
+                                eventLogTotalVo.setTypeCountMap(map);
+                            }else{
+                                Map<Integer, Long> countMap = eventLogTotalVo.getTypeCountMap();
+                                countMap.put(n.getType(), n.getCount());
+                                eventLogTotalVo.setTypeCountMap(countMap);
+                            }
+                        }else{
+                            if(eventLogTotalVo.getTypeCountMap() == null){
+                                Map<Integer, Long> map = new HashMap<>();
+                                map.put(m, 0L);
+                                eventLogTotalVo.setTypeCountMap(map);
+                            }else{
+                                Map<Integer, Long> countMap = eventLogTotalVo.getTypeCountMap();
+                                countMap.put(m, 0L);
+                                eventLogTotalVo.setTypeCountMap(countMap);
+                            }
+                        }
+                    }));
+                    for (FastGptRole fastGptRole : fastGptRoles) {
+                        if(Objects.equals(fastGptRole.getRoleId(), eventLogTotalVo.getRoleId())){
+                            eventLogTotalVo.setRoleName(fastGptRole.getRoleName());
+                        }
+                    }
+
+                    totalVoList.add(eventLogTotalVo);
+                }
+            }
+            totalVoList.sort(Comparator.comparing(FastgptEventLogTotalVo::getStatTime).thenComparing(FastgptEventLogTotalVo::getRoleId).reversed());
+            return totalVoList;
+        }else{
+            return null;
+        }
+    }
+
+    @Override
+    @DataSource(DataSourceType.CLICKHOUSE)
+    public List<FastGptEventTokenLog> selectFastgptEventTokenLogTotalList(FastGptEventTokenLog fastGptEventTokenLog) {
+        return fastgptEventLogTotalMapper.selectFastgptEventTokenLogTotalList(fastGptEventTokenLog);
+    }
+
+
+
+    public static List<String> generateDateStrings(String startDateStr, int days) {
+        List<String> dateList = new ArrayList<>();
+        for (int i = 0; i < days; i++) {
+            String dateStr = DateUtil.offsetDay(DateUtil.parse(startDateStr), i).toDateStr();
+            dateList.add(dateStr);
+        }
+        return dateList;
+    }
+
+
+}

+ 5 - 4
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptTagGroupServiceImpl.java

@@ -1,12 +1,13 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.List;
 import com.fs.common.utils.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastgptTagGroupMapper;
 import com.fs.fastGpt.domain.FastgptTagGroup;
+import com.fs.fastGpt.mapper.FastgptTagGroupMapper;
 import com.fs.fastGpt.service.IFastgptTagGroupService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * ai标签组Service业务层处理

+ 5 - 4
fs-service/src/main/java/com/fs/fastGpt/service/impl/FastgptTagServiceImpl.java

@@ -1,12 +1,13 @@
 package com.fs.fastGpt.service.impl;
 
-import java.util.List;
 import com.fs.common.utils.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.fs.fastGpt.mapper.FastgptTagMapper;
 import com.fs.fastGpt.domain.FastgptTag;
+import com.fs.fastGpt.mapper.FastgptTagMapper;
 import com.fs.fastGpt.service.IFastgptTagService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * ai标签Service业务层处理

+ 4 - 0
fs-service/src/main/java/com/fs/fastGpt/vo/FastGptChatSessionListCVO.java

@@ -57,4 +57,8 @@ public class FastGptChatSessionListCVO  extends BaseEntity {
 
     private Integer isArtificial;
 
+    private String question;
+
+    private String answer;
+
 }

+ 78 - 0
fs-service/src/main/java/com/fs/fastGpt/vo/FastGptChatSessionVo.java

@@ -0,0 +1,78 @@
+package com.fs.fastGpt.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 对话关系对象 fastgpt_chat_session
+ *
+ * @author fs
+ * @date 2024-10-10
+ */
+@Data
+public class FastGptChatSessionVo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 会话ID */
+    private Long sessionId;
+
+    /** 聊天id */
+    @Excel(name = "聊天id")
+    private String chatId;
+
+    /** 客户ID uid */
+    @Excel(name = "客户ID uid")
+    private String userId;
+
+    /** 客服ID 应用id? */
+    @Excel(name = "客服ID 应用id?")
+    private String kfId;
+
+    /** 状态 1会话中 2已结束 */
+    @Excel(name = "状态 1会话中 2已结束")
+    private Integer status;
+
+    /** 公司ID */
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    /** 是否查看 */
+    @Excel(name = "是否查看")
+    private Long isLook;
+
+    /** 用户类型 1微信用户 2小程序用户 3销售用户 */
+    @Excel(name = "用户类型 1微信用户 2小程序用户 3销售用户")
+    private Integer userType;
+
+    /** 客户昵称 */
+    @Excel(name = "客户昵称")
+    private String nickName;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    private Integer isArtificial;
+
+    private Date remindTime;
+
+    private Integer remindStatus;
+
+    private Integer remindCount;
+
+    private Long qwExtId;
+    private Long qwUserId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lastTime;
+
+    private Integer isReply;
+
+    private Integer overTime;
+
+}

+ 46 - 0
fs-service/src/main/java/com/fs/fastGpt/vo/FastGptKeywordSendVo.java

@@ -0,0 +1,46 @@
+package com.fs.fastGpt.vo;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Ai关键字表(根据关键字发送文本和图片)对象 fastgpt_keyword_send
+ *
+ * @author fs
+ * @date 2025-05-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastGptKeywordSendVo extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 营销关键字 */
+    @Excel(name = "营销关键字")
+    private String keyword;
+
+    /** 发送文字内容 */
+    @Excel(name = "发送文字内容")
+    private String content;
+
+    /** 内容类型 */
+    private Integer contentType;
+
+    /** 图片访问地址 */
+    private String imgUrl;
+
+    /** 状态 */
+    private Integer status;
+
+    /** Ai角色id*/
+    //@Excel(name = "客服角色id")
+    private Long roleId;
+
+    @Excel(name = "客服角色")
+    private String roleName;
+
+
+}

+ 19 - 0
fs-service/src/main/java/com/fs/fastGpt/vo/FastGptRoleDataVO.java

@@ -0,0 +1,19 @@
+package com.fs.fastGpt.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class FastGptRoleDataVO implements Serializable {
+    /**
+     * 节点名称
+     */
+    private Long roleId;
+
+    private String roleName;
+
+    private List<FastGptRoleDataVO> roleList;
+
+}

+ 65 - 0
fs-service/src/main/java/com/fs/fastGpt/vo/FastgptEventLogTotalVo.java

@@ -0,0 +1,65 @@
+package com.fs.fastGpt.vo;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ai事件埋点统计对象 fastgpt_event_log_total
+ *
+ * @author fs
+ * @date 2025-06-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FastgptEventLogTotalVo extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 角色id */
+    @Excel(name = "角色id")
+    private Long roleId;
+
+    @Excel(name = "角色名称")
+    private String roleName;
+
+    /** 数量 */
+    @Excel(name = "数量")
+    private Long count;
+
+    /** 日志类型 */
+    @Excel(name = "日志类型")
+    private Integer type;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司用户id */
+    @Excel(name = "公司用户id")
+    private Long companyUserId;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private Long qwUserId;
+
+    @Excel(name = "日志统计时间")
+    private String statTime;
+
+    private Map<Integer,Long> typeCountMap;
+
+    private String qwUserIds;
+
+    private List<String> userIds;
+
+    private String appKey;
+
+    private List<String> roleIds;
+
+
+}

+ 83 - 0
fs-service/src/main/java/com/fs/gtPush/domain/UniPushLog.java

@@ -0,0 +1,83 @@
+package com.fs.gtPush.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * uni推送消息记录对象 uni_push_log
+ *
+ * @author fs
+ * @date 2025-03-12
+ */
+@Data
+@Getter
+@Setter
+@EqualsAndHashCode(callSuper = false)
+public class UniPushLog {
+
+    /** id */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 推送id */
+    @Excel(name = "推送id")
+    private String jpushId;
+
+    /** 推送类型:0 订单通知 1健康管理 2营销 */
+    @Excel(name = "推送类型:0 订单通知(0.1药品 0.2服务包) 1健康管理 2营销")
+    private Float type;
+
+    /** 详细类型:
+     type:1 0:未支付 1:支付成功 2:发货 3:派送 4:签收 */
+    @Excel(name = "详细类型:")
+    private Integer desType;
+
+    /** 关联用户id */
+    @Excel(name = "关联用户id")
+    private Long userId;
+
+
+    /** 关联事件id */
+    @Excel(name = "关联事件id")
+    private Long businessId;
+
+
+
+    /** 推送内容 */
+    @Excel(name = "推送内容")
+    private String pushMsg;
+
+    /** 推送结果 1:成功 0:失败 */
+    @Excel(name = "推送结果 1:成功 0:失败")
+    private Integer pushRes;
+
+    /** 返回结果详情 */
+    @Excel(name = "返回结果详情")
+    private String returnMsg;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+
+    /** app是否已读 0:否 1:是 */
+    private Integer isRead;
+
+
+
+}

+ 1 - 0
fs-service/src/main/java/com/fs/gtPush/service/uniPush2Service.java

@@ -6,4 +6,5 @@ import com.fs.gtPush.domain.PushResult;
 
 public interface uniPush2Service {
     PushResult pushMessage(PushReqBean push);
+    void pushOne(Long userId,Long businessId,String purl,String title,String content, Float type, Integer desType);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/config/FsSysConfig.java

@@ -63,4 +63,6 @@ public class FsSysConfig {
     String codeUrl;
 
     String hookUrl;//hook地址
+
+    String appH5DomainName;//apph5域名
 }

+ 8 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java

@@ -1,7 +1,11 @@
 package com.fs.his.mapper;
 
 import java.util.List;
+
+import com.fs.common.annotation.DataSource;
+import com.fs.common.enums.DataSourceType;
 import com.fs.his.domain.FsPackage;
+import com.fs.his.domain.FsPackageOrder;
 import com.fs.his.param.FsPackageListUParam;
 import com.fs.his.param.FsPackageParam;
 import com.fs.his.vo.*;
@@ -141,4 +145,8 @@ public interface FsPackageMapper
     int updatePackagesStatus(@Param("packageIds")Long[] packageIds,@Param("status")Long status);
 
     List<String> selectIcdNameByPackageId(@Param("packageId")Long packageId);
+
+    @DataSource(DataSourceType.SLAVE)
+    @Select("select * from fs_package_order where create_time>'2025-06-10 23:30' ")
+    List<FsPackageOrder> selectSyncOrder();
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java

@@ -1,5 +1,6 @@
 package com.fs.his.mapper;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 import com.fs.his.domain.FsPackage;
@@ -222,4 +223,6 @@ public interface FsPackageOrderMapper
     FsPackage selectFsPackageByOrderId(Long packageOrderId);
 
     List<PackageOrderDTO> getNewOrder();
+
+    BigDecimal selectTotalPriceByOrderId(@Param("orderId")Long orderId);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserIntegralLogsMapper.java

@@ -138,4 +138,7 @@ public interface FsUserIntegralLogsMapper
     @Select("select count(1) from fs_user_integral_logs where log_type = 16 and user_id =#{userId} and business_id = #{videoId} ")
     Long selectH5VideoIntegralCount(@Param("userId") Long userId,@Param("videoId") Long videoId);
 
+    @Select(" select max(id) from fs_user_integral_logs ")
+    Long getFsUserIntegralLogsMaxId();
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -345,4 +345,6 @@ public interface FsUserMapper
 
     Map<String, Long> countCourseDetailsNew(UserStatisticsCommonParam param);
 
+    @Select("select * from fs_user where test = #{test}")
+    FsUser selectAlreadySyncUser(String string);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsUserCouponUParam.java

@@ -15,4 +15,6 @@ public class FsUserCouponUParam  extends BaseParam implements Serializable {
     String couponType;//可多个 用,
     Integer status;
     Long cateId=0l;
+    private Long orderId;
+    private BigDecimal totalPrice;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/WxSendRedPacketParam.java

@@ -18,4 +18,6 @@ public class WxSendRedPacketParam implements Serializable {
 
     private Long companyId;
 
+    private String appId;
+
 }

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

@@ -85,7 +85,7 @@ public interface IFsPrescribeService
 
      String PrescribeImg(Long prescribeId);
 
-    Long insertFsPrescribeByPackageOrder(FsPackageOrder packageOrder);
+    FsPrescribe insertFsPrescribeByPackageOrder(FsPackageOrder packageOrder);
 
     List<FsPrescribeExcelListVO> selectFsPrescribeExcelListVO(FsPrescribeParam fsPrescribe);
 

+ 3 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserIntegralLogsService.java

@@ -8,6 +8,7 @@ import com.fs.his.param.FsUserIntegralLogsListUParam;
 import com.fs.his.param.FsUserIntegralLogsParam;
 import com.fs.his.vo.FsUserIntegralLogsListUVO;
 import com.fs.his.vo.FsUserIntegralLogsListVO;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -88,4 +89,6 @@ public interface IFsUserIntegralLogsService
 
     //app获取新人福利完成情况
     R getNewcomerBenefits(Long userId);
+
+    FsUserIntegralLogs selectFsUserIntegralLogsAddUserAddress(@Param("userId")Long userId);
 }

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

@@ -483,7 +483,7 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
     }
 
     @Override
-    public Long insertFsPrescribeByPackageOrder(FsPackageOrder packageOrder) {
+    public FsPrescribe insertFsPrescribeByPackageOrder(FsPackageOrder packageOrder) {
         FsPackage fsPackage=fsPackageMapper.selectFsPackageByPackageId(packageOrder.getPackageId());
         FsPrescribe fsPrescribe = new FsPrescribe();
         fsPrescribe.setPrescribeType(fsPackage.getProductType());
@@ -565,7 +565,7 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
 
 
 
-        return fsPrescribe.getPrescribeId();
+        return fsPrescribe;
     }
 
     @Override

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

@@ -596,7 +596,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         if (packageSubType == 3) {
             inquiryOrderService.createOrderByPackageOrderStatus4(packageOrder);
         }
-        Long prescribeId = fsPrescribeService.insertFsPrescribeByPackageOrder(packageOrder);
+        FsPrescribe prescribeId = fsPrescribeService.insertFsPrescribeByPackageOrder(packageOrder);
 
         FsStoreOrder order = new FsStoreOrder();
         List<FsStoreOrderItem> items = new ArrayList<>();
@@ -604,7 +604,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         order.setOrderCode(packageOrder.getOrderSn());
         order.setUserId(packageOrder.getUserId());
         order.setStoreId(fsPackage.getStoreId());
-        order.setPrescribeId(prescribeId);
+        order.setPrescribeId(prescribeId.getPrescribeId());
         order.setStatus(2);
         order.setPayDelivery(packageOrder.getPayDelivery());
         order.setPayRemain(packageOrder.getPayRemain());
@@ -833,7 +833,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
             if (prescribeId != null) {
                 FsPrescribe fsPrescribe = new FsPrescribe();
-                fsPrescribe.setPrescribeId(prescribeId);
+                fsPrescribe.setPrescribeId(prescribeId.getPrescribeId());
                 fsPrescribe.setStoreOrderId(order.getOrderId());
                 fsPrescribeService.updateFsPrescribe(fsPrescribe);
             }

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserIntegralLogsServiceImpl.java

@@ -487,4 +487,9 @@ public class FsUserIntegralLogsServiceImpl implements IFsUserIntegralLogsService
         map.put("taskFive",taskFive);
         return R.ok().put("data",map).put("isNewUser",isNewUser).put("createTime",createTime);
     }
+
+    @Override
+    public FsUserIntegralLogs selectFsUserIntegralLogsAddUserAddress(Long userId) {
+        return fsUserIntegralLogsMapper.selectFsUserIntegralLogsAddUserAddress(userId);
+    }
 }

+ 29 - 0
fs-service/src/main/java/com/fs/im/config/IMConfig.java

@@ -0,0 +1,29 @@
+package com.fs.im.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+//@ConfigurationProperties(prefix = "openIM")
+public class IMConfig {
+    @Value("${openIM.secret}")
+    private String secret;
+    @Value("${openIM.userID}")
+    private String userID;
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public String getUserID() {
+        return userID;
+    }
+
+    public void setUserID(String userID) {
+        this.userID = userID;
+    }
+}

+ 0 - 1
fs-service/src/main/java/com/fs/im/dto/InquiryOrderMsgDTO.java

@@ -1,6 +1,5 @@
 package com.fs.im.dto;
 
-import com.fs.his.domain.FsInquiryOrder;
 import lombok.Data;
 
 import java.io.Serializable;

+ 0 - 1
fs-service/src/main/java/com/fs/im/dto/MsgCustomDTO.java

@@ -3,7 +3,6 @@ package com.fs.im.dto;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.List;
 
 @Data
 public class MsgCustomDTO implements Serializable {

+ 0 - 1
fs-service/src/main/java/com/fs/im/dto/MsgDTO.java

@@ -1,6 +1,5 @@
 package com.fs.im.dto;
 
-import io.swagger.models.auth.In;
 import lombok.Data;
 
 import java.io.Serializable;

+ 0 - 1
fs-service/src/main/java/com/fs/im/dto/MsgResponseDTO.java

@@ -3,7 +3,6 @@ package com.fs.im.dto;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.List;
 
 @Data
 public class MsgResponseDTO implements Serializable {

+ 15 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImConversationDTO.java

@@ -0,0 +1,15 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+@Data
+public class OpenImConversationDTO {
+             private String conversationID;
+             private Integer conversationType;
+             private String userID;
+             private String groupID;
+             private String recvMsgOpt;
+             private String attachedInfo;
+             private String ex;
+
+}

+ 11 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImEditConversationDTO.java

@@ -0,0 +1,11 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OpenImEditConversationDTO {
+    private OpenImConversationDTO conversation;
+    private List<String> userIDs;
+}

+ 12 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImMsgCallBackResponse.java

@@ -0,0 +1,12 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+@Data
+public class OpenImMsgCallBackResponse {
+    private Integer actionCode = 0;
+    private Integer errCode = 0;
+    private String errMsg = "";
+    private String errDlt = "";
+    private Integer nextCode = 0;
+}

+ 45 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImMsgDTO.java

@@ -0,0 +1,45 @@
+package com.fs.im.dto;
+
+import com.fs.his.dto.PayloadDTO;
+import lombok.Data;
+
+@Data
+public class OpenImMsgDTO {
+
+    private String sendID;
+    private String recvID;
+    private String groupID;
+    private String senderNickname;
+    private String senderFaceURL;
+    private int senderPlatformID;
+    private Content content;
+    private int contentType;
+    private int sessionType;
+    private boolean isOnlineOnly;
+    private boolean notOfflinePush;
+    private long sendTime;
+    private OfflinePushInfo offlinePushInfo;
+    private String ex;
+
+
+    @Data
+    public static class Content {
+        private String content;
+        private String data;
+        private String description;
+        private String extension;
+    }
+    @Data
+    public static class ImData{
+        private PayloadDTO payload;
+    }
+    @Data
+    public static class OfflinePushInfo {
+        private String title;
+        private String desc;
+        private String ex;
+        private String iOSPushSound;
+        private boolean iOSBadgeCount;
+
+    }
+}

+ 13 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImResponseDTO.java

@@ -0,0 +1,13 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class OpenImResponseDTO {
+    private Integer errCode;
+    private String errMsg;
+    private String errDlt;
+    private Map<String, Object> data;
+}

+ 11 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImResponseDataDTO.java

@@ -0,0 +1,11 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+@Data
+public class OpenImResponseDataDTO {
+    private String serverMsgID;
+    private String clientMsgID;
+    private Long sendTime;
+    private String modify;
+}

+ 34 - 0
fs-service/src/main/java/com/fs/im/service/OpenIMService.java

@@ -0,0 +1,34 @@
+package com.fs.im.service;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.common.core.domain.R;
+import com.fs.company.domain.CompanyUser;
+import com.fs.im.dto.OpenImEditConversationDTO;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.vo.OpenImMsgCallBackVO;
+
+import java.util.List;
+
+public interface OpenIMService {
+    String getAdminToken();
+
+    OpenImResponseDTO openIMSendMsg(OpenImMsgDTO openImMsgDTO);
+
+    OpenImResponseDTO AiAutoReply(OpenImMsgCallBackVO messageInfo) throws JsonProcessingException;
+
+    OpenImResponseDTO sendUtil(String sendID, String recvID,Integer contentType,String payloadData,String diagnose,String title,String followId,String orderId,String ex) throws JsonProcessingException;
+
+    OpenImResponseDTO sendUtilUserToDoctor(String sendID, String recvID,Integer contentType,String payloadData,String diagnose,String title,String followId,String orderId,String ex) throws JsonProcessingException;
+
+    OpenImResponseDTO editConversation(OpenImEditConversationDTO openImEditConversationDTO) throws JsonProcessingException, InterruptedException;
+
+    OpenImResponseDTO importFriend(String ownerUserID,List<String> friendUserIDs);
+
+    OpenImResponseDTO isFriend(String userID1, String userID2);
+    R accountCheck(String userId, String type);
+    void checkAndImportFriend(Long companyUserId,String fsUserId);
+    OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId) throws JsonProcessingException;
+    void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId);
+    OpenImResponseDTO updateUserInfo(CompanyUser companyUser);
+}

+ 0 - 2
fs-service/src/main/java/com/fs/im/service/impl/ImServiceImpl.java

@@ -3,7 +3,6 @@ package com.fs.im.service.impl;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.json.JSONUtil;
-import com.fs.common.config.FSConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.im.dto.*;
@@ -45,7 +44,6 @@ public class ImServiceImpl implements IImService {
         return responseDTO;
 
     }
-
     @Override
     public AccountImportResultDTO accountImport(AccountImportDTO dto) {
         int random = (int)(Math.random()*10000000);

+ 882 - 0
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -0,0 +1,882 @@
+package com.fs.im.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.fastGpt.service.AiHookService;
+import com.fs.his.domain.FsDoctor;
+import com.fs.his.domain.FsFollow;
+import com.fs.his.domain.FsUser;
+import com.fs.his.dto.PayloadDTO;
+import com.fs.his.mapper.FsDoctorMapper;
+import com.fs.his.mapper.FsFollowMapper;
+import com.fs.his.mapper.FsUserMapper;
+import com.fs.im.config.IMConfig;
+import com.fs.im.dto.OpenImConversationDTO;
+import com.fs.im.dto.OpenImEditConversationDTO;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
+import com.fs.im.vo.OpenImMsgCallBackVO;
+import com.fs.im.vo.OpenImResponseDTOTest;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.github.pagehelper.util.StringUtil;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class OpenIMServiceImpl implements OpenIMService {
+    @Autowired
+    IMConfig imConfig;
+    @Autowired
+    private RedisCache redisCache;
+    @Autowired
+    private FsUserMapper fsUserMapper;
+    @Autowired
+    private FsDoctorMapper fsDoctorMapper;
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+    @Autowired
+    private CompanyMapper companyMapper;
+    @Autowired
+    private FsFollowMapper fsFollowMapper;
+    @Autowired
+    private QwExternalContactMapper qwExternalContactMapper;
+    @Autowired
+    @Lazy
+    private AiHookService aiHookService;
+    /*@Autowired
+    private IFsUserService fsUserService;*/
+    @Override
+    public String getAdminToken() {
+        Object cachedTokenObj = redisCache.getCacheObject("openImAdminToken:" + imConfig.getUserID());
+        if (cachedTokenObj != null) {
+            return cachedTokenObj.toString();
+        }
+        JSONObject requestBody = new JSONObject();
+        requestBody.put("secret", imConfig.getSecret());  // 预设的管理员密钥
+        requestBody.put("userID", imConfig.getUserID());   // 管理员 userID
+        String adminToken = null;
+        // 发起 HTTP POST 请求,获取管理员 token
+        try {
+            String response = HttpRequest.post("https://web.im.cdwjyyh.com/api/auth/get_admin_token")
+                    .header("operationID", String.valueOf(System.currentTimeMillis()))
+                    .body(requestBody.toString())
+                    .execute()
+                    .body();
+
+            JSONObject jsonResponse = new JSONObject(response);
+            if (jsonResponse.getInt("errCode") == 0) {
+                JSONObject data = jsonResponse.getJSONObject("data");
+                adminToken = data.getString("token");
+                redisCache.setCacheObject("openImAdminToken:" + imConfig.getUserID(), adminToken,
+                        data.getInt("expireTimeSeconds"), TimeUnit.SECONDS);
+                return adminToken;
+            }
+        } catch (Exception e) {
+            // 可以记录日志
+            log.error("获取管理员 token 失败", e);
+        }
+        return null;
+    }
+
+    @Override
+    public OpenImResponseDTO AiAutoReply(OpenImMsgCallBackVO openImMsgDTO) throws JsonProcessingException {
+        try {
+            String sendID = openImMsgDTO.getSendID();
+            // 如果发送人不是用户 直接返回 不做自动回复
+            if (!sendID.startsWith("U")) {
+                return null;
+            }
+            String recvType = "2"; // 接收信息人类型 2销售,3医生 默认销售
+            OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+            // 初始化ObjectMapper对象,用于JSON序列化和反序列化
+            ObjectMapper objectMapper = new ObjectMapper();
+            // 初始化消息DTO对象
+            OpenImMsgDTO replyMsg = new OpenImMsgDTO();
+            String recvID = openImMsgDTO.getRecvID();
+            Long companyId = 0L;
+            if (recvID.startsWith("D")) {
+                // 因为主要是销售想接入ai ,所以医生不回复,只回复销售 下面暂时保留
+                return null;
+//                FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(Long.parseLong(recvID.replace("D", "")));
+//                if (null != fsDoctor && StringUtils.isNotEmpty(fsDoctor.getAvatar())) {
+//                    offlinePushInfo.setTitle(fsDoctor.getDoctorName());
+//                    replyMsg.setSenderFaceURL(fsDoctor.getAvatar());
+//                }
+            } else if (recvID.startsWith("C")) {
+                CompanyUser company = companyUserMapper.selectCompanyUserByUserId(Long.parseLong(recvID.replace("C", "")));
+                companyId = company.getCompanyId();
+                if (null != company && StringUtils.isNotEmpty(company.getAvatar())) {
+                    offlinePushInfo.setTitle(company.getImNickName());
+                    replyMsg.setSenderFaceURL(company.getAvatar());
+                }
+                recvType = "2";
+            }
+            // 对接收者ID进行账户校验
+            accountCheck(recvID.toString(), recvType);
+            if (companyId == 0L) {
+                return null;
+            }
+            // ai接口智能回复
+            R r = aiHookService.AiReply(openImMsgDTO, companyId);
+            if (r.get("code").equals(500)) {
+                return null;
+            }
+            String aiReplyContent = r.get("content").toString();
+
+            // 设置消息的发送者ID、接收者ID、内容类型等基础信息
+            // 将发送者和接收者交换一下
+            replyMsg.setSendID(recvID);
+            replyMsg.setRecvID(sendID);
+            replyMsg.setContentType(101);
+            replyMsg.setSenderPlatformID(5);
+            replyMsg.setSessionType(1);
+
+            // 初始化消息内容对象
+            OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+            // 初始化负载数据对象,并设置数据内容
+            PayloadDTO payload = new PayloadDTO();
+            payload.setData(aiReplyContent);
+
+            PayloadDTO.Extension extension = new PayloadDTO.Extension();
+            extension.setTitle("快速回复"); // 可选标题
+            payload.setExtension(extension);
+            OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+            imData.setPayload(payload);
+            String imJson = objectMapper.writeValueAsString(imData);
+            content.setData(imJson);
+            content.setContent(aiReplyContent);
+            replyMsg.setContent(content);
+            offlinePushInfo.setDesc("快速回复");
+            offlinePushInfo.setIOSBadgeCount(true);
+            offlinePushInfo.setIOSPushSound("");
+            replyMsg.setOfflinePushInfo(offlinePushInfo);
+            // 发送消息
+            OpenImResponseDTO response = openIMSendMsg(replyMsg);
+            if (response.getErrCode() == 0) {
+                Thread.sleep(1000);
+                OpenImEditConversationDTO openImEditConversationDTO = new OpenImEditConversationDTO();
+                ArrayList<String> userIDs = new ArrayList<>();
+                userIDs.add(recvID);
+                openImEditConversationDTO.setUserIDs(userIDs);
+                OpenImConversationDTO openImConversationDTO = new OpenImConversationDTO();
+                openImConversationDTO.setConversationID("si_" + recvID + "_" + sendID);
+                openImConversationDTO.setConversationType(1);
+                openImConversationDTO.setUserID(sendID);
+                openImEditConversationDTO.setConversation(openImConversationDTO);
+                OpenImResponseDTO openImResponseDTO1 = editConversation(openImEditConversationDTO);
+                log.info("修改回话返回参数:{}", openImResponseDTO1);
+            }
+            return null;
+        } catch (Exception e) {
+            log.error("openImMsgCallBack,自动销售回复消息,发送消息失败:", e);
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+
+    //批量修改销售名称,由昵称-公司名,改为昵称
+    public static void main(String[] args) {
+        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOiJpbUFkbWluIiwiUGxhdGZvcm1JRCI6MTAsImV4cCI6MTc1OTkxMDgwNywiaWF0IjoxNzUyMTM0ODAyfQ.y0akpb-TnOBqJewPUD13tnUeR1iF41A3CcgaXXsjyKE";
+        long time = System.currentTimeMillis();
+        int pageSize = 5000;
+        int pageNumber = 1;
+
+        while (true) {
+            // 构建分页查询请求体
+            JSONObject requestPage = new JSONObject();
+            JSONObject pagination = new JSONObject();
+            pagination.put("pageNumber", pageNumber);
+            pagination.put("showNumber", pageSize);
+            requestPage.put("pagination", pagination);
+
+            String result = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/get_all_users_uid")
+                    .header("operationID", String.valueOf(time))
+                    .header("token", token)
+                    .body(requestPage.toString())
+                    .execute()
+                    .body();
+
+            OpenImResponseDTO responseDTO = JSONUtil.toBean(result, OpenImResponseDTO.class);
+            List<String> userIDs = (List<String>) responseDTO.getData().get("userIDs");
+
+            if (CollectionUtil.isEmpty(userIDs)) {
+                System.out.println("数据为空,处理结束");
+                break;
+            }
+
+            // 过滤出以C开头的用户ID
+            List<String> userIds = userIDs.stream()
+                    .filter(uid -> uid.startsWith("C"))
+                    .collect(Collectors.toList());
+
+            if (CollectionUtil.isNotEmpty(userIds)) {
+                Map<String, Object> paramMap = new HashMap<>();
+                paramMap.put("userIDs", userIds);
+
+                String jsonBody = JSONUtil.toJsonStr(paramMap);
+                String result1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/get_users_info")
+                        .header("operationID", String.valueOf(time))
+                        .header("token", token)
+                        .body(jsonBody)
+                        .execute()
+                        .body();
+
+                OpenImResponseDTOTest responseDTO1 = JSONUtil.toBean(result1, OpenImResponseDTOTest.class);
+                List<UserInfo> users = responseDTO1.getData().getUsersInfo();
+
+                for (UserInfo user : users) {
+                    if (StringUtil.isNotEmpty(user.getNickname()) && user.getNickname().contains("-")) {
+                        UpdateUserInfo updateUserInfo = new UpdateUserInfo();
+                        updateUserInfo.setUserID(user.getUserID());
+                        updateUserInfo.setNickname(user.getNickname().split("-")[0]);
+                        updateUserInfo.setFaceURL(Optional.ofNullable(user.getFaceURL()).orElse(""));
+                        updateUserInfo.setEx(Optional.ofNullable(user.getEx()).orElse(""));
+
+                        Map<String, Object> bodyMap = new HashMap<>();
+                        bodyMap.put("userInfo", updateUserInfo);
+
+                        String jsonBody1 = JSONUtil.toJsonStr(bodyMap);
+                        String result2 = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/update_user_info_ex")
+                                .header("operationID", String.valueOf(System.currentTimeMillis()))
+                                .header("token", token)
+                                .body(jsonBody1)
+                                .execute()
+                                .body();
+
+                        OpenImResponseDTO responseDTO2 = JSONUtil.toBean(result2, OpenImResponseDTO.class);
+                        if (responseDTO2.getErrCode() != 0) {
+                            System.out.println("更新失败 userID=" + user.getUserID() + ",错误信息:" + responseDTO2.getErrMsg());
+                        }
+                    }
+                }
+            }
+
+            System.out.println("已处理第 " + pageNumber + " 页,共处理用户数:" + userIDs.size());
+            if (userIDs.size() < pageSize) {
+                System.out.println("已是最后一页,处理完毕!");
+                break;
+            }
+            pageNumber++; // 下一页
+        }
+    }
+
+    /**
+     * 修改im用户信息
+     * @param companyUser
+     * @return
+     */
+    @Override
+    public OpenImResponseDTO updateUserInfo(CompanyUser companyUser){
+        String adminToken = getAdminToken();
+        long time = System.currentTimeMillis();
+        OpenImResponseDTO responseDTO = null;
+        Map<String, Object> paramMap = new HashMap<>();
+        ArrayList<String> userIDs = new ArrayList<>();
+        userIDs.add("C"+companyUser.getUserId());
+        paramMap.put("userIDs", userIDs);
+
+        String jsonBody = JSONUtil.toJsonStr(paramMap);
+        String result1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/get_users_info")
+                .header("operationID", String.valueOf(time))
+                .header("token", adminToken)
+                .body(jsonBody)
+                .execute()
+                .body();
+        UpdateUserInfo updateUserInfo = new UpdateUserInfo();
+        OpenImResponseDTOTest responseDTO1 = JSONUtil.toBean(result1, OpenImResponseDTOTest.class);
+        List<UserInfo> users = responseDTO1.getData().getUsersInfo();
+        if (users.size()<=0){
+            return null;
+        }
+        for (UserInfo user : users) {
+            updateUserInfo.setUserID(user.getUserID());
+            updateUserInfo.setNickname(StringUtils.isNotEmpty(companyUser.getImNickName())?companyUser.getImNickName():companyUser.getNickName());
+            updateUserInfo.setFaceURL(Optional.ofNullable(user.getFaceURL()).orElse(""));
+            updateUserInfo.setEx(Optional.ofNullable(user.getEx()).orElse(""));
+
+            Map<String, Object> bodyMap = new HashMap<>();
+            bodyMap.put("userInfo", updateUserInfo);
+            String jsonBody1 = JSONUtil.toJsonStr(bodyMap);
+            String result2 = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/update_user_info_ex")
+                    .header("operationID", String.valueOf(System.currentTimeMillis()))
+                    .header("token", adminToken)
+                    .body(jsonBody1)
+                    .execute()
+                    .body();
+            responseDTO= JSONUtil.toBean(result2,OpenImResponseDTO.class);
+        }
+
+        return responseDTO;
+    }
+    @Data
+    public static class UpdateUserInfo {
+        private String userID;
+        private String nickname;
+        private String faceURL = "";
+        private String ex = "";
+    }
+
+    @Data
+    public class UserInfo {
+        private String userID;
+        private String nickname;
+        private String faceURL;
+        private String ex;
+        private Long createTime;
+        private Integer appMangerLevel;
+        private Integer globalRecvMsgOpt;
+    }
+
+
+    @Override
+    public OpenImResponseDTO openIMSendMsg(OpenImMsgDTO openImMsgDTO) {
+        log.info("进入发消息的方法");
+        String adminToken = getAdminToken();
+        JSONObject jsonObject = new JSONObject(openImMsgDTO);
+        log.info("发送消息的请求体:\n{}", jsonObject.toString());
+        long time = new Date().getTime();
+        String result = HttpRequest.post("https://web.im.cdwjyyh.com/api/msg/send_msg")
+                .header("operationID", time + "")
+                .header("token",adminToken)
+                .body(jsonObject.toString())
+                .execute()
+                .body();
+        OpenImResponseDTO responseDTO= JSONUtil.toBean(result,OpenImResponseDTO.class);
+        log.info("发送消息返回内容:\n{}", responseDTO);
+        return responseDTO;
+    }
+    @Override
+    public OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId) throws JsonProcessingException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        //userId = 61l;
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null字段
+        checkAndImportFriendByDianBo(companyUserId,userId.toString(),cropId);
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+        PayloadDTO payload = new PayloadDTO();
+        PayloadDTO.Extension extension = new PayloadDTO.Extension();
+        payload.setData("course");
+        extension.setTitle(title);
+        extension.setAppRealLink(url);
+        extension.setSendTime(new Date());
+        extension.setCourseUrl(linkImageUrl);
+        payload.setExtension(extension);
+        imData.setPayload(payload);
+        String imJson = objectMapper.writeValueAsString(imData);
+        content.setData(imJson);
+
+        OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+        offlinePushInfo.setDesc(title);
+        offlinePushInfo.setTitle("芳华未来");
+        offlinePushInfo.setIOSBadgeCount(true);
+        offlinePushInfo.setIOSPushSound("");
+
+        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+        openImMsgDTO.setContent(content);
+
+
+
+        openImMsgDTO.setSendID("C"+companyUserId);
+        openImMsgDTO.setRecvID("U"+userId);
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSessionType(1);
+        // 输出格式化JSON日志
+        log.info("课程消息:\n{}", objectMapper.writeValueAsString(openImMsgDTO));
+        OpenImResponseDTO openImResponseDTO = openIMSendMsg(openImMsgDTO);
+        openImMsgDTO = null;
+        content = null;
+        return openImResponseDTO;
+    }
+    @Override
+    public OpenImResponseDTO sendUtil(String sendID, String recvID, Integer contentType, String payloadData, String diagnose,String title,String followId,String orderId,String ex) throws JsonProcessingException {
+        try {
+            OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+            ObjectMapper objectMapper = new ObjectMapper();
+            OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+            if (sendID.startsWith("D")){
+                FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(Long.parseLong(sendID.replace("D","")));
+                //FsUser fsUser = fsUserService.selectFsUserByUserId(sendID);
+                if (null!=fsDoctor&&StringUtils.isNotEmpty(fsDoctor.getAvatar())){
+                    offlinePushInfo.setTitle(fsDoctor.getDoctorName());
+                    openImMsgDTO.setSenderFaceURL(fsDoctor.getAvatar());
+                }
+            }else if (sendID.startsWith("C")){
+                CompanyUser company = companyUserMapper.selectCompanyUserByUserId(Long.parseLong(sendID.replace("C", "")));
+                if (null!=company&&StringUtils.isNotEmpty(company.getAvatar())){
+                    offlinePushInfo.setTitle(company.getImNickName());
+                    openImMsgDTO.setSenderFaceURL(company.getAvatar());
+                }
+            }
+            accountCheck(recvID.toString(),"1");
+            openImMsgDTO.setSendID(sendID);
+            openImMsgDTO.setRecvID(recvID);
+            openImMsgDTO.setContentType(contentType);
+            openImMsgDTO.setSenderPlatformID(5);
+            openImMsgDTO.setSessionType(1);
+            if (StringUtils.isNotEmpty(ex)){
+                openImMsgDTO.setEx(ex);
+            }
+            OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+            //content.setContent(ext);
+            PayloadDTO payload = new PayloadDTO();
+            payload.setData(payloadData);
+            PayloadDTO.Extension extension = new PayloadDTO.Extension();
+            //extension.setDiagnose(diagnose);
+            if (StringUtils.isNotEmpty(title)){
+                extension.setTitle(title);
+            }
+            if (StringUtils.isNotEmpty(diagnose)){
+                extension.setDiagnose(diagnose);
+            }
+            if (StringUtils.isNotEmpty(followId)){
+                //随访医生与患者加好友
+                ArrayList<String> userIds = new ArrayList<>();
+                userIds.add(recvID);
+                importFriend(sendID,userIds);
+                extension.setFollowId(followId);
+            }
+            if (StringUtils.isNotEmpty(orderId)){
+                payload.setDescription(orderId);
+            }
+
+            payload.setExtension(extension);
+            OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+            imData.setPayload(payload);
+
+            String imJson = objectMapper.writeValueAsString(imData);
+            content.setData(imJson);
+            openImMsgDTO.setContent(content);
+            if (contentType == 101){
+                content.setContent(title);
+            }
+            //cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject(openImMsgDTO);
+
+            //openImMsgDTO.setEx(payload);
+
+            offlinePushInfo.setDesc(title);
+
+            offlinePushInfo.setIOSBadgeCount(true);
+            offlinePushInfo.setIOSPushSound("");
+            openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+            OpenImResponseDTO openImResponseDTO = openIMSendMsg(openImMsgDTO);
+            if (openImResponseDTO.getErrCode()==0){
+                Thread.sleep(1000 );
+                OpenImEditConversationDTO openImEditConversationDTO = new OpenImEditConversationDTO();
+                ArrayList<String> userIDs = new ArrayList<>();
+                userIDs.add(sendID);
+                openImEditConversationDTO.setUserIDs(userIDs);
+                OpenImConversationDTO openImConversationDTO = new OpenImConversationDTO();
+                openImConversationDTO.setConversationID("si_"+sendID+"_"+recvID);
+                openImConversationDTO.setConversationType(1);
+                openImConversationDTO.setUserID(recvID);
+                openImConversationDTO.setEx(ex);
+                log.info("更新到会话的ex的值:{}",ex);
+                openImEditConversationDTO.setConversation(openImConversationDTO);
+
+                OpenImResponseDTO openImResponseDTO1 = editConversation(openImEditConversationDTO);
+                log.info("修改回话返回参数:{}",openImResponseDTO1);
+
+            }
+            return openImResponseDTO;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    public OpenImResponseDTO sendUtilUserToDoctor(String sendID, String recvID, Integer contentType, String payloadData, String diagnose,String title,String followId,String orderId,String ex) throws JsonProcessingException {
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+            if (sendID.startsWith("U")){
+                //FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(Long.parseLong(sendID.replace("D","")));
+                FsUser fsUser = fsUserMapper.selectFsUserByUserId(Long.parseLong(sendID.replace("U","")));
+                if (null!=fsUser&&StringUtils.isNotEmpty(fsUser.getAvatar())){
+                    openImMsgDTO.setSenderFaceURL(fsUser.getAvatar());
+                }
+            }
+            accountCheck(sendID.toString(),"1");
+            openImMsgDTO.setSendID(sendID);
+            openImMsgDTO.setRecvID(recvID);
+            openImMsgDTO.setContentType(contentType);
+            openImMsgDTO.setSenderPlatformID(5);
+            openImMsgDTO.setSessionType(1);
+            if (StringUtils.isNotEmpty(ex)){
+                openImMsgDTO.setEx(ex);
+            }
+            OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+            //content.setContent(ext);
+            PayloadDTO payload = new PayloadDTO();
+            payload.setData(payloadData);
+            PayloadDTO.Extension extension = new PayloadDTO.Extension();
+            extension.setDiagnose(diagnose);
+            if (StringUtils.isNotEmpty(title)){
+                extension.setTitle(title);
+            }
+            if (StringUtils.isNotEmpty(diagnose)){
+                extension.setDiagnose(diagnose);
+            }
+            if (StringUtils.isNotEmpty(followId)){
+                FsFollow follow=fsFollowMapper.selectFsFollowByFollowId(Long.parseLong(followId));
+
+                //随访医生与患者加好友
+                ArrayList<String> userIds = new ArrayList<>();
+                userIds.add(recvID);
+                importFriend(sendID,userIds);
+                extension.setFollowId(followId);
+                extension.setWriteStatus(follow.getWriteStatus().toString());
+            }
+            if (StringUtils.isNotEmpty(orderId)){
+                payload.setDescription(orderId);
+            }
+            payload.setExtension(extension);
+            OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+            imData.setPayload(payload);
+
+            String imJson = objectMapper.writeValueAsString(imData);
+            content.setData(imJson);
+            openImMsgDTO.setContent(content);
+
+            //cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject(openImMsgDTO);
+
+            //openImMsgDTO.setEx(payload);
+            OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+            offlinePushInfo.setDesc(title);
+            offlinePushInfo.setTitle("芳华未来");
+            offlinePushInfo.setIOSBadgeCount(true);
+            offlinePushInfo.setIOSPushSound("");
+            openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+            OpenImResponseDTO openImResponseDTO = openIMSendMsg(openImMsgDTO);
+            if (openImResponseDTO.getErrCode()==0){
+                Thread.sleep(1000 );
+                OpenImEditConversationDTO openImEditConversationDTO = new OpenImEditConversationDTO();
+                ArrayList<String> userIDs = new ArrayList<>();
+                userIDs.add(sendID);
+                openImEditConversationDTO.setUserIDs(userIDs);
+                OpenImConversationDTO openImConversationDTO = new OpenImConversationDTO();
+                openImConversationDTO.setConversationID("si_"+sendID+"_"+recvID);
+                openImConversationDTO.setConversationType(1);
+                openImConversationDTO.setUserID(recvID);
+                openImConversationDTO.setEx(ex);
+                log.info("更新到会话的ex的值:{}",ex);
+                openImEditConversationDTO.setConversation(openImConversationDTO);
+
+                OpenImResponseDTO openImResponseDTO1 = editConversation(openImEditConversationDTO);
+                log.info("修改回话返回参数:{}",openImResponseDTO1);
+
+            }
+            return openImResponseDTO;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    /**
+     * 修改会话
+     * @return
+     */
+    public OpenImResponseDTO editConversation(OpenImEditConversationDTO dto) throws JsonProcessingException, InterruptedException {
+        String adminToken = getAdminToken();
+        ObjectMapper objectMapper = new ObjectMapper();
+        String requestBody = objectMapper.writeValueAsString(dto);
+
+        int retryCount = 0;
+        int maxRetries = 3;
+        OpenImResponseDTO responseDTO = null;
+
+        while (retryCount < maxRetries) {
+            try {
+                JSONObject jsonObject = new JSONObject(dto);
+                String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/conversation/set_conversations")
+                        .header("operationID", String.valueOf(System.currentTimeMillis()))
+                        .header("token", adminToken)
+                        .body(jsonObject.toString())
+                        .execute()
+                        .body();
+                responseDTO = JSONUtil.toBean(body, OpenImResponseDTO.class);
+
+                if (responseDTO.getErrCode() == 0) {
+                    break; // 成功则退出重试
+                } else if (responseDTO.getErrCode() == 1501) {
+                    adminToken = getAdminToken(); // 刷新token
+                }
+            } catch (Exception e) {
+                log.error("修改会话失败,重试次数: {}", retryCount, e);
+            }
+            retryCount++;
+            if (retryCount < maxRetries) {
+                Thread.sleep(1000 * retryCount); // 指数退避
+            }
+        }
+        return responseDTO;
+    }
+    /**
+     * 检查两个用户是否存在好友关系
+     */
+    @Override
+    public OpenImResponseDTO isFriend(String userID1, String userID2) {
+        String adminToken = getAdminToken();
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("userID1",userID1);
+        jsonObject.put("userID2",userID2);
+        String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/friend/is_friend")
+                .header("operationID", String.valueOf(System.currentTimeMillis()))
+                .header("token", adminToken)
+                .body(jsonObject.toString())
+                .execute()
+                .body();
+        OpenImResponseDTO responseDTO= JSONUtil.toBean(body,OpenImResponseDTO.class);
+        return responseDTO;
+    }
+    /**
+     * 添加好友
+     */
+    @Override
+    public OpenImResponseDTO importFriend(String ownerUserID, List<String> friendUserIDs) {
+        //先检查用户是否存在好友关系
+        List<String> newFriendIds = new ArrayList<>();
+        for (String friendUserID : friendUserIDs) {
+            OpenImResponseDTO friend = isFriend(ownerUserID,friendUserID);
+            if (friend.getErrCode()==0){
+                Object data = friend.getData();
+                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(data);
+                Boolean inUser1Friends = (Boolean)jsonObject.get("inUser1Friends");
+                Boolean inUser2Friends = (Boolean)jsonObject.get("inUser2Friends");
+                //如果不存在好友关系
+                if (!inUser1Friends&&!inUser2Friends){
+                    newFriendIds.add(friendUserID);
+                    //friendUserIDs.remove(friendUserID);
+                }
+            }
+        }
+        if (newFriendIds.size()<=0){
+            return null;
+        }
+        String adminToken = getAdminToken();
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("ownerUserID",ownerUserID);
+        jsonObject.put("friendUserIDs",newFriendIds);
+        String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/friend/import_friend")
+                .header("operationID", String.valueOf(System.currentTimeMillis()))
+                .header("token", adminToken)
+                .body(jsonObject.toString())
+                .execute()
+                .body();
+        OpenImResponseDTO responseDTO= JSONUtil.toBean(body,OpenImResponseDTO.class);
+        return responseDTO;
+    }
+
+    /**
+     * 通用注册im
+     * @param userId
+     * @param type 1用户,2销售,3医生
+     * @return
+     */@Override
+    public R accountCheck(String userId,String type){
+        String adminToken = getAdminToken();
+        JSONObject requestBody = new JSONObject();
+        // 解析响应
+        if (StringUtil.isNotEmpty(adminToken)) {
+            //查询用户是否注册
+            /*switch (type){
+                case "1":
+                    userId = "U"+userId;
+                    break;
+                case "2":
+                    userId = userId;
+                    break;
+                case "3":
+                    userId = userId;
+                    break;
+            }*/
+            ArrayList<String> userIds = new ArrayList<>();
+            requestBody = new JSONObject();
+            userIds.add(userId);
+            requestBody.put("checkUserIDs", userIds);
+            String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/account_check")
+                    .header("operationID", String.valueOf(System.currentTimeMillis()))
+                    .header("token", adminToken)
+                    .body(requestBody.toString())
+                    .execute()
+                    .body();
+            JSONObject jsonObject = new JSONObject(body);
+            JSONArray results = jsonObject.getJSONObject("data").getJSONArray("results");
+            if (results != null && results.length() > 0) {
+                JSONObject resultObj = results.getJSONObject(0);
+                int accountStatus = resultObj.getInt("accountStatus");
+                //未注册自动注册
+                if (accountStatus==0){
+                    HashMap<String, String> map = new HashMap<>();
+                    ArrayList<Object> users = new ArrayList<>();
+                    String s = "";
+                    switch (type){
+                        case "2":
+                            s = userId.replaceFirst("^C", "");
+                            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(Long.parseLong(s));
+                            if (null==companyUser){
+                                return R.error("用户不存在");
+                            }
+                            Company company = companyMapper.selectCompanyById(companyUser.getCompanyId());
+                            map.put("userID",userId);
+                            map.put("nickname",companyUser.getImNickName());
+                            map.put("faceURL",companyUser.getAvatar());
+                            break;
+                        case "1":
+                            s = userId.replaceFirst("^U", "");
+                            FsUser fsUser = fsUserMapper.selectFsUserByUserId(Long.parseLong(s));
+                            if (null==fsUser){
+                                return R.error("用户不存在");
+                            }
+                            map.put("userID",userId);
+                            map.put("nickname",StringUtils.isEmpty(fsUser.getNickName())?"微信用户":fsUser.getNickName());
+                            map.put("faceURL",fsUser.getAvatar());
+                            break;
+                        case "3":
+                            s = userId.replaceFirst("^D", "");
+                            FsDoctor fsDoctor = fsDoctorMapper.selectFsDoctorByDoctorId(Long.parseLong(s));
+                            if (null==fsDoctor){
+                                return R.error("用户不存在");
+                            }
+                            map.put("userID",userId);
+                            map.put("nickname",fsDoctor.getDoctorName());
+                            map.put("faceURL",fsDoctor.getAvatar());
+                            break;
+                    }
+
+                    users.add(map);
+                    requestBody = new JSONObject();
+                    userIds.add(userId);
+                    requestBody.put("users", users);
+                    HttpRequest.post("https://web.im.cdwjyyh.com/api/user/user_register")
+                            .header("operationID", String.valueOf(System.currentTimeMillis()))
+                            .header("token", adminToken).body(requestBody.toString()).execute().body();
+                }
+            } else {
+                return R.error("返回结果为空");
+            }
+           /* HashMap<String, String> tokenMap = new HashMap<>();
+            tokenMap.put("platformID","1");
+            tokenMap.put("userID",userId);*/
+            requestBody = new JSONObject();
+            requestBody.put("platformID",5);
+            requestBody.put("userID",userId);
+            String body1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/auth/get_user_token")
+                    .header("operationID", String.valueOf(System.currentTimeMillis()))
+                    .header("token", adminToken)
+                    .body(requestBody.toString()).execute().body();
+            JSONObject userJson = new JSONObject(body1);
+            Integer errCode = (Integer)userJson.get("errCode");
+            if (errCode==0){
+                JSONObject userData = userJson.getJSONObject("data");
+                String userToken = userData.getString("token");
+                return R.ok().put("token", userToken);
+            }
+            return R.error("注册失败");
+        } else {
+            return R.error("获取管理员token失败");
+        }
+    }
+    @Async
+    @Override
+    public void checkAndImportFriend(Long companyUserId,String fsUserId) {
+        try {
+            // 注册账号
+            accountCheck("C" + companyUserId, "2");
+            accountCheck("U"+fsUserId, "1");
+
+            // 导入好友关系
+            ArrayList<String> userIds = new ArrayList<>();
+            userIds.add("U" + fsUserId);
+            importFriend("C" + companyUserId, userIds);
+        } catch (Exception e) {
+            log.error("异步执行IM注册/添加好友失败:", e);
+        }
+    }
+
+    @Async
+    @Override
+    public void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId) {
+        try {
+            // 注册账号
+            accountCheck("C" + companyUserId, "2");
+            accountCheck("U"+fsUserId, "1");
+
+            // 导入好友关系
+            ArrayList<String> userIds = new ArrayList<>();
+            userIds.add("U" + fsUserId);
+            importFriend("C" + companyUserId, userIds);
+            updateFriendByDianBo("C" + companyUserId, userIds,cropId);
+        } catch (Exception e) {
+            log.error("异步执行IM注册/添加好友失败:", e);
+        }
+    }
+
+    /**
+     * 修改好友信息
+     * @param ownerUserID
+     * @param friendUserIDs
+     * @return
+     */
+    public OpenImResponseDTO updateFriendByDianBo(String ownerUserID, List<String> friendUserIDs,String cropId) {
+        //先检查用户是否存在好友关系
+        //List<String> newFriendIds = new ArrayList<>();
+        for (String friendUserID : friendUserIDs) {
+            OpenImResponseDTO friend = isFriend(ownerUserID,friendUserID);
+            if (friend.getErrCode()==0){
+                Object data = friend.getData();
+                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(data);
+                Boolean inUser1Friends = (Boolean)jsonObject.get("inUser1Friends");
+                Boolean inUser2Friends = (Boolean)jsonObject.get("inUser2Friends");
+                //如果不存在好友关系,则不执行im修改好友信息
+                if (!inUser1Friends&&!inUser2Friends){
+                    return null;
+                    //friendUserIDs.remove(friendUserID);
+                }
+            }
+        }
+        List<String> remark = qwExternalContactMapper.selectRemarkByCompanyUserAndFsUser(friendUserIDs.get(0).replaceFirst("^U", ""), ownerUserID.replaceFirst("^C", ""),cropId);
+        if (CollectionUtils.isEmpty(remark)||remark.size()<=0){
+            return null;
+        }
+        String adminToken = getAdminToken();
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("ownerUserID",ownerUserID);
+        jsonObject.put("friendUserIDs",friendUserIDs);
+        jsonObject.put("remark",remark.get(0));
+        String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/friend/update_friends")
+                .header("operationID", String.valueOf(System.currentTimeMillis()))
+                .header("token", adminToken)
+                .body(jsonObject.toString())
+                .execute()
+                .body();
+        OpenImResponseDTO responseDTO= JSONUtil.toBean(body,OpenImResponseDTO.class);
+        return responseDTO;
+    }
+}

+ 28 - 0
fs-service/src/main/java/com/fs/im/vo/OpenImMsgCallBackVO.java

@@ -0,0 +1,28 @@
+package com.fs.im.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OpenImMsgCallBackVO {
+    private String sendID;
+    private String callbackCommand;
+    private String serverMsgID;
+    private String clientMsgID;
+    private String operationID;
+    private Integer senderPlatformID;
+    private String senderNickname;
+    private Integer sessionType;
+    private Integer msgFrom;
+    private Integer contentType;
+    private Integer status;
+    private Long sendTime;
+    private Long createTime;
+    private String content;
+    private Integer seq;
+    private List<String> atUserList;
+    private String faceURL;
+    private String ex;
+    private String recvID;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/im/vo/OpenImResponseDTOTest.java

@@ -0,0 +1,18 @@
+package com.fs.im.vo;
+
+import com.fs.im.service.impl.OpenIMServiceImpl;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+    public class OpenImResponseDTOTest {
+        private Integer errCode;
+        private String errMsg;
+        private String errDlt;
+        private UserData data;
+        @Data
+        public static class UserData {
+            private List<OpenIMServiceImpl.UserInfo> usersInfo;
+        }
+    }

+ 44 - 0
fs-service/src/main/java/com/fs/store/domain/FsInquiryOrderMsgScrm.java

@@ -0,0 +1,44 @@
+package com.fs.store.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 图文订单对象 fs_inquiry_order_msg
+ *
+ * @author fs
+ * @date 2023-06-12
+ */
+@Data
+public class FsInquiryOrderMsgScrm extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long msgId;
+
+    /** 消息类型 1会员消息 2医生消息 */
+    @Excel(name = "消息类型 1会员消息 2医生消息")
+    private String msgType;
+
+    /** 会员ID */
+    @Excel(name = "会员ID")
+    private String fromAccount;
+
+    /** 医生ID */
+    @Excel(name = "医生ID")
+    private String toAccount;
+
+    /** 消息内容 */
+    @Excel(name = "消息内容")
+    private String content;
+
+    /** 订单ID */
+    @Excel(name = "订单ID")
+    private Long orderId;
+
+    private String msgKey;
+    private Integer msgContentType;
+    private String companyUserAccount;
+}

+ 159 - 0
fs-service/src/main/java/com/fs/store/domain/FsPackageOrderScrm.java

@@ -0,0 +1,159 @@
+package com.fs.store.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 套餐订单对象 fs_package_order
+ *
+ * @author fs
+ * @date 2023-08-25
+ */
+@Data
+public class FsPackageOrderScrm extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long orderId;
+
+    /** 订单号 */
+    @Excel(name = "订单号")
+    private String orderSn;
+
+    /** 用户ID */
+    @Excel(name = "用户ID")
+    private Long userId;
+
+    /** 医生ID */
+    @Excel(name = "医生ID")
+    private Long doctorId;
+
+    /** 套餐ID */
+    @Excel(name = "套餐ID")
+    private Long packageId;
+
+    /** 套餐名称 */
+    @Excel(name = "套餐名称")
+    private String packageName;
+
+    /** 套餐名称 */
+    @Excel(name = "套餐别名")
+    private String packageSecondName;
+
+    /** 支付金额 */
+    @Excel(name = "支付金额")
+    private BigDecimal payMoney;
+
+    /** 是否支付 */
+    @Excel(name = "是否支付")
+    private Integer isPay;
+
+    /** 天数 */
+    @Excel(name = "天数")
+    private Integer days;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Integer status;
+
+    /** 开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date startTime;
+
+    /** 结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date finishTime;
+
+    @Excel(name = "json")
+    private String formJson;
+
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    @Excel(name = "公司用户ID")
+    private Long companyUserId;
+
+    @Excel(name = "问诊订单ID")
+    private Long inquiryOrderId;
+
+    @Excel(name = "商品订单ID")
+    private Long storeOrderId;
+
+    @Excel(name = "套餐包数据")
+    private String packageJson;
+
+    @Excel(name = "患者数据")
+    private String patientJson;
+
+    @Excel(name = "退款图片")
+    private String refundImg;
+
+    @Excel(name = "退款用户说明")
+    private String refundExplain;
+
+    @Excel(name = "不退款的理由")
+    private String refundReason;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "退款时间")
+    private Date refundTime;
+
+    @Excel(name = "退款金额")
+    private BigDecimal refundMoney;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "支付时间")
+    private Date payTime;
+
+    @Excel(name = "退款状态")
+    private Integer refundStatus;
+
+    @Excel(name = "套餐价格")
+    private BigDecimal totalPrice;
+    @Excel(name = "地址")
+    private String addressJson;
+    @Excel(name = "付款类型")
+    private Integer payType;
+    @Excel(name = "备注")
+    private String remark;
+    @Excel(name = "店铺id")
+    private Long storeId;
+    @Excel(name = "实际支付金额")
+    private BigDecimal payPrice;
+    @Excel(name = "剩余金额")
+    private BigDecimal payRemain;
+    @Excel(name = "邮费")
+    private BigDecimal payDelivery;
+    @Excel(name = "优惠金额")
+    private BigDecimal discountMoney;
+    @Excel(name = "随访次数")
+    private Integer followNum;
+    @Excel(name = "已随访次数")
+    private Integer followCount;
+    private BigDecimal productCostPrice;
+    private BigDecimal inquiryCostPrice;
+    private BigDecimal totalCostPrice;
+    private BigDecimal costDiscountMoney;
+    private Integer cycle;
+    private Integer packageSubType;
+    private Long followTempId;
+    private Integer followRate;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date followTime;
+    private Long followDoctorId;
+    private BigDecimal prescribePrice;
+    private Long deptId;
+    private String doctorRemark;
+
+    private Long userCouponId;
+    private String icdCode;
+    private Integer source;
+    private String phone;
+}

+ 41 - 0
fs-service/src/main/java/com/fs/store/domain/FsStoreAfterSalesItemScrm.java

@@ -0,0 +1,41 @@
+package com.fs.store.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 售后子对象 fs_store_after_sales_item
+ *
+ * @author fs
+ * @date 2023-12-27
+ */
+@Data
+public class FsStoreAfterSalesItemScrm extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 主键id */
+    private Long id;
+
+    /** 售后id */
+    @Excel(name = "售后id")
+    private Long afterSalesId;
+
+    /** 商品id */
+    @Excel(name = "商品id")
+    private Long productId;
+
+    /** 退货东西的详情信息 */
+    @Excel(name = "退货东西的详情信息")
+    private String jsonInfo;
+
+    /** 逻辑删除 */
+
+    private Integer isDel;
+
+    /** $column.columnComment */
+
+    private Long productAttrValueId;
+
+}

+ 133 - 0
fs-service/src/main/java/com/fs/store/domain/FsStoreAfterSalesLogsScrm.java

@@ -0,0 +1,133 @@
+package com.fs.store.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 售后订单操作对象 fs_store_after_sales_logs
+ *
+ * @author fs
+ * @date 2023-06-13
+ */
+public class FsStoreAfterSalesLogsScrm extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long logsId;
+
+    /** 售后id */
+    @Excel(name = "售后id")
+    private Long storeAfterSalesId;
+
+    /** 操作类型 */
+    @Excel(name = "操作类型")
+    private Integer changeType;
+
+    /** 操作备注 */
+    @Excel(name = "操作备注")
+    private String changeMessage;
+
+    /** 操作时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date changeTime;
+
+    /** 操作人 */
+    @Excel(name = "操作人")
+    private String operator;
+
+    private Long companyId;
+
+    private Long storeId;
+
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public Long getStoreId() {
+        return storeId;
+    }
+
+    public void setStoreId(Long storeId) {
+        this.storeId = storeId;
+    }
+
+    public void setLogsId(Long logsId)
+    {
+        this.logsId = logsId;
+    }
+
+    public Long getLogsId()
+    {
+        return logsId;
+    }
+    public void setStoreAfterSalesId(Long storeAfterSalesId)
+    {
+        this.storeAfterSalesId = storeAfterSalesId;
+    }
+
+    public Long getStoreAfterSalesId()
+    {
+        return storeAfterSalesId;
+    }
+    public void setChangeType(Integer changeType)
+    {
+        this.changeType = changeType;
+    }
+
+    public Integer getChangeType()
+    {
+        return changeType;
+    }
+    public void setChangeMessage(String changeMessage)
+    {
+        this.changeMessage = changeMessage;
+    }
+
+    public String getChangeMessage()
+    {
+        return changeMessage;
+    }
+    public void setChangeTime(Date changeTime)
+    {
+        this.changeTime = changeTime;
+    }
+
+    public Date getChangeTime()
+    {
+        return changeTime;
+    }
+    public void setOperator(String operator)
+    {
+        this.operator = operator;
+    }
+
+    public String getOperator()
+    {
+        return operator;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+            .append("logsId", getLogsId())
+            .append("storeAfterSalesId", getStoreAfterSalesId())
+            .append("changeType", getChangeType())
+            .append("changeMessage", getChangeMessage())
+            .append("changeTime", getChangeTime())
+            .append("operator", getOperator())
+            .append("companyId", getCompanyId())
+            .append("storeId", getStoreId())
+            .toString();
+    }
+}

+ 154 - 0
fs-service/src/main/java/com/fs/store/domain/FsStoreOrderBillLogScrm.java

@@ -0,0 +1,154 @@
+package com.fs.store.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntityTow;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 订单开票记录对象 fs_store_order_bill_log
+ *
+ * @author fs
+ * @date 2025-01-07
+ */
+@Data
+public class FsStoreOrderBillLogScrm extends BaseEntityTow {
+    private static final long serialVersionUID = 1L;
+
+    /** 订单ID */
+    @Excel(name = "订单ID")
+    private Long orderId;
+    @Excel(name = "药品订单号")
+    private String orderCode;
+
+    /** 开票类型0企业1个人 */
+    @Excel(name = "开票类型", readConverterExp = "0=企业,1=个人")
+    private Integer billType;
+
+    /** 开票订单号 */
+    @Excel(name = "开票订单号")
+    private String orderNo;
+
+    /** 开票流水号 */
+    private String serialNo;
+
+    /** 开票流水号 */
+    private String redNo;
+
+    /** 发票代码 */
+    private String invoiceCode;
+
+    /** 是否上传API,0是1否 */
+    private Integer uploadApi;
+
+    /** 发票号码 */
+    @Excel(name = "发票号码")
+    private String invoiceNo;
+
+    /** 红字确认单编号 */
+    @Excel(name = "红字确认单编号")
+    private String billNo;
+
+    /** 红字确认单uuid */
+    @Excel(name = "红字确认单uuid")
+    private String billUuid;
+
+    /** 冲红订单号 */
+    private String redOrderNo;
+
+    /** 数电票号码 */
+    private String allElectronicInvoiceNumbe;
+
+    /** 发票种类 */
+    @Excel(name = "发票种类")
+    private String invoiceKind;
+
+    /** 开票金额 */
+    @Excel(name = "开票金额")
+    private BigDecimal orderAmount;
+
+    /** 购方名称 */
+    @Excel(name = "购方名称")
+    private String payerName;
+
+    /** 购方税号 */
+    @Excel(name = "购方税号")
+    private String payerTaxNo;
+
+    /** 购方地址 */
+    private String address;
+
+    /** 购方电话 */
+    private String telephone;
+
+    /** 冲红原因 1:销货退回;2:开票有误;3:服务中止;4:发生销售折让 */
+    @Excel(name = "冲红原因", readConverterExp = "1=销货退回,2=开票有误,3=服务中止,4=发生销售折让")
+    private Integer redReason;
+
+    /** 含底图纸票pdf地址 */
+    private String paperPdfUrl;
+
+    /** 冲红时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "冲红时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime redTime;
+
+    /** 开票时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "开票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime invoiceTime;
+
+    @Excel(name = "发票图片")
+    private String imgUrls;
+    /** 发票图片地址 */
+    private String pictureUrl;
+
+    /** 发票pdf地址 */
+    @Excel(name = "发票pdf")
+    private String pdfUrl;
+
+    /** 失败原因 */
+    @Excel(name = "失败原因")
+    private String failCause;
+
+    /** 发票状态描述 */
+    @Excel(name = "发票状态描述")
+    private String statusMsg;
+
+    /** 开票状态0未开始1冲红中2 :开票完成( 最终状 态),其他状态分别为: 20:开票中; 21:开票成功签章中;22:开票失败;24: 开票成功签章失败;3:发票已作废 31: 发票作废中 备注:22、24状态时,无需再查询,请确认开票失败原因以及签章失败原因; 注:请以该状态码区分发票状态 */
+    @Excel(name = "开票状态", readConverterExp = "2=开票完成,20=开票中,21=开票成功签章中,22=开票失败,24=开票成功签章失败,3=发票已作废,31=发票作废中")
+    private Integer status;
+    /** : 01 无需确认 02 销方录入待购方确认 03 购方录入待销方确认 04 购销双方已确认 05 作废(销方录入购方否认) 06 作废(购方录入销方否认) 07 作废(超72小时未确认) 08 作废(发起方已撤销) 09 作废(确认后撤销) 15 申请中 16 申请失败 */
+    @Excel(name = "红字确认单状态", readConverterExp = "01=冲红")
+    private String redStatus;
+
+
+    private String json;
+
+
+
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(exist = false)
+    private LocalDate sBillTime;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(exist = false)
+    private LocalDate eBillTime;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(exist = false)
+    private LocalDate sRedTime;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(exist = false)
+    private LocalDate eRedTime;
+    @TableField(exist = false)
+    private Long companyId;
+    @TableField(exist = false)
+    private Long companyUserId;
+
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.