Browse Source

Merge branch 'master_feat_ysy_20250929' of http://1.14.104.71:10880/root/ylrz_his_scrm_java into master_feat_ysy_20250929

caoliqin 3 days ago
parent
commit
adb4960f0e
100 changed files with 3264 additions and 327 deletions
  1. 1 0
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  2. 26 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  3. 35 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  4. 9 0
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  5. 70 0
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  6. 12 0
      fs-admin/src/main/java/com/fs/his/task/FsCourseTask.java
  7. 266 9
      fs-admin/src/main/java/com/fs/his/task/Task.java
  8. 10 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  9. 70 23
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java
  10. 1 0
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  11. 98 0
      fs-admin/src/main/java/com/fs/qw/controller/FsUserAdminByQwController.java
  12. 99 0
      fs-admin/src/main/java/com/fs/qw/controller/FsUserCompanyUserQwController.java
  13. 1 4
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java
  14. 163 0
      fs-admin/src/main/java/com/fs/qw/controller/QwPushCountController.java
  15. 83 3
      fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java
  16. 11 0
      fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java
  17. 105 0
      fs-admin/src/main/java/com/fs/transfer/CustomerTransferApprovalQwController.java
  18. 1 1
      fs-admin/src/main/resources/application.yml
  19. 0 181
      fs-admin/src/test/java/com/fs/course/controller/OpenIMServiceTest.java
  20. 25 0
      fs-common/src/main/java/com/fs/common/utils/DateUtils.java
  21. 31 1
      fs-company/src/main/java/com/fs/company/controller/common/Test.java
  22. 11 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  23. 15 0
      fs-company/src/main/java/com/fs/company/controller/course/qw/FsQwCourseWatchLogController.java
  24. 144 0
      fs-company/src/main/java/com/fs/company/controller/qw/FsUserAdminByQwController.java
  25. 106 0
      fs-company/src/main/java/com/fs/company/controller/qw/FsUserCompanyUserQwController.java
  26. 27 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java
  27. 14 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java
  28. 10 0
      fs-company/src/main/java/com/fs/company/controller/store/FsPackageController.java
  29. 5 9
      fs-company/src/main/java/com/fs/company/controller/store/FsPackageOrderController.java
  30. 61 0
      fs-company/src/main/java/com/fs/company/controller/store/FsStoreAfterSalesController.java
  31. 16 13
      fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java
  32. 1 0
      fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java
  33. 50 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsQuestionAndAnswerController.java
  34. 50 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java
  35. 3 7
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineScrmController.java
  36. 14 7
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  37. 122 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsUserInformationCollectionController.java
  38. 125 0
      fs-company/src/main/java/com/fs/transfer/CustomerTransferApprovalQwController.java
  39. 9 4
      fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeController.java
  40. 91 0
      fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeCommonController.java
  41. 12 12
      fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java
  42. 54 0
      fs-doctor-app/src/main/java/com/fs/app/controller/UserInfoCollectionController.java
  43. 67 18
      fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java
  44. 9 1
      fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java
  45. 77 0
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  46. 36 0
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  47. 11 0
      fs-service/src/main/java/com/fs/company/domain/CompanyUser.java
  48. 4 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  49. 4 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  50. 48 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  51. 3 0
      fs-service/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java
  52. 67 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUserQw.java
  53. 71 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserQwMapper.java
  54. 13 0
      fs-service/src/main/java/com/fs/course/param/CollectionInfoConfirmParam.java
  55. 88 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserQwService.java
  56. 3 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  57. 149 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserQwServiceImpl.java
  58. 93 7
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  59. 3 3
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogStatisticsListVO.java
  60. 68 0
      fs-service/src/main/java/com/fs/course/vo/FsUserInfoCollectionUVO.java
  61. 3 0
      fs-service/src/main/java/com/fs/erp/domain/ErpDeliverys.java
  62. 7 0
      fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryMergeResponse.java
  63. 1 0
      fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryRequert.java
  64. 4 0
      fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java
  65. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  66. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java
  67. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java
  68. 19 2
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  69. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java
  70. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java
  71. 22 0
      fs-service/src/main/java/com/fs/fastGpt/domain/FastGptPushTokenTotal.java
  72. 4 4
      fs-service/src/main/java/com/fs/fastGpt/service/impl/AiHookServiceImpl.java
  73. 2 2
      fs-service/src/main/java/com/fs/fastgptApi/util/EventLogUtils.java
  74. 43 0
      fs-service/src/main/java/com/fs/his/domain/FsDoctorPrescribeCommon.java
  75. 13 1
      fs-service/src/main/java/com/fs/his/domain/FsStoreOrder.java
  76. 8 0
      fs-service/src/main/java/com/fs/his/domain/FsStorePayment.java
  77. 2 1
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  78. 25 0
      fs-service/src/main/java/com/fs/his/dto/FsStoreOrderAmountScrmStatsQueryDto.java
  79. 25 0
      fs-service/src/main/java/com/fs/his/dto/FsStoreOrderAmountStatsQueryDto.java
  80. 44 0
      fs-service/src/main/java/com/fs/his/mapper/FsDoctorPrescribeCommonMapper.java
  81. 3 0
      fs-service/src/main/java/com/fs/his/mapper/FsExportTaskMapper.java
  82. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsHfpayConfigMapper.java
  83. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageMapper.java
  84. 2 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java
  85. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsPatientMapper.java
  86. 12 3
      fs-service/src/main/java/com/fs/his/mapper/FsPrescribeMapper.java
  87. 10 1
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  88. 6 0
      fs-service/src/main/java/com/fs/his/mapper/FsStorePaymentMapper.java
  89. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  90. 3 0
      fs-service/src/main/java/com/fs/his/param/FsDoctorPrescribeAddEditParam.java
  91. 20 0
      fs-service/src/main/java/com/fs/his/param/FsDoctorPrescribeCommonQueryParam.java
  92. 1 0
      fs-service/src/main/java/com/fs/his/param/FsPackageOrderComputeParam.java
  93. 3 0
      fs-service/src/main/java/com/fs/his/param/FsPackageOrderCreateParam.java
  94. 43 0
      fs-service/src/main/java/com/fs/his/service/IFsDoctorPrescribeCommonService.java
  95. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsExportTaskService.java
  96. 5 0
      fs-service/src/main/java/com/fs/his/service/IFsPackageService.java
  97. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsPrescribeService.java
  98. 12 7
      fs-service/src/main/java/com/fs/his/service/IFsStoreOrderService.java
  99. 4 0
      fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java
  100. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java

+ 1 - 0
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -1,5 +1,6 @@
 package com.fs.api.controller;
 
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysDept;
 import com.fs.common.core.redis.RedisCache;

+ 26 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -19,8 +19,12 @@ import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmCustomerVisitService;
 import com.fs.crm.vo.CrmCustomerStatisticsVO;
 import com.fs.crm.vo.CrmCustomerVisitStatisticsVO;
+import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
+import com.fs.his.dto.FsStoreOrderAmountStatsQueryDto;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStorePaymentService;
+import com.fs.his.vo.FsStoreOrderStatsRowVo;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -61,6 +65,10 @@ public class CompanyStatisticsController extends BaseController
     private ICrmCustomerService crmCustomerService;
     @Autowired
     private ICrmCustomerVisitService crmCustomerVisitService;
+
+    //app商城订单接口Service
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
     @GetMapping("/storeOrder")
     public R storeOrder(FsStoreStatisticsParam param)
     {
@@ -643,4 +651,22 @@ public class CompanyStatisticsController extends BaseController
         return util.exportExcel(qwIpadTotalVos, "visit");
     }
 
+    /**
+     * 获取互联网医院订单统计数据
+     * */
+    @GetMapping("/hisOrderCountStats")
+    public AjaxResult getHisOrderCount(FsStoreOrderAmountStatsQueryDto statsQueryDto){
+        List<FsStoreOrderStatsRowVo> fsStoreOrderStatsRowVos = storeOrderService.selectFsStoreOrderAmountStats(statsQueryDto);
+        return AjaxResult.success(fsStoreOrderStatsRowVos);
+    }
+
+    /**
+     * 获取App商城订单统计数据
+     * */
+    @GetMapping("/appOrderCountStats")
+    public AjaxResult getAppOrderCount(FsStoreOrderAmountScrmStatsQueryDto statsQueryDto){
+        List<FsStoreOrderStatsRowVo> fsStoreOrderStatsRowVos = fsStoreOrderScrmService.selectFsStoreOrderAmountScrmStats(statsQueryDto);
+        return AjaxResult.success(fsStoreOrderStatsRowVos);
+    }
+
 }

+ 35 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -150,6 +150,41 @@ public class CompanyUserController extends BaseController
     {
         return toAjax(companyUserService.changeCompanyUser(users, companyUserId, companyId));
     }
+
+    /**
+     * 更换会员归属销售-企微的
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:changeQw')")
+    @Log(title = "更换会员归属-企微", businessType = BusinessType.OTHER)
+    @PostMapping("/changeCompanyUserQw")
+    public AjaxResult changeCompanyUserQw(@RequestBody List<UserProjectDTO> users, @RequestParam Long companyUserId, @RequestParam Long companyId)
+    {
+        return toAjax(companyUserService.changeCompanyUserQw(users, companyUserId, companyId));
+    }
+
+    /**
+     * 允许客户能看其他销售课-开关
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('company:companyUser:isAllView')")
+    @Log(title = "允许客户能看其他销售课开关", businessType = BusinessType.UPDATE)
+    @GetMapping("/changeCompanyUserAllView/{allViewNum}")
+    public AjaxResult changeCompanyUserAllView(@PathVariable Integer allViewNum)
+    {
+        return toAjax(companyUserService.changeCompanyUserAllView(allViewNum));
+    }
+
+    /**
+     * 获取是否允许客户能看其他销售课-开关
+     * @return
+     */
+    @GetMapping("/getIsAllowedEveryoneView")
+    public Integer getIsAllowedEveryoneView()
+    {
+        return companyUserService.getIsAllowedEveryoneView();
+    }
+
     /**
      * 根据登录的用户公司获取所有的销售
      * @return

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

@@ -423,6 +423,15 @@ public class FsStoreOrderController extends BaseController
         return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
     }
 
+    @Log(title = "订单", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateAddressErpFsStoreOrder")
+    public AjaxResult updateAddressErpFsStoreOrder(@RequestBody FsStoreOrder fsStoreOrder)
+    {
+        logger.info("修改订单 参数: {}",fsStoreOrder);
+
+        return toAjax(fsStoreOrderService.updateAddressErpFsStoreOrder(fsStoreOrder));
+    }
+
     /**
      * 修改订单
      */

+ 70 - 0
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -15,6 +15,7 @@ import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.course.dto.BatchSendCourseDTO;
 import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.service.IFsUserCompanyUserQwService;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.domain.FsUserAddress;
@@ -82,6 +83,8 @@ public class FsUserController extends BaseController
     private IFsUserIntegralLogsService userIntegralLogsService;
     @Autowired
     private IFsUserCompanyUserService userCompanyUserService;
+    @Autowired
+    private IFsUserCompanyUserQwService userCompanyUserQwService;
 
     @Autowired
     private SqlSessionFactory sqlSessionFactory;
@@ -166,6 +169,34 @@ public class FsUserController extends BaseController
         return getDataTable(list);
     }
 
+    @PreAuthorize("@ss.hasPermi('his:userQw:list')")
+    @GetMapping("/listProjectByQw")
+    public TableDataInfo listProjectByQw(FsUser fsUser)
+    {
+        startPage();
+        if(StringUtils.isNotEmpty(fsUser.getPhone())){
+            fsUser.setPhone(encryptPhone(fsUser.getPhone()));
+        }
+        List<FsUserVO> list = fsUserService.selectFsUserVOListByProjectByQw(fsUser);
+        boolean checkPhone = isCheckPhone();
+        for (FsUserVO fsUserVO : list) {
+            if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
+                if (!checkPhone){
+                    if (fsUserVO.getPhone().length()>11){
+                        fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
+                    }else {
+                        fsUserVO.setPhone(fsUserVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                } else {
+                    if (fsUserVO.getPhone().length()>11) {
+                        fsUserVO.setPhone(decryptPhone(fsUserVO.getPhone()));
+                    }
+                }
+            }
+        }
+        return getDataTable(list);
+    }
+
     @PreAuthorize("@ss.hasPermi('his:user:export')")
     @GetMapping("/exportListProject")
     public AjaxResult exportListProject(FsUser fsUser)
@@ -194,6 +225,34 @@ public class FsUserController extends BaseController
         return util.exportExcel(list, "项目会员数据");
     }
 
+    @PreAuthorize("@ss.hasPermi('his:user:exportQw')")
+    @GetMapping("/exportListProjectQw")
+    public AjaxResult exportListProjectQw(FsUser fsUser)
+    {
+        if(StringUtils.isNotEmpty(fsUser.getPhone())){
+            fsUser.setPhone(encryptPhone(fsUser.getPhone()));
+        }
+        List<FsUserVO> list = fsUserService.selectFsUserVOListByProjectByQw(fsUser);
+        boolean checkPhone = isCheckPhone();
+        for (FsUserVO fsUserVO : list) {
+            if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
+                if (!checkPhone){
+                    if (fsUserVO.getPhone().length()>11){
+                        fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
+                    }else {
+                        fsUserVO.setPhone(fsUserVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
+                } else {
+                    if (fsUserVO.getPhone().length()>11) {
+                        fsUserVO.setPhone(decryptPhone(fsUserVO.getPhone()));
+                    }
+                }
+            }
+        }
+        ExcelUtil<FsUserVO> util = new ExcelUtil<FsUserVO>(FsUserVO.class);
+        return util.exportExcel(list, "项目会员数据");
+    }
+
     /**
      * 导出用户列表
      */
@@ -301,6 +360,17 @@ public class FsUserController extends BaseController
         return toAjax(userCompanyUserService.deleteFsUserCompanyUserById(id));
     }
 
+    /**
+     * 删除微信用户和销售关系信息-企微
+     */
+    @PreAuthorize("@ss.hasPermi('his:userCompanyUserQw:remove')")
+    @Log(title = "微信用户和销售关系-企微", businessType = BusinessType.DELETE)
+    @DeleteMapping("/deleteQw/{id}")
+    public AjaxResult deleteQw(@PathVariable Long id)
+    {
+        return toAjax(userCompanyUserQwService.deleteFsUserCompanyUserQwById(id));
+    }
+
     /**
      * 查询用户
      */

+ 12 - 0
fs-admin/src/main/java/com/fs/his/task/FsCourseTask.java

@@ -1,6 +1,7 @@
 package com.fs.his.task;
 
 import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.qw.service.ICustomerTransferApprovalQwService;
 import com.fs.qw.service.ICustomerTransferApprovalService;
 import com.fs.qw.service.IHyWorkTaskService;
 import com.fs.statis.service.FsStatisSalerWatchService;
@@ -21,8 +22,12 @@ public class FsCourseTask {
 
     @Autowired
     private FsStatisSalerWatchService fsStatisSalerWatchService;
+
     @Autowired
     private ICustomerTransferApprovalService customerTransferApprovalService;
+
+    @Autowired
+    private ICustomerTransferApprovalQwService customerTransferApprovalQwService;
     /**
      * 添加会员观看日志
      * @throws Exception
@@ -58,4 +63,11 @@ public class FsCourseTask {
         customerTransferApprovalService.autoApprovePass();
     }
 
+    /**
+     * 企微客户转移审批自动通过
+     */
+    public void fsUserTransferAutoPassQw(){
+        customerTransferApprovalQwService.autoApprovePassQw();
+    }
+
 }

+ 266 - 9
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -1,9 +1,16 @@
 package com.fs.his.task;
 
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
+import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
+import com.fs.fastgptApi.util.AudioUtils;
+import com.fs.fastgptApi.vo.AudioVO;
+import com.fs.sop.domain.QwSopTempVoice;
 import com.alibaba.fastjson.JSONObject;
 import com.baidu.dev2.api.sdk.payment.api.PaymentService;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -24,11 +31,15 @@ import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.ITencentCloudCosService;
 import com.fs.erp.domain.ErpDeliverys;
+import com.fs.erp.domain.ErpOrder;
 import com.fs.erp.domain.ErpOrderQuery;
+import com.fs.erp.domain.FsErpFinishPush;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
+import com.fs.erp.dto.OrderQueryResponseDTO;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastGptPushTokenTotal;
 import com.fs.fastGpt.domain.FastgptEventLogTotal;
 import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
 import com.fs.fastGpt.service.IFastgptEventLogTotalService;
@@ -46,13 +57,19 @@ import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.FsSubOrderResultVO;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.domain.FsUserInformationCollection;
+import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
+import com.fs.hisStore.mapper.FsUserInformationCollectionMapper;
 import com.fs.hisStore.service.IFsStorePaymentScrmService;
+import com.fs.hisStore.service.IFsUserInformationCollectionService;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
 import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwCompany;
+import com.fs.qw.mapper.QwRestrictionPushRecordMapper;
 import com.fs.qw.service.*;
 import com.fs.qwApi.service.QwApiService;
+import com.fs.sop.service.IQwSopTempVoiceService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.wx.domain.FsWxExpressTask;
@@ -77,9 +94,18 @@ import java.util.stream.Collectors;
 @Slf4j
 @Component("task")
 public class Task {
+
+    @Autowired
+    private FsUserInformationCollectionMapper userInformationCollectionMapper;
+
+    @Autowired
+    private IFsUserInformationCollectionService userInformationCollectionService;
+
     @Autowired
     private FsUserCouponMapper fsUserCouponMapper;
     @Autowired
+    private FsStoreOrderScrmMapper fsStoreOrderScrmMapper;
+    @Autowired
     private SysConfigMapper sysConfigMapper;
     @Autowired
     private IFsPrescribeService fsPrescribeService;
@@ -186,6 +212,16 @@ public class Task {
     private IFsStorePaymentService paymentScrmService;
     @Autowired
     ShippingService shippingService;
+
+    @Autowired
+    private QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper;
+
+    @Autowired
+    private FastgptChatVoiceHomoMapper fastgptChatVoiceHomoMapper;
+    @Autowired
+    private IQwSopTempVoiceService qwSopTempVoiceService;
+
+    public static final String SOP_TEMP_VOICE_KEY = "sop:tempVoice";
     public void syncExpressToWx() {
         List<FsWxExpressTask> fsWxExpressTasks = fsWxExpressTaskMapper.selectPendingData();
         if (CollectionUtils.isEmpty(fsWxExpressTasks)) {
@@ -207,7 +243,7 @@ public class Task {
 
 
                 if(ObjectUtil.isNotNull(fsStoreOrder)){
-                    List<FsStorePaymentScrm> fsStorePayments = paymentScrmService.selectFsStorePaymentByOrderScrm(fsStoreOrder.getId());
+                    List<FsStorePaymentScrm> fsStorePayments = paymentScrmService.selectFsStorePaymentByOrderScrmStatus1(fsStoreOrder.getId());
 
 
                     if(CollectionUtils.isNotEmpty(fsStorePayments)){
@@ -270,6 +306,87 @@ public class Task {
 //        fsWxExpressTaskMapper.batchUpdate(fsWxExpressTasks);
 
     }
+    /**
+     * sop任务token消耗统计
+     */
+    public void sopPushTokenTotal() {
+        // 判断是否是凌晨 00:00 - 00:59
+        boolean isEarlyMorning = isEarlyMorning();
+
+        // 获取日期字符串(今天或昨天)
+        String dateTime;
+        if (isEarlyMorning) {
+            dateTime = DateUtils.addDateDays(-1); // 昨天
+        } else {
+            dateTime = DateUtils.getDate(); // 今天
+        }
+        log.info("开始执行sop任务token消耗统计");
+        try {
+            List<FastGptPushTokenTotal> fastGptPushTotalList = qwRestrictionPushRecordMapper.selectFastgptPushTokenTotal(dateTime);
+            if (fastGptPushTotalList != null && !fastGptPushTotalList.isEmpty()) {
+                for (FastGptPushTokenTotal fastGptPushTotal : fastGptPushTotalList) {
+                    // 获取统计数据
+                    Integer type = fastGptPushTotal.getType();
+                    Long count = 0L;
+                    if(type == 7){
+                        count = fastGptPushTotal.getCount() * 450;
+                    }else{
+                        count = fastGptPushTotal.getCount() * 150;
+                    }
+                    fastGptPushTotal.setCount(count);
+                    FastGptPushTokenTotal pushTotal = qwRestrictionPushRecordMapper.selectFastGptPushTokenTotalByInfo(fastGptPushTotal);
+                    if(pushTotal == null){
+                        qwRestrictionPushRecordMapper.insertPushTokenTotal(fastGptPushTotal);
+                    }else{
+                        fastGptPushTotal.setId(pushTotal.getId());
+                        qwRestrictionPushRecordMapper.updatePushTokenTotal(fastGptPushTotal);
+                    }
+                }
+            }
+            log.info("结束执行sop任务token消耗统计");
+        } catch (Exception e) {
+            log.error("执行sop任务token消耗统计异常", e);
+        }
+    }
+
+    /**
+     * 一键生成语音定时任务
+     */
+    public void ConsumerSopTempVoice() {
+        try {
+            Long newCompanyUserId = redisCache.popVoiceKey(SOP_TEMP_VOICE_KEY);
+            if (newCompanyUserId != null) {
+                List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + newCompanyUserId);
+                if (sopTempVoices != null && !sopTempVoices.isEmpty()) {
+                    try {
+                        for (QwSopTempVoice qwSopTempVoice : sopTempVoices) {
+                            try {
+                                AudioVO audioVO = new AudioVO();
+                                List<FastgptChatVoiceHomo> homos = fastgptChatVoiceHomoMapper.selectFastgptChatVoiceHomoList(new FastgptChatVoiceHomo());
+                                audioVO = AudioUtils.createUserUrlAndUrl(homos, qwSopTempVoice.getCompanyUserId(), qwSopTempVoice.getVoiceTxt());
+                                if (audioVO != null && audioVO.getWavUrl() != null && audioVO.getUrl() != null) {
+                                    qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
+                                    qwSopTempVoice.setUserVoiceUrl(audioVO.getWavUrl());
+                                    qwSopTempVoice.setDuration(audioVO.getDuration());
+                                    qwSopTempVoice.setRecordType(1);
+                                    qwSopTempVoiceService.updateQwSopTempVoice(qwSopTempVoice);
+                                }
+                            } catch (Exception e) {
+
+                            }
+                        }
+                    } finally {
+                        redisCache.deleteObject(SOP_TEMP_VOICE_KEY + ":" + newCompanyUserId);
+                    }
+                }
+            } else {
+                log.info("没有需要生成的语音");
+            }
+        } catch (Exception e) {
+            log.error("生成语音定时任务执行异常", e);
+        }
+    }
+
 
     /**
      * 获取订单商品信息
@@ -536,6 +653,20 @@ public class Task {
             qwUserService.syncQwUserName(company.getCorpId());
         }
     }
+    @Autowired
+    IFsStorePaymentService fsStorePaymentService;
+    public void payment(){
+        List<FsStorePayment> fsStorePayments = fsStorePaymentService.selectAllPayment();
+        for (FsStorePayment fsStorePayment : fsStorePayments) {
+            try{
+                fsStorePaymentService.updateFsStorePaymentByDecryptForm(fsStorePayment.getPaymentId());
+            }catch (Exception e){
+                logger.error("同步支付失败:"+fsStorePayment.getPaymentId());
+            }
+
+        }
+
+    }
 
     public void videoTranscode() throws Exception
     {
@@ -635,9 +766,114 @@ public class Task {
             fsPrescribeService.auditPrescribe();
         }
     }
+    public void queryOrder(){
+        IErpOrderService erpOrderService = getErpService();
 
-    public void deliveryOp()
-    {
+        List<FsStoreOrder> orders = fsStoreOrderMapper.selectNoMergeOrder();
+        if (CollectionUtils.isNotEmpty(orders)) {
+            for(FsStoreOrder order:orders){
+                ErpOrderQueryRequert request=new ErpOrderQueryRequert();
+                request.setSo_id(order.getOrderCode());
+                if (erpOrderService != null) {
+                    OrderQueryResponseDTO mergeOrder = null;
+                    try {
+                        mergeOrder = erpOrderService.getMergeOrder(request);
+                        Thread.sleep(2000); // 1000毫秒 = 1秒
+                    } catch (Exception e) {
+                        logger.error("调用ERP接口异常:",e);
+                        try {
+
+                        } catch (Exception ex) {
+
+                        }
+                        continue;
+                        //throw new RuntimeException(e);
+                    }
+                    if (erpOrderService == jSTOrderService) {
+                        if (mergeOrder != null && mergeOrder.getOrders() != null && mergeOrder.getOrders().size() > 1) {
+                            List<OrderQueryResponseDTO.Order> collect = mergeOrder.getOrders()
+                                    .stream()
+                                    .filter(s -> s.getIsMerge() != null && s.getIsMerge())
+                                    .collect(Collectors.toList());
+                            OrderQueryResponseDTO.Order order1 = collect.get(0);
+                            if (order1 != null){
+                                List<OrderQueryResponseDTO.OrderPay> pays = order1.getPays();
+                                if (pays != null && !pays.isEmpty()) {
+                                    pays.forEach(pay -> {
+                                        FsStoreOrder fsStoreOrder = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(pay.getOuterPayId());
+                                        FsStoreOrder map = new FsStoreOrder();
+                                        map.setIsMerge(1);
+                                        map.setExtendOrderId(pay.getOId().toString());
+                                        map.setOrderId(fsStoreOrder.getOrderId());
+                                        fsStoreOrderMapper.updateFsStoreOrder(map);
+                                    });
+                                }
+                            }
+                        }
+                    }
+
+                }
+            }
+        }
+
+
+
+    }
+    public void queryOrderScrm(){
+        IErpOrderService erpOrderService = getErpService();
+
+        List<FsStoreOrderScrm> orders = fsStoreOrderMapper.selectNoMergeOrderScrm();
+        if (CollectionUtils.isNotEmpty(orders)) {
+            for(FsStoreOrderScrm order:orders){
+                ErpOrderQueryRequert request=new ErpOrderQueryRequert();
+                request.setSo_id(order.getOrderCode());
+                if (erpOrderService != null) {
+                    OrderQueryResponseDTO mergeOrder = null;
+                    try {
+                        mergeOrder = erpOrderService.getMergeOrder(request);
+                        Thread.sleep(2000); // 1000毫秒 = 1秒
+                    } catch (Exception e) {
+                        logger.error("调用ERP接口异常:",e);
+                        try {
+
+                        } catch (Exception ex) {
+
+                        }
+                        continue;
+                        //throw new RuntimeException(e);
+                    }
+                    if (erpOrderService == jSTOrderService) {
+                        if (mergeOrder != null && mergeOrder.getOrders() != null && mergeOrder.getOrders().size() > 1) {
+                            List<OrderQueryResponseDTO.Order> collect = mergeOrder.getOrders()
+                                    .stream()
+                                    .filter(s -> s.getIsMerge() != null && s.getIsMerge())
+                                    .collect(Collectors.toList());
+                            OrderQueryResponseDTO.Order order1 = collect.get(0);
+                            if (order1 != null){
+                                List<OrderQueryResponseDTO.OrderPay> pays = order1.getPays();
+                                if (pays != null && !pays.isEmpty()) {
+                                    pays.forEach(pay -> {
+                                        FsStoreOrderScrm fsStoreOrderScrm = fsStoreOrderScrmMapper.selectFsStoreOrderByOrderCode(pay.getOuterPayId());
+                                        FsStoreOrderScrm map = new FsStoreOrderScrm();
+                                        map.setIsMerge(1);
+                                        map.setExtendOrderId(pay.getOId().toString());
+                                        map.setId(fsStoreOrderScrm.getId());
+                                        fsStoreOrderScrmMapper.updateFsStoreOrder(map);
+                                    });
+                                }
+                            }
+                        }
+                    }
+
+                }
+            }
+        }
+
+
+
+    }
+
+    public void deliveryOp() {
         IErpOrderService erpOrderService = getErpService();
         List<FsStoreOrder> orders = null;
         if (erpOrderService == gyOrderService){
@@ -647,13 +883,14 @@ public class Task {
         }
         for(FsStoreOrder order:orders){
 
-            ErpOrderQueryRequert request=new ErpOrderQueryRequert();
+            ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+
             request.setCode(order.getExtendOrderId());
             if (erpOrderService != null){
                 ErpOrderQueryResponse response= null;
                 try {
                     response=erpOrderService.getOrder(request);
-                    Thread.sleep(1000); // 1000毫秒 = 1秒
+                    Thread.sleep(2000); // 1000毫秒 = 1秒
                 } catch (Exception e) {
                     logger.error("调用ERP接口异常:",e);
                     try {
@@ -672,7 +909,7 @@ public class Task {
                                 for(ErpDeliverys delivery:orderQuery.getDeliverys()){
                                     if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
                                         //更新商订单状态 删除REDIS
-                                        fsStoreOrderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                        fsStoreOrderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name(),delivery.getSend_date());
                                         redisCache.deleteObject("delivery"+":"+order.getExtendOrderId());
                                     }
                                 }
@@ -699,8 +936,9 @@ public class Task {
             if (erpOrderService != null){
                 ErpOrderQueryResponse response= null;
                 try {
+                    Thread.sleep(2000); // 1000毫秒 = 1秒
                     response = erpOrderService.getScrmOrder(request);
-                    Thread.sleep(1000); // 1000毫秒 = 1秒
+                    Thread.sleep(2000); // 1000毫秒 = 1秒
                 } catch (Exception e) {
                     logger.error("调用ERP接口异常:",e);
                     try {
@@ -717,9 +955,10 @@ public class Task {
                             if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
                                 for(ErpDeliverys delivery:orderQuery.getDeliverys()){
                                     if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
+
                                         logger.info("调用erp获取订单详情接口:"+response);
                                         //更新商订单状态 删除REDIS
-                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name(),delivery.getSend_date());
                                         redisCache.deleteObject("delivery"+":"+order.getExtendOrderId());
                                     }
                                 }
@@ -781,7 +1020,7 @@ public class Task {
         for (Long l : omsList) {
             try {
                 fsStoreOrderService.createOmsOrder(l);
-                Thread.sleep(1000); // 1000毫秒 = 1秒
+                Thread.sleep(2000); // 1000毫秒 = 1秒
             } catch (Exception e) {
                 logger.error("推送订单异常:",e);
                 continue;
@@ -1596,5 +1835,23 @@ public class Task {
         }
     }
 
+    //用户信息采集 自动退款
+    void autoRefund(){
+        List<FsUserInformationCollection> collections = userInformationCollectionMapper.selectAutoRefundOrderCode();
+        if (ObjectUtil.isNotEmpty(collections)) {
+            for(FsUserInformationCollection collection :collections) {
+                try {
+                    userInformationCollectionService.autoRefund(collection);
+                    Thread.sleep(2000);
+                } catch (Exception e) {
+                    logger.info("自动退款失败,订单号:{}", collection.getPackageOrderCode());
+                    continue;
+                    //throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
+
 
 }

+ 10 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -530,7 +530,16 @@ public class FsStoreOrderScrmController extends BaseController {
     public AjaxResult edit(@RequestBody FsStoreOrderScrm fsStoreOrder) {
         return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
     }
-
+    /**
+     * 修改订单
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:edit')")
+    @Log(title = "订单", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateAddressErpFsStoreOrder")
+    public AjaxResult updateAddressErpFsStoreOrder(@RequestBody FsStoreOrderScrm fsStoreOrder) {
+        logger.info("修改订单 参数: {}",fsStoreOrder);
+        return toAjax(fsStoreOrderService.updateAddressErpFsStoreOrder(fsStoreOrder));
+    }
     /**
      * 修改物流
      * @param fsStoreOrder

+ 70 - 23
fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -11,17 +11,23 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.spring.SpringUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.config.cloud.CloudHostProper;
+import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.FsHfpayConfig;
+import com.fs.his.domain.FsStorePayment;
 import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.hisStore.domain.FsPayConfigScrm;
 import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.domain.HuifuConfirmrefundResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentDelaytransConfirmrefundRequest;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
@@ -209,31 +215,72 @@ public class FsStorePaymentScrmController extends BaseController
                         huifuId=fsPayConfig.getHuifuId();
                     }
                 }
-                V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
-                request.setHuifuId(huifuId);
-                request.setOrdAmt(payment.getPayMoney().toString());
-                request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
-                request.setReqSeqId("refund-"+payment.getPayCode());
-                Map<String, Object> extendInfoMap = new HashMap<>();
-                extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
-                request.setExtendInfo(extendInfoMap);
-                HuiFuRefundResult refund = huiFuService.refund(request);
-                logger.info("退款:"+refund);
-                if((refund.getResp_code().equals("00000000")||refund.getResp_code().equals("00000100"))&&(refund.getTrans_stat().equals("S")||refund.getTrans_stat().equals("P"))){
-                    payment.setRefundMoney(fsStorePayment.getRefundMoney());
-                    payment.setStatus(-1);
-                    payment.setRefundTime(new Date());
-                    fsStorePaymentService.updateFsStorePayment(payment);
-                    //收款 减去所有
-                    if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
-                        companyService.subCompanyPaymentMoney(payment);
+                if (payment.getIsShare() == 1 && payment.getShareStatus() == 1) {
+                    V2TradePaymentDelaytransConfirmrefundRequest confirmRefundRequest = new V2TradePaymentDelaytransConfirmrefundRequest();
+                    //Map<String, Object> extendInfoMap = new HashMap<>();
+                    String orderCode = OrderCodeUtils.getOrderSn();
+                    if (StringUtils.isEmpty(orderCode)) {
+                        throw new CustomException("订单生成失败,请重试");
+                    }
+                    confirmRefundRequest.setReqSeqId(orderCode);
+                    confirmRefundRequest.setOrgReqSeqId(payment.getShareCode());
+                    confirmRefundRequest.setOrgReqDate(payment.getShareDate());
+                    //多汇付使用appID
+                    HuifuConfirmrefundResult result = huiFuService.confirmRefund(confirmRefundRequest, payment.getAppId());
+                    if (result.getResp_code().equals("00000000") && (result.getTrans_stat().equals("S") || result.getTrans_stat().equals("P"))) {
+                        V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                        request.setHuifuId(huifuId);
+                        request.setOrdAmt(payment.getPayMoney().toString());
+                        request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                        request.setReqSeqId("refund-"+payment.getPayCode());
+                        Map<String, Object> extendInfoMap = new HashMap<>();
+                        extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                        request.setExtendInfo(extendInfoMap);
+                        HuiFuRefundResult refund = huiFuService.refund(request);
+                        logger.info("退款:"+refund);
+                        if((refund.getResp_code().equals("00000000")||refund.getResp_code().equals("00000100"))&&(refund.getTrans_stat().equals("S")||refund.getTrans_stat().equals("P"))){
+                            payment.setRefundMoney(fsStorePayment.getRefundMoney());
+                            payment.setStatus(-1);
+                            payment.setRefundTime(new Date());
+                            fsStorePaymentService.updateFsStorePayment(payment);
+                            //收款 减去所有
+                            if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
+                                companyService.subCompanyPaymentMoney(payment);
+                            }
+                            return R.ok();
+                        }else {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return R.error(refund.getResp_desc());
+                        }
+                    } else {
+                        throw new CustomException("交易确认退款请求失败" + result.getResp_desc());
+                    }
+                } else {
+                    V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                    request.setHuifuId(huifuId);
+                    request.setOrdAmt(payment.getPayMoney().toString());
+                    request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                    request.setReqSeqId("refund-"+payment.getPayCode());
+                    Map<String, Object> extendInfoMap = new HashMap<>();
+                    extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                    request.setExtendInfo(extendInfoMap);
+                    HuiFuRefundResult refund = huiFuService.refund(request);
+                    logger.info("退款:"+refund);
+                    if((refund.getResp_code().equals("00000000")||refund.getResp_code().equals("00000100"))&&(refund.getTrans_stat().equals("S")||refund.getTrans_stat().equals("P"))){
+                        payment.setRefundMoney(fsStorePayment.getRefundMoney());
+                        payment.setStatus(-1);
+                        payment.setRefundTime(new Date());
+                        fsStorePaymentService.updateFsStorePayment(payment);
+                        //收款 减去所有
+                        if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
+                            companyService.subCompanyPaymentMoney(payment);
+                        }
+                        return R.ok();
+                    }else {
+                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                        return R.error(refund.getResp_desc());
                     }
-                    return R.ok();
-                }else {
-                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-                    return R.error(refund.getResp_desc());
                 }
-
             }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("wx")){
 
             }

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

@@ -169,6 +169,7 @@ public class MallStoreTask
                 fsStoreOrderService.createOmsOrder(id);
             } catch (Exception e) {
                 log.error("订单推送失败", e);
+                continue;
             }
         }
     }

+ 98 - 0
fs-admin/src/main/java/com/fs/qw/controller/FsUserAdminByQwController.java

@@ -0,0 +1,98 @@
+package com.fs.qw.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.company.cache.ICompanyUserCacheService;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsUserService;
+import com.fs.his.utils.PhoneUtil;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.domain.CustomerTransferApproval;
+import com.fs.qw.dto.FsUserTransferParamDTO;
+import com.fs.qw.service.ICustomerTransferApprovalQwService;
+import com.fs.qw.service.ICustomerTransferApprovalService;
+import com.fs.store.param.h5.FsUserPageListParam;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+
+@Api(tags = "企微会员管理接口")
+@RestController
+@Slf4j
+@RequestMapping("/qw/fsUserByQw")
+@AllArgsConstructor
+public class FsUserAdminByQwController extends BaseController {
+
+    @Autowired
+    private IFsUserService fsUserService;
+
+    @Autowired
+    private ICompanyUserCacheService companyUserCacheService;
+
+    @Autowired
+    private ICustomerTransferApprovalQwService transferApprovalQwService;
+
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:list')")
+    @PostMapping("/list")
+    @ApiOperation("会员列表(与移动端使用的相同查询)")
+    public TableDataInfo pageList(@RequestBody FsUserPageListParam param) {
+
+
+        if(param.getPhone()!=null && !"".equals(param.getPhone())){
+            param.setPhone(PhoneUtil.encryptPhone(param.getPhone()));
+        }
+        return fsUserService.selectFsUserPageListNewQw(param);
+    }
+
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:myList')")
+    @PostMapping("/myList")
+    @ApiOperation("我的会员列表(与移动端使用的相同查询)")
+    public TableDataInfo pageMyList(@RequestBody FsUserPageListParam param) {
+
+        if(param.getCompanyUserId() == null) {
+            throw new IllegalArgumentException("当前销售不存在!");
+        }
+        return fsUserService.selectFsUserPageListNewQw(param);
+    }
+
+    /**
+     * 获取用户详细信息
+     */
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(fsUserService.selectFsUserPageListVOByUserIdQw(userId));
+    }
+
+    /**
+     * 修改用户
+     */
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:edit')")
+    @Log(title = "用户", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUser fsUser)
+    {
+        return toAjax(fsUserService.updateFsUser(fsUser));
+    }
+
+
+}

+ 99 - 0
fs-admin/src/main/java/com/fs/qw/controller/FsUserCompanyUserQwController.java

@@ -0,0 +1,99 @@
+package com.fs.qw.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.course.service.IFsUserCompanyUserQwService;
+import com.fs.qw.param.FsUserCompanyUserQwParam;
+import com.fs.qw.vo.FsUserCompanyUserQwVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 微信用户和销售关系-企业微信自动的Controller
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+@RestController
+@RequestMapping("/qw/fsUserCompanyUserQw")
+public class FsUserCompanyUserQwController extends BaseController
+{
+    @Autowired
+    private IFsUserCompanyUserQwService fsUserCompanyUserQwService;
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCompanyUserQwParam userQwParam)
+    {
+        startPage();
+        List<FsUserCompanyUserQwVO> list = fsUserCompanyUserQwService.selectFsUserCompanyUserQwListVO(userQwParam);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出微信用户和销售关系-企业微信自动的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:export')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCompanyUserQwParam userQwParam)
+    {
+        List<FsUserCompanyUserQwVO> list = fsUserCompanyUserQwService.selectFsUserCompanyUserQwListVO(userQwParam);
+        ExcelUtil<FsUserCompanyUserQwVO> util = new ExcelUtil<FsUserCompanyUserQwVO>(FsUserCompanyUserQwVO.class);
+        return util.exportExcel(list, "微信用户和销售关系-企业微信自动的数据");
+    }
+
+    /**
+     * 获取微信用户和销售关系-企业微信自动的详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserCompanyUserQwService.selectFsUserCompanyUserQwById(id));
+    }
+
+    /**
+     * 新增微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:add')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        return toAjax(fsUserCompanyUserQwService.insertFsUserCompanyUserQw(fsUserCompanyUserQw));
+    }
+
+    /**
+     * 修改微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:edit') || @ss.hasPermi('qw:fsUserCompanyUserQw:myEdit')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        return toAjax(fsUserCompanyUserQwService.updateFsUserCompanyUserQw(fsUserCompanyUserQw));
+    }
+
+    /**
+     * 删除微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:remove')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserCompanyUserQwService.deleteFsUserCompanyUserQwByIds(ids));
+    }
+}

+ 1 - 4
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java

@@ -57,11 +57,8 @@ public class QwExternalContactController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(QwExternalContactParam qwExternalContact)
     {
-        if(ObjectUtil.isEmpty(qwExternalContact.getCompanyId())){
-            throw new ServiceException("操作失败,请选择企业!");
-        }
         startPage();
-        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVONewSys(qwExternalContact);
         list.forEach(item->{
 
             if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {

+ 163 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwPushCountController.java

@@ -0,0 +1,163 @@
+package com.fs.qw.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptPushTokenTotal;
+import com.fs.qw.domain.QwPushCount;
+import com.fs.qw.service.IQwPushCountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * 定义销售推送不同类型的企业消息的次数Controller
+ *
+ * @author fs
+ * @date 2025-08-22
+ */
+@RestController
+@RequestMapping("/qw/qwPushCount")
+public class QwPushCountController extends BaseController {
+    @Autowired
+    private IQwPushCountService qwPushCountService;
+    @Autowired
+    private ResourceLoader resourceLoader;
+
+    /**
+     * 查询定义销售推送不同类型的企业消息的次数列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwPushCount qwPushCount) {
+        startPage();
+        List<QwPushCount> list = qwPushCountService.selectQwPushCountList(qwPushCount);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出定义销售推送不同类型的企业消息的次数列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:export')")
+    @Log(title = "定义销售推送不同类型的企业消息的次数", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwPushCount qwPushCount) {
+        List<QwPushCount> list = qwPushCountService.selectQwPushCountList(qwPushCount);
+        ExcelUtil<QwPushCount> util = new ExcelUtil<QwPushCount>(QwPushCount.class);
+        return util.exportExcel(list, "定义销售推送不同类型的企业消息的次数数据");
+    }
+
+    /**
+     * 获取定义销售推送不同类型的企业消息的次数详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        List<Long> companyIdList=new ArrayList<>();
+        QwPushCount qwPushCount = qwPushCountService.selectQwPushCountById(id);
+        companyIdList.add(qwPushCount.getCompanyId());
+        qwPushCount.setCompanyIdList(companyIdList);
+        return AjaxResult.success(qwPushCount);
+    }
+
+
+    /**
+     * 新增定义销售推送不同类型的企业消息的次数
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:add')")
+    @Log(title = "定义销售推送不同类型的企业消息的次数", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwPushCount qwPushCount) {
+        List<Long> existingIds = new ArrayList<>();
+        Map<String, Long> existingDataMap = new HashMap<>();
+        List<QwPushCount> existingPushCounts = qwPushCountService.selectQwPushCountLists();
+        if (existingPushCounts != null && !existingPushCounts.isEmpty()) {
+            existingPushCounts.forEach(item -> {
+                String key = buildDataKey(item.getType(), item.getCompanyId());
+                existingDataMap.put(key, item.getId());
+            });
+        }
+        // 处理公司ID列表(可能为null或空)
+        List<Long> companyIdList = qwPushCount.getCompanyIdList();
+        boolean isEmptyList = companyIdList == null || companyIdList.isEmpty();
+
+        if (isEmptyList) {
+            // 处理无公司ID列表的情况
+            String key = buildDataKey(qwPushCount.getType(), null);
+            if (existingDataMap.containsKey(key)) {
+                existingIds.add(qwPushCount.getId());
+            } else {
+                qwPushCountService.insertQwPushCount(qwPushCount);
+            }
+        } else {
+            // 处理有公司ID列表的情况
+            companyIdList.forEach(companyId -> {
+                String key = buildDataKey(qwPushCount.getType(), companyId);
+                if (existingDataMap.containsKey(key)) {
+                    existingIds.add(companyId);
+                } else {
+                    qwPushCount.setCompanyId(companyId);
+                    qwPushCountService.insertQwPushCount(qwPushCount);
+                }
+            });
+        }
+
+        // 统一处理返回结果
+        if (!existingIds.isEmpty()) {
+            return error("新增限定类型已存在:失败条数" + existingIds.size());
+        } else {
+            return toAjax(1);
+        }
+    }
+    private String buildDataKey(Integer type, Long companyId) {
+        return type + "_" + (companyId == null ? "null" : companyId);
+    }
+
+    /**
+     * 修改定义销售推送不同类型的企业消息的次数
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:edit')")
+    @Log(title = "定义销售推送不同类型的企业消息的次数", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwPushCount qwPushCount) {
+        QwPushCount pushCount;
+        if (qwPushCount.getCompanyId() != null) {
+            pushCount = qwPushCountService.SelectQwPushCountByCompanyId(qwPushCount.getType(), qwPushCount.getCompanyId());
+        } else {
+            pushCount = qwPushCountService.SelectQwPushCountByType(qwPushCount.getType());
+        }
+        if (pushCount != null) {
+            if (!Objects.equals(pushCount.getId(), qwPushCount.getId()) && Objects.equals(pushCount.getCompanyId(), qwPushCount.getCompanyId()) && Objects.equals(pushCount.getType(), qwPushCount.getType())) {
+                return toAjax(0);
+            }
+            if (Objects.equals(pushCount.getPushCount(), qwPushCount.getPushCount())) {
+                return toAjax(0);
+            }
+        }
+        return toAjax(qwPushCountService.updateQwPushCount(qwPushCount));
+    }
+
+    /**
+     * 删除定义销售推送不同类型的企业消息的次数
+     */
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:remove')")
+    @Log(title = "定义销售推送不同类型的企业消息的次数", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(qwPushCountService.deleteQwPushCountByIds(ids));
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:tokenList')")
+    @GetMapping("/tokenList")
+    public TableDataInfo tokenList(FastGptPushTokenTotal pushTokenInfo) {
+        startPage();
+        List<FastGptPushTokenTotal> list = qwPushCountService.selectFastGptPushTokenTotalList(pushTokenInfo);
+        return getDataTable(list);
+    }
+}

+ 83 - 3
fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java

@@ -1,5 +1,6 @@
 package com.fs.qw.controller;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
@@ -16,19 +17,27 @@ import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.domain.QwSopUpdateStatus;
 import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwUserVO;
 import com.fs.sop.domain.QwSop;
+import com.fs.sop.domain.QwSopTempContent;
+import com.fs.sop.domain.QwSopTempVoice;
 import com.fs.sop.params.QwSopAutoTime;
 import com.fs.sop.params.QwSopEditQwUserParam;
 import com.fs.sop.service.IQwSopService;
+import com.fs.sop.service.IQwSopTempContentService;
+import com.fs.sop.service.IQwSopTempVoiceService;
 import com.fs.sop.vo.SopVoiceListVo;
+import org.apache.commons.beanutils.ConvertUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 企微sopController
@@ -52,6 +61,12 @@ public class QwSopController extends BaseController
     private FsUserCourseMapper fsUserCourseMapper;
     @Autowired
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+
+    @Autowired
+    private IQwSopTempContentService qwSopTempContentService;
+
+    @Autowired
+    private IQwSopTempVoiceService voiceService;
     /**
      * 查询企微sop列表
      */
@@ -133,9 +148,59 @@ public class QwSopController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwSop.setCreateBy(loginUser.getUser().getNickName());
         qwSop.setCreateTime(sdf.format(new Date()));
+        int count = qwSopService.insertQwSop(qwSop);
+        if(count > 0){
+            if(qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return toAjax(count);
 
-        return toAjax(qwSopService.insertQwSop(qwSop));
+    }
+    /**
+     * 修改qwSop任务,新增或者删除qwUser
+     * @param qwSop
+     */
+    private void updateTempVoiceInfo(QwSop qwSop) {
+        try {
+            String tempId = qwSop.getTempId();
+            String[] split = qwSop.getQwUserIds().split(",");
+            Long[] qwUserIds = (Long[]) ConvertUtils.convert(split, Long.class);
 
+            List<QwSopTempContent> qwSopTempContentList = qwSopTempContentService.selectQwSopTempContentByTempId(tempId);
+            if(qwSopTempContentList != null && !qwSopTempContentList.isEmpty()){
+                for (QwSopTempContent qwSopTemp : qwSopTempContentList) {
+                    if(qwSopTemp != null && qwSopTemp.getContent() != null){
+                        String content = qwSopTemp.getContent();
+                        JSONObject jsonObject = JSONObject.parseObject(content);
+                        String voiceTxt = jsonObject.getString("value");
+                        String contentType = jsonObject.getString("contentType");
+                        if("7".equals(contentType)){
+                            List<QwUserVO> qwUserVoS = qwUserService.selectQwUserVOByIds(qwUserIds);
+                            if(qwUserVoS != null && !qwUserVoS.isEmpty()){
+                                List<Long> companyUserIdList = qwUserVoS.stream().map(QwUserVO::getCompanyUserId).collect(Collectors.toList());
+                                for (Long companyUserId : companyUserIdList) {
+                                    QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceByCompanyUserIdAndVoiceTxt(companyUserId,voiceTxt);
+                                    if(qwSopTempVoice == null){
+                                        if(companyUserId != null && voiceTxt != null){
+                                            QwSopTempVoice tempVoice = new QwSopTempVoice();
+                                            tempVoice.setVoiceTxt(voiceTxt);
+                                            tempVoice.setCompanyUserId(companyUserId);
+                                            tempVoice.setRecordType(0);
+                                            tempVoice.setCreateTime(LocalDateTime.now());
+                                            tempVoice.setTempId(tempId);
+                                            voiceService.insertQwSopTempVoice(tempVoice);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            logger.error("修改企微sop任务,新增或者删除qwUser异常:" + e.getMessage());
+        }
     }
 
     /**
@@ -146,7 +211,14 @@ public class QwSopController extends BaseController
     @PutMapping
     public R edit(@RequestBody QwSop qwSop)
     {
-        return qwSopService.updateQwSop(qwSop);
+        R sop = qwSopService.updateQwSop(qwSop);
+        String code = sop.get("code").toString();
+        if(code.equals("200")){
+            if(qwSop != null && qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return sop;
     }
 
 
@@ -201,7 +273,15 @@ public class QwSopController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:sop:updateSopQwUser')")
     public R updateSopQwUser(@RequestBody QwSopEditQwUserParam param)
     {
-        return qwSopService.updateSopQwUser(param);
+        R sop = qwSopService.updateSopQwUser(param);
+        String code = sop.get("code").toString();
+        if(code.equals("200")){
+            QwSop qwSop = qwSopService.selectQwSopById(param.getId());
+            if(qwSop != null && qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return sop;
     }
 
     /**

+ 11 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java

@@ -5,11 +5,14 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwOptionsVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 /**
  * 企微用户Controller
  *
@@ -34,4 +37,12 @@ public class QwUserController extends BaseController {
     public R getQwUserInfo(QwFsUserParam param){
         return R.ok().put("data",qwUserService.getQwUserInfo(param));
     }
+
+
+   @GetMapping("/getMyQwCompanyList")
+    public R getMyQwCompanyList()
+    {
+        List<QwOptionsVO> list = qwUserService.selectQwCompanyListOptionsVOBySys();
+        return  R.ok().put("data",list);
+    }
 }

+ 105 - 0
fs-admin/src/main/java/com/fs/transfer/CustomerTransferApprovalQwController.java

@@ -0,0 +1,105 @@
+package com.fs.transfer;
+
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.framework.web.service.TokenService;
+import com.fs.qw.domain.CustomerTransferApprovalQw;
+import com.fs.qw.service.ICustomerTransferApprovalQwService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 客户转移审批-企微的Controller
+ *
+ * @author fs
+ * @date 2025-10-24
+ */
+@RestController
+@RequestMapping("qw/system/approval")
+public class CustomerTransferApprovalQwController extends BaseController
+{
+    @Autowired
+    private ICustomerTransferApprovalQwService customerTransferApprovalQwService;
+
+    @Autowired
+    private TokenService tokenService;
+    /**
+     * 查询客户转移审批-企微的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        customerTransferApprovalQw.setInitiatorUserId(loginUser.getUser().getUserId());
+        List<CustomerTransferApprovalQw> list = customerTransferApprovalQwService.selectCustomerTransferApprovalQwList(customerTransferApprovalQw);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出客户转移审批-企微的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:export')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        List<CustomerTransferApprovalQw> list = customerTransferApprovalQwService.selectCustomerTransferApprovalQwList(customerTransferApprovalQw);
+        ExcelUtil<CustomerTransferApprovalQw> util = new ExcelUtil<CustomerTransferApprovalQw>(CustomerTransferApprovalQw.class);
+        return util.exportExcel(list, "客户转移审批-企微的数据");
+    }
+
+    /**
+     * 获取客户转移审批-企微的详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(customerTransferApprovalQwService.selectCustomerTransferApprovalQwById(id));
+    }
+
+    /**
+     * 新增客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:add')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        return toAjax(customerTransferApprovalQwService.insertCustomerTransferApprovalQw(customerTransferApprovalQw));
+    }
+
+    /**
+     * 修改客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:edit') || @ss.hasPermi('qw:approval:revoke')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        return toAjax(customerTransferApprovalQwService.updateCustomerTransferApprovalQw(customerTransferApprovalQw));
+    }
+
+    /**
+     * 删除客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:remove')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(customerTransferApprovalQwService.deleteCustomerTransferApprovalQwByIds(ids));
+    }
+}

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

@@ -4,7 +4,7 @@ server:
 # Spring配置
 spring:
   profiles:
-    active: druid-jnmy-test
+    active: dev
 #    active: druid-hdt
 #    active: druid-yzt
 #    active: druid-sxjz

+ 0 - 181
fs-admin/src/test/java/com/fs/course/controller/OpenIMServiceTest.java

@@ -1,181 +0,0 @@
-package com.fs.course.controller;
-
-import cn.hutool.json.JSONUtil;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fs.FSApplication;
-import com.fs.common.annotation.DataSource;
-import com.fs.his.domain.FsPrescribe;
-import com.fs.his.domain.FsPrescribeDrug;
-import com.fs.his.domain.FsStoreOrder;
-import com.fs.his.dto.FsPrescribeUsageDTO;
-import com.fs.his.mapper.FsInquiryOrderMapper;
-import com.fs.his.mapper.FsPrescribeDrugMapper;
-import com.fs.his.mapper.FsPrescribeMapper;
-import com.fs.his.param.PrescribeXyImgParam;
-import com.fs.his.service.IFsStoreOrderService;
-import com.fs.his.service.PrescriptionImageService;
-import com.fs.his.vo.FsInquiryOrderVO;
-import com.fs.his.vo.FsPrescribeVO;
-import com.fs.im.dto.OpenImMsgDTO;
-import com.fs.im.dto.OpenImResponseDTO;
-import com.fs.im.service.OpenIMService;
-import lombok.extern.slf4j.Slf4j;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.test.context.ActiveProfiles;
-
-import java.util.List;
-
-import static org.junit.Assert.assertNotNull;
-
-@Slf4j
-@ActiveProfiles("druid-syysy-test")
-@RunWith(org.springframework.test.context.junit4.SpringRunner.class)
-@SpringBootTest(classes = FSApplication.class)
-public class OpenIMServiceTest {
-
-    @Autowired
-    private OpenIMService openIMService;
-    @Autowired
-    private PrescriptionImageService prescriptionImageService;
-    @Autowired
-    private FsPrescribeMapper fsPrescribeMapper;
-
-    @Autowired
-    private IFsStoreOrderService storeOrderService;
-
-    @Autowired
-    private FsInquiryOrderMapper fsInquiryOrderMapper;
-
-    @Autowired
-    private FsPrescribeDrugMapper fsPrescribeDrugMapper;
-
-    @Test
-    public void generateImg() {
-        FsPrescribeVO f = fsPrescribeMapper.selectFsPrescribeByPrescribeIdVO(11L);
-
-        FsStoreOrder fsStoreOrder = storeOrderService.selectFsStoreOrderByOrderId(f.getStoreOrderId());
-        FsInquiryOrderVO order = fsInquiryOrderMapper.selectFsInquiryOrderVOByOrderId(f.getInquiryOrderId());
-        FsPrescribeDrug d = new FsPrescribeDrug();
-        d.setPrescribeId(f.getPrescribeId());
-        List<FsPrescribeDrug> list = fsPrescribeDrugMapper.selectFsPrescribeDrugList(d);
-        PrescribeXyImgParam o = new PrescribeXyImgParam();
-        o.setTotalPrice(fsStoreOrder.getPayPrice());
-        o.setTime(f.getCreateTime());
-        o.setPrescribeId(f.getPrescribeCode());
-        o.setPatientName(f.getPatientName());
-        o.setPatientGender(f.getPatientGender());
-        o.setPatientAge(f.getPatientAge());
-        o.setOutpatientId(f.getPrescribeCode());
-        o.setUrl(f.getPrescribeDoctorSignUrl());
-        o.setDrugDoctorUrl(f.getDrugDoctorSignUrl());
-        if (order != null) {
-            o.setBedId(order.getDeptName());
-        } else {
-            o.setBedId("中医科");
-        }
-        String remark = "";
-        if (f.getUsageJson() != null) {
-            FsPrescribeUsageDTO usage = JSONUtil.toBean(f.getUsageJson(), FsPrescribeUsageDTO.class);
-            remark = usage.getRemark();
-        }
-        if (remark != null && remark != "") {
-            o.setRemark(remark);
-        } else {
-            o.setRemark("请按照用药说明书服用药品,如有不适,请及时就医!");
-        }
-        o.setHistoryAllergic(f.getHistoryAllergic());
-        o.setDiagnose("慢性咽炎。");
-        o.setPrescribeDrug(list); // 在这里添加处方药品列表的值
-        o.setDoctorName(f.getDoctorName());
-        o.setAuditDoctor(f.getDoctorDrugName());
-        o.setDispatcher("");
-        o.setCheckDoctor("");
-        o.setDoctorName(f.getDoctorName());
-        o.setTelPhone("15560889998");
-        o.setDoctorTitle("砖家");
-        o.setDoctorNo("155608608433128");
-        String s = prescriptionImageService.generatePrescriptionImage(o);
-        log.info(s);
-    }
-
-    @Test
-    public void openIMSendMsg() {
-        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
-        openImMsgDTO.setSendID("fbyC8584");
-        openImMsgDTO.setRecvID("fbyU1077739");
-//        openImMsgDTO.setGroupID("group789");
-        openImMsgDTO.setSenderNickname("测试用户");
-        openImMsgDTO.setSenderFaceURL("https://example.com/avatar.jpg");
-        openImMsgDTO.setSenderPlatformID(1);
-        openImMsgDTO.setContentType(101);
-        openImMsgDTO.setSessionType(1);
-        openImMsgDTO.setOnlineOnly(false);
-        openImMsgDTO.setNotOfflinePush(false);
-        openImMsgDTO.setSendTime(System.currentTimeMillis());
-        openImMsgDTO.setEx("额外信息");
-
-        // Content
-        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
-        content.setContent("Hello World");
-        content.setData("test data");
-        content.setDescription("测试消息");
-        content.setExtension("ext");
-        openImMsgDTO.setContent(content);
-
-        // OfflinePushInfo
-        OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
-        offlinePushInfo.setTitle("新消息");
-        offlinePushInfo.setDesc("您收到一条新消息");
-        offlinePushInfo.setEx("push ex");
-        offlinePushInfo.setIOSPushSound("default");
-        offlinePushInfo.setIOSBadgeCount(true);
-        openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
-
-        // 调用方法
-        OpenImResponseDTO result = openIMService.openIMSendMsg(openImMsgDTO);
-
-        // 断言
-        assertNotNull(result);
-    }
-
-    @Test
-    public void aiAutoReply() {
-    }
-
-    @Test
-    public void sendUtil() {
-    }
-
-    @Test
-    public void sendUtilUserToDoctor() {
-    }
-
-    @Test
-    public void editConversation() {
-    }
-
-    @Test
-    public void sendCourse() throws JsonProcessingException {
-        Long userId = 1077739L;
-        Long companyUserId = 8584L;
-        String url = "https://example.com/course/123";
-        String title = "Java编程基础课程";
-        String linkImageUrl = "https://example.com/images/course-cover.jpg";
-        String cropId = "crop_123456";
-
-        OpenImResponseDTO actualResponse = openIMService.sendCourse(
-                userId, companyUserId, url, title, linkImageUrl, cropId
-        );
-        log.info("返回结果: {}", actualResponse);
-    }
-
-    @Test
-    public void sendPackageUtil() {
-    }
-}

+ 25 - 0
fs-common/src/main/java/com/fs/common/utils/DateUtils.java

@@ -270,5 +270,30 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         cal.add(Calendar.DATE, days);
         return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
     }
+    /**
+     * 获取到当天时间的开始:当天0时0分0秒0毫秒
+     * @return
+     */
+    public static Long toStartTime( ) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTimeInMillis();
+    }
+
+    /**
+     * 获取到当天时间的结束:当天23时59分59秒999毫秒
+     * @return
+     */
+    public static Long toEndTime() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        return calendar.getTimeInMillis();
+    }
 
 }

+ 31 - 1
fs-company/src/main/java/com/fs/company/controller/common/Test.java

@@ -28,6 +28,10 @@ import com.fs.his.service.impl.FsPackageOrderServiceImpl;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
+import com.fs.hisStore.vo.FsStoreOrderVO;
 import com.fs.im.service.IImService;
 import com.fs.im.service.OpenIMService;
 import com.fs.qw.service.IQwAppContactWayService;
@@ -41,6 +45,7 @@ import com.fs.sop.service.IQwSopTempDayService;
 import com.fs.sop.service.IQwSopTempRulesService;
 import com.fs.sop.service.IQwSopTempService;
 import com.fs.system.mapper.SysConfigMapper;
+import com.fs.wx.domain.FsWxExpressTask;
 import com.google.zxing.WriterException;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
@@ -52,6 +57,7 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 import javax.imageio.ImageIO;
@@ -81,6 +87,8 @@ public class Test {
     @Autowired
     IFsStoreOrderService fsStoreOrderService;
     @Autowired
+    FsStoreOrderScrmMapper fsStoreOrderScrmMapper    ;
+    @Autowired
     FsStoreOrderMapper fsStoreOrderMapper;
     @Autowired
     private RedisCache redisCache;
@@ -239,7 +247,7 @@ public class Test {
                                         //更新商订单状态 删除REDIS
                                         logger.info("查询到的"+delivery);
 
-                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name(),delivery.getSend_date());
                                         redisCache.deleteObject("delivery"+":"+order.getExtendOrderId());
                                     }
                                 }
@@ -251,4 +259,26 @@ public class Test {
         }
     }
 
+
+//    void save(){
+//        List<FsStoreOrderScrm> FsStoreOrderScrms = fsStoreOrderScrmMapper.selectFsStoreOrderList(new FsStoreOrderScrm());
+//        for (FsStoreOrderScrm fsStoreOrderScrm : FsStoreOrderScrms) {
+//            FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
+//            fsWxExpressTask.setUserId(order.getUserId());
+//            fsWxExpressTask.setStatus(0);
+//            fsWxExpressTask.setRetryCount(0);
+//            fsWxExpressTask.setCreateTime(LocalDateTime.now());
+//            fsWxExpressTask.setUpdateTime(LocalDateTime.now());
+//            fsWxExpressTask.setOrderCode(order.getOrderCode());
+//            fsWxExpressTask.setExpressCompany(express.getCode());
+//            fsWxExpressTask.setExpressNo(deliveryId);
+//            List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentScrmService.selectFsStorePaymentByOrderIdNew(order.getId());
+//            if(fsStorePayments!=null&&!fsStorePayments.isEmpty()){
+//                FsStorePaymentScrm  fsStorePayment = fsStorePayments.get(0);
+//                fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());
+//            }
+//            fsWxExpressTaskMapper.insert(fsWxExpressTask);
+//        }
+//
+//    }
 }

+ 11 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java

@@ -539,6 +539,17 @@ public class CompanyUserController extends BaseController
             return AjaxResult.error("操作失败");
         }
     }
+
+    @Log(title = "是否允许客户能在其他销售那里能看", businessType = BusinessType.UPDATE)
+    @PutMapping("/allowedEveryoneView")
+    public AjaxResult allowedEveryoneView(@RequestParam Integer status, @RequestBody List<Long> userIds) {
+        Boolean r = companyUserService.isAllowedEveryoneView(status, userIds);
+        if (r) {
+            return AjaxResult.success();
+        } else {
+            return AjaxResult.error("操作失败");
+        }
+    }
     @PostMapping("/common/uploadOSS")
     public R uploadOSS(@RequestParam("file") MultipartFile file,
                        @RequestParam("userId") String userId) throws Exception {

+ 15 - 0
fs-company/src/main/java/com/fs/company/controller/course/qw/FsQwCourseWatchLogController.java

@@ -81,6 +81,21 @@ public class FsQwCourseWatchLogController extends BaseController
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
         return getDataTable(list);
     }
+    @Log(title = "企微看课记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/statisticsExport")
+    public AjaxResult statisticsExport(FsCourseWatchLogStatisticsListParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return AjaxResult.error("请选择时间");
+        }
+        param.setSendType(2);
+        List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
+        ExcelUtil<FsCourseWatchLogStatisticsListVO> util = new ExcelUtil<FsCourseWatchLogStatisticsListVO>(FsCourseWatchLogStatisticsListVO.class);
+        return util.exportExcel(list, "企微看课记录数据");
+    }
+
 
     @GetMapping("/qwWatchLogStatisticsList")
     public TableDataInfo qwWatchLogStatisticsList(QwWatchLogStatisticsListParam param)

+ 144 - 0
fs-company/src/main/java/com/fs/company/controller/qw/FsUserAdminByQwController.java

@@ -0,0 +1,144 @@
+package com.fs.company.controller.qw;
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.cache.ICompanyUserCacheService;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+
+import com.fs.his.domain.FsUser;
+import com.fs.his.service.IFsUserService;
+import com.fs.his.utils.PhoneUtil;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.domain.CustomerTransferApproval;
+import com.fs.qw.domain.CustomerTransferApprovalQw;
+import com.fs.qw.dto.FsUserTransferParamDTO;
+import com.fs.qw.service.ICustomerTransferApprovalQwService;
+import com.fs.qw.service.ICustomerTransferApprovalService;
+import com.fs.store.param.h5.FsUserPageListParam;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
+
+@Api(tags = "企微会员管理接口")
+@RestController
+@Slf4j
+@RequestMapping("/qw/fsUserByQw")
+@AllArgsConstructor
+public class FsUserAdminByQwController extends BaseController {
+
+    @Autowired
+    private IFsUserService fsUserService;
+
+    @Autowired
+    private ICompanyUserCacheService companyUserCacheService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ICustomerTransferApprovalQwService transferApprovalQwService;
+
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:list')")
+    @PostMapping("/list")
+    @ApiOperation("会员列表(与移动端使用的相同查询)")
+    public TableDataInfo pageList(@RequestBody FsUserPageListParam param) {
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        if(param.getPhone()!=null && !"".equals(param.getPhone())){
+            param.setPhone(PhoneUtil.encryptPhone(param.getPhone()));
+        }
+        return fsUserService.selectFsUserPageListNewQw(param);
+    }
+
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:myList')")
+    @PostMapping("/myList")
+    @ApiOperation("我的会员列表(与移动端使用的相同查询)")
+    public TableDataInfo pageMyList(@RequestBody FsUserPageListParam param) {
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(String.valueOf(loginUser.getUser().getUserId()));
+        param.setIsAdmin(loginUser.getUser().isAdmin());
+
+        if(param.getCompanyUserId() == null) {
+            throw new IllegalArgumentException("当前销售不存在!");
+        }
+        return fsUserService.selectFsUserPageListNewQw(param);
+    }
+
+    /**
+     * 转移
+     * @param param
+     */
+    @PostMapping("/transfer")
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:transfer') || @ss.hasPermi('user:fsUserQw:myTransfer') ")
+    public R transfer(@RequestBody FsUserTransferParamDTO param){
+        log.info("客户转移: {}",param);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setSourceCompanyUserId(loginUser.getUser().getUserId());
+        CustomerTransferApprovalQw transferApprovalQw = new CustomerTransferApprovalQw();
+        transferApprovalQw.setCorpId(String.valueOf(loginUser.getCompany().getCompanyId()));
+        transferApprovalQw.setCustomerIds(JSON.toJSONString(param.getUserIds()));
+        transferApprovalQw.setOriginalUserId(param.getSourceCompanyUserId());
+        transferApprovalQw.setTargetUserId(param.getTargetCompanyUserId());
+        transferApprovalQw.setInitiatorUserId(param.getSourceCompanyUserId());
+        transferApprovalQw.setContent(param.getContent());
+        transferApprovalQw.setCreatedAt(new Date());
+        transferApprovalQw.setUpdatedAt(new Date());
+        transferApprovalQw.setApprovalStatus(0);
+        transferApprovalQw.setTransferType(2);
+        transferApprovalQwService.insertCustomerTransferApprovalQw(transferApprovalQw);
+        return R.ok("转移申请已经提交,等待转移成功!");
+    }
+
+    /**
+     * 获取用户详细信息
+     */
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(fsUserService.selectFsUserPageListVOByUserIdQw(userId));
+    }
+
+    /**
+     * 修改用户
+     */
+    @PreAuthorize("@ss.hasPermi('user:fsUserQw:edit')")
+    @Log(title = "用户", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUser fsUser)
+    {
+        return toAjax(fsUserService.updateFsUser(fsUser));
+    }
+
+
+}

+ 106 - 0
fs-company/src/main/java/com/fs/company/controller/qw/FsUserCompanyUserQwController.java

@@ -0,0 +1,106 @@
+package com.fs.company.controller.qw;
+
+import java.util.List;
+
+import com.fs.qw.param.FsUserCompanyUserQwParam;
+import com.fs.qw.vo.FsUserCompanyUserQwVO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.course.service.IFsUserCompanyUserQwService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 微信用户和销售关系-企业微信自动的Controller
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+@RestController
+@RequestMapping("/qw/fsUserCompanyUserQw")
+public class FsUserCompanyUserQwController extends BaseController
+{
+    @Autowired
+    private IFsUserCompanyUserQwService fsUserCompanyUserQwService;
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCompanyUserQwParam userQwParam)
+    {
+        startPage();
+        List<FsUserCompanyUserQwVO> list = fsUserCompanyUserQwService.selectFsUserCompanyUserQwListVO(userQwParam);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出微信用户和销售关系-企业微信自动的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:export')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCompanyUserQwParam userQwParam)
+    {
+        List<FsUserCompanyUserQwVO> list = fsUserCompanyUserQwService.selectFsUserCompanyUserQwListVO(userQwParam);
+        ExcelUtil<FsUserCompanyUserQwVO> util = new ExcelUtil<FsUserCompanyUserQwVO>(FsUserCompanyUserQwVO.class);
+        return util.exportExcel(list, "微信用户和销售关系-企业微信自动的数据");
+    }
+
+    /**
+     * 获取微信用户和销售关系-企业微信自动的详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserCompanyUserQwService.selectFsUserCompanyUserQwById(id));
+    }
+
+    /**
+     * 新增微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:add')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        return toAjax(fsUserCompanyUserQwService.insertFsUserCompanyUserQw(fsUserCompanyUserQw));
+    }
+
+    /**
+     * 修改微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:edit') || @ss.hasPermi('qw:fsUserCompanyUserQw:myEdit')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        return toAjax(fsUserCompanyUserQwService.updateFsUserCompanyUserQw(fsUserCompanyUserQw));
+    }
+
+    /**
+     * 删除微信用户和销售关系-企业微信自动的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:fsUserCompanyUserQw:remove')")
+    @Log(title = "微信用户和销售关系-企业微信自动的", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserCompanyUserQwService.deleteFsUserCompanyUserQwByIds(ids));
+    }
+}

+ 27 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java

@@ -20,6 +20,7 @@ import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.vo.CrmMyCustomerListQueryVO;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
+import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwTag;
@@ -28,10 +29,12 @@ import com.fs.qw.service.*;
 import com.fs.qw.vo.QwExternalContactVO;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.qw.vo.QwUserDelLossLogVO;
+import com.fs.voice.utils.StringUtil;
 import com.github.pagehelper.PageHelper;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.codehaus.jettison.json.JSONException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -51,6 +54,7 @@ import static com.fs.his.utils.PhoneUtil.encryptPhone;
  * @author fs
  * @date 2024-06-20
  */
+@Slf4j
 @RestController
 @RequestMapping("/qw/externalContact")
 public class QwExternalContactController extends BaseController
@@ -202,11 +206,34 @@ public class QwExternalContactController extends BaseController
 
                 item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
             }
+            //获取用户下单次数
+            try {
+                fillOrderCount(item);
+            }catch (Exception e){
+                log.error("获取用户下单次数异常:{}",e.getMessage());
+            }
         });
 
         return getDataTable(list);
     }
 
+    /**
+     * 根据用户ID查询并设置下单次数(若用户不存在或ID无效,则设为0)
+     */
+    private void fillOrderCount(QwExternalContactVO item){
+        Long fsUserId = item.getFsUserId();
+        if (fsUserId==null){
+            item.setOrderCount(0L);
+            return;
+        }
+        FsUser fsUser = fsUserService.selectFsUserById(fsUserId);
+        if (fsUser == null) {
+            item.setOrderCount(0L);
+            return;
+        }
+        Long orderCount = fsUser.getOrderCount();
+        item.setOrderCount(orderCount != null ? orderCount : 0);
+    }
 
     @Log(title = "同步我的企业微信客户", businessType = BusinessType.INSERT)
     @GetMapping("/syncMyExternalContact/{id}")

+ 14 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.qw;
 
+import cn.hutool.core.util.IdUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
@@ -346,6 +347,15 @@ public class QwUserController extends BaseController
     }
 
 
+    /**
+     * 根据销售账号密码 获取 他的所有企业微信账号以及云主机和账号密码
+     */
+    @GetMapping("/qwExternalContactAddAndDelByRedis")
+    public R selectCloudByCompany()  {
+        qwExternalContactService.qwExternalContactAddAndDelByRedis();
+        return R.ok();
+    }
+
     /**
      * 企业微信员工账号 绑定 云主机
      */
@@ -663,6 +673,10 @@ public class QwUserController extends BaseController
                     qu.setCompanyUserId(qwUserParam.getCompanyUserId());
                     qu.setStatus(1);
                     qu.setCompanyId(companyUser.getCompanyId());
+
+                    String snowKey = IdUtil.getSnowflake(0, 0).nextIdStr();
+                    qu.setAppKey(StringUtil.strIsNullOrEmpty(qu.getAppKey())? snowKey:qu.getAppKey());
+                    qu.setQwHookId(StringUtil.strIsNullOrEmpty(qu.getAppKey())? snowKey:qu.getAppKey());
                     qwUserService.updateQwUser(qu);
 
                 }

+ 10 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsPackageController.java

@@ -122,4 +122,14 @@ public class FsPackageController extends BaseController
         List<FsPackageListVO> list = fsPackageService.selectFsPackageListVByName(packageName);
         return AjaxResult.success(list);
     }
+
+    /**
+     * 查询私有套餐包列表
+     */
+    @GetMapping("/privatePackageList")
+    public TableDataInfo selectAllPrivatePackageList()
+    {
+        List<OptionsVO> list = fsPackageService.selectAllPrivatePackageList();
+        return getDataTable(list);
+    }
 }

+ 5 - 9
fs-company/src/main/java/com/fs/company/controller/store/FsPackageOrderController.java

@@ -171,16 +171,12 @@ public class FsPackageOrderController extends BaseController
     @Log(title = "查看套餐电话", businessType = BusinessType.GRANT)
     public R getPhone(@PathVariable("orderId") Long orderId)
     {
-        LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (loginUser.getUser().getUserType().equals("00")){
-            FsPackageOrderVO order = fsPackageOrderService.selectFsPackageOrderByOrderIdVO(orderId);
-            String userPhone = order.getPhone();
-            if (StringUtils.isNotBlank(userPhone) && userPhone.trim().length() > 11) {
-                userPhone = PhoneUtil.decryptPhone(userPhone);
-            }
-            return R.ok().put("userPhone",userPhone);
+        FsPackageOrderVO order = fsPackageOrderService.selectFsPackageOrderByOrderIdVO(orderId);
+        String userPhone = order.getPhone();
+        if (StringUtils.isNotBlank(userPhone) && userPhone.trim().length() > 11) {
+            userPhone = PhoneUtil.decryptPhone(userPhone);
         }
-        return R.error("无权查看");
+        return R.ok().put("userPhone",userPhone);
     }
 
     /**

+ 61 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsStoreAfterSalesController.java

@@ -1,17 +1,22 @@
 package com.fs.company.controller.store;
 
+import cn.hutool.core.date.DateTime;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import com.fs.his.domain.FsExportTask;
 import com.fs.his.domain.FsStoreAfterSales;
+import com.fs.his.domain.FsStoreAfterSalesLogs;
+import com.fs.his.enums.FsStoreAfterSalesStatusEnum;
 import com.fs.his.param.FsStoreAfterSalesParam;
 import com.fs.his.service.IFsExportTaskService;
+import com.fs.his.service.IFsStoreAfterSalesLogsService;
 import com.fs.his.service.IFsStoreAfterSalesService;
 import com.fs.his.vo.FsStoreAfterSalesListVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,6 +40,8 @@ public class FsStoreAfterSalesController extends BaseController
     private IFsStoreAfterSalesService fsStoreAfterSalesService;
     @Autowired
     private IFsExportTaskService exportTaskService;
+    @Autowired
+    private IFsStoreAfterSalesLogsService fsStoreAfterSalesLogsService;
     /**
      * 查询售后记录列表
      */
@@ -182,6 +189,15 @@ public class FsStoreAfterSalesController extends BaseController
     public AjaxResult edit(@RequestBody FsStoreAfterSales fsStoreAfterSales)
     {
         fsStoreAfterSales.setStatus(2);
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        //操作记录
+        FsStoreAfterSalesLogs logs = new FsStoreAfterSalesLogs();
+        logs.setChangeTime(new DateTime());
+        logs.setChangeType(2);
+        logs.setOperator(loginUser.getUser().getNickName());
+        logs.setStoreAfterSalesId(fsStoreAfterSales.getId());
+        logs.setChangeMessage(FsStoreAfterSalesStatusEnum.STATUS_2.getDesc());
+        fsStoreAfterSalesLogsService.insertFsStoreAfterSalesLogs(logs);
         return toAjax(fsStoreAfterSalesService.updateFsStoreAfterSales(fsStoreAfterSales));
     }
 
@@ -231,5 +247,50 @@ public class FsStoreAfterSalesController extends BaseController
         return AjaxResult.success(s);
     }
 
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:audit')")
+    @PutMapping("/auditing")
+    @Log(title = "销售端平台审核", businessType = BusinessType.UPDATE)
+    public AjaxResult auditing(@RequestBody FsStoreAfterSales fsStoreAfterSales)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsStoreAfterSales.setOperator(loginUser.getUser().getNickName());
+        return toAjax(fsStoreAfterSalesService.auditing(fsStoreAfterSales));
+    }
+
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:depot')")
+    @Log(title = "销售端仓库审核", businessType = BusinessType.UPDATE)
+    @PutMapping("/depotAuditing")
+    public AjaxResult depotAuditing(@RequestBody FsStoreAfterSales fsStoreAfterSales)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsStoreAfterSales.setOperator(loginUser.getUser().getNickName());
+        return toAjax(fsStoreAfterSalesService.depotAuditing(fsStoreAfterSales));
+    }
+    /**
+     * 审核
+     */
+    @Log(title = "销售端撤销审核", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:revoke')")
+    @PutMapping("/noAuditing")
+    public AjaxResult noAuditing(@RequestBody FsStoreAfterSales fsStoreAfterSales)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsStoreAfterSales.setOperator(loginUser.getUser().getNickName());
+        return toAjax(fsStoreAfterSalesService.noAuditing(fsStoreAfterSales));
+    }
+
+    /**
+     * 财务审核并退款
+     */
+    @Log(title = "销售端财务审核", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:finance')")
+    @PutMapping("/tuiMoney")
+    public AjaxResult tuiMoney(@RequestBody FsStoreAfterSales fsStoreAfterSales)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsStoreAfterSales.setOperator(loginUser.getUser().getNickName());
+        return toAjax(fsStoreAfterSalesService.refundMoney(fsStoreAfterSales));
+    }
+
 
 }

+ 16 - 13
fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java

@@ -242,19 +242,12 @@ public class FsStoreOrderController extends BaseController
     @Log(title = "查看电话", businessType = BusinessType.GRANT)
     public R getPhone(@PathVariable("orderId") Long orderId)
     {
-        LoginUser loginUser = SecurityUtils.getLoginUser();
-        if (loginUser.getUser().getUserType().equals("00")){
-            FsStoreOrderVO order = fsStoreOrderService.selectFsStoreOrderByOrderIdVO(orderId);
-            if (order.getUserPhone().length()>11){
-
-                return R.ok().put("userPhone",PhoneUtil.decryptPhone(order.getUserPhone()));
-            }else {
-                return R.ok().put("userPhone",order.getUserPhone());
-            }
-
-
+        FsStoreOrderVO order = fsStoreOrderService.selectFsStoreOrderByOrderIdVO(orderId);
+        if (order.getUserPhone().length()>11){
+            return R.ok().put("userPhone",PhoneUtil.decryptPhone(order.getUserPhone()));
+        }else {
+            return R.ok().put("userPhone",order.getUserPhone());
         }
-        return R.error("无权查看");
     }
 
     /**
@@ -297,7 +290,17 @@ public class FsStoreOrderController extends BaseController
     {
         return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
     }
-
+    /**
+     * 修改订单
+     */
+    @PreAuthorize("@ss.hasPermi('his:storeOrder:edit')")
+    @Log(title = "订单修改", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateAddressErpFsStoreOrder")
+    public AjaxResult updateAddressErpFsStoreOrder(@RequestBody FsStoreOrder fsStoreOrder)
+    {
+        logger.info("修改订单 参数: {}",fsStoreOrder);
+        return toAjax(fsStoreOrderService.updateAddressErpFsStoreOrder(fsStoreOrder));
+    }
     /**
      * 修改订单
      */

+ 1 - 0
fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java

@@ -132,6 +132,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .antMatchers("/druid/**").anonymous()
                 .antMatchers("/qw/data/**").anonymous()
                 .antMatchers("/qw/user/selectCloudByCompany").anonymous()
+                .antMatchers("/qw/user/qwExternalContactAddAndDelByRedis").anonymous()
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()
                 .and()

+ 50 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsQuestionAndAnswerController.java

@@ -0,0 +1,50 @@
+package com.fs.hisStore.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsQuestionAndAnswer;
+import com.fs.his.service.IFsQuestionAndAnswerService;
+import com.fs.his.vo.OptionsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 问答Controller
+ * 
+ * @author fs
+ * @date 2025-09-29
+ */
+@RestController
+@RequestMapping("/store/answer")
+public class FsQuestionAndAnswerController extends BaseController
+{
+    @Autowired
+    private IFsQuestionAndAnswerService fsQuestionAndAnswerService;
+
+
+    /**
+     * 获取问答详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsQuestionAndAnswerService.selectFsQuestionAndAnswerById(id));
+    }
+
+    /**
+     * 查询问答列表
+     */
+    @GetMapping("/allList")
+    public TableDataInfo getHospital()
+    {
+        List<OptionsVO> list = fsQuestionAndAnswerService.selectAllQuestionOptions();
+        return getDataTable(list);
+    }
+}

+ 50 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java

@@ -12,6 +12,7 @@ import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
@@ -19,6 +20,10 @@ import com.fs.hisStore.domain.FsStoreAfterSalesItemScrm;
 import com.fs.hisStore.domain.FsStoreAfterSalesScrm;
 import com.fs.hisStore.domain.FsStoreAfterSalesStatusScrm;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.param.FsStoreAfterSalesAudit1Param;
+import com.fs.hisStore.param.FsStoreAfterSalesAudit2Param;
+import com.fs.hisStore.param.FsStoreAfterSalesCancelParam;
+import com.fs.hisStore.param.FsStoreAfterSalesRefundParam;
 import com.fs.hisStore.service.IFsStoreAfterSalesItemScrmService;
 import com.fs.hisStore.service.IFsStoreAfterSalesScrmService;
 import com.fs.hisStore.service.IFsStoreAfterSalesStatusScrmService;
@@ -28,6 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import java.text.ParseException;
 import java.util.List;
 
 /**
@@ -149,6 +155,50 @@ public class FsStoreAfterSalesScrmController extends BaseController
         return toAjax(fsStoreAfterSalesService.updateFsStoreAfterSales(fsStoreAfterSales));
     }
 
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:audit1')")
+    @PostMapping("/audit1")
+    //平台审核
+    public R audit1(@RequestBody FsStoreAfterSalesAudit1Param param)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        param.setOperator(loginUser.getUser().getNickName());
+        return fsStoreAfterSalesService.audit1(param);
+    }
+
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:audit2')")
+    @PostMapping("/audit2")
+    //仓库审核
+    public R audit2(@RequestBody FsStoreAfterSalesAudit2Param param)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        param.setOperator(loginUser.getUser().getNickName());
+        return fsStoreAfterSalesService.audit2(param);
+    }
+    //财务审核
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:refund')")
+    @PostMapping("/refund")
+    public R refund(@RequestBody FsStoreAfterSalesRefundParam param)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        param.setOperator(loginUser.getUser().getNickName());
+        return fsStoreAfterSalesService.refundMoney(param);
+    }
+    //平台撤销
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:cancel')")
+    @PostMapping("/cancel")
+    public R cancel(@RequestBody FsStoreAfterSalesCancelParam param) throws ParseException {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        param.setOperator(loginUser.getUser().getNickName());
+        return fsStoreAfterSalesService.cancel(param);
+    }
+
+    @GetMapping("/getStoreAfterSales")
+    public R getStoreAfterSales(@RequestParam("orderCode") String orderCode)
+    {
+        List<FsStoreAfterSalesVO> vo = fsStoreAfterSalesService.selectFsStoreAfterSalesVOByOrderCode(orderCode);
+        return R.ok().put("data",vo);
+    }
+
 
 
 

+ 3 - 7
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderOfflineScrmController.java

@@ -110,13 +110,9 @@ public class FsStoreOrderOfflineScrmController extends BaseController
     @Log(title = "查看电话", businessType = BusinessType.GRANT)
     public R getPhone(@PathVariable("orderId") Long orderId)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if (loginUser.getUser().getUserType().equals("00")){
-            FsStoreOrderOfflineListVO order=fsStoreOrderOfflineService.selectFsStoreOrderOfflineVOById(orderId);
-            String userPhone = order.getMobile();
-            return R.ok().put("userPhone",userPhone);
-        }
-        return R.error("无权查看");
+        FsStoreOrderOfflineListVO order=fsStoreOrderOfflineService.selectFsStoreOrderOfflineVOById(orderId);
+        String userPhone = order.getMobile();
+        return R.ok().put("userPhone",userPhone);
     }
 
     /**

+ 14 - 7
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -236,13 +236,9 @@ public class FsStoreOrderScrmController extends BaseController
     @Log(title = "查看电话", businessType = BusinessType.GRANT)
     public R getPhone(@PathVariable("id") Long id)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if (loginUser.getUser().getUserType().equals("00")){
-            FsStoreOrderScrm order = fsStoreOrderService.selectFsStoreOrderById(id);
-            String userPhone = order.getUserPhone();
-            return R.ok().put("userPhone",userPhone);
-        }
-        return R.error("无权查看");
+        FsStoreOrderScrm order = fsStoreOrderService.selectFsStoreOrderById(id);
+        String userPhone = order.getUserPhone();
+        return R.ok().put("userPhone",userPhone);
     }
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:express')")
@@ -286,6 +282,17 @@ public class FsStoreOrderScrmController extends BaseController
     {
         return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
     }
+    /**
+     * 修改订单
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:edit')")
+    @Log(title = "订单", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateAddressErpFsStoreOrder")
+    public AjaxResult updateAddressErpFsStoreOrder(@RequestBody FsStoreOrderScrm fsStoreOrder)
+    {
+        logger.info("修改订单 参数: {}",fsStoreOrder);
+        return toAjax(fsStoreOrderService.updateAddressErpFsStoreOrder(fsStoreOrder));
+    }
 
     /**
      * 删除订单

+ 122 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsUserInformationCollectionController.java

@@ -0,0 +1,122 @@
+package com.fs.hisStore.controller;
+
+import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
+import com.fs.hisStore.param.FsUserInformationCollectionParam;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.hisStore.domain.FsUserInformationCollection;
+import com.fs.hisStore.service.IFsUserInformationCollectionService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 用户信息采集Controller
+ * 
+ * @author fs
+ * @date 2025-10-14
+ */
+@RestController
+@RequestMapping("/hisStore/collection")
+public class FsUserInformationCollectionController extends BaseController
+{
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
+
+    /**
+     * 查询用户信息采集列表
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserInformationCollection fsUserInformationCollection)
+    {
+        startPage();
+        List<FsUserInformationCollection> list = fsUserInformationCollectionService.selectFsUserInformationCollectionList(fsUserInformationCollection);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户信息采集列表
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:export')")
+    @Log(title = "用户信息采集", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserInformationCollection fsUserInformationCollection)
+    {
+        List<FsUserInformationCollection> list = fsUserInformationCollectionService.selectFsUserInformationCollectionList(fsUserInformationCollection);
+        ExcelUtil<FsUserInformationCollection> util = new ExcelUtil<FsUserInformationCollection>(FsUserInformationCollection.class);
+        return util.exportExcel(list, "用户信息采集数据");
+    }
+
+    /**
+     * 获取用户信息采集详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserInformationCollectionService.selectFsUserInformationCollectionById(id));
+    }
+
+    /**
+     * 新增用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:add')")
+    @Log(title = "用户信息采集", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsUserInformationCollection.setCompanyUserId(loginUser.getUser().getUserId());
+        return toAjax(fsUserInformationCollectionService.insertFsUserInformationCollection(fsUserInformationCollection));
+    }
+
+    /**
+     * 修改用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:edit')")
+    @Log(title = "用户信息采集", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsUserInformationCollection.setCompanyUserId(loginUser.getUser().getUserId());
+        return toAjax(fsUserInformationCollectionService.updateFsUserInformationCollection(fsUserInformationCollection));
+    }
+
+    /**
+     * 删除用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:remove')")
+    @Log(title = "用户信息采集", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserInformationCollectionService.deleteFsUserInformationCollectionByIds(ids));
+    }
+
+    @GetMapping("/getInfo")
+    public AjaxResult getInfo(FsUserInformationCollection fsUserInformationCollection){
+        return AjaxResult.success(fsUserInformationCollectionService.getInfo(fsUserInformationCollection));
+    }
+
+    /**
+     * 生成套餐包付款二维码
+     */
+    @PreAuthorize("@ss.hasPermi('hisStore:collection:WxaCodeCollectionUnLimit')")
+    @GetMapping("/getWxaCodeCollectionUnLimit/{collectionId}")
+    public R getWxaCodeCollectionUnLimit(@PathVariable("collectionId") Long orderId)
+    {
+
+        return fsUserInformationCollectionService.getWxaCodePackageOrderUnLimit(orderId);
+
+    }
+}

+ 125 - 0
fs-company/src/main/java/com/fs/transfer/CustomerTransferApprovalQwController.java

@@ -0,0 +1,125 @@
+package com.fs.transfer;
+
+import java.util.List;
+
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.CustomerTransferApprovalQw;
+import com.fs.qw.service.ICustomerTransferApprovalQwService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 客户转移审批-企微的Controller
+ *
+ * @author fs
+ * @date 2025-10-24
+ */
+@RestController
+@RequestMapping("qw/system/approval")
+public class CustomerTransferApprovalQwController extends BaseController
+{
+    @Autowired
+    private ICustomerTransferApprovalQwService customerTransferApprovalQwService;
+
+    @Autowired
+    private TokenService tokenService;
+    /**
+     * 查询客户转移审批-企微的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        customerTransferApprovalQw.setCorpId(String.valueOf(loginUser.getCompany().getCompanyId()));
+        List<CustomerTransferApprovalQw> list = customerTransferApprovalQwService.selectCustomerTransferApprovalQwList(customerTransferApprovalQw);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询我的客户转移审批-企微的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:myList')")
+    @GetMapping("/myList")
+    public TableDataInfo myList(CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        customerTransferApprovalQw.setInitiatorUserId(loginUser.getUser().getUserId());
+        List<CustomerTransferApprovalQw> list = customerTransferApprovalQwService.selectCustomerTransferApprovalQwList(customerTransferApprovalQw);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出客户转移审批-企微的列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:export')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        List<CustomerTransferApprovalQw> list = customerTransferApprovalQwService.selectCustomerTransferApprovalQwList(customerTransferApprovalQw);
+        ExcelUtil<CustomerTransferApprovalQw> util = new ExcelUtil<CustomerTransferApprovalQw>(CustomerTransferApprovalQw.class);
+        return util.exportExcel(list, "客户转移审批-企微的数据");
+    }
+
+    /**
+     * 获取客户转移审批-企微的详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(customerTransferApprovalQwService.selectCustomerTransferApprovalQwById(id));
+    }
+
+    /**
+     * 新增客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:add')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        return toAjax(customerTransferApprovalQwService.insertCustomerTransferApprovalQw(customerTransferApprovalQw));
+    }
+
+    /**
+     * 修改客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:edit') || @ss.hasPermi('qw:approval:revoke')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CustomerTransferApprovalQw customerTransferApprovalQw)
+    {
+        return toAjax(customerTransferApprovalQwService.updateCustomerTransferApprovalQw(customerTransferApprovalQw));
+    }
+
+    /**
+     * 删除客户转移审批-企微的
+     */
+    @PreAuthorize("@ss.hasPermi('qw:approval:remove')")
+    @Log(title = "客户转移审批-企微的", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(customerTransferApprovalQwService.deleteCustomerTransferApprovalQwByIds(ids));
+    }
+}

+ 9 - 4
fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeController.java

@@ -17,6 +17,8 @@ import com.fs.his.service.IFsExportTaskService;
 import com.fs.his.service.IFsPrescribeService;
 import com.fs.his.vo.FsPrescribeListVO;
 import com.fs.his.vo.FsPrescribeVO;
+import com.fs.hisStore.domain.FsUserInformationCollection;
+import com.fs.hisStore.service.IFsUserInformationCollectionService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
@@ -43,6 +45,9 @@ public class FsPrescribeController extends BaseController
     @Autowired
     private FsPatientMapper fsPatientMapper;
 
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
+
     /**
      * 确认处方
      * @param param 处方
@@ -180,7 +185,10 @@ public class FsPrescribeController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody FsPrescribe fsPrescribe)
     {
-        return toAjax(fsPrescribeService.updateFsPrescribe(fsPrescribe));
+        int i = fsPrescribeService.updateFsPrescribe(fsPrescribe);
+        fsPrescribeService.delUrl(fsPrescribe.getPrescribeId());
+        exportTaskService.updateFsExportTaskByPrescribeId(fsPrescribe.getPrescribeId());
+        return toAjax(i);
     }
 
     /**
@@ -193,7 +201,4 @@ public class FsPrescribeController extends BaseController
         return toAjax(fsPrescribeService.deleteFsPrescribeByPrescribeIds(prescribeIds));
     }
 
-
-
-
 }

+ 91 - 0
fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeCommonController.java

@@ -0,0 +1,91 @@
+package com.fs.app.controller;
+
+import com.fs.app.annotation.Login;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsDoctorPrescribeCommon;
+import com.fs.his.param.FsDiagnosisListDParam;
+import com.fs.his.param.FsDoctorPrescribeCommonQueryParam;
+import com.fs.his.service.IFsDoctorPrescribeCommonService;
+import com.fs.his.vo.FsDiagnosisListDVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 医生常用诊断/建议用语 控制器
+ */
+@Api("医生常用语管理")
+@RestController
+@RequestMapping("/app/prescribe/common")
+public class PrescribeCommonController extends BaseController {
+
+    @Autowired
+    private IFsDoctorPrescribeCommonService fsDoctorPrescribeCommonService;
+
+    /**
+     * 分页查询常用语列表
+     */
+    @ApiOperation("查询常用语列表")
+    @GetMapping("/getPrescribeCommonList")
+    public R getPrescribeCommonList(FsDoctorPrescribeCommonQueryParam param){
+        PageInfo<FsDoctorPrescribeCommon> list = fsDoctorPrescribeCommonService.getList(param);
+        return R.ok().put("data", list);
+    }
+
+    /**
+     * 根据ID查询
+     */
+    @ApiOperation("根据ID查询常用语")
+    @GetMapping("/{commonId}")
+    public R getInfo(@PathVariable Long commonId) {
+        FsDoctorPrescribeCommon prescribeCommon = fsDoctorPrescribeCommonService.getById(commonId);
+        return R.ok().put("data",prescribeCommon);
+    }
+
+    /**
+     * 新增常用语
+     */
+    @ApiOperation("新增常用语")
+    @PostMapping
+    public R add(@Validated @RequestBody FsDoctorPrescribeCommon common) {
+        fsDoctorPrescribeCommonService.save(common);
+        return R.ok("操作成功");
+    }
+
+    /**
+     * 修改常用语
+     */
+    @ApiOperation("修改常用语")
+    @PutMapping
+    public R edit(@Validated @RequestBody FsDoctorPrescribeCommon common) {
+        fsDoctorPrescribeCommonService.update(common);
+        return R.ok("操作成功");
+    }
+
+    /**
+     * 删除常用语
+     */
+    @ApiOperation("删除常用语")
+    @DeleteMapping("/{commonId}")
+    public R remove(@PathVariable Long commonId) {
+        fsDoctorPrescribeCommonService.removeById(commonId);
+        return R.ok("操作成功");
+    }
+
+    /**
+     * 批量删除
+     */
+    @ApiOperation("批量删除常用语")
+    @DeleteMapping("/batch/{ids}")
+    public R batchRemove(@PathVariable Long[] ids) {
+        fsDoctorPrescribeCommonService.removeByIds(ids);
+        return R.ok("操作成功");
+    }
+}

+ 12 - 12
fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java

@@ -157,13 +157,13 @@ public class PrescribeController extends  AppBaseController {
         BeanUtils.copyProperties(param,doctorPrescribe);
         doctorPrescribe.setDoctorId(Long.parseLong(getDoctorId()));
         doctorPrescribeService.insertFsDoctorPrescribe(doctorPrescribe);
-        HashSet<Long> set = new HashSet<>();
+//        HashSet<Long> set = new HashSet<>();
         List<FsDoctorPrescribeDrug> drugs = param.getDrugs();
-        for (FsDoctorPrescribeDrug drug : drugs) {
-            if (!set.add(drug.getProductId())) {
-                return R.error("存在重复药品");
-            }
-        }
+//        for (FsDoctorPrescribeDrug drug : drugs) {
+//            if (!set.add(drug.getProductId())) {
+//                return R.error("存在重复药品");
+//            }
+//        }
 
         for(FsDoctorPrescribeDrug drug:drugs){
             drug.setPrescribeId(doctorPrescribe.getPrescribeId());
@@ -178,12 +178,12 @@ public class PrescribeController extends  AppBaseController {
     public R editPrescribe(@Validated @RequestBody FsDoctorPrescribeAddEditParam param, HttpServletRequest request){
         FsDoctorPrescribe prescribe=doctorPrescribeService.selectFsDoctorPrescribeByPrescribeId(param.getPrescribeId());
         List<FsDoctorPrescribeDrug> drugs = param.getDrugs();
-        HashSet<Long> set = new HashSet<>();
-        for (FsDoctorPrescribeDrug drug : drugs) {
-            if (!set.add(drug.getProductId())) {
-                return R.error("存在重复药品");
-            }
-        }
+//        HashSet<Long> set = new HashSet<>();
+//        for (FsDoctorPrescribeDrug drug : drugs) {
+//            if (!set.add(drug.getProductId())) {
+//                return R.error("存在重复药品");
+//            }
+//        }
         BeanUtils.copyProperties(param,prescribe);
         prescribe.setDoctorId(Long.parseLong(getDoctorId()));
         doctorPrescribeService.updateFsDoctorPrescribe(prescribe);

+ 54 - 0
fs-doctor-app/src/main/java/com/fs/app/controller/UserInfoCollectionController.java

@@ -0,0 +1,54 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.his.param.FsDiagnosisListDParam;
+import com.fs.his.vo.FsDiagnosisListDVO;
+import com.fs.hisStore.domain.FsUserInformationCollection;
+import com.fs.hisStore.param.FsUserInformationCollectionListDParam;
+import com.fs.hisStore.service.IFsUserInformationCollectionService;
+import com.fs.hisStore.vo.FsUserInformationCollectionListDVO;
+import com.fs.hisStore.vo.FsUserInformationCollectionVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+//用户信息采集控制
+@RestController
+@RequestMapping("/app/collection")
+public class UserInfoCollectionController extends AppBaseController{
+    @Autowired
+    private IFsUserInformationCollectionService userInfoCollectionService;
+
+    @GetMapping("/getCollectionList")
+    public R getDiagnosisList(FsUserInformationCollectionListDParam param){
+        param.setDoctorId(Long.parseLong(getDoctorId()));
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsUserInformationCollectionListDVO> list = userInfoCollectionService.selectFsUserInformationCollectionListDVO(param);
+        PageInfo<FsUserInformationCollectionListDVO> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data", pageInfo);
+    }
+
+    @GetMapping("/detail/{id}")
+    public R detail(@PathVariable("id") Long id){
+        FsUserInformationCollectionVO detail = userInfoCollectionService.detail(id);
+        return R.ok().put("data", detail);
+    }
+
+    /**
+     * 医生确认
+     */
+    @PutMapping("/doctorConfirm")
+    public R doctorConfirm(@RequestBody FsUserInformationCollection collection){
+        return userInfoCollectionService.doctorConfirm(collection);
+    }
+
+    //用户采集信息详情
+    @GetMapping("/getCollectionByUserId/{userId}")
+    public R getCollectionByUserId(@PathVariable("userId") Long userId){
+        FsUserInformationCollectionVO detail = userInfoCollectionService.getCollectionByUserId(userId);
+        return R.ok().put("data", detail);
+    }
+}

+ 67 - 18
fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.app.service.IpadSendServer;
 import com.fs.common.core.redis.RedisCacheT;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.PubFun;
 import com.fs.company.service.ICompanyMiniappService;
 import com.fs.course.config.CourseConfig;
@@ -12,8 +13,12 @@ import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.ipad.vo.BaseVo;
 import com.fs.qw.domain.QwIpadServer;
+import com.fs.qw.domain.QwPushCount;
+import com.fs.qw.domain.QwRestrictionPushRecord;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwIpadServerMapper;
+import com.fs.qw.mapper.QwPushCountMapper;
+import com.fs.qw.mapper.QwRestrictionPushRecordMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.service.impl.AsyncSopTestService;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
@@ -55,6 +60,8 @@ public class SendMsg {
     private final AsyncSopTestService asyncSopTestService;
     private final ICompanyMiniappService companyMiniappService;
     private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    private final QwPushCountMapper qwPushCountMapper;
+    private final QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper;
 
     @Value("${group-no}")
     private String groupNo;
@@ -65,7 +72,7 @@ public class SendMsg {
     @Qualifier("customThreadPool")
     private ThreadPoolTaskExecutor customThreadPool;
 
-    public SendMsg(QwUserMapper qwUserMapper, QwSopLogsMapper qwSopLogsMapper, IpadSendServer sendServer, SysConfigMapper sysConfigMapper, IQwSopLogsService qwSopLogsService, QwIpadServerMapper qwIpadServerMapper, RedisCacheT<Long> redisCache, AsyncSopTestService asyncSopTestService, ICompanyMiniappService companyMiniappService, IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService) {
+    public SendMsg(QwUserMapper qwUserMapper, QwSopLogsMapper qwSopLogsMapper, IpadSendServer sendServer, SysConfigMapper sysConfigMapper, IQwSopLogsService qwSopLogsService, QwIpadServerMapper qwIpadServerMapper, RedisCacheT<Long> redisCache, AsyncSopTestService asyncSopTestService, ICompanyMiniappService companyMiniappService, IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService, QwPushCountMapper qwPushCountMapper, QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper) {
         this.qwUserMapper = qwUserMapper;
         this.qwSopLogsMapper = qwSopLogsMapper;
         this.sendServer = sendServer;
@@ -76,6 +83,8 @@ public class SendMsg {
         this.asyncSopTestService = asyncSopTestService;
         this.companyMiniappService = companyMiniappService;
         this.fsCoursePlaySourceConfigService = fsCoursePlaySourceConfigService;
+        this.qwPushCountMapper = qwPushCountMapper;
+        this.qwRestrictionPushRecordMapper = qwRestrictionPushRecordMapper;
     }
     private List<QwUser> getQwUserList() {
         if (qwUserList.isEmpty()) {
@@ -191,27 +200,67 @@ public class SendMsg {
                 continue;
             }
             redisCache.setCacheObject(key, System.currentTimeMillis(), 24, TimeUnit.HOURS);
+            List<QwPushCount> pushCountList = qwPushCountMapper.selectQwPushCountLists();
+            Map<Integer, List<QwPushCount>> pushMap = pushCountList.stream().collect(Collectors.groupingBy(QwPushCount::getType));
             // 循环发送消息里面的每一条消息
             for (QwSopCourseFinishTempSetting.Setting content : setting.getSetting()) {
                 long start4 = System.currentTimeMillis();
-                // 发送
-                sendServer.send(content, user, qwSopLogs, miniMap, parentVo);
-                long end4 = System.currentTimeMillis();
-                log.info("请求pad发送完成:{}, {}, 时长4:{}", user.getQwUserName(), qwSopLogs.getId(), end4 - start4);
-                if(content.getSendStatus() == 2 && ("请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks()) || "请求失败:请求频率异常".equals(content.getSendRemarks()))){
-                    QwUser update = new QwUser();
-                    update.setRemark("请求频率异常,暂停发送,三小时后恢复继续发送");
-                    update.setUpdateTime(new Date());
-                    qwUserMapper.update(update, new QueryWrapper<QwUser>().eq("id", user.getId()));
-                    redisCache.setCacheObject("qw:user:id:" + user.getId(), user.getId(), 3, TimeUnit.HOURS);
-                    return;
+                //判断当前销售推送客户消息限制
+                Long qwUserId = qwUser.getId();//销售的Id
+                Integer type = Integer.valueOf(content.getContentType());//发送消息的类型
+                Long customerId = qwSopLogs.getExternalId();//客户ID
+                Long companyId = qwSopLogs.getCompanyId();//公司ID
+                Integer pushCount = -99;
+                if(pushMap.containsKey(type)){
+                    List<QwPushCount> qwPushCounts = pushMap.get(type);
+                    Optional<QwPushCount> optional = qwPushCounts.stream().filter(e -> Objects.equals(e.getCompanyId(), companyId)).findFirst();
+                    if(optional.isPresent()){
+                        pushCount = optional.get().getPushCount();
+                    }else{
+                        Optional<QwPushCount> nullCount = qwPushCounts.stream().filter(e -> e.getCompanyId() == null).findFirst();
+                        if(nullCount.isPresent()){
+                            pushCount = nullCount.get().getPushCount();
+                        }
+                    }
                 }
-                try {
-                    int delay = ThreadLocalRandom.current().nextInt(300, 1000);
-                    log.debug("pad发送消息等待:{}ms", delay);
-                    Thread.sleep(delay);
-                } catch (InterruptedException e) {
-                    log.error("线程等待错误!");
+                //查询是否有设置限制客服推送消息次数
+//                    Integer pushCount=pushCountMap.containsKey(String.valueOf(companyId)) ? pushCountMap.get(String.valueOf(companyId)): pushCountMap.getOrDefault(String.valueOf(type), -99);
+                int salesPushCustomerMessageCount = qwRestrictionPushRecordMapper.selectQwRestrictionPushRecord(qwUserId, customerId, type, DateUtils.toStartTime(), DateUtils.toEndTime());
+                if (pushCount != -99 && salesPushCustomerMessageCount >= pushCount) {
+                    content.setSendStatus(2);//设置发送失败状态
+                    content.setSendRemarks("发送次数达到上限");
+                } else {
+                    // 发送
+                    sendServer.send(content, user, qwSopLogs, miniMap, parentVo);
+                    //判断销售推送成功:保存记录
+                    if (content.getSendStatus() != 2) {
+                        QwRestrictionPushRecord qrpr = new QwRestrictionPushRecord();
+                        qrpr.setType(type);
+                        qrpr.setQwUserId(qwUserId);
+                        qrpr.setQwExternalId(customerId);
+                        qrpr.setCompanyId(companyId);
+                        qrpr.setStatus(1);
+                        qrpr.setCreateTime(DateUtils.getTime());
+                        qrpr.setTime(System.currentTimeMillis());
+                        qwRestrictionPushRecordMapper.insert(qrpr);
+                    }
+                    long end4 = System.currentTimeMillis();
+                    log.info("请求pad发送完成:{}, {}, 时长4:{}", user.getQwUserName(), qwSopLogs.getId(), end4 - start4);
+                    if (content.getSendStatus() == 2 && ("请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks()) || "请求失败:请求频率异常".equals(content.getSendRemarks()))) {
+                        QwUser update = new QwUser();
+                        update.setRemark("请求频率异常,暂停发送,三小时后恢复继续发送");
+                        update.setUpdateTime(new Date());
+                        qwUserMapper.update(update, new QueryWrapper<QwUser>().eq("id", user.getId()));
+                        redisCache.setCacheObject("qw:user:id:" + user.getId(), user.getId(), 3, TimeUnit.HOURS);
+                        return;
+                    }
+                    try {
+                        int delay = ThreadLocalRandom.current().nextInt(300, 1000);
+                        log.debug("pad发送消息等待:{}ms", delay);
+                        Thread.sleep(delay);
+                    } catch (InterruptedException e) {
+                        log.error("线程等待错误!");
+                    }
                 }
             }
             // 推送 APP

+ 9 - 1
fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java

@@ -20,6 +20,7 @@ import com.fs.qwApi.domain.QwResult;
 import com.fs.qwApi.param.QwEditUserTagParam;
 import com.fs.qwApi.param.QwOpenidByUserParams;
 import com.fs.qwApi.util.AesException;
+import com.fs.voice.utils.StringUtil;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.tencent.wework.Finance;
@@ -43,6 +44,7 @@ import java.security.PrivateKey;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 @Service
 @Slf4j
@@ -200,7 +202,13 @@ public class QwDataCallbackService {
                             if(WelcomeCodeList.getLength() > 0) {
                                 WelcomeCode = WelcomeCodeList.item(0).getTextContent();
                             }
-                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
+                            String qwApiExternal=redisCache.getCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent());
+                            if (StringUtil.strIsNullOrEmpty(qwApiExternal)){
+                                redisCache.setCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent() ,"1",10, TimeUnit.MINUTES);
+                                qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
+
+                            }
+//                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
                             break;
                         case "edit_external_contact":
                             qwExternalContactService.updateQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);

+ 77 - 0
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -8,10 +8,17 @@ import com.fs.app.taskService.SopLogsTaskService;
 import com.fs.app.taskService.SopWxLogsService;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.course.domain.FsUserCourse;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.param.FsUserCourseVideoAddKfUParam;
 import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
 import com.fs.course.service.*;
 import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsInquiryOrderService;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.qw.domain.QwCompany;
@@ -39,6 +46,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 
 @Api("公共接口")
 @RestController
@@ -109,6 +117,75 @@ public class CommonController {
     @Autowired
     private IFsCourseLinkService iFsCourseLinkService;
 
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
+    @Autowired
+    private FsUserCourseMapper fsUserCourseMapper;
+
+
+    @Autowired
+    private IFsUserCompanyUserQwService userCompanyUserQwService;
+
+    @Autowired
+    private FsUserMapper fsUserMapper;
+
+    /**
+     * 发官方通连
+     */
+    @GetMapping("/Relationship")
+    public R Relationship() throws Exception {
+
+        FsUserCourseVideoAddKfUParam param=new FsUserCourseVideoAddKfUParam();
+        param.setQwUserId("34391");
+        param.setVideoId(336L);
+        param.setUserId(84L);
+        param.setCorpId("ww74ad121092304bd8");
+        param.setCompanyUserId(687L);
+        param.setCompanyId(1L);
+        param.setCourseId(23L);
+        param.setQwExternalId(221749L);
+
+
+        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
+
+        try {
+            // 判断该销售是否存在
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+            if (companyUser == null) {
+                return R.error(405, "当前客服不存在");
+            }
+
+            if (companyUser.getIsAllowedEveryoneView()!=null && companyUser.getIsAllowedEveryoneView() == 2) {
+                // 获取课程所属项目id
+                FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
+                Long courseProject = fsUserCourse.getProject();
+                if (Objects.isNull(courseProject)) {
+                    return R.error(504, "课程配置错误,项目归属为空,课程ID: " + param.getCourseId());
+                }
+
+                // 查询【用户-项目】关系
+                FsUserCompanyUserQw userCompanyUserQw = userCompanyUserQwService.selectByUserIdAndProjectId(fsUser.getUserId(), courseProject);
+
+                // 添加逻辑:如果存在fs_user表数据,但是又不存在fs_user_company_user表,则表示给他绑上(看客户更喜欢哪个销售)
+                if (Objects.isNull(userCompanyUserQw)) {
+                    userCompanyUserQw = userCompanyUserQwService.bindRelationship(param.getUserId(), courseProject, companyUser.getCompanyId(), companyUser.getUserId(), 1);
+                }
+
+                // 逻辑调整:如果客户已经绑定了销售,直接提示,
+                if (!param.getCompanyUserId().equals(userCompanyUserQw.getCompanyUserId())) {
+                    return R.error(500, "该用户(" + fsUser.getUserId() + ")已成为其他客服会员,请在相应客服上观看");
+                }
+            }
+
+        }catch (Exception e){
+            return null;
+        }
+
+        return R.ok();
+    }
+
+
     /**
     * 发官方通连
     */

+ 36 - 0
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -674,11 +674,40 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         if(content.getSetting() == null){
             return;
         }
+        List<QwSopTempSetting.Content.Setting> setting = content.getSetting().stream().filter(e -> "7".equals(e.getContentType())).collect(Collectors.toList());
+        if (!setting.isEmpty()) {
+            List<String> valuesList = PubFun.listToNewList(setting, QwSopTempSetting.Content.Setting::getValue);
+            if (valuesList != null && !valuesList.isEmpty()) {
+                try {
+                    List<QwSopTempVoice> voiceList = qwSopTempVoiceService.getVoiceByText(Long.parseLong(companyUserId), valuesList);
+                    if (voiceList != null && !voiceList.isEmpty()) {
+                        Map<String, QwSopTempVoice> collect = voiceList.stream().collect(Collectors.toMap(QwSopTempVoice::getVoiceTxt, e -> e));
+                        setting.parallelStream().filter(e -> "7".equals(e.getContentType())).forEach(st -> {
+                            QwSopTempVoice voice = collect.get(st.getValue());
+                            if (voice.getVoiceUrl() == null) {
+                                return;
+                            }
+                            st.setVoiceUrl(voice.getVoiceUrl());
+                            st.setVoiceDuration(voice.getDuration() + "");
+                        });
+                    }
+                } catch (NumberFormatException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
 //        // 发送语音 end
         if (content.getType()==5){
             sopAddTag(logVo,content,sendTime);
         }
 
+        //当语音模板的qw_sop_temp_voice中无对应语音,就不生成qw_sop_logs记录
+        if (content.getType() == 7 && content.getSetting() != null && !content.getSetting().isEmpty()) {
+            if (content.getSetting().get(0).getVoiceUrl() == null) {
+                return;
+            }
+        }
+
         if (StringUtils.isNotEmpty(logVo.getChatId())) {
             QwGroupChat groupChat = groupChatMap.get(logVo.getChatId());
             ruleTimeVO.setSendType(6);
@@ -839,11 +868,18 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             case 5:
 //                handleTagMessage(sopLogs, content);
                 break;
+            case 7:
+                handleVoiceMessage(sopLogs, content, companyUserId);
+                break;
             default:
                 log.error("未知的消息类型 {},跳过处理。", type);
                 break;
         }
     }
+    private void handleVoiceMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content, String companyUserId) {
+        sopLogs.setContentJson(JSON.toJSONString(content));
+        enqueueQwSopLogs(sopLogs);
+    }
 
     private void handleNormalMessage(QwSopLogs sopLogs, QwSopTempSetting.Content content,String companyUserId) {
 

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

@@ -177,6 +177,17 @@ public class CompanyUser extends BaseEntity
     /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
     private Integer isAllowedAllRegister;
 
+    /** 是否允许客户能在其他销售那里能看,1-是,2-否,默认1(用于企业微信客户和销售之间的关系) */
+    private Integer isAllowedEveryoneView;
+
+    public Integer getIsAllowedEveryoneView() {
+        return isAllowedEveryoneView;
+    }
+
+    public void setIsAllowedEveryoneView(Integer isAllowedEveryoneView) {
+        this.isAllowedEveryoneView = isAllowedEveryoneView;
+    }
+
     public String getMaOpenId() {
         return maOpenId;
     }

+ 4 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -60,6 +60,9 @@ public interface CompanyUserMapper
      */
     public int updateCompanyUser(CompanyUser companyUser);
 
+    @Update("UPDATE company_user SET is_allowed_everyone_view=#{allViewNum} ")
+    public int updateCompanyUserByAllViewNum(Integer allViewNum);
+
     @Update("UPDATE company_user SET qw_user_id = NULL,qw_status=0 where user_id=#{userId}")
     public int updateCompanyUserByNullQwUserID(@Param("userId") Long companyUserId);
 
@@ -304,6 +307,7 @@ public interface CompanyUserMapper
     String selectCompanyUserNameByIds(@Param("companyUserIds")String companyUserIds);
 
     int updateAllowedAllRegister(@Param("status") boolean status, @Param("userIds")List<Long> userIds);
+    int updateAllowedEveryoneView(@Param("statusNum") Integer statusNum, @Param("userIds")List<Long> userIds);
 
     List<QwIpadTotalVo> selectCompanyByIpadStatus(@Param("dateTime") String dateTime);
 

+ 4 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -183,6 +183,9 @@ public interface ICompanyUserService {
      * @return
      */
     int changeCompanyUser(List<UserProjectDTO> users, Long companyUserId, Long companyId);
+    int changeCompanyUserQw(List<UserProjectDTO> users, Long companyUserId, Long companyId);
+    int changeCompanyUserAllView(Integer allViewNum);
+    int getIsAllowedEveryoneView();
 
     /**
      * 查询销售选项列表
@@ -224,6 +227,7 @@ public interface ICompanyUserService {
      * @return true/false
      */
     Boolean isAllowedAllRegister(boolean status,  List<Long> userIds);
+    Boolean isAllowedEveryoneView(Integer status,  List<Long> userIds);
 
     List<QwIpadTotalVo> selectCompanyByIpadStatus(String dateTime);
 

+ 48 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -25,6 +25,7 @@ import com.fs.company.param.CompanyUserQwParam;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.*;
+import com.fs.course.service.IFsUserCompanyUserQwService;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsCityService;
@@ -99,9 +100,13 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Autowired
     private FsUserMapper fsUserMapper;
+
     @Autowired
     private IFsUserCompanyUserService userCompanyUserService;
 
+    @Autowired
+    private IFsUserCompanyUserQwService userCompanyUserQwService;
+
     @Autowired
     private ICompanyUserService companyUserService;
 
@@ -799,6 +804,39 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return 1;
     }
 
+    @Override
+    public int changeCompanyUserQw(List<UserProjectDTO> users, Long companyUserId, Long companyId) {
+
+        CompanyUser toUser = companyUserMapper.selectCompanyUserById(companyUserId);
+        if (Objects.isNull(toUser)) {
+            throw new ServiceException("需要更换归属的销售不存在");
+        }
+        for (UserProjectDTO u : users) {
+            userCompanyUserQwService.changeRelationship(u.getUserId(), u.getProjectId(), toUser.getCompanyId(), toUser.getUserId());
+        }
+        return 1;
+    }
+
+    @Override
+    public int changeCompanyUserAllView(Integer allViewNum) {
+
+        companyUserMapper.updateCompanyUserByAllViewNum(allViewNum);
+
+        redisCache.setCacheObject("isAllowedEveryoneView",allViewNum);
+
+        return 1;
+    }
+
+    @Override
+    public int getIsAllowedEveryoneView() {
+       Integer num= redisCache.getCacheObject("isAllowedEveryoneView");
+        if (num!=null){
+            return num;
+        }else {
+            return 1;
+        }
+    }
+
     /**
      * 查询销售选项列表
      * @param params    参数
@@ -924,6 +962,16 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return true;
     }
 
+    @Override
+    public Boolean isAllowedEveryoneView(Integer status, List<Long> userIds) {
+        try {
+            companyUserMapper.updateAllowedEveryoneView(status, userIds);
+        } catch (RuntimeException e) {
+            throw new ServiceException("操作异常");
+        }
+        return true;
+    }
+
     @Override
     public List<QwIpadTotalVo> selectCompanyByIpadStatus(String dateTime) {
         return companyUserMapper.selectCompanyByIpadStatus(dateTime);

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

@@ -128,6 +128,9 @@ public class CompanyUserQwListVO extends BaseEntity {
     /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
     private Integer isAllowedAllRegister;
 
+    /** 是否允许客户能在其他销售那里能看,1-是,2-否,默认1(用于企业微信客户和销售之间的关系) */
+    private Integer isAllowedEveryoneView;
+
     /** 医生id */
     private Long doctorId;
 

+ 67 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCompanyUserQw.java

@@ -0,0 +1,67 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 微信用户和销售关系-企业微信自动的对象 fs_user_company_user_qw
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+@Data
+public class FsUserCompanyUserQw {
+
+    /** id */
+    private Long id;
+
+    /** 用户id(关联fs_user表user_id) */
+    @Excel(name = "用户id", readConverterExp = "关=联fs_user表user_id")
+    private Long userId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 公司ID */
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    /** 是否重粉,1-是;0-否 */
+    @Excel(name = "是否重粉,1-是;0-否")
+    private Integer isRepeatFans;
+
+    /** 课程项目ID */
+    @Excel(name = "课程项目ID")
+    private Long projectId;
+
+    /** 企微用户ID */
+    @Excel(name = "企微用户ID")
+    private Long qwUserId;
+
+    /** 企微外部联系人ID */
+    @Excel(name = "企微外部联系人ID")
+    private Long qwExternalContactId;
+
+    /** 企微主体ID */
+    @Excel(name = "企微主体ID")
+    private Long qwCompanyId;
+
+    /** 状态 0小黑屋 1正常 2拉黑 */
+    @Excel(name = "状态 0小黑屋 1正常 2拉黑")
+    private Integer status;
+
+    @Excel(name = "备注")
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+}

+ 71 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserQwMapper.java

@@ -0,0 +1,71 @@
+package com.fs.course.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.qw.param.FsUserCompanyUserQwParam;
+import com.fs.qw.vo.FsUserCompanyUserQwVO;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * 微信用户和销售关系-企业微信自动的Mapper接口
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+public interface FsUserCompanyUserQwMapper extends BaseMapper<FsUserCompanyUserQw>{
+    /**
+     * 查询微信用户和销售关系-企业微信自动的
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 微信用户和销售关系-企业微信自动的
+     */
+    FsUserCompanyUserQw selectFsUserCompanyUserQwById(Long id);
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的列表
+     *
+     * @param userQwParam 微信用户和销售关系-企业微信自动的
+     * @return 微信用户和销售关系-企业微信自动的集合
+     */
+    List<FsUserCompanyUserQw> selectFsUserCompanyUserQwList(FsUserCompanyUserQw userQwParam);
+
+    @Select("<script> " +
+            "select cuq.id, cuq.user_id, cuq.project_id, cuq.create_time, cuq.remark, cu.nick_name as companyUserName  " +
+            "from fs_user_company_user_qw cuq " +
+            "left join  company_user cu on cuq.company_user_id=cu.user_id " +
+            "</script> ")
+    List<FsUserCompanyUserQwVO> selectFsUserCompanyUserQwListVO(FsUserCompanyUserQwParam userQwParam);
+
+    /**
+     * 新增微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    int insertFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw);
+
+    /**
+     * 修改微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    int updateFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw);
+
+    /**
+     * 删除微信用户和销售关系-企业微信自动的
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 结果
+     */
+    int deleteFsUserCompanyUserQwById(Long id);
+
+    /**
+     * 批量删除微信用户和销售关系-企业微信自动的
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserCompanyUserQwByIds(Long[] ids);
+}

+ 13 - 0
fs-service/src/main/java/com/fs/course/param/CollectionInfoConfirmParam.java

@@ -0,0 +1,13 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+@Data
+public class CollectionInfoConfirmParam {
+    private Long id;
+
+    private Long userId;
+
+    //用户建议
+    private String userAdvice;
+}

+ 88 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserQwService.java

@@ -0,0 +1,88 @@
+package com.fs.course.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.qw.param.FsUserCompanyUserQwParam;
+import com.fs.qw.vo.FsUserCompanyUserQwVO;
+
+/**
+ * 微信用户和销售关系-企业微信自动的Service接口
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+public interface IFsUserCompanyUserQwService extends IService<FsUserCompanyUserQw>{
+    /**
+     * 查询微信用户和销售关系-企业微信自动的
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 微信用户和销售关系-企业微信自动的
+     */
+    FsUserCompanyUserQw selectFsUserCompanyUserQwById(Long id);
+
+    FsUserCompanyUserQw selectByUserIdAndProjectId(Long userId, Long projectId);
+
+    /**
+     * 绑定客户-项目-销售关系
+     *
+     * @param userId        小程序id
+     * @param projectId     项目ID
+     * @param companyId     公司ID
+     * @param companyUserId 销售ID
+     * @param status        状态 1正常 0小黑屋
+     */
+    FsUserCompanyUserQw bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId, int status);
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的列表
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 微信用户和销售关系-企业微信自动的集合
+     */
+    List<FsUserCompanyUserQw> selectFsUserCompanyUserQwList(FsUserCompanyUserQw fsUserCompanyUserQw);
+    List<FsUserCompanyUserQwVO> selectFsUserCompanyUserQwListVO(FsUserCompanyUserQwParam userQwParam);
+
+    /**
+     * 新增微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    int insertFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw);
+
+    /**
+     * 修改微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    int updateFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw);
+
+
+    /**
+     * 修改会员-项目-销售关系
+     * @param userId        会员ID
+     * @param projectId     项目ID
+     * @param companyId     公司ID
+     * @param companyUserId 销售ID
+     */
+    void changeRelationship(Long userId, Long projectId, Long companyId, Long companyUserId);
+
+    /**
+     * 批量删除微信用户和销售关系-企业微信自动的
+     *
+     * @param ids 需要删除的微信用户和销售关系-企业微信自动的主键集合
+     * @return 结果
+     */
+    int deleteFsUserCompanyUserQwByIds(Long[] ids);
+
+    /**
+     * 删除微信用户和销售关系-企业微信自动的信息
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 结果
+     */
+    int deleteFsUserCompanyUserQwById(Long id);
+}

+ 3 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -705,7 +705,9 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         questionMap.put("A", importDTO.getQuestionA().trim());
         questionMap.put("B", importDTO.getQuestionB().trim());
         questionMap.put("C", importDTO.getQuestionC().trim());
-        questionMap.put("D", importDTO.getQuestionD().trim());
+        if (StringUtils.isNotBlank(importDTO.getQuestionD())) {
+            questionMap.put("D", importDTO.getQuestionD().trim());
+        }
 
         List<String> selectedAnswers = answerList.stream()
                 .map(questionMap::get)

+ 149 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserQwServiceImpl.java

@@ -0,0 +1,149 @@
+package com.fs.course.service.impl;
+
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.domain.FsUserCompanyUser;
+import com.fs.qw.param.FsUserCompanyUserQwParam;
+import com.fs.qw.vo.FsUserCompanyUserQwVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.course.mapper.FsUserCompanyUserQwMapper;
+import com.fs.course.domain.FsUserCompanyUserQw;
+import com.fs.course.service.IFsUserCompanyUserQwService;
+
+/**
+ * 微信用户和销售关系-企业微信自动的Service业务层处理
+ *
+ * @author fs
+ * @date 2025-10-23
+ */
+@Service
+public class FsUserCompanyUserQwServiceImpl extends ServiceImpl<FsUserCompanyUserQwMapper, FsUserCompanyUserQw> implements IFsUserCompanyUserQwService {
+
+
+    @Autowired
+    private FsUserCompanyUserQwMapper fsUserCompanyUserQwMapper;
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 微信用户和销售关系-企业微信自动的
+     */
+    @Override
+    public FsUserCompanyUserQw selectFsUserCompanyUserQwById(Long id)
+    {
+        return baseMapper.selectFsUserCompanyUserQwById(id);
+    }
+
+    @Override
+    public FsUserCompanyUserQw selectByUserIdAndProjectId(Long userId, Long projectId) {
+        LambdaQueryWrapper<FsUserCompanyUserQw> queryWrapper = Wrappers.<FsUserCompanyUserQw>lambdaQuery()
+                .eq(FsUserCompanyUserQw::getUserId, userId)
+                .eq(FsUserCompanyUserQw::getProjectId, projectId);
+        return getOne(queryWrapper);
+    }
+
+    @Override
+    public FsUserCompanyUserQw bindRelationship(Long userId, Long projectId, Long companyId, Long companyUserId, int status) {
+        FsUserCompanyUserQw companyUserQw = new FsUserCompanyUserQw();
+        companyUserQw.setUserId(userId);
+        companyUserQw.setProjectId(projectId);
+        companyUserQw.setCompanyId(companyId);
+        companyUserQw.setCompanyUserId(companyUserId);
+        companyUserQw.setIsRepeatFans(0);
+        companyUserQw.setStatus(status);
+        companyUserQw.setCreateTime(LocalDateTime.now());
+        save(companyUserQw);
+        return companyUserQw;
+    }
+
+    /**
+     * 查询微信用户和销售关系-企业微信自动的列表
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 微信用户和销售关系-企业微信自动的
+     */
+    @Override
+    public List<FsUserCompanyUserQw> selectFsUserCompanyUserQwList(FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        return baseMapper.selectFsUserCompanyUserQwList(fsUserCompanyUserQw);
+
+    }
+
+    @Override
+    public List<FsUserCompanyUserQwVO> selectFsUserCompanyUserQwListVO(FsUserCompanyUserQwParam userQwParam) {
+        return fsUserCompanyUserQwMapper.selectFsUserCompanyUserQwListVO(userQwParam);
+    }
+
+    /**
+     * 新增微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+        fsUserCompanyUserQw.setCreateTime(LocalDateTime.now());
+        return baseMapper.insertFsUserCompanyUserQw(fsUserCompanyUserQw);
+    }
+
+    /**
+     * 修改微信用户和销售关系-企业微信自动的
+     *
+     * @param fsUserCompanyUserQw 微信用户和销售关系-企业微信自动的
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserCompanyUserQw(FsUserCompanyUserQw fsUserCompanyUserQw)
+    {
+
+        return baseMapper.updateFsUserCompanyUserQw(fsUserCompanyUserQw);
+    }
+
+    @Override
+    public void changeRelationship(Long userId, Long projectId, Long companyId, Long companyUserId) {
+        LambdaQueryWrapper<FsUserCompanyUserQw> queryWrapper = Wrappers.<FsUserCompanyUserQw>lambdaQuery()
+                .eq(FsUserCompanyUserQw::getUserId, userId)
+                .eq(FsUserCompanyUserQw::getProjectId, projectId)
+                .last("limit 1");
+        FsUserCompanyUserQw userCompanyUserQw = getOne(queryWrapper);
+        if (Objects.nonNull(userCompanyUserQw)) {
+            userCompanyUserQw.setCompanyId(companyId);
+            userCompanyUserQw.setCompanyUserId(companyUserId);
+            updateById(userCompanyUserQw);
+        }
+    }
+
+    /**
+     * 批量删除微信用户和销售关系-企业微信自动的
+     *
+     * @param ids 需要删除的微信用户和销售关系-企业微信自动的主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCompanyUserQwByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsUserCompanyUserQwByIds(ids);
+    }
+
+    /**
+     * 删除微信用户和销售关系-企业微信自动的信息
+     *
+     * @param id 微信用户和销售关系-企业微信自动的主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserCompanyUserQwById(Long id)
+    {
+        return baseMapper.deleteFsUserCompanyUserQwById(id);
+    }
+}

+ 93 - 7
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -31,6 +31,7 @@ import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.*;
+import com.fs.course.service.IFsUserCompanyUserQwService;
 import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.service.IFsVideoResourceService;
@@ -220,6 +221,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private FsCourseProductMapper courseProductMapper;
     @Autowired
     private IFsUserCompanyUserService userCompanyUserService;
+
+    @Autowired
+    private IFsUserCompanyUserQwService userCompanyUserQwService;
+
     @Autowired
     private SysDictDataMapper dictDataMapper;
 
@@ -475,7 +480,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if(oneCompanyCourse && fsUser.getQwExtId() != null){
             QwExternalContact qwExternalContact = qwExternalContactMapper.selectById(fsUser.getQwExtId());
             if(qwExternalContact.getCompanyUserId() != null && !qwExternalContact.getCompanyUserId().equals(param.getCompanyUserId())){
-                return R.error(500, "该用户("+fsUser.getUserId() + ")已成为其他销售会员");
+                return R.error(500, "该用户("+fsUser.getUserId() + ")已成为其他客服会员");
             }
         }
         Integer isRoom = param.getIsRoom();
@@ -483,7 +488,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         // 处理逻辑
         if (isRoom == null || isRoom == 0) {
             // 当 isRoom 为 null 或 0 时走 handleExt
-            return handleExt(param,msg, oneCompanyCourse);
+            return handleExt(param,msg, oneCompanyCourse,fsUser);
         } else if (isRoom == 1) {
             // 当 isRoom 为 1 时走 handleRoom
             return handleRoom(param,fsUser);
@@ -498,10 +503,13 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private R handleRoom(FsUserCourseVideoAddKfUParam param,FsUser user) {
         //查询客户列表
         List<QwExternalContact> contacts = qwExternalContactMapper.selectQwExternalContactListVOByfsUserId(user.getUserId());
-        log.info("查出来的企微客户数量:"+contacts.size());
-        if (!contacts.isEmpty()){
+        List<QwExternalContact> nonNullContacts = contacts.stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        log.info("查出来的企微客户数量:"+nonNullContacts.size());
+        if (!nonNullContacts.isEmpty()){
             //找出对应销售匹配的客户
-            QwExternalContact matchedContact = contacts.stream()
+            QwExternalContact matchedContact = nonNullContacts.stream()
                     .filter(contact -> contact.getQwUserId().equals(Long.parseLong(param.getQwUserId())))
                     .findFirst()
                     .orElse(null);
@@ -517,9 +525,34 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                     createWatchLog(param);
                 }
                 return R.error(567,"群聊通用链接").put("qwExternalId", matchedContact.getId());
+            }else {
+                QwExternalContact contact = nonNullContacts.get(0);
+                log.info("匹配到的第一个企微用户:"+contact.getUserId());
+                log.info("企微id:"+contact.getId());
+                log.info("用户:"+param.getVideoId());
+                log.info("企微用户:"+param.getQwUserId());
+                param.setQwExternalId(contact.getId());
+                FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(contact.getId(), param.getVideoId(),param.getQwUserId());
+                if (log==null){
+                    createWatchLog(param);
+                }
+                return R.error(567,"群聊通用链接").put("qwExternalId", matchedContact.getId());
             }
         }
-
+        //一个都找不到
+        QwExternalContact UnionEXt = qwExternalContactMapper.selectQwExternalByUnionID(user.getUnionId());
+        if (UnionEXt!=null){
+            log.info("匹配到的第一个企微用户:"+UnionEXt.getUserId());
+            log.info("企微id:"+UnionEXt.getId());
+            log.info("用户:"+param.getVideoId());
+            log.info("企微用户:"+param.getQwUserId());
+            param.setQwExternalId(UnionEXt.getId());
+            FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(UnionEXt.getId(), param.getVideoId(),param.getQwUserId());
+            if (log==null){
+                createWatchLog(param);
+            }
+            return R.error(567,"群聊通用链接").put("qwExternalId", UnionEXt.getId());
+        }
         String msg = "<div style=\"color: red;margin-bottom: 15px;font-weight: bold;\">本课程为群会员独享<br>请长按二维码</div>\n" +
                 "\t\t\t\t\t<div style=\"color: #999;font-size: 14px;font-weight: bold;\">添加伴学助手免费领取会员权限</div>";
 
@@ -613,7 +646,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         courseWatchLogMapper.insertFsCourseWatchLog(log);
     }
 
-    private R handleExt(FsUserCourseVideoAddKfUParam param, String msg, boolean oneCompanyCourse){
+    private R handleExt(FsUserCourseVideoAddKfUParam param, String msg, boolean oneCompanyCourse,FsUser fsUser){
         if (param.getLinkType()!=null&&param.getLinkType()==1){
             if (param.getLinkId()!=null){
                 // 从数据库中查找短链对应的真实链接
@@ -636,6 +669,13 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             return R.error("链接过期");
         }
 
+        if("益善缘".equals(signProjectName)){
+                R result = validateSalesAndUserRelationship(param, fsUser);
+                if (result != null) {
+                    return result;
+                }
+        }
+
         Long qwExternalId = param.getQwExternalId();
 
         FsCourseWatchLog log=new FsCourseWatchLog();
@@ -757,6 +797,52 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         }
     }
 
+
+    /**
+     * 验证销售和用户关系
+     * @param param 请求参数
+     * @param fsUser 用户信息
+     * @return 验证结果,null表示验证通过
+     */
+    private R validateSalesAndUserRelationship(FsUserCourseVideoAddKfUParam param, FsUser fsUser) {
+
+        try {
+            // 判断该销售是否存在
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+            if (companyUser == null) {
+                return R.error(405, "当前客服不存在");
+            }
+
+            if (companyUser.getIsAllowedEveryoneView()!=null && companyUser.getIsAllowedEveryoneView() == 2) {
+                // 获取课程所属项目id
+                FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
+                Long courseProject = fsUserCourse.getProject();
+                if (Objects.isNull(courseProject)) {
+                    return R.error(504, "课程配置错误,项目归属为空,课程ID: " + param.getCourseId());
+                }
+
+                // 查询【用户-项目】关系
+                FsUserCompanyUserQw userCompanyUserQw = userCompanyUserQwService.selectByUserIdAndProjectId(fsUser.getUserId(), courseProject);
+
+                // 添加逻辑:如果存在fs_user表数据,但是又不存在fs_user_company_user表,则表示给他绑上(看客户更喜欢哪个销售)
+                if (Objects.isNull(userCompanyUserQw)) {
+                    userCompanyUserQw = userCompanyUserQwService.bindRelationship(param.getUserId(), courseProject, companyUser.getCompanyId(), companyUser.getUserId(), 1);
+                }
+
+                // 逻辑调整:如果客户已经绑定了销售,直接提示,
+                if (!param.getCompanyUserId().equals(userCompanyUserQw.getCompanyUserId())) {
+                    return R.error(500, "该用户(" + fsUser.getUserId() + ")已成为其他客服会员,请在相应客服上观看");
+                }
+            }
+
+        }catch (Exception e){
+            logger.error("企微用户课程项目绑定失败{}",param,e);
+            return null;
+        }
+
+        return null;
+    }
+
     private R addCustomerService(String qwUserById,String msg){
         String contactWay = "";
         QwUser qwUser = qwUserMapper.selectQwUserById(Long.parseLong(qwUserById));

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

@@ -22,11 +22,11 @@ public class FsCourseWatchLogStatisticsListVO {
     @Excel(name = "小节名称")
     private String videoName;
 
-    @Excel(name = "待看课")
-    private String type1;
     @Excel(name = "看课中")
-    private String type2;
+    private String type1;
     @Excel(name = "已完课")
+    private String type2;
+    @Excel(name = "待看课")
     private String type3;
     @Excel(name = "看课中断")
     private String type4;

+ 68 - 0
fs-service/src/main/java/com/fs/course/vo/FsUserInfoCollectionUVO.java

@@ -0,0 +1,68 @@
+package com.fs.course.vo;
+
+import com.fs.his.domain.FsDoctor;
+import com.fs.his.domain.FsPackage;
+import com.fs.his.vo.AnswerVO;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class FsUserInfoCollectionUVO {
+    private Long id;
+
+    //套餐包id
+    private Long packageId;
+
+    //支付类型 0-全款 1-物流代收
+    private Integer payType;
+
+    //代收金额
+    private BigDecimal amount;
+
+    private List<AnswerVO> answers;
+
+    //是否关联套餐包 0-不关联 1-关联
+    private Integer isPackage;
+
+    //确认状态 1第一次确认 2第二次确认
+    private Integer status;
+
+    private Integer doctorConfirm;
+
+    private Integer userConfirm;
+
+    private Integer userConfirm2;
+
+    private FsPackage fsPackage;
+
+    //销售id
+    private Long companyUserId;
+
+    //销售公司id
+    private Long companyId;
+
+    //套餐包订单号
+    private String packageOrderCode;
+
+    //订单状态 0-待支付 1-待发货 2-待收货 3-已完成 4-已取消
+    private Integer orderStatus;
+
+    private Long orderId;
+
+    private String userAdvice;
+
+    private String doctorAdvice;
+
+
+    private String patientJson;
+
+    //处方图片
+    private String prescribeImgUrl;
+
+    private FsDoctor doctor;
+
+    //处方审核状态 0待审核 1通过 2拒绝
+    private Integer prescribeStatus;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/erp/domain/ErpDeliverys.java

@@ -3,6 +3,8 @@ package com.fs.erp.domain;
 import com.fs.erp.dto.df.DFDeliveryResponse;
 import lombok.Data;
 
+import java.util.Date;
+
 @Data
 public class ErpDeliverys extends DFDeliveryResponse {
 
@@ -13,6 +15,7 @@ public class ErpDeliverys extends DFDeliveryResponse {
     String code;
     String warehouse_name;
     String warehouse_code;
+    String send_date;
 
 
 }

+ 7 - 0
fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryMergeResponse.java

@@ -0,0 +1,7 @@
+package com.fs.erp.dto;
+
+import lombok.Data;
+
+@Data
+public class ErpOrderQueryMergeResponse extends BaseResponse{
+}

+ 1 - 0
fs-service/src/main/java/com/fs/erp/dto/ErpOrderQueryRequert.java

@@ -10,4 +10,5 @@ public class ErpOrderQueryRequert implements Serializable {
     Integer page_no;
     Integer page_size;
     String platform_code;
+    String so_id;
 }

+ 4 - 0
fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java

@@ -16,7 +16,11 @@ public interface IErpOrderService
     ErpOrderResponse refundOrder(ErpRefundOrder order);
     ErpDeliverysResponse getDeliver(ErpDeliverysRequest param);
     ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param);
+
     ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param);
+
+    OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param);
+    //OrderQueryResponseDTO getMergeOrderScrm(ErpOrderQueryRequert param);
     BaseResponse refundUpdate(ErpRefundUpdateRequest param);
     BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param);
 

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java

@@ -245,6 +245,11 @@ public class DfOrderServiceImpl implements IErpOrderService
         return null;
     }
 
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest request) {
         ErpRefundOrder erpRefundOrder = new ErpRefundOrder();

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java

@@ -123,6 +123,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return null;
     }
 
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest request) {
         FsSysConfig sysConfig = configUtil.getSysConfig();

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

@@ -92,6 +92,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
 

+ 19 - 2
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -345,10 +345,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
         requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
 
-
         // 2. 调用ERP服务查询订单
         OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
-
         // 3. 构建响应对象
         ErpOrderQueryResponse response = new ErpOrderQueryResponse();
 
@@ -397,6 +395,21 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
 
         return response;
     }
+
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        // 1. 构建查询请求DTO
+        OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
+        requestDTO.setSoIds(Collections.singletonList(param.getSo_id()));
+        // 2. 调用ERP服务查询订单
+        return jstErpHttpService.query(requestDTO);
+    }
+
+//    @Override
+//    public OrderQueryResponseDTO getMergeOrderScrm(ErpOrderQueryRequert param) {
+//        return null;
+//    }
+
     /**
      * 将OrderQueryResponseDTO.Order转换为ErpOrderQuery
      *
@@ -466,6 +479,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             delivery.setExpress_name(order.getLogisticsCompany());
             delivery.setDelivery(true);
             delivery.setCode(order.getSoId());
+            //发货日期
+            delivery.setSend_date(order.getSendDate());
 
             deliverysList.add(delivery);
             erpOrder.setDeliverys(deliverysList);
@@ -544,6 +559,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             delivery.setExpress_name(order.getLogisticsCompany());
             delivery.setDelivery(true);
             delivery.setCode(order.getSoId());
+            //发货日期
+            delivery.setSend_date(order.getSendDate());
 
             deliverysList.add(delivery);
             erpOrder.setDeliverys(deliverysList);

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java

@@ -133,6 +133,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
         return null;

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java

@@ -832,6 +832,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public OrderQueryResponseDTO getMergeOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
         FsSysConfig sysConfig = configUtil.getSysConfig();

+ 22 - 0
fs-service/src/main/java/com/fs/fastGpt/domain/FastGptPushTokenTotal.java

@@ -0,0 +1,22 @@
+package com.fs.fastGpt.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class FastGptPushTokenTotal extends BaseEntity {
+
+    private Long id;
+    private Integer type;
+    private Long qwUserId;
+    private Long companyId;
+    @Excel(name = "公司名称")
+    private String companyName;
+    @Excel(name = "token消耗数")
+    private Long count;
+    private Integer status;
+    @Excel(name = "生成时间")
+    private String statTime;
+
+}

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

@@ -427,6 +427,10 @@ public class AiHookServiceImpl implements AiHookService {
             log.error("没有外部联系人" + "user:" + user);
             return R.ok();
         }
+        //用户是未回复状态
+        if(qwExternalContacts.getIsReply() == 0){
+            qwExternalContactMapper.updateQwExternalContactIsRePlyById(qwExternalContacts.getId());
+        }
         if(qwExternalContacts.getType()==2){
 
             return R.ok();
@@ -467,10 +471,6 @@ public class AiHookServiceImpl implements AiHookService {
                     addSaveAiMsg(1,1,contentEmj,user,fastGptChatSession.getSessionId(),role.getRoleId(),qwExternalContacts,fastGptChatSession.getUserId(),null,null,null);
                     //通过用户发送的对话去查询用户是否为新客,是就删除sop,否就不做处理
                     cleanNewUserDialogue(user, qwExternalContacts);
-                    //用户是未回复状态
-                    if(qwExternalContacts.getIsReply() == 0){
-                        qwExternalContactMapper.updateQwExternalContactIsRePlyById(qwExternalContacts.getId());
-                    }
                 }else {
                     contentEmj ="用户发送表情:"+qwContent;
                     if (type==16){

+ 2 - 2
fs-service/src/main/java/com/fs/fastgptApi/util/EventLogUtils.java

@@ -80,7 +80,7 @@ public class EventLogUtils {
 
 
         EventLogQueue.addEventLog(fastGptEventLog); // 入队
-        fastGptChatMsgService.insertFastGptEventLog(fastGptEventLog);
+        //fastGptChatMsgService.insertFastGptEventLog(fastGptEventLog);
     }
 
     /**
@@ -104,7 +104,7 @@ public class EventLogUtils {
         fastGptEventTokenLog.setQwUserId(user.getId());
         fastGptEventTokenLog.setCreateTime(new Date());
 
-        //EventLogQueue.addEventTokenLog(fastGptEventTokenLog); // 入队
+        EventLogQueue.addEventTokenLog(fastGptEventTokenLog); // 入队
         //fastGptChatMsgService.insertFastGptEventTokenLog(fastGptEventTokenLog);
     }
 

+ 43 - 0
fs-service/src/main/java/com/fs/his/domain/FsDoctorPrescribeCommon.java

@@ -0,0 +1,43 @@
+package com.fs.his.domain;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 医生常用诊断/建议用语对象 fs_doctor_prescribe_common
+ *
+ * @author fs
+ * @date 2025-03-28
+ */
+@Data
+public class FsDoctorPrescribeCommon extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    private Long commonId;
+
+    /**
+     * 内容类型 1:诊断 2:建议
+     */
+    private Integer commonType;
+
+    /**
+     * 文字内容
+     */
+    private String textContent;
+
+    /**
+     * 医生ID
+     */
+    private Long doctorId;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+}

+ 13 - 1
fs-service/src/main/java/com/fs/his/domain/FsStoreOrder.java

@@ -266,5 +266,17 @@ public class FsStoreOrder extends BaseEntity
     private BigDecimal billPrice;
     private String erpPhone;
     private String orderKey;
-
+    //0未合并 1已合并
+    private Integer isMerge;
+
+    //用户信息采集是否确认 1-确认
+    private Integer isConfirm;
+    //分账商户id
+    private String divHuifuId;
+    //中医院商户id
+    private String zyyHuifuId;
+    //分账金额
+    private BigDecimal divAmount;
+    //中医院分账金额
+    private BigDecimal zyyDivAmount;
 }

+ 8 - 0
fs-service/src/main/java/com/fs/his/domain/FsStorePayment.java

@@ -96,11 +96,19 @@ public class FsStorePayment extends BaseEntity
     private BigDecimal shareMoney;
     private Integer isShare;
 
+    private String shareDate;
+
 
     //小程序appId
     private String appId;
 
+    public String getShareDate() {
+        return shareDate;
+    }
 
+    public void setShareDate(String shareDate) {
+        this.shareDate = shareDate;
+    }
     public Integer getIsShare() {
         return isShare;
     }

+ 2 - 1
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -147,7 +147,8 @@ public class FsUser extends BaseEntity
     private String courseMaOpenId; //看课小程序openid
 
     private Long qwExtId;
-
+    /** 下单次数 */
+    private Long orderCount;
     /**
      * 企微销售ID
      * **/

+ 25 - 0
fs-service/src/main/java/com/fs/his/dto/FsStoreOrderAmountScrmStatsQueryDto.java

@@ -0,0 +1,25 @@
+package com.fs.his.dto;
+
+import lombok.Data;
+/**
+ * app商城订单金额统计queryDto对象
+ * */
+@Data
+public class FsStoreOrderAmountScrmStatsQueryDto {
+    /**
+     * 销售公司id
+     * */
+    private Long companyId;
+    /**
+     * 销售人员id
+     * */
+    private Long companyUserId;
+    /**
+     * 订单开始时间
+     * */
+    private String startTime;
+    /**
+     * 订单结束时间
+     * */
+    private String endTime;
+}

+ 25 - 0
fs-service/src/main/java/com/fs/his/dto/FsStoreOrderAmountStatsQueryDto.java

@@ -0,0 +1,25 @@
+package com.fs.his.dto;
+
+import lombok.Data;
+/**
+ * 互联网医院订单金额统计queryDto对象
+ * */
+@Data
+public class FsStoreOrderAmountStatsQueryDto {
+    /**
+     * 销售公司id
+     * */
+    private Long companyId;
+    /**
+     * 销售人员id
+     * */
+    private Long companyUserId;
+    /**
+     * 订单开始时间
+     * */
+    private String startTime;
+    /**
+     * 订单结束时间
+     * */
+    private String endTime;
+}

+ 44 - 0
fs-service/src/main/java/com/fs/his/mapper/FsDoctorPrescribeCommonMapper.java

@@ -0,0 +1,44 @@
+package com.fs.his.mapper;
+
+import com.fs.his.domain.FsDoctorPrescribeCommon;
+import com.fs.his.param.FsDoctorPrescribeCommonQueryParam;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 医生常用诊断/建议用语Mapper接口
+ */
+@Mapper
+public interface FsDoctorPrescribeCommonMapper {
+    /**
+     * 查询医生常用语列表
+     */
+    List<FsDoctorPrescribeCommon> selectFsDoctorPrescribeCommonList(@Param("query") FsDoctorPrescribeCommonQueryParam query);
+
+    /**
+     * 根据ID查询医生常用语
+     */
+    FsDoctorPrescribeCommon selectFsDoctorPrescribeCommonById(Long commonId);
+
+    /**
+     * 新增医生常用语
+     */
+    int insertFsDoctorPrescribeCommon(FsDoctorPrescribeCommon common);
+
+    /**
+     * 修改医生常用语
+     */
+    int updateFsDoctorPrescribeCommon(FsDoctorPrescribeCommon common);
+
+    /**
+     * 删除医生常用语
+     */
+    int deleteFsDoctorPrescribeCommonById(Long commonId);
+
+    /**
+     * 批量删除医生常用语
+     */
+    int deleteFsDoctorPrescribeCommonByIds(Long[] commonIds);
+}

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

@@ -64,4 +64,7 @@ public interface FsExportTaskMapper
     Integer isExportType1(Long userId);
     @Select("select count(1) from fs_export_task where sys_type=2 and `status`=0 and company_user_id=#{userId}")
     Integer isExportType2(Long userId);
+
+    @Select("update prescription_task_record set execute_status=0 where prescribe_id=#{id}")
+    void updateFsExportTaskByPrescribeId(Long id);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/mapper/FsHfpayConfigMapper.java

@@ -62,4 +62,10 @@ public interface FsHfpayConfigMapper extends BaseMapper<FsHfpayConfig>{
 
     @Select("select * from fs_hfpay_config where app_id = #{appId} limit 1")
     FsHfpayConfig selectByAppId(String appId);
+
+    @Select("select huifu_id from fs_hfpay_config where huifu_id != #{huifuId}")
+    List<String> selectByHuifuId(String huifuId);
+
+    @Select("select huifu_id from fs_hfpay_config ")
+    List<String> selectHuifuId();
 }

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

@@ -68,6 +68,8 @@ public interface FsPackageMapper
 
     @Select("select package_id dictValue,package_name dictLabel from fs_package where package_sub_type != 3 order by sort")
     List<OptionsVO> selectAllPackageList();
+    @Select("select package_id dictValue,package_name dictLabel from fs_package where is_show = 0  order by sort")
+    List<OptionsVO> selectAllPrivatePackageList();
     @Select({"<script> " +
             "select * from fs_package "+
             "where 1=1 "+

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

@@ -231,4 +231,6 @@ public interface FsPackageOrderMapper
     FsPackage selectFsPackageByOrderId(Long packageOrderId);
 
     List<PackageOrderDTO> getNewOrder();
+
+    FsPackageOrder selectByOderCode(String orderCode);
 }

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

@@ -95,7 +95,7 @@ public interface FsPatientMapper
     @Select("SELECT * FROM fs_patient WHERE user_id=#{userId}")
     List<FsPatientVO> selectFsPatientListByUserId(Long userId);
     @Select({"<script> " +
-            "select DISTINCT p.patient_id, p.patient_name,p.id_card,p.birthday,p.sex,p.weight,p.mobile,o.create_time  from fs_inquiry_order o inner join fs_patient p  on o.patient_id=p.patient_id     " +
+            "select DISTINCT p.patient_id,p.user_id, p.patient_name,p.id_card,p.birthday,p.sex,p.weight,p.mobile,o.create_time  from fs_inquiry_order o inner join fs_patient p  on o.patient_id=p.patient_id     " +
             "where  p.status=1 and  o.doctor_id=#{maps.doctorId}  " +
             "<if test = 'maps.patientName != null     '> " +
             "and p.patient_name like CONCAT('%',#{maps.patientName},'%')" +

+ 12 - 3
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeMapper.java

@@ -9,6 +9,7 @@ import com.fs.his.param.FsPrescribeParam;
 import com.fs.his.vo.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 /**
  * 处方Mapper接口
@@ -107,11 +108,17 @@ public interface FsPrescribeMapper
             "<if test = ' maps.type==1  '> " +
             "and p.doctor_id = #{maps.doctorId} " +
             "</if>" +
-            "<if test = ' maps.type==2 and maps.status != null and maps.status == 1  '> " +
+            "<if test = ' maps.type==2  '> " +
+            " and p.drug_doctor_id = #{maps.doctorId} " +
+            "</if>" +
+            "<if test = ' maps.type==2 and maps.status != null and maps.status == 0  '> " +
             "and p.status = 0 " +
             "</if>" +
             "<if test = ' maps.type==2 and maps.status != null and maps.status == 2  '> " +
-            "and (p.status = 1 || p.status = 2) and p.drug_doctor_id = #{maps.doctorId} " +
+            "and p.status = 2 and p.drug_doctor_id = #{maps.doctorId} " +
+            "</if>" +
+            "<if test = ' maps.type==2 and maps.status != null and maps.status == 1  '> " +
+            "and p.status = 1 and p.drug_doctor_id = #{maps.doctorId} " +
             "</if>" +
             "<if test=' maps.beginTime != null and maps.beginTime != \"\" '>" +
             "AND date_format(p.create_time,'%y%m%d') &gt;= date_format(#{maps.beginTime},'%y%m%d')  " +
@@ -153,7 +160,7 @@ public interface FsPrescribeMapper
 
 
 
-    @Select("select so.*,ffff.doctor_name prescribeDoctorName, us.nick_name ,dc.doctor_name,dp.doctor_name doctor_drug_name,fso.order_code,fso.`status` order_status,fse.store_name FROM fs_prescribe so  LEFT JOIN fs_user us ON us.user_id=so.user_id LEFT JOIN fs_doctor dc ON dc.doctor_id = so.doctor_id LEFT JOIN fs_doctor dp ON dp.doctor_id =so.drug_doctor_id LEFT JOIN fs_store_order fso ON fso.order_id = so.store_order_id LEFT JOIN fs_store fse ON fse.store_id = so.store_id  LEFT JOIN fs_doctor ffff ON ffff.doctor_id=so.prescribe_doctor_id  where so.prescribe_id=#{prescribeId}")
+    @Select("select so.*,dc.sign_url url,ffff.doctor_name prescribeDoctorName, us.nick_name ,dc.doctor_name,dp.doctor_name doctor_drug_name,fso.order_code,fso.`status` order_status,fse.store_name FROM fs_prescribe so  LEFT JOIN fs_user us ON us.user_id=so.user_id LEFT JOIN fs_doctor dc ON dc.doctor_id = so.doctor_id LEFT JOIN fs_doctor dp ON dp.doctor_id =so.drug_doctor_id LEFT JOIN fs_store_order fso ON fso.order_id = so.store_order_id LEFT JOIN fs_store fse ON fse.store_id = so.store_id  LEFT JOIN fs_doctor ffff ON ffff.doctor_id=so.prescribe_doctor_id  where so.prescribe_id=#{prescribeId}")
     FsPrescribeVO selectFsPrescribeByPrescribeIdVO(Long prescribeId);
     @Select({"<script> " +
             "select so.*,us.nick_name,dc.doctor_name,dp.doctor_name doctor_drug_name,fso.order_code,fso.`status` order_status,fse.store_name,fio.order_sn FROM fs_prescribe so  LEFT JOIN fs_user us ON us.user_id=so.user_id LEFT JOIN fs_doctor dc ON dc.doctor_id = so.doctor_id LEFT JOIN fs_doctor dp ON dp.doctor_id =so.drug_doctor_id LEFT JOIN fs_store_order fso ON fso.order_id = so.store_order_id LEFT JOIN fs_store fse ON fse.store_id = so.store_id LEFT JOIN fs_inquiry_order fio ON fio.order_id=so.inquiry_order_id "+
@@ -281,4 +288,6 @@ public interface FsPrescribeMapper
     List<Long> selectFsPrescribeByPrescribeIdByOrderType();
 
     List<FsPrescribeListVO> selectFsPrescribeListVOWithConfirm(FsPrescribeParam fsPrescribe);
+    @Update("UPDATE fs_prescribe SET prescribe_img_url = NULL WHERE prescribe_id = #{prescribeId}")
+    void delUrl(Long prescribeId);
 }

+ 10 - 1
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java

@@ -14,6 +14,7 @@ import com.fs.his.domain.FsInquiryOrderMsg;
 import com.fs.his.domain.FsStoreOrder;
 import com.fs.his.domain.FsStoreOrderItem;
 import com.fs.his.domain.FsStoreOrderLogs;
+import com.fs.his.dto.FsStoreOrderAmountStatsQueryDto;
 import com.fs.his.param.*;
 import com.fs.his.vo.*;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
@@ -651,7 +652,7 @@ public interface FsStoreOrderMapper
             "</if>" +
             "</script>"})
     Long selectFsStoreOrderTotalCount(@Param("type") int type, @Param("companyId") Long companyId);
-    @Select("select order_id from fs_store_order WHERE `status`= 2 and  extend_order_id is null ")
+    @Select("select order_id from fs_store_order WHERE `status`= 2 and  extend_order_id is null and is_confirm = 1 ")
     List<Long> selectFsStoreOrderNoCreateOms();
     @Select("select order_id from fs_store_order WHERE `status`= 2 and order_type=2 and store_id in(select store_id from fs_store where delivery_type=1) and  extend_order_id is null ")
     List<Long> selectFsStoreOrderNoTuiOrder();
@@ -1157,6 +1158,12 @@ public interface FsStoreOrderMapper
     @Select("select * from fs_store_order_scrm where  `status`=1 and extend_order_id is not null and extend_order_id != '' ")
     List<FsStoreOrderScrm> selectWdtOmsOrderdeliveryOpScrm();
 
+    @Select("select * from fs_store_order where  `status`=2 and extend_order_id is not null and `is_merge` = 0 and extend_order_id != '' ")
+    List<FsStoreOrder> selectNoMergeOrder();
+
+    @Select("select * from fs_store_order_scrm where  `status`=1 and extend_order_id is not null and `is_merge` = 0 and extend_order_id != '' ")
+    List<FsStoreOrderScrm> selectNoMergeOrderScrm();
+
     int batchUpdateErpByOrderIds(@Param("maps") List<Map<String, String>> maps);
 
     @Select(" select * from fs_store_order where order_code=#{orderCode} and store_id=#{storeId}")
@@ -1188,4 +1195,6 @@ public interface FsStoreOrderMapper
     @Select("select * from fs_store_order_scrm where status=2")
     List<FsStoreOrderScrm> selectOrdersBy2();
 
+
+    FsStoreOrderAmountStatsDetailVo selectFsStoreOrderAmountStats(FsStoreOrderAmountStatsQueryDto queryDto);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStorePaymentMapper.java

@@ -10,6 +10,7 @@ import com.fs.his.domain.FsStorePayment;
 import com.fs.his.param.FsStorePaymentParam;
 import com.fs.his.vo.FsStorePaymentExcelVO;
 import com.fs.his.vo.FsStorePaymentVO;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -314,4 +315,9 @@ public interface FsStorePaymentMapper
     List<FsStorePaymentVO> selectFsStorePaymentListQueryVO(@Param("maps") FsStorePaymentParam fsStorePayment);
 
     FsStorePayment selectLastByBusinessCode(@Param("orderSn")String orderSn);
+    @Select(" select  * from fs_store_payment where status = 0 ")
+    List<FsStorePayment> selectAllPayment();
+
+    @Select("select * from fs_store_payment_scrm where business_type=2 and order_id=#{orderId} and bank_transaction_id is not null ")
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrmStatus1(Long id);
 }

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

@@ -269,6 +269,7 @@ public interface FsUserMapper
     void transferCompanyUser(FsUserTransferParamDTO param);
 
     List<FsUserPageListVO> selectFsUserPageListNew(FsUserPageListParam param);
+    List<FsUserPageListVO> selectFsUserPageListNewQw(FsUserPageListParam param);
 
     Long selectFsUserPageListCount(FsUserPageListParam param);
 
@@ -349,8 +350,11 @@ public interface FsUserMapper
 
     @Select("select * from fs_user where user_id=#{userId} for update")
     FsUser selectFsUserByIdForUpdate(Long userId);
+
     List<FsUserVO> selectFsUserVOListByProject(@Param("maps") FsUser fsUser);
 
+    List<FsUserVO> selectFsUserVOListByProjectByQw(@Param("maps") FsUser fsUser);
+
     FsUserAndCompanyAndDoctorVo selectCompanyAndDoctor(@Param("userId")Long userId);
 
     List<FsUser> selectUserNameByIds(@Param("userIds") String userIds);

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

@@ -30,4 +30,7 @@ public class FsDoctorPrescribeAddEditParam   implements Serializable {
 
     List<FsDoctorPrescribeDrug> drugs;
 
+    //备注
+    private String remark;
+
 }

+ 20 - 0
fs-service/src/main/java/com/fs/his/param/FsDoctorPrescribeCommonQueryParam.java

@@ -0,0 +1,20 @@
+package com.fs.his.param;
+
+import com.fs.common.core.page.PageDomain;
+import lombok.Data;
+
+/**
+ * 医生常用语查询参数
+ */
+@Data
+public class FsDoctorPrescribeCommonQueryParam extends PageDomain {
+    /**
+     * 内容类型 1:诊断 2:建议
+     */
+    private Integer commonType;
+
+    /**
+     * 文字内容(用于模糊查询)
+     */
+    private String textContent;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/his/param/FsPackageOrderComputeParam.java

@@ -15,6 +15,7 @@ public class FsPackageOrderComputeParam implements Serializable {
     Long companyId;
     Long companyUserId;
     private String createPackageOrderKey;
+    String orderCode;
 
 
 }

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

@@ -22,6 +22,9 @@ public class FsPackageOrderCreateParam implements Serializable {
     private String createPackageOrderKey;
     private Integer payType;
 
+    //用户信息采集id
+    private Long collectionId;
+
 
 
 }

+ 43 - 0
fs-service/src/main/java/com/fs/his/service/IFsDoctorPrescribeCommonService.java

@@ -0,0 +1,43 @@
+package com.fs.his.service;
+
+import com.fs.his.domain.FsDoctorPrescribeCommon;
+import com.fs.his.param.FsDoctorPrescribeCommonQueryParam;
+import com.github.pagehelper.PageInfo;
+
+import java.util.List;
+
+/**
+ * 医生常用语Service接口
+ */
+public interface IFsDoctorPrescribeCommonService {
+
+    /**
+     * 分页查询常用语列表
+     */
+    PageInfo<FsDoctorPrescribeCommon> getList(FsDoctorPrescribeCommonQueryParam query);
+
+    /**
+     * 根据ID查询
+     */
+    FsDoctorPrescribeCommon getById(Long commonId);
+
+    /**
+     * 新增
+     */
+    int save(FsDoctorPrescribeCommon common);
+
+    /**
+     * 修改
+     */
+    int update(FsDoctorPrescribeCommon common);
+
+    /**
+     * 删除(单条)
+     */
+    int removeById(Long commonId);
+
+    /**
+     * 批量删除
+     */
+    int removeByIds(Long[] commonIds);
+}

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

@@ -72,4 +72,7 @@ public interface IFsExportTaskService
     void exportStorePaymentData(FsStorePaymentParam fsStorePayment);
 
     Integer isExportType2(Long userId);
+
+    void updateFsExportTaskByPrescribeId(Long id);
+
 }

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

@@ -90,4 +90,9 @@ public interface IFsPackageService
     List<FsPackage> selectFsPackageListByIds(Long[] packageIds);
 
     int bulkCopyFsPackageByPackage(Long[] packageIds);
+
+    /**
+     * 查询私有套餐包列表
+     */
+    List<OptionsVO> selectAllPrivatePackageList();
 }

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

@@ -111,4 +111,7 @@ public interface IFsPrescribeService
 
     void confirmPrescribe(FsPrescribeParam param);
 
+    void collectionPrescribe(Long prescribeId);
+
+    void delUrl(Long prescribeId);
 }

+ 12 - 7
fs-service/src/main/java/com/fs/his/service/IFsStoreOrderService.java

@@ -2,6 +2,7 @@ package com.fs.his.service;
 
 import java.math.BigDecimal;
 import java.text.ParseException;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -15,13 +16,11 @@ import com.fs.erp.dto.df.BspOrderResponse;
 import com.fs.erp.dto.df.DFConfigVo;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.his.domain.*;
-import com.fs.his.dto.ExpressInfoDTO;
-import com.fs.his.dto.ExpressNotifyDTO;
-import com.fs.his.dto.ExpressResultDTO;
-import com.fs.his.dto.StoreOrderExpressExportDTO;
+import com.fs.his.dto.*;
 import com.fs.his.param.*;
 import com.fs.his.vo.*;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.huifuPay.domain.HuifuOrderConfirmResult;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -63,6 +62,7 @@ public interface IFsStoreOrderService
      * @return 结果
      */
     public int updateFsStoreOrder(FsStoreOrder fsStoreOrder);
+    public int updateAddressErpFsStoreOrder(FsStoreOrder fsStoreOrder);
 
     /**
      * 修改订单状态-收货信息
@@ -107,7 +107,7 @@ public interface IFsStoreOrderService
 
     R createOrder(Long prescribeId);
 
-    R createOrderByPackageOrder(FsPackageOrder packageOrder);
+    R createOrderByPackageOrder(FsPackageOrder packageOrder, HuifuOrderConfirmResult result);
 
     R payConfirm(String orderCode,String payCode, String tradeNo,String payType,Integer type,String bankTransactionId,String bankSerialNo);
 
@@ -145,7 +145,7 @@ public interface IFsStoreOrderService
     Long selectFsStoreOrderTotalCount(int i, Long companyId);
 
 
-    void deliveryOrder(String orderCode, String mailNo, String expressCode, String expressName);
+    void deliveryOrder(String orderCode, String mailNo, String expressCode, String expressName, String sendDate);
 
     int afterSales(FsStoreOrderSalesParam fsStoreOrder);
 
@@ -267,9 +267,14 @@ public interface IFsStoreOrderService
 
     String selectFsStoreOrderProductStatistics(FsStoreOrderParam fsStoreOrder);
 
-    void deliveryOrderScrm(String orderCode, String mailNo, String expressCode, String expressName);
+    void deliveryOrderScrm(String orderCode, String mailNo, String expressCode, String expressName,String sendDate);
 
     FsStoreOrderScrm selectFsStoreOrderScrmByOrderCode(String soId);
 
     FsStoreOrder confirmOrder(FsPackageOrder packageOrder,String createOrderKey);
+
+    /**
+     * 查询互联网医院订单金额统计信息
+     * */
+    List<FsStoreOrderStatsRowVo> selectFsStoreOrderAmountStats(FsStoreOrderAmountStatsQueryDto queryDto);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java

@@ -123,4 +123,8 @@ public interface IFsStorePaymentService
     R getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param);
 
     List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrm(Long id);
+
+    List<FsStorePayment> selectAllPayment();
+
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrmStatus1(Long id);
 }

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

@@ -153,6 +153,7 @@ public interface IFsUserService
     void transfer(FsUserTransferParamDTO transferParam);
 
     TableDataInfo selectFsUserPageListNew(FsUserPageListParam param);
+    TableDataInfo selectFsUserPageListNewQw(FsUserPageListParam param);
 
     Long selectFsUserCount(FsUserPageListParam param);
     Long selectFsUserCount(int type,Long companyI,Long companyUserId);
@@ -186,6 +187,7 @@ public interface IFsUserService
     ResponseResult<Boolean> becomeMember(@Valid FsUserCourseBeMemberParam param);
 
     FsUserPageListVO selectFsUserPageListVOByUserId(Long userId);
+    FsUserPageListVO selectFsUserPageListVOByUserIdQw(Long userId);
 
     /**
      * 查询项目会员数据
@@ -194,6 +196,7 @@ public interface IFsUserService
      * @return
      */
     List<FsUserVO> selectFsUserVOListByProject(FsUser fsUser);
+    List<FsUserVO> selectFsUserVOListByProjectByQw(FsUser fsUser);
 
     FsUserAndCompanyAndDoctorVo selectCompanyAndDoctor(Long userId);
 

Some files were not shown because too many files changed in this diff