فهرست منبع

Merge remote-tracking branch 'origin/master'

xyx 1 هفته پیش
والد
کامیت
0bd2e483d4
100فایلهای تغییر یافته به همراه4307 افزوده شده و 217 حذف شده
  1. 13 0
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  2. 108 0
      fs-admin/src/main/java/com/fs/his/controller/FsQuestionAndAnswerController.java
  3. 4 0
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  4. 12 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java
  5. 6 0
      fs-admin/src/main/java/com/fs/hisStore/task/ExpressTask.java
  6. 5 0
      fs-admin/src/main/java/com/fs/hisStore/task/LiveTask.java
  7. 1 1
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  8. 2 1
      fs-admin/src/main/java/com/fs/live/controller/LiveDataController.java
  9. 34 7
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  10. 1 1
      fs-common/src/main/java/com/fs/common/constant/LiveKeysConstant.java
  11. 1 1
      fs-company-app/src/main/resources/application.yml
  12. 45 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyConfigController.java
  13. 64 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  14. 26 5
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  15. 12 0
      fs-company/src/main/java/com/fs/company/controller/live/LiveController.java
  16. 2 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveDataController.java
  17. 16 37
      fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java
  18. 1 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopTempController.java
  19. 139 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserInformationCollectionController.java
  20. 120 0
      fs-company/src/main/java/com/fs/company/controller/store/FsUserInformationCollectionScheduleController.java
  21. 1 1
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  22. 1 1
      fs-company/src/main/resources/application.yml
  23. 47 0
      fs-doctor-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java
  24. 8 0
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  25. 22 3
      fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java
  26. 52 21
      fs-live-app/src/main/java/com/fs/live/task/Task.java
  27. 11 15
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  28. 22 0
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  29. 25 0
      fs-service/src/main/java/com/fs/common/VerifyCodeUtil.java
  30. 2 0
      fs-service/src/main/java/com/fs/common/service/ISmsService.java
  31. 82 0
      fs-service/src/main/java/com/fs/common/service/impl/SmsServiceImpl.java
  32. 3 0
      fs-service/src/main/java/com/fs/company/domain/CompanyUser.java
  33. 12 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyConfigMapper.java
  34. 15 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  35. 30 0
      fs-service/src/main/java/com/fs/company/param/SaveCompanyMiniAppParam.java
  36. 18 0
      fs-service/src/main/java/com/fs/company/service/ICompanyConfigService.java
  37. 15 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  38. 90 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyConfigServiceImpl.java
  39. 10 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  40. 32 0
      fs-service/src/main/java/com/fs/company/vo/CompanyMiniAppVO.java
  41. 10 10
      fs-service/src/main/java/com/fs/core/utils/OrderCodeUtils.java
  42. 4 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  43. 1 1
      fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  44. 9 9
      fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java
  45. 92 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  46. 5 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  47. 6 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  48. 8 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java
  49. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  50. 23 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  51. 24 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  52. 97 95
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  53. 6 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  54. 1 1
      fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java
  55. 42 0
      fs-service/src/main/java/com/fs/his/domain/DoctorMsg.java
  56. 47 0
      fs-service/src/main/java/com/fs/his/domain/FsDoctorConfirm.java
  57. 10 0
      fs-service/src/main/java/com/fs/his/domain/FsInquiryOrder.java
  58. 28 0
      fs-service/src/main/java/com/fs/his/domain/FsQuestionAndAnswer.java
  59. 1 0
      fs-service/src/main/java/com/fs/his/domain/FsStoreOrder.java
  60. 15 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  61. 105 0
      fs-service/src/main/java/com/fs/his/domain/FsUserInformationCollection.java
  62. 71 0
      fs-service/src/main/java/com/fs/his/domain/FsUserInformationCollectionSchedule.java
  63. 103 0
      fs-service/src/main/java/com/fs/his/dto/FsUserInformationCollectionDTO.java
  64. 3 1
      fs-service/src/main/java/com/fs/his/dto/PayloadDTO.java
  65. 79 0
      fs-service/src/main/java/com/fs/his/enums/PrescriptionTaskStepEnum.java
  66. 75 0
      fs-service/src/main/java/com/fs/his/mapper/DoctorMsgMapper.java
  67. 62 0
      fs-service/src/main/java/com/fs/his/mapper/FsDoctorConfirmMapper.java
  68. 67 0
      fs-service/src/main/java/com/fs/his/mapper/FsQuestionAndAnswerMapper.java
  69. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  70. 101 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionMapper.java
  71. 69 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionScheduleMapper.java
  72. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  73. 18 0
      fs-service/src/main/java/com/fs/his/param/CollectionInfoConfirmParam.java
  74. 1 0
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderCreateParam.java
  75. 1 0
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderListPDParam.java
  76. 2 0
      fs-service/src/main/java/com/fs/his/param/FsPackageOrderCreateParam.java
  77. 16 0
      fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionListDParam.java
  78. 52 0
      fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionParam.java
  79. 13 0
      fs-service/src/main/java/com/fs/his/param/UserInformationDoctorType2Param.java
  80. 63 0
      fs-service/src/main/java/com/fs/his/service/IFsDoctorConfirmService.java
  81. 66 0
      fs-service/src/main/java/com/fs/his/service/IFsQuestionAndAnswerService.java
  82. 70 0
      fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionScheduleService.java
  83. 114 0
      fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionService.java
  84. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java
  85. 95 0
      fs-service/src/main/java/com/fs/his/service/impl/FsDoctorConfirmServiceImpl.java
  86. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java
  87. 11 1
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  88. 113 0
      fs-service/src/main/java/com/fs/his/service/impl/FsQuestionAndAnswerServiceImpl.java
  89. 105 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionScheduleServiceImpl.java
  90. 1011 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java
  91. 5 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  92. 20 0
      fs-service/src/main/java/com/fs/his/utils/PhoneUtil.java
  93. 32 0
      fs-service/src/main/java/com/fs/his/vo/AnswerVO.java
  94. 15 0
      fs-service/src/main/java/com/fs/his/vo/FsQuestionAndAnswerVO.java
  95. 79 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInfoCollectionUVO.java
  96. 18 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionAndPatientVO.java
  97. 23 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionListDVO.java
  98. 47 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionVO.java
  99. 19 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreProductScrm.java
  100. 10 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java

+ 13 - 0
fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java

@@ -23,6 +23,7 @@ import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import com.fs.qw.service.IQwWatchLogService;
 import com.fs.qw.vo.QwWatchLogAllStatisticsListVO;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -39,6 +40,9 @@ import java.util.List;
 @RequestMapping("/qw/course/courseWatchLog")
 public class QwFsCourseWatchLogController extends BaseController
 {
+    @Value("${cloud_host.company_name}")
+    private String signProjectName;
+
     @Autowired
     private IFsCourseWatchLogService fsCourseWatchLogService;
 
@@ -78,9 +82,18 @@ public class QwFsCourseWatchLogController extends BaseController
         }
         param.setSendType(2); //企微
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
+        if("济南联志健康".equals(signProjectName)){
+            FsCourseWatchLogStatisticsListVO totalData = fsCourseWatchLogService.getTotalDataAddItem(param);
+            list.add(totalData);
+        }
         return getDataTable(list);
     }
 
+    @GetMapping("/getSignProjectName")
+    public R getSignProjectName(){
+        return R.ok().put("signProjectName", signProjectName);
+    }
+
     @GetMapping("/statisticsListByCompany")
     public R statisticsListByCompany(FsCourseWatchLogStatisticsListParam param)
     {

+ 108 - 0
fs-admin/src/main/java/com/fs/his/controller/FsQuestionAndAnswerController.java

@@ -0,0 +1,108 @@
+package com.fs.his.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("/his/answer")
+public class FsQuestionAndAnswerController extends BaseController
+{
+    @Autowired
+    private IFsQuestionAndAnswerService fsQuestionAndAnswerService;
+
+    /**
+     * 查询问答列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        startPage();
+        List<FsQuestionAndAnswer> list = fsQuestionAndAnswerService.selectFsQuestionAndAnswerList(fsQuestionAndAnswer);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出问答列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:export')")
+    @Log(title = "问答", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        List<FsQuestionAndAnswer> list = fsQuestionAndAnswerService.selectFsQuestionAndAnswerList(fsQuestionAndAnswer);
+        ExcelUtil<FsQuestionAndAnswer> util = new ExcelUtil<FsQuestionAndAnswer>(FsQuestionAndAnswer.class);
+        return util.exportExcel(list, "问答数据");
+    }
+
+    /**
+     * 获取问答详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsQuestionAndAnswerService.selectFsQuestionAndAnswerById(id));
+    }
+
+    /**
+     * 新增问答
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:add')")
+    @Log(title = "问答", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        return toAjax(fsQuestionAndAnswerService.insertFsQuestionAndAnswer(fsQuestionAndAnswer));
+    }
+
+    /**
+     * 修改问答
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:edit')")
+    @Log(title = "问答", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        return toAjax(fsQuestionAndAnswerService.updateFsQuestionAndAnswer(fsQuestionAndAnswer));
+    }
+
+    /**
+     * 删除问答
+     */
+    @PreAuthorize("@ss.hasPermi('his:answer:remove')")
+    @Log(title = "问答", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsQuestionAndAnswerService.deleteFsQuestionAndAnswerByIds(ids));
+    }
+
+    /**
+     * 查询问答列表
+     */
+    @GetMapping("/allList")
+    public TableDataInfo getHospital()
+    {
+        List<OptionsVO> list = fsQuestionAndAnswerService.selectAllQuestionOptions();
+        return getDataTable(list);
+    }
+}

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

@@ -190,6 +190,10 @@ public class FsUserController extends BaseController
         if(StringUtils.isNotEmpty(fsUser.getPhone())){
             fsUser.setPhone(encryptPhone(fsUser.getPhone()));
         }
+        if(StringUtils.isNotEmpty(fsUser.getCompanyUserIdMulti())){
+            String[] split = fsUser.getCompanyUserIdMulti().split(",");
+            fsUser.setCompanyUserIds(split);
+        }
 //        List<FsUserVO> list = fsUserService.selectFsUserVOListByProject(fsUser);
 
         // xgb sql执行太慢,优化修改

+ 12 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java

@@ -113,6 +113,18 @@ public class FsStoreProductScrmController extends BaseController
     }
 
 
+    /**
+     * 导出商品列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeProduct:copy')")
+    @Log(title = "商品管理", businessType = BusinessType.INSERT, isStoreLog = true,logParam = {"商品","复制商品信息"})
+    @GetMapping("/copyStoreProduct")
+    public R copyStoreProduct(@RequestParam Long productId)
+    {
+        return fsStoreProductService.copyStoreProduct(productId);
+    }
+
+
     @Log(title = "商品管理", businessType = BusinessType.IMPORT,isStoreLog = true,logParam = {"商品","商品导入"})
     @PreAuthorize("@ss.hasPermi('store:storeProduct:import')")
     @PostMapping("/importData")

+ 6 - 0
fs-admin/src/main/java/com/fs/hisStore/task/ExpressTask.java

@@ -20,4 +20,10 @@ public class ExpressTask {
         fsStoreOrderScrmService.syncExpressToWx();
     }
 
+
+    //定时任务刷新订单结算状态
+    public void refreshOrderSettlementStatus(){
+        fsStoreOrderScrmService.refreshOrderSettlementStatus();
+    }
+
 }

+ 5 - 0
fs-admin/src/main/java/com/fs/hisStore/task/LiveTask.java

@@ -181,6 +181,10 @@ public class LiveTask {
     //每5分钟执行一次
     public void deliveryOp() {
         List<LiveOrder> list = liveOrderService.selectUpdateExpress();
+        if(list == null || list.isEmpty()) return;
+        if (list.size() > 100) {
+            list = list.subList(0, 100);
+        }
         for (LiveOrder order : list) {
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();
             request.setCode(order.getExtendOrderId());
@@ -202,6 +206,7 @@ public class LiveTask {
                 }
             }
         }
+
     }
 
     public void couponOp() {

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

@@ -386,7 +386,7 @@ public class MallStoreTask
         for (Long orderId : list){
             FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(orderId);
             String lastFourNumber = "";
-            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())  || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
                 lastFourNumber = order.getUserPhone();
                 if (lastFourNumber.length() == 11) {
                     lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);

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

@@ -8,6 +8,7 @@ import com.fs.live.domain.LiveData;
 import com.fs.live.param.LiveDataParam;
 import com.fs.live.service.ILiveDataService;
 import com.fs.live.vo.LiveUserFirstVo;
+import com.github.pagehelper.PageHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -49,7 +50,7 @@ public class LiveDataController extends BaseController {
     @PostMapping("/listLiveData")
     public R listLiveData(@RequestBody LiveDataParam param, HttpServletRequest request)
     {
-        startPage();
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         return liveDataService.listLiveData(param);
     }
 

+ 34 - 7
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -6,6 +6,7 @@ import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
@@ -32,6 +33,9 @@ import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
 import com.fs.hisStore.dto.StoreOrderExpressExportDTO;
 import com.fs.hisStore.param.*;
+import com.fs.hisStore.service.IFsExpressScrmService;
+import com.fs.hisStore.task.ExpressTask;
+import com.fs.hisStore.task.LiveTask;
 import com.fs.hisStore.vo.FsStoreOrderVO;
 import com.fs.live.domain.*;
 import com.fs.live.dto.LiveOrderCustomerExportDTO;
@@ -43,6 +47,7 @@ import com.fs.live.enums.LiveOrderCancleReason;
 import com.fs.live.param.LiveOrderScrmSetErpPhoneParam;
 import com.fs.live.service.*;
 import com.fs.live.vo.*;
+import com.fs.qw.utils.RSAUtils;
 import com.fs.store.domain.FsStoreDelivers;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
@@ -92,7 +97,7 @@ public class LiveOrderController extends BaseController
     @Autowired
     private TokenService tokenService;
     @Autowired
-    private IFsExpressService expressService;
+    private IFsExpressScrmService expressService;
 //    @Autowired
 //    private FsWarehousesMapper fsWarehousesMapper;
     @Autowired
@@ -109,6 +114,11 @@ public class LiveOrderController extends BaseController
     @Autowired
     private ILiveOrderDfService liveOrderDfService;
 
+    @Autowired
+    private LiveTask liveTask;
+
+
+
 
     @GetMapping("/importTemplate")
     public AjaxResult importTemplate() {
@@ -153,14 +163,24 @@ public class LiveOrderController extends BaseController
     public TableDataInfo listZm(LiveOrder liveOrder)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         List<LiveOrderVoZm> list = liveOrderService.selectLiveOrderListZm(liveOrder);
         for (LiveOrderVoZm vo : list){
             vo.setUserPhone(ParseUtils.parsePhone(vo.getUserPhone()));
             vo.setCompanyUserPhone(ParseUtils.parsePhone(vo.getCompanyUserPhone()));
             vo.setUserBindPhone(ParseUtils.parsePhone(vo.getUserBindPhone()));
             vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
-            vo.setCost(BigDecimal.ZERO);
-            vo.setCostPrice(BigDecimal.ZERO);
+
+            // 财务独特字段
+            if (loginUser.getPermissions().contains("live:liveOrder:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                vo.setCostPrice(vo.getCostPrice());
+                vo.setFPrice(vo.getCostPrice().multiply(BigDecimal.valueOf(Long.parseLong(vo.getTotalNum()))));
+            } else {
+                vo.setCostPrice(BigDecimal.ZERO);
+                vo.setFPrice(BigDecimal.ZERO);
+            }
+            vo.setCost(vo.getCostPrice());
+
         }
         return getDataTable(list);
     }
@@ -174,13 +194,21 @@ public class LiveOrderController extends BaseController
     public AjaxResult exportZm(LiveOrder liveOrder)
     {
         List<LiveOrderVoZm> list = liveOrderService.selectLiveOrderListZm(liveOrder);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         for (LiveOrderVoZm vo : list){
             vo.setUserPhone(ParseUtils.parsePhone(vo.getUserPhone()));
             vo.setCompanyUserPhone(ParseUtils.parsePhone(vo.getCompanyUserPhone()));
             vo.setUserBindPhone(ParseUtils.parsePhone(vo.getUserBindPhone()));
             vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
-            vo.setCost(BigDecimal.ZERO);
-            vo.setCostPrice(BigDecimal.ZERO);
+            // 财务独特字段
+            if (loginUser.getPermissions().contains("live:liveOrder:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                vo.setCostPrice(vo.getCostPrice());
+                vo.setFPrice(vo.getCostPrice().multiply(BigDecimal.valueOf(Long.parseLong(vo.getTotalNum()))));
+            } else {
+                vo.setCostPrice(BigDecimal.ZERO);
+                vo.setFPrice(BigDecimal.ZERO);
+            }
+            vo.setCost(vo.getCostPrice());
         }
         ExcelUtil<LiveOrderVoZm> util = new ExcelUtil<LiveOrderVoZm>(LiveOrderVoZm.class);
         return util.exportExcel(list, "订单数据");
@@ -372,8 +400,7 @@ public class LiveOrderController extends BaseController
     @ApiOperation("物流查询")
     @PostMapping("/getExpressByDeliverId")
     public R getExpressByDeliverId(@Validated @RequestBody FsStoreOrderExpressParam param, HttpServletRequest request){
-//        return expressService.getLiveExpressByDeliverId(param);
-        return R.ok();
+        return expressService.getLiveExpressByDeliverId(param);
     }
 
     @PreAuthorize("@ss.hasPermi('live:liveOrder:auditPayRemain')")

+ 1 - 1
fs-common/src/main/java/com/fs/common/constant/LiveKeysConstant.java

@@ -28,7 +28,7 @@ public class LiveKeysConstant {
     public static final String TOP_MSG = "topMsg"; //抽奖记录
 
     public static final String LIVE_FLAG_CACHE = "live:flag:%s"; //直播间直播/回放状态缓存
-    public static final Integer LIVE_FLAG_CACHE_EXPIRE = 60; //直播间状态缓存过期时间(秒)
+    public static final Integer LIVE_FLAG_CACHE_EXPIRE = 300; //直播间状态缓存过期时间(秒)
 
 
 }

+ 1 - 1
fs-company-app/src/main/resources/application.yml

@@ -6,4 +6,4 @@ server:
 spring:
   profiles:
 #    active: druid-fcky-test
-    active: druid-bjzm-test
+    active: druid-jnmy-test

+ 45 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyConfigController.java

@@ -4,8 +4,11 @@ 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.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyConfig;
+import com.fs.company.param.SaveCompanyMiniAppParam;
 import com.fs.company.service.ICompanyConfigService;
+import com.fs.company.vo.CompanyMiniAppVO;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.system.domain.SysConfig;
@@ -15,6 +18,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * 系统配置
  *
@@ -78,7 +83,47 @@ public class CompanyConfigController extends BaseController
 
     }
 
+    /**
+     * 获取公司可配置小程序列表
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('company:miniConfig:list')")
+    @GetMapping(value = "/getCompanyMiniAppList")
+    public R getCompanyMiniAppList()
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(null == loginUser) {
+            return R.error("用户信息错误");
+        }
+        Long companyId = loginUser.getCompany().getCompanyId();
+        List<CompanyMiniAppVO> companyMiniAppList = companyConfigService.getCompanyMiniAppList(companyId);
+        SaveCompanyMiniAppParam param = companyConfigService.getCurrentCompanyMiniApp(companyId);
+        return R.ok().put("data",companyMiniAppList).put("current",param);
+
+    }
 
+    /**
+     * 公司编辑保存主备小程序数据
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('company:miniConfig:addOrEdit')")
+    @PostMapping(value = "/saveCompanyMiniApp")
+    public R saveCompanyMiniApp(@RequestBody SaveCompanyMiniAppParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(null == loginUser) {
+            return R.error("用户信息错误");
+        }
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+//        if(null == param.getCompanyId() || !companyId.equals(param.getCompanyId())) {
+//            return R.error("公司信息错误");
+//        }
+        Long userId = loginUser.getUser().getUserId();
+        param.setUpdateBy(userId);
+        return companyConfigService.saveCompanyMiniApp(param);
+
+    }
 
 
 

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

@@ -35,6 +35,7 @@ import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.his.vo.OptionsVO;
+import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.hisStore.vo.FsStoreProductExportVO;
 import com.fs.im.config.IMConfig;
 import com.fs.im.dto.OpenImResponseDTO;
@@ -112,6 +113,9 @@ public class CompanyUserController extends BaseController {
     @Autowired
     private CloudHostProper cloudHostProper;
 
+    @Autowired
+    private IFsUserScrmService fsUserScrmService;
+
     private static final String appLink = "https://jump.ylrztop.com/jumpapp/pages/index/index?link=";
 
     /**
@@ -805,4 +809,64 @@ public class CompanyUserController extends BaseController {
         OpenImResponseDTO openImResponseDTO = openIMService.importFriend(ownerUserID, friendUserIDs);
         return R.ok().put("data",openImResponseDTO);
     }
+
+    /**
+     * 根据手机号码精确查询fs_user(完全匹配)
+     * @param phone 手机号码
+     * @return 用户列表
+     */
+    @ApiOperation("根据手机号码精确查询fs_user")
+    @GetMapping("/fsUser/queryByPhone")
+    public R queryFsUserByPhone(@RequestParam("phone") String phone) {
+        if (StringUtils.isEmpty(phone)) {
+            return R.error("手机号码不能为空");
+        }
+        List<com.fs.hisStore.domain.FsUserScrm> userList = fsUserScrmService.selectFsUserListByPhoneExact(phone);
+        return R.ok().put("data", userList);
+    }
+
+    /**
+     * 批量绑定用户到员工
+     * @param data 包含 userIds(公司用户ID列表)和 bindCompanyUserId(绑定的销售ID)
+     * @return 操作结果
+     */
+    @ApiOperation("批量绑定用户到员工")
+    @PostMapping("/batchBindCompanyUserId")
+    public R batchBindCompanyUserId(@RequestBody Map<String, Object> data) {
+        List<Long> userIds = (List<Long>) data.get("fsUserIds");
+        Long bindCompanyUserId = null;
+        if (data.get("companyUserId") != null) {
+            if (data.get("companyUserId") instanceof Integer) {
+                bindCompanyUserId = ((Integer) data.get("companyUserId")).longValue();
+            } else if (data.get("companyUserId") instanceof Long) {
+                bindCompanyUserId = (Long) data.get("companyUserId");
+            }
+        }
+
+        if (userIds == null || userIds.isEmpty()) {
+            return R.error("用户ID列表不能为空");
+        }
+
+        int result = companyUserService.batchUpdateBindCompanyUserId(userIds, bindCompanyUserId);
+        if (result > 0) {
+            return R.ok("绑定成功");
+        } else {
+            return R.error("绑定失败");
+        }
+    }
+
+    /**
+     * 查询已绑定的用户
+     * @param companyUserId 销售ID
+     * @return 绑定的用户列表
+     */
+    @ApiOperation("查询已绑定的用户")
+    @GetMapping("/getBoundUsers/{companyUserId}")
+    public R getBoundUsers(@PathVariable("companyUserId") Long companyUserId) {
+        if (companyUserId == null) {
+            return R.error("销售ID不能为空");
+        }
+        List<com.fs.hisStore.domain.FsUserScrm> userList = companyUserService.selectBoundFsUsersByCompanyUserId(companyUserId);
+        return R.ok().put("data", userList);
+    }
 }

+ 26 - 5
fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java

@@ -10,6 +10,7 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
@@ -37,10 +38,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDate;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
 /**
@@ -104,6 +102,20 @@ public class FsUserCoursePeriodController extends BaseController {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserCoursePeriod.setCompanyIdList(Collections.singletonList(loginUser.getCompany().getCompanyId()));
         List<FsUserCoursePeriodVO> list = fsUserCoursePeriodService.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
+        // 使用Stream API的简洁写法
+        Long currentCompanyId = loginUser.getCompany().getCompanyId();
+        for (FsUserCoursePeriodVO vo : list) {
+            String isNeedRegisterMember = vo.getIsNeedRegisterMember();
+
+            if (StringUtils.isNotEmpty(isNeedRegisterMember)) {
+                boolean containsCurrentCompany = Arrays.stream(isNeedRegisterMember.split(","))
+                        .map(String::trim)
+                        .anyMatch(id -> id.equals(String.valueOf(currentCompanyId)));
+                vo.setIsNeedRegisterMember(containsCurrentCompany ? "1" : "0");
+            } else {
+                vo.setIsNeedRegisterMember("0");
+            }
+        }
         PageInfo<FsUserCoursePeriodVO> pageInfo = new PageInfo<>(list);
         Map<String, Object> result = new HashMap<>();
         result.put("rows", pageInfo.getList());
@@ -173,7 +185,14 @@ public class FsUserCoursePeriodController extends BaseController {
     @PutMapping("/editIsNeedRegisterMember")
     public AjaxResult editIsNeedRegisterMember(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
-        return toAjax(fsUserCoursePeriodService.editIsNeedRegisterMember(fsUserCoursePeriod));
+        FsUserCoursePeriod fsUserCoursePeriod1 = fsUserCoursePeriodService.selectFsUserCoursePeriodById(fsUserCoursePeriod.getPeriodId());
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if (ObjectUtil.isEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())){
+            throw new CustomException("修改失败!");
+        }
+
+        return toAjax(fsUserCoursePeriodService.editIsNeedRegisterMember(fsUserCoursePeriod,loginUser.getCompany().getCompanyId().toString()));
+
     }
 
     /**
@@ -259,6 +278,8 @@ public class FsUserCoursePeriodController extends BaseController {
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
         FsUserCoursePeriod period = fsUserCoursePeriodService.selectFsUserCoursePeriodById(param.getPeriodId());
         param.setMaxDate(LocalDate.now().plusDays(period.getMaxViewNum()));
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
         List<FsPeriodCountVO> list = fsUserCoursePeriodDaysService.periodCourseCount(param);
         long count = fsUserCoursePeriodDaysService.periodCourseByCount(param);
         PageInfo<FsPeriodCountVO> pageInfo = new PageInfo<>(list);

+ 12 - 0
fs-company/src/main/java/com/fs/company/controller/live/LiveController.java

@@ -51,6 +51,18 @@ public class LiveController extends BaseController
     @Autowired
     private ILiveCompanyCodeService liveCompanyCodeService;
 
+    /**
+     * 查询未结束直播间
+     */
+    @PreAuthorize("@ss.hasPermi('live:live:list')")
+    @GetMapping("/listToLiveNoEnd")
+    public TableDataInfo listToLiveNoEnd(Live live)
+    {
+        startPage();
+        List<Live> list = liveService.listToLiveNoEnd(live);
+        return getDataTable(list);
+    }
+
     /**
      * 查询直播列表
      */

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

@@ -14,6 +14,7 @@ import com.fs.live.domain.LiveData;
 import com.fs.live.param.LiveDataParam;
 import com.fs.live.service.ILiveDataService;
 import com.fs.live.vo.ColumnsConfigVo;
+import com.github.pagehelper.PageHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -67,7 +68,7 @@ public class LiveDataController extends BaseController
     public R listLiveData(@RequestBody LiveDataParam param, HttpServletRequest request)
     {
         param.setCompanyId(tokenService.getLoginUser(request).getUser().getCompanyId());
-        startPage();
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         return liveDataService.listLiveData(param);
     }
 

+ 16 - 37
fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.live;
 
+import cn.hutool.core.util.StrUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -8,6 +9,7 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
@@ -18,7 +20,10 @@ import com.fs.his.domain.FsUser;
 import com.fs.his.param.FsStoreOrderBindCustomerParam;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
+import com.fs.hisStore.dto.ExpressInfoDTO;
+import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.param.FsStoreOrderExpressParam;
+import com.fs.hisStore.service.IFsExpressScrmService;
 import com.fs.live.domain.*;
 import com.fs.live.enums.LiveOrderCancleReason;
 import com.fs.live.param.LiveOrderExpressParam;
@@ -40,6 +45,8 @@ import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
+import static com.fs.his.utils.PhoneUtil.decryptPhone;
+
 
 /**
  * 订单Controller
@@ -67,7 +74,7 @@ public class LiveOrderController extends BaseController
     @Autowired
     private TokenService tokenService;
     @Autowired
-    private IFsExpressService expressService;
+    private IFsExpressScrmService expressService;
 
 
 //    @Autowired
@@ -204,8 +211,8 @@ public class LiveOrderController extends BaseController
     @PostMapping("/getExpressByDeliverId")
     public R getExpressByDeliverId(@Validated @RequestBody FsStoreOrderExpressParam param, HttpServletRequest request){
 
-//        return expressService.getLiveExpressByDeliverId(param);
-        return R.ok();
+        return expressService.getLiveExpressByDeliverId(param);
+//        return R.ok();
     }
 
     /**
@@ -287,40 +294,12 @@ public class LiveOrderController extends BaseController
     /**
      * 查看物流状态
      * */
-//    @PreAuthorize("@ss.hasPermi('live:liveOrder:express')")
-//    @GetMapping(value = "/getExpress/{id}")
-//    public R getExpress(@PathVariable("id") String id)
-//    {
-//        LiveOrder order=liveOrderService.selectLiveOrderByOrderId(id);
-//        ExpressInfoDTO expressInfoDTO=null;
-//        if(StringUtils.isNotEmpty(order.getDeliverySn())){
-//            String lastFourNumber = "";
-//            if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue())) {
-//
-//                lastFourNumber = order.getUserPhone();
-//                if (lastFourNumber.length() == 11) {
-//                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-//                }else if (lastFourNumber.length()>11){
-//                    String jm = decryptPhone(lastFourNumber);
-//                    lastFourNumber = StrUtil.sub(jm, jm.length(), -4);
-//                }
-//            }
-//            expressInfoDTO=expressService.getExpressInfo(order.getOrderCode(),order.getDeliveryCode(),order.getDeliverySn(),lastFourNumber);
-//
-//            if((expressInfoDTO.getStateEx()!=null&&expressInfoDTO.getStateEx().equals("0"))&&(expressInfoDTO.getState()!=null&&expressInfoDTO.getState().equals("0"))){
-//                lastFourNumber = "19923690275";
-//                if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue())) {
-//                    if (lastFourNumber.length() == 11) {
-//                        lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-//                    }
-//                }
-//
-//                expressInfoDTO=expressService.getExpressInfo(order.getOrderCode(),order.getDeliveryCode(),order.getDeliverySn(),lastFourNumber);
-//
-//            }
-//        }
-//        return R.ok().put("data",expressInfoDTO);
-//    }
+    @PreAuthorize("@ss.hasPermi('live:liveOrder:express')")
+    @GetMapping(value = "/getExpress/{id}")
+    public R getExpress(@PathVariable("id") String id)
+    {
+        return liveOrderService.syncExpress(Long.valueOf(id));
+    }
 
     /**
      * 支付订单

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwSopTempController.java

@@ -145,7 +145,7 @@ public class QwSopTempController extends BaseController
     public TableDataInfo deptList(QwSopTemp qwSopTemp)
     {
 
-        if ("济南联志健康".equals(signProjectName)) {
+        if (!"今正科技".equals(signProjectName)) {
             return list(qwSopTemp);
         }
 

+ 139 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserInformationCollectionController.java

@@ -0,0 +1,139 @@
+package com.fs.company.controller.store;
+
+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.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUserUser;
+import com.fs.company.service.ICompanyUserUserService;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
+import com.fs.his.domain.FsUserInformationCollection;
+import com.fs.his.param.FsUserInformationCollectionParam;
+import com.fs.his.service.IFsUserInformationCollectionService;
+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-14
+ */
+@RestController
+@RequestMapping("/store/collection")
+public class FsUserInformationCollectionController extends BaseController
+{
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
+    @Autowired
+    private ICompanyUserUserService companyUserUserService;
+
+    /**
+     * 查询用户信息采集列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:collection:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserInformationCollection fsUserInformationCollection)
+    {
+        startPage();
+        List<FsUserInformationCollection> list = fsUserInformationCollectionService.selectFsUserInformationCollectionList(fsUserInformationCollection);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户信息采集列表
+     */
+    @PreAuthorize("@ss.hasPermi('his: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('his:collection:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserInformationCollectionService.selectFsUserInformationCollectionById(id));
+    }
+
+    /**
+     * 新增用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('his:collection:add')")
+    @Log(title = "用户信息采集", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        Long companyUserId = loginUser.getUser().getUserId();
+        //查询用户是否绑定销售
+        Long userId = fsUserInformationCollection.getUserId();
+        if (userId == null || userId < 0){
+            return AjaxResult.error("请选择绑定用户");
+        }
+        CompanyUserUser companyUserUser = new CompanyUserUser();
+        companyUserUser.setCompanyUserId(companyUserId);
+        companyUserUser.setUserId(userId);
+        List<CompanyUserUser> companyUserUsers = companyUserUserService.selectCompanyUserUserList(companyUserUser);
+        if (companyUserUsers == null || companyUserUsers.isEmpty()){
+            return AjaxResult.error("用户未绑定该销售");
+        }
+        fsUserInformationCollection.setCompanyUserId(companyUserId);
+        return AjaxResult.success(fsUserInformationCollectionService.insertFsUserInformationCollection(fsUserInformationCollection));
+    }
+
+    /**
+     * 修改用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('his:collection:edit')")
+    @Log(title = "用户信息采集", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection)
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        fsUserInformationCollection.setCompanyUserId(loginUser.getUser().getUserId());
+        return AjaxResult.success(fsUserInformationCollectionService.updateFsUserInformationCollection(fsUserInformationCollection));
+    }
+
+    /**
+     * 删除用户信息采集
+     */
+    @PreAuthorize("@ss.hasPermi('his: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('his:collection:WxaCodeCollectionUnLimit')")
+    @GetMapping("/getWxaCodeCollectionUnLimit/{collectionId}")
+    public R getWxaCodeCollectionUnLimit(@PathVariable("collectionId") Long orderId)
+    {
+
+        return fsUserInformationCollectionService.getWxaCodePackageOrderUnLimit(orderId);
+
+    }
+}

+ 120 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsUserInformationCollectionScheduleController.java

@@ -0,0 +1,120 @@
+package com.fs.company.controller.store;
+
+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.FsUserInformationCollectionSchedule;
+import com.fs.his.enums.PrescriptionTaskStepEnum;
+import com.fs.his.service.IFsUserInformationCollectionScheduleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+/**
+ * 用户信息采集进度Controller
+ *
+ * @author cgp
+ * @date 2025-11-18
+ */
+@RestController
+@RequestMapping("/store/collectionSchedule")
+public class FsUserInformationCollectionScheduleController extends BaseController
+{
+    @Autowired
+    private IFsUserInformationCollectionScheduleService fsUserInformationCollectionScheduleService;
+
+    /**
+     * 对于每条用户信息采集记录,只获取其最新的任务流程
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        startPage();
+        List<FsUserInformationCollectionSchedule> list = fsUserInformationCollectionScheduleService.getUserRecordLatestTaskProcess(fsUserInformationCollectionSchedule);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户信息采集进度列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:export')")
+    @Log(title = "用户信息采集进度", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        List<FsUserInformationCollectionSchedule> list = fsUserInformationCollectionScheduleService.selectFsUserInformationCollectionScheduleList(fsUserInformationCollectionSchedule);
+        ExcelUtil<FsUserInformationCollectionSchedule> util = new ExcelUtil<FsUserInformationCollectionSchedule>(FsUserInformationCollectionSchedule.class);
+        return util.exportExcel(list, "用户信息采集进度数据");
+    }
+
+    /**
+     * 获取用户信息采集进度详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserInformationCollectionScheduleService.selectFsUserInformationCollectionScheduleById(id));
+    }
+
+    /**
+     * 新增用户信息采集进度
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:add')")
+    @Log(title = "用户信息采集进度", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        return toAjax(fsUserInformationCollectionScheduleService.insertFsUserInformationCollectionSchedule(fsUserInformationCollectionSchedule));
+    }
+
+    /**
+     * 修改用户信息采集进度
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:edit')")
+    @Log(title = "用户信息采集进度", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        return toAjax(fsUserInformationCollectionScheduleService.updateFsUserInformationCollectionSchedule(fsUserInformationCollectionSchedule));
+    }
+
+    /**
+     * 删除用户信息采集进度
+     */
+    @PreAuthorize("@ss.hasPermi('his:collectionSchedule:remove')")
+    @Log(title = "用户信息采集进度", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserInformationCollectionScheduleService.deleteFsUserInformationCollectionScheduleByIds(ids));
+    }
+
+    /**
+     * 获取用户信息采集任务流程步骤枚举列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:collectionSchedule:list')")
+    @GetMapping("/steps")
+    public AjaxResult getTaskSteps() {
+        List<Map<String, Object>> steps = Arrays.stream(PrescriptionTaskStepEnum.values())
+                .map(enumItem -> {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put("dictValue", enumItem.getCode());
+                    map.put("dictLabel", enumItem.getDesc());
+                    return map;
+                })
+                .collect(Collectors.toList());
+        return AjaxResult.success(steps);
+    }
+}

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

@@ -270,7 +270,7 @@ public class FsStoreOrderScrmController extends BaseController
         if(StringUtils.isNotEmpty(order.getDeliveryId())){
 
             String lastFourNumber = "";
-            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
                 lastFourNumber = order.getUserPhone();
                 if (lastFourNumber.length() == 11) {
                     lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);

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

@@ -7,7 +7,7 @@ spring:
 #    active: druid-jnmy-test
 #    active: druid-jzzx-test
 #    active: druid-hdt
-    active: druid-sxjz-test
+    active: druid-bjzm-test
 #    active: druid-yzt
 #    active: druid-myhk
 #    active: druid-sft

+ 47 - 0
fs-doctor-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java

@@ -0,0 +1,47 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsUserInformationCollection;
+import com.fs.his.dto.FsUserInformationCollectionDTO;
+import com.fs.his.param.CollectionInfoConfirmParam;
+import com.fs.his.param.UserInformationDoctorType2Param;
+import com.fs.his.service.IFsUserInformationCollectionService;
+import com.fs.his.vo.FsInquiryOrderListPDVO;
+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("/user/collection")
+public class FsUserInformationCollectionController extends  AppBaseController {
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
+    @GetMapping("/getUserInformation")
+    public R getUserInformation(@RequestParam("id") Long id) {
+        FsUserInformationCollectionDTO fsUserInformationCollection = fsUserInformationCollectionService.selectFsUserInformationCollectionDTOById(id);
+
+
+        return R.ok().put("data", fsUserInformationCollection);
+    }
+    @PostMapping("/doctorConfirm")
+    public R doctorConfirm(@RequestBody FsUserInformationCollection collection){
+        return fsUserInformationCollectionService.doctorConfirm(collection);
+    }
+
+    @GetMapping("/getCollectionList")
+    private R getCollectionList(UserInformationDoctorType2Param userInformationDoctorType2Param) {
+        PageHelper.startPage(userInformationDoctorType2Param.getPageNum(), userInformationDoctorType2Param.getPageSize());
+        userInformationDoctorType2Param.setDoctorType2Id(Long.parseLong(getDoctorId()));
+        List<FsUserInformationCollection> fsUserInformationCollections = fsUserInformationCollectionService.selectFsUserInformationCollectionByDoctorType2(userInformationDoctorType2Param);
+        PageInfo<FsUserInformationCollection> listPageInfo=new PageInfo<>(fsUserInformationCollections);
+        return R.ok().put("data",listPageInfo);
+    }
+
+    @PostMapping("/doctorType2Confirm")
+    public R doctorType2Confirm(@RequestBody FsUserInformationCollection collection){
+        return fsUserInformationCollectionService.doctorType2Confirm(collection);
+    }
+}

+ 8 - 0
fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -186,6 +186,14 @@ public class InquiryOrderController extends  AppBaseController {
         return inquiryOrderService.receiveOrder(param);
     }
 
+    @Login
+    @ApiOperation("接用户信息采集订单")
+    @PostMapping("/receiveInformationOrder")
+    public R receiveInformationOrder(@Validated @RequestBody FsInquiryOrderReceiveParam param, HttpServletRequest request) throws JsonProcessingException {
+        param.setDoctorId(Long.parseLong(getDoctorId()));
+        return inquiryOrderService.receiveOrder(param);
+    }
+
     @Login
     @ApiOperation("拒单")
     @PostMapping("/refuseOrder")

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

@@ -14,7 +14,9 @@ import com.fs.common.utils.StringUtils;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
+import com.fs.his.dto.FsUserInformationCollectionDTO;
 import com.fs.his.dto.PayloadDTO;
+import com.fs.his.mapper.FsUserInformationCollectionMapper;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.FsDoctorPrescribeListDVO;
@@ -41,6 +43,8 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 @Slf4j
@@ -69,6 +73,8 @@ public class PrescribeController extends  AppBaseController {
     private IImService imService;
     @Autowired
     private OpenIMService openIMService;
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
     @Login
     @GetMapping("/getDoctorPrescribeList")
     public R getDoctorPrescribeList(FsDoctorPrescribeListDParam param)
@@ -372,9 +378,22 @@ public class PrescribeController extends  AppBaseController {
         //fsUserCouponService.updateFsUserCouponStatusByLimtType2();
 //        openIMService.checkAndImportFriendByDianBo(Long.parseLong(map.get("sendId")),map.get("userId"),qwExternalContact.getCorpId());
         //OpenImResponseDTO openImResponseDTO = openIMService.sendCourse(Long.parseLong(map.get("userId")), Long.parseLong(map.get("sendId")), "/pages/courseAnswer/index?link=1932017457275338752", "《五仙传医2.0》","https://cos.his.cdwjyyh.com/fs/20241108/a8ed49ae9a264c7483cec5bdcbcf6060.png");
-        log.info("请求地址{}",IMConfig.URL);
-//        log.info("前缀{}",IMConfig.PREFIX);
-        //OpenImResponseDTO openImResponseDTO = openIMService.sendUtil("D" +map.get("sendId"), "U"+map.get("userId").toString(), 110, map.get("payloadDAata").toString(), "", map.get("title").toString(), "", "3135749",ex);
+//        log.info("请求地址{}",IMConfig.URL);
+////        log.info("前缀{}",IMConfig.PREFIX);
+//        OpenImResponseDTO openImResponseDTO = openIMService.sendUserInformation(4050279479l,10086l,1l);
+        CollectionInfoConfirmParam collectionInfoConfirmParam = new CollectionInfoConfirmParam();
+        collectionInfoConfirmParam.setId(1l);
+        collectionInfoConfirmParam.setUserId(4050279479l);
+        collectionInfoConfirmParam.setUserAdvice("wdgcvghfsmjgfjgdgfnbb mjkhkljhgk");
+        fsUserInformationCollectionService.userConfirm(collectionInfoConfirmParam);
         return R.ok().put("data",null);
     }
+
+    @GetMapping("/getUserInformation")
+    public R getUserInformation(@RequestParam("id") Long id) {
+        FsUserInformationCollectionDTO fsUserInformationCollection = fsUserInformationCollectionService.selectFsUserInformationCollectionDTOById(id);
+
+
+        return R.ok().put("data", fsUserInformationCollection);
+    }
 }

+ 52 - 21
fs-live-app/src/main/java/com/fs/live/task/Task.java

@@ -461,27 +461,58 @@ public class Task {
             return;
         liveDatas.forEach(liveData ->{
 
-            Long resultLikeCount = getAsLong(redisCache, "live:like:" + liveData.getLiveId());
-            resultLikeCount = resultLikeCount > 0L ? resultLikeCount : liveData.getLikes();
-            redisCache.setCacheObject("live:like:" + liveData.getLiveId(), resultLikeCount.intValue());
-            liveData.setLikes(
-                    resultLikeCount
-            );
-
-       /* for (Long liveId : liveIds) {
-            LiveData liveData = liveDataService.selectLiveDataByLiveId(liveId);
-            if (liveData == null) {
-                continue; // 防止空指针异常
-            }*/
-
-
-            // 从 redis 获取数据,并提供默认值,避免 NPE
-            liveData.setPageViews(
-                    Math.max( liveData.getPageViews(), Optional.ofNullable(redisCache.incr(PAGE_VIEWS_KEY + liveData.getLiveId(),0)).orElse(0L))
-            );
-            liveData.setTotalViews(
-                    Math.max( liveData.getTotalViews(), Optional.ofNullable(redisCache.incr(TOTAL_VIEWS_KEY + liveData.getLiveId(),0)).orElse(0L))
-            );
+            Map<String, Integer> flagMap = liveWatchUserService.getLiveFlagWithCache(liveData.getLiveId());
+            Integer liveFlag = flagMap.get("liveFlag");
+
+            // 判断是直播还是回放
+            if (liveFlag != null && liveFlag == 1) {
+                // 直播:更新 likes 和 totalViews
+                Long resultLikeCount = getAsLong(redisCache, "live:like:" + liveData.getLiveId());
+                resultLikeCount = resultLikeCount > 0L ? resultLikeCount : liveData.getLikes();
+                redisCache.setCacheObject("live:like:" + liveData.getLiveId(), resultLikeCount.intValue());
+                liveData.setLikes(resultLikeCount);
+
+                // 从 redis 获取数据,并提供默认值,避免 NPE
+                liveData.setPageViews(
+                        Math.max( liveData.getPageViews(), Optional.ofNullable(redisCache.incr(PAGE_VIEWS_KEY + liveData.getLiveId(),0)).orElse(0L))
+                );
+                liveData.setTotalViews(
+                        Math.max( liveData.getTotalViews(), Optional.ofNullable(redisCache.incr(TOTAL_VIEWS_KEY + liveData.getLiveId(),0)).orElse(0L))
+                );
+            } else {
+                // 回放:使用 Redis 中的数据减去直播的数据,得到回放的数据
+                String likeKey = "live:like:" + liveData.getLiveId();
+                String totalViewsKey = TOTAL_VIEWS_KEY + liveData.getLiveId();
+                
+                // 从 Redis 获取总数据(直播+回放)
+                Long totalLikeCount = getAsLong(redisCache, likeKey);
+                Long totalViewCount = getAsLong(redisCache, totalViewsKey);
+                
+                // 获取数据库中直播的数据
+                Long liveLikeCount = liveData.getLikes() != null ? liveData.getLikes() : 0L;
+                Long liveViewCount = liveData.getTotalViews() != null ? liveData.getTotalViews() : 0L;
+                
+                // 回放数据 = Redis总数据 - 直播数据
+                Long replayLikeNum = totalLikeCount - liveLikeCount;
+                Long replayViewNum = totalViewCount - liveViewCount;
+                
+                // 确保回放数据不为负数
+                if (replayLikeNum < 0L) {
+                    replayLikeNum = 0L;
+                }
+                if (replayViewNum < 0L) {
+                    replayViewNum = 0L;
+                }
+                
+                // 更新回放数据
+                liveData.setReplayLikeNum(replayLikeNum);
+                liveData.setReplayViewNum(replayViewNum);
+
+                // 从 redis 获取数据,并提供默认值,避免 NPE
+                liveData.setPageViews(
+                        Math.max( liveData.getPageViews(), Optional.ofNullable(redisCache.incr(PAGE_VIEWS_KEY + liveData.getLiveId(),0)).orElse(0L))
+                );
+            }
             liveData.setUniqueVisitors(
                     /*Optional.ofNullable(redisCache.getCacheSet(UNIQUE_VISITORS_KEY + liveId))
                             .map(Set::size)  // 获取集合大小

+ 11 - 15
fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -263,21 +263,11 @@ public class WebSocketServer {
                             return;
                         }
 
-                        // 根据直播状态设置live_flag或replay_flag
-                        Live msgLive = liveService.selectLiveByLiveId(msg.getLiveId());
-                        if (msgLive != null && msgLive.getFinishTime() != null) {
-                            Date finishTime = java.sql.Timestamp.valueOf(msgLive.getFinishTime());
-                            if (new Date().after(finishTime)) {
-                                liveMsg.setReplayFlag(1);
-                                liveMsg.setLiveFlag(0);
-                            } else {
-                                liveMsg.setLiveFlag(1);
-                                liveMsg.setReplayFlag(0);
-                            }
-                        } else {
-                            liveMsg.setLiveFlag(1);
-                            liveMsg.setReplayFlag(0);
-                        }
+                        Map<String, Integer> flagMap = liveWatchUserService.getLiveFlagWithCache(liveId);
+                        Integer liveFlag = flagMap.get("liveFlag");
+                        Integer replayFlag = flagMap.get("replayFlag");
+                        liveMsg.setLiveFlag(liveFlag);
+                        liveMsg.setReplayFlag(replayFlag);
 
                         liveMsgService.insertLiveMsg(liveMsg);
                     }
@@ -465,6 +455,12 @@ public class WebSocketServer {
     //错误时调用
     @OnError
     public void onError(Session session, Throwable throwable) {
+
+        try {
+            this.onClose(session);
+        } catch (Exception e) {
+            log.error("webSocket 错误 onError", e);
+        }
         if (throwable instanceof EOFException) {
             log.info("WebSocket连接被客户端正常关闭(EOF),sessionId: {}", session.getId());
         } else {

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

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.app.taskService.SopLogsTaskService;
+import com.fs.common.config.FSSysConfig;
 import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.Company;
@@ -1097,6 +1098,27 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                         setting.setMiniprogramAppid("未找到匹配的公司的自定义小程序:"+companyId);
                     }
 
+                    break;
+                //直播小程序单独
+                case "12":
+                    String sortLiveLink;
+                    sortLiveLink = "/pages_course/living?companyId=" + companyId + "&companyUserId=" + companyUserId + "&liveId=" + setting.getLiveId();
+
+
+                    String miniprogramLiveTitle = setting.getMiniprogramTitle();
+                    int maxLiveLength = 17;
+                    setting.setMiniprogramTitle(miniprogramLiveTitle.length() > maxLiveLength ? miniprogramLiveTitle.substring(0, maxLiveLength) + "..." : miniprogramLiveTitle);
+                    String json = configService.selectConfigByKey("his.config");
+                    FSSysConfig sysConfig= JSON.parseObject(json,FSSysConfig.class);
+                    setting.setMiniprogramAppid(sysConfig.getAppId());
+                    setting.setMiniprogramPage(sortLiveLink);
+                    setting.setContentType("4");
+                    try {
+                        setting.setMiniprogramPicUrl(StringUtil.strIsNullOrEmpty(setting.getMiniprogramPicUrl()) ? "https://cos.his.cdwjyyh.com/fs/20250331/ec2b4e73be8048afbd526124a655ad56.png" : setting.getMiniprogramPicUrl());
+                    } catch (Exception e) {
+                        log.error("赋值-小程序封面地址失败-" + e);
+                    }
+
                     break;
                 default:
                     break;

+ 25 - 0
fs-service/src/main/java/com/fs/common/VerifyCodeUtil.java

@@ -0,0 +1,25 @@
+package com.fs.common;
+
+import java.security.SecureRandom;
+
+public class VerifyCodeUtil {
+
+    // 使用 SecureRandom 保证安全性
+    private static final SecureRandom random = new SecureRandom();
+
+    /**
+     * 生成随机 6 位数字验证码
+     * @return 六位验证码字符串
+     */
+    public static String generateCode() {
+        int code = 100000 + random.nextInt(900000); // 保证是六位数,范围 100000-999999
+        return String.valueOf(code);
+    }
+
+    public static void main(String[] args) {
+        // 测试
+        for (int i = 0; i < 5; i++) {
+            System.out.println(VerifyCodeUtil.generateCode());
+        }
+    }
+}

+ 2 - 0
fs-service/src/main/java/com/fs/common/service/ISmsService.java

@@ -21,4 +21,6 @@ public interface ISmsService
     R sendOrderMsg(SmsSendUserParam param);
 
     R sendPackageOrderMsg(SmsSendUserParam param);
+
+    R sendCaptcha(String phone, String captcha, String code);
 }

+ 82 - 0
fs-service/src/main/java/com/fs/common/service/impl/SmsServiceImpl.java

@@ -36,6 +36,7 @@ import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.gson.Gson;
 import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -48,6 +49,7 @@ import java.util.Date;
 import java.util.List;
 
 @Service
+@Slf4j
 public class SmsServiceImpl implements ISmsService
 {
     @Autowired
@@ -527,6 +529,86 @@ public class SmsServiceImpl implements ISmsService
         }
     }
 
+    @Override
+    public R sendCaptcha(String phone, String captcha, String code) {
+        log.info(captcha);
+        CompanySmsTemp temp = smsTempService.selectCompanySmsTempByCode(code);
+        if (temp == null) {
+            return R.error("没有模板");
+        }
+        String content = temp.getContent();
+        if (StringUtils.isNotEmpty(captcha)) {
+            content = content.replace("${sms.captcha}", captcha);
+        }
+        String urls = null;
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.sms");
+        FsSmsConfig sms = JSON.parseObject(sysConfig.getConfigValue(), FsSmsConfig.class);
+        if (sms.getType().equals("rf")) {
+            try {
+                content = content.replace("${sms.sign}",sms.getRfSign());
+                urls = sms.getRfUrl1() + "sms?action=send&account=" + sms.getRfAccount1() + "&password=" + sms.getRfPassword1() + "&mobile=" + phone + "&content=" + URLEncoder.encode(content, "UTF-8") + "&extno=" + sms.getRfCode1() + "&rt=json";
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+            String post = HttpRequest.get(urls)
+                    .execute().body();
+            SmsSendVO vo = JSONUtil.toBean(post, SmsSendVO.class);
+            if (vo.getStatus().equals(0)) {
+                for (SmsSendItemVO itemVO : vo.getList()) {
+                    if (itemVO.getResult().equals("0")) {
+                        CompanySmsLogs logs = new CompanySmsLogs();
+                        logs.setContent(content);
+                        logs.setTempCode(temp.getTempCode());
+                        logs.setTempId(temp.getTempId());
+                        logs.setPhone(phone);
+                        logs.setSendTime(new Date());
+                        logs.setStatus(0);
+                        logs.setType(sms.getType());
+                        logs.setMid(itemVO.getMid());
+                        Integer counts = logs.getContent().length() / 67;
+                        if (logs.getContent().length() % 67 > 0) {
+                            counts = counts + 1;
+                        }
+                        if (counts == 0) {
+                            counts = 1;
+                        }
+                        logs.setNumber(counts);
+                        smsLogsService.insertCompanySmsLogs(logs);
+                    }
+                }
+            }
+        } else if (sms.getType().equals("dh")) {
+            SendSmsReturn sendSmsReturn = null;
+            content = content.replace("${sms.sign}",sms.getDhSign());
+            sendSmsReturn = smsTService.sendSms(sms.getDhAccount1(), sms.getDhPassword1(), content, phone);
+            if (sendSmsReturn != null) {
+                if (sendSmsReturn.getResult() != null && sendSmsReturn.getResult().equals("0")) {
+                    CompanySmsLogs logs = new CompanySmsLogs();
+                    logs.setContent(content);
+                    logs.setTempCode(temp.getTempCode());
+                    logs.setTempId(temp.getTempId());
+                    logs.setPhone(phone);
+                    logs.setSendTime(new Date());
+                    logs.setStatus(0);
+                    logs.setType(sms.getType());
+                    logs.setMid(sendSmsReturn.getMsgid());
+                    Integer counts = logs.getContent().length() / 67;
+                    if (logs.getContent().length() % 67 > 0) {
+                        counts = counts + 1;
+                    }
+                    if (counts == 0) {
+                        counts = 1;
+                    }
+                    logs.setNumber(counts);
+                    smsLogsService.insertCompanySmsLogs(logs);
+                }
+            }
+        }
+
+
+        return R.ok();
+    }
+
 
     @Override
     @Synchronized

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

@@ -178,6 +178,9 @@ public class CompanyUser extends BaseEntity
     /** 是否允许所有方式注册会员,1-是,0-否,默认1(用于个微注册会员) */
     private Integer isAllowedAllRegister;
 
+    /** 绑定的公司用户ID */
+    private Long bindCompanyUserId;
+
     @TableField(exist = false)
     private List<Long> deptList;
 

+ 12 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyConfigMapper.java

@@ -1,6 +1,7 @@
 package com.fs.company.mapper;
 
 import com.fs.company.domain.CompanyConfig;
+import com.fs.company.vo.CompanyMiniAppVO;
 import com.fs.system.domain.SysConfig;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -74,4 +75,15 @@ public interface CompanyConfigMapper
 
     @Select("select config_value from company_config where company_id=#{companyId} and config_key='redPacket:config' ")
     String selectRedPacketConfigByKey(Long companyId);
+
+    @Select("select \n" +
+            "id,\n" +
+            "name,\n" +
+            "appid\n" +
+            "from\n" +
+            "fs_course_play_source_config\n" +
+            "where \n" +
+            "is_del = 0\n" +
+            "and FIND_IN_SET(#{companyId},set_company_ids)")
+    List<CompanyMiniAppVO> getCompanyMiniAppList(@Param("companyId") Long companyId);
 }

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

@@ -336,4 +336,19 @@ public interface CompanyUserMapper
             "</script>")
     List<Long> selectCompanyQwUserByDept(@Param("companyUserIDs") List<Long> companyUserIDs, @Param("userType") String userType);
 
+    /**
+     * 批量更新公司用户的绑定销售ID
+     * @param userIds 公司用户ID列表
+     * @param bindCompanyUserId 绑定的销售ID
+     * @return 更新结果
+     */
+    int batchUpdateBindCompanyUserId(@Param("userIds") List<Long> userIds, @Param("bindCompanyUserId") Long bindCompanyUserId);
+
+    /**
+     * 根据销售ID查询绑定的fs_user用户列表
+     * @param companyUserId 销售ID
+     * @return 绑定的用户列表
+     */
+    List<com.fs.hisStore.domain.FsUserScrm> selectBoundFsUsersByCompanyUserId(@Param("companyUserId") Long companyUserId);
+
 }

+ 30 - 0
fs-service/src/main/java/com/fs/company/param/SaveCompanyMiniAppParam.java

@@ -0,0 +1,30 @@
+package com.fs.company.param;
+
+import lombok.Data;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/22 下午1:59)
+ */
+
+@Data
+public class SaveCompanyMiniAppParam {
+
+    /**
+     * 公司id
+     */
+    private Long companyId;
+
+    /**
+     * 主要小程序
+     */
+    private String mainMiniAppId;
+
+    /**
+     * 备用小程序
+     */
+    private String backupMiniAppId;
+
+    private Long updateBy;
+
+}

+ 18 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyConfigService.java

@@ -1,6 +1,9 @@
 package com.fs.company.service;
 
+import com.fs.common.core.domain.R;
 import com.fs.company.domain.CompanyConfig;
+import com.fs.company.param.SaveCompanyMiniAppParam;
+import com.fs.company.vo.CompanyMiniAppVO;
 
 import java.util.List;
 
@@ -69,4 +72,19 @@ public interface ICompanyConfigService
     CompanyConfig selectCompanyConfigByServerKey(String key);
 
     String selectRedPacketConfigByKey(Long companyId);
+
+    /**
+     * 获取公司可配置小程序列表
+     * @param companyId
+     * @return
+     */
+    List<CompanyMiniAppVO> getCompanyMiniAppList(Long companyId);
+
+    SaveCompanyMiniAppParam getCurrentCompanyMiniApp(Long companyId);
+    /**
+     * 公司编辑保存主备小程序数据
+     * @param param
+     * @return
+     */
+    R saveCompanyMiniApp(SaveCompanyMiniAppParam param);
 }

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

@@ -249,4 +249,19 @@ public interface ICompanyUserService {
     R updateBatchUserRoles(BatchUserRolesVO batchUserRolesVO);
 
     List<Long> selectCompanyQwUserByDept(List<Long> deptList,String userType);
+
+    /**
+     * 批量更新公司用户的绑定销售ID
+     * @param userIds 公司用户ID列表
+     * @param bindCompanyUserId 绑定的销售ID
+     * @return 更新结果
+     */
+    int batchUpdateBindCompanyUserId(List<Long> userIds, Long bindCompanyUserId);
+
+    /**
+     * 根据销售ID查询绑定的fs_user用户列表
+     * @param companyUserId 销售ID
+     * @return 绑定的用户列表
+     */
+    List<com.fs.hisStore.domain.FsUserScrm> selectBoundFsUsersByCompanyUserId(Long companyUserId);
 }

+ 90 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyConfigServiceImpl.java

@@ -1,19 +1,26 @@
 package com.fs.company.service.impl;
 
+import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.core.text.Convert;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyConfig;
+import com.fs.company.domain.CompanyMiniapp;
 import com.fs.company.mapper.CompanyConfigMapper;
+import com.fs.company.mapper.CompanyMiniappMapper;
+import com.fs.company.param.SaveCompanyMiniAppParam;
 import com.fs.company.service.ICompanyConfigService;
+import com.fs.company.vo.CompanyMiniAppVO;
 import com.fs.system.domain.SysConfig;
 import org.apache.http.util.Asserts;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
@@ -38,6 +45,8 @@ public class CompanyConfigServiceImpl implements ICompanyConfigService
     private static final String REDIS_KEY_PREFIX = "red_packet_config:";
     private static final long CACHE_TIMEOUT = 24 * 60 * 60;
 
+    @Autowired
+    CompanyMiniappMapper companyMiniappMapper;
     /**
      * 查询参数配置
      *
@@ -171,4 +180,85 @@ public class CompanyConfigServiceImpl implements ICompanyConfigService
     private static Object getSynchronizationObject(Long companyId) {
         return LOCKS.computeIfAbsent(companyId, k -> new Object());
     }
+
+    /**
+     * 获取公司可配置小程序列表
+     * @param companyId
+     * @return
+     */
+    public List<CompanyMiniAppVO> getCompanyMiniAppList(Long companyId){
+        return companyConfigMapper.getCompanyMiniAppList(companyId);
+    }
+
+    //主要小程序
+    Integer type_main = 0;
+    //备用小程序
+    Integer type_backup = 1;
+
+    @Override
+    public SaveCompanyMiniAppParam getCurrentCompanyMiniApp(Long companyId){
+        SaveCompanyMiniAppParam result = new SaveCompanyMiniAppParam();
+        CompanyMiniapp companyMiniapp = new CompanyMiniapp();
+        companyMiniapp.setCompanyId(companyId);
+        List<CompanyMiniapp> companyMiniapps = companyMiniappMapper.selectCompanyMiniappList(companyMiniapp);
+        if(null != companyMiniapps && !companyMiniapps.isEmpty() && companyMiniapps.size() == 2){
+            for (CompanyMiniapp miniapp : companyMiniapps) {
+                //主要小程序更新
+                if(type_main.equals(miniapp.getType())){
+                    result.setMainMiniAppId(miniapp.getAppId());
+                }
+                //备用小程序更新
+                if(type_backup.equals(miniapp.getType())){
+                    result.setBackupMiniAppId(miniapp.getAppId());
+                }
+            }
+        }
+
+        return result;
+    }
+
+
+    /**
+     * 公司编辑保存主备小程序数据
+     * @param param
+     * @return
+     */
+    @Override
+    @Transactional
+    public R saveCompanyMiniApp(SaveCompanyMiniAppParam param){
+        CompanyMiniapp companyMiniapp = new CompanyMiniapp();
+        companyMiniapp.setCompanyId(param.getCompanyId());
+
+        List<CompanyMiniapp> companyMiniapps = companyMiniappMapper.selectCompanyMiniappList(companyMiniapp);
+        if(null != companyMiniapps && !companyMiniapps.isEmpty() && companyMiniapps.size() == 2){
+            for (CompanyMiniapp miniapp : companyMiniapps) {
+                //主要小程序更新
+                if(type_main.equals(miniapp.getType())){
+                    miniapp.setAppId(param.getMainMiniAppId());
+                }
+                //备用小程序更新
+                if(type_backup.equals(miniapp.getType())){
+                    miniapp.setAppId(param.getBackupMiniAppId());
+                }
+                miniapp.setUpdateTime(new Date());
+                int i = companyMiniappMapper.updateCompanyMiniapp(miniapp);
+            }
+        }else{
+            CompanyMiniapp mainMiniapp = new CompanyMiniapp();
+            mainMiniapp.setCreateTime(new Date());
+            mainMiniapp.setType(type_main);
+            mainMiniapp.setAppId(param.getMainMiniAppId());
+            mainMiniapp.setSortNum(0);
+            mainMiniapp.setCompanyId(param.getCompanyId());
+            int i = companyMiniappMapper.insertCompanyMiniapp(mainMiniapp);
+            CompanyMiniapp backupMiniapp = new CompanyMiniapp();
+            backupMiniapp.setCreateTime(new Date());
+            backupMiniapp.setType(type_backup);
+            backupMiniapp.setAppId(param.getBackupMiniAppId());
+            backupMiniapp.setSortNum(0);
+            backupMiniapp.setCompanyId(param.getCompanyId());
+            int  j = companyMiniappMapper.insertCompanyMiniapp(backupMiniapp);
+        }
+        return R.ok();
+    }
 }

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

@@ -1086,4 +1086,14 @@ public class CompanyUserServiceImpl implements ICompanyUserService
     public List<Long> selectCompanyQwUserByDept(List<Long> deptList,String userType) {
         return companyUserMapper.selectCompanyQwUserByDept(deptList,userType);
     }
+
+    @Override
+    public int batchUpdateBindCompanyUserId(List<Long> userIds, Long bindCompanyUserId) {
+        return companyUserMapper.batchUpdateBindCompanyUserId(userIds, bindCompanyUserId);
+    }
+
+    @Override
+    public List<com.fs.hisStore.domain.FsUserScrm> selectBoundFsUsersByCompanyUserId(Long companyUserId) {
+        return companyUserMapper.selectBoundFsUsersByCompanyUserId(companyUserId);
+    }
 }

+ 32 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyMiniAppVO.java

@@ -0,0 +1,32 @@
+package com.fs.company.vo;
+
+import lombok.Data;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/22 下午1:42)
+ */
+
+@Data
+public class CompanyMiniAppVO {
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 小程序/公众号名称
+     */
+    private String name;
+
+    /**
+     * 小程序/公众号appid
+     */
+    private String appid;
+
+    /**
+     * 小程序所属公司id
+     */
+    private Long companyId;
+
+}

+ 10 - 10
fs-service/src/main/java/com/fs/core/utils/OrderCodeUtils.java

@@ -44,16 +44,16 @@ public class OrderCodeUtils {
 
     }
     public static String getOrderSn(){
-        String url= FSConfig.getCommonApi()+ "/app/common/genOrderCode";
-//        String url= "42.194.245.189:8010/app/common/genOrderCode";
-        String json = HttpRequest.get(url)
-                .execute().body();
-        OrderCodeVO vo= JSONUtil.toBean(json, OrderCodeVO.class);
-        if(vo.getCode()==200){
-            return vo.getOrderCode();
-        }
-        else return null;
-        //return OrderCodeUtils.genOrderSn();
+//        String url= FSConfig.getCommonApi()+ "/app/common/genOrderCode";
+////        String url= "42.194.245.189:8010/app/common/genOrderCode";
+//        String json = HttpRequest.get(url)
+//                .execute().body();
+//        OrderCodeVO vo= JSONUtil.toBean(json, OrderCodeVO.class);
+//        if(vo.getCode()==200){
+//            return vo.getOrderCode();
+//        }
+//        else return null;
+        return OrderCodeUtils.genOrderSn();
 
     }
 

+ 4 - 0
fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java

@@ -82,6 +82,10 @@ public class FsCoursePlaySourceConfig {
      */
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    private String setCompanyIds;
     /**
      * 销售ID
      */

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

@@ -118,5 +118,5 @@ public class FsUserCoursePeriod
      */
     private Date periodLine;
     /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
-    private Integer isNeedRegisterMember;
+    private String isNeedRegisterMember;
 }

+ 9 - 9
fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java

@@ -13,10 +13,10 @@ public class FsOrderDeliveryNoteDTO {
     /**
      * 系统订单号
      * **/
-    @Excel(name = "原始单号",width = 20,sort = 1)
+    @Excel(name = "系统订单号(必填)",width = 20,sort = 1)
     private String orderNumber;
 
-//    @Excel(name = "物流公司",width = 30,sort = 2)
+    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦、YTO:圆通)",width = 30,sort = 2)
     private String deliverySn;
 
     @Excel(name = "物流公司",width = 10,sort = 10)
@@ -24,25 +24,25 @@ public class FsOrderDeliveryNoteDTO {
 
     private String deliveryName;
 
-    @Excel(name = "快递单号",width = 20,sort = 23)
+    @Excel(name = "快递单号(必填)",width = 20,sort = 3)
     private String deliveryId;
 
-//    @Excel(name = "物流状态(0:暂无信息、1:已揽收、2:在途中、3:签收、4:问题件)",width = 40,sort = 4)
+    @Excel(name = "物流状态(0:暂无信息、1:已揽收、2:在途中、3:签收、4:问题件)",width = 40,sort = 4)
     private Integer deliveryStatus;
 
-//    @Excel(name = "物流结算费用",width = 20,sort = 5)
+    @Excel(name = "物流结算费用",width = 20,sort = 5)
     private BigDecimal deliveryPayMoney;
 
-//    @Excel(name = "物流跟踪状态(311:快递柜或驿站签收、304:派件异常后最终签收、301:正常签收、211:已放入快递柜或驿站、202:派件中、201:到达派件城市、401:发货无信息、412:快递柜或驿站超时未取、407:退货未签收)",width = 40,sort = 6)
+    @Excel(name = "物流跟踪状态(311:快递柜或驿站签收、304:派件异常后最终签收、301:正常签收、211:已放入快递柜或驿站、202:派件中、201:到达派件城市、401:发货无信息、412:快递柜或驿站超时未取、407:退货未签收)",width = 40,sort = 6)
     private Integer deliveryType;
 
-//    @Excel(name = "物流结算状态(1:已结算、2:冻结、3:解冻、4:退回运费、5.调账)",width = 20,sort = 7)
+    @Excel(name = "物流结算状态(1:已结算、2:冻结、3:解冻、4:退回运费、5.调账)",width = 20,sort = 7)
     private Integer deliveryPayStatus;
 
-//    @Excel(name = "快递账单日期",width = 20,sort = 8)
+    @Excel(name = "快递账单日期",width = 20,sort = 8)
     private String deliveryTime;
 
-//    @Excel(name = "快递结算日期",width = 20,sort = 9)
+    @Excel(name = "快递结算日期",width = 20,sort = 9)
     private String deliveryPayTime;
 
 //    /**

+ 92 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -295,6 +295,98 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             "</script>"})
     List<FsCourseWatchLogStatisticsListVO> selectFsCourseWatchLogStatisticsListVO(FsCourseWatchLogStatisticsListParam param);
 
+    @Select({"<script> " +
+            " \tselect \n" +
+            "\t'总合计' as qw_user_name,\n" +
+            "\tsum(t1.type1) as type1,\n" +
+            "\tsum(t1.type2) as type2,\n" +
+            "\tsum(t1.type3) as type3,\n" +
+            "\tsum(t1.type4) as type4,\n" +
+            "\t (\n" +
+            "     sum(t1.type1)+\n" +
+            "     sum(t1.type2) +\n" +
+            "     sum(t1.type4)\n" +
+            "   ) AS on_line_num,\n" +
+            "\t sum(send_number) as send_number,\n" +
+            "\t sum(is_user_wait_number) as is_user_wait_number,\n" +
+            "\t sum(no_user_wait_number) as no_user_wait_number,\n" +
+            "\t sum(red_amount) as red_amount\n" +
+            "\tfrom  ( select t.* " +
+            "<if test= 'sendType != 1 '> " +
+            " ,concat(round(if(t.send_number=0,0,(t.on_line_num/t.send_number)*100),2),'%') on_line_rate" +
+            " ,concat(round(if(t.send_number=0,0,(t.type2/t.send_number)*100),2),'%') finished_rate" +
+            "</if> " +
+            "from (" +
+            "SELECT \n" +
+            "o.video_id,o.company_id,o.qw_user_id,DATE(o.create_time) create_time," +
+            "<if test= 'sendType != 1 '> " +
+            " qu.qw_user_name qw_user_name," +
+            "</if>\n" +
+            "<if test= 'sendType == 1 '> " +
+            " cu.nick_name qw_user_name," +
+            "</if>\n" +
+            "v.title videoName,uc.course_name,\n" +
+            "SUM(CASE WHEN o.log_type = '1' THEN 1 ELSE 0 END) AS type1,\n" +
+            "SUM(CASE WHEN o.log_type = '2' THEN 1 ELSE 0 END) AS type2,\n" +
+            "SUM(CASE WHEN o.log_type = '3' THEN 1 ELSE 0 END) AS type3,\n" +
+            "SUM(CASE WHEN o.log_type = '4' THEN 1 ELSE 0 END) AS type4,\n" +
+            "(\n" +
+            "  SUM(CASE WHEN o.log_type = '1' THEN 1 ELSE 0 END) +\n" +
+            "  SUM(CASE WHEN o.log_type = '2' THEN 1 ELSE 0 END) +\n" +
+            "  SUM(CASE WHEN o.log_type = '4' THEN 1 ELSE 0 END)\n" +
+            ") AS on_line_num " +
+            "<if test= 'sendType != 1 '> " +
+            " ,count(o.log_id) send_number" +
+            " ,sum(if((o.user_id is not null or o.user_id>0) and o.log_type=3,1,0)) is_user_wait_number" +
+            " ,sum(if((o.user_id is null or o.user_id=0) and o.log_type=3,1,0)) no_user_wait_number" +
+//            " ,sum(ifnull(fcr.amount,0)) red_amount" +
+            ",(SELECT SUM(amount) FROM fs_course_red_packet_log \n" +
+            "     WHERE user_id = o.user_id AND video_id = o.video_id) as red_amount " +
+            "</if> " +
+            "FROM fs_course_watch_log o " +
+            "<if test= 'sendType != 1 '> " +
+            " LEFT JOIN qw_user qu on qu.id=o.qw_user_id " +
+//            " LEFT JOIN fs_course_red_packet_log fcr on o.user_id = fcr.user_id and fcr.video_id = o.video_id" + //会有笛卡尔积问题
+            "</if>\n" +
+            "LEFT JOIN fs_user_course_video v on v.video_id=o.video_id \n" +
+            "LEFT JOIN fs_user_course uc on uc.course_id=v.course_id\n" +
+            "<if test= 'sendType == 1 '> " +
+            " LEFT JOIN company_user cu on cu.user_id=o.company_user_id\n" +
+            "</if>\n" +
+            "where o.company_id=#{companyId} " +
+            "<if test= 'sendType != null '> " +
+            "       and  send_type= #{sendType} " +
+            "</if>\n" +
+            "<if test= 'sTime != null '> " +
+            "       and DATE(o.create_time) &gt;= DATE(#{sTime})\n" +
+            "</if>\n" +
+            "<if test='eTime != null '> " +
+            "      and DATE(o.create_time) &lt;= DATE(#{eTime})\n" +
+            "</if>" +
+            "<if test ='sendType != 1 and nickName !=null and nickName!=\"\"'>\n" +
+            "   and qu.qw_user_name like concat( #{nickName}, '%')\n" +
+            "</if>" +
+            "<if test ='sendType == 1 and nickName !=null and nickName!=\"\"'>\n" +
+            "   and cu.nick_name like concat( #{nickName}, '%')\n" +
+            "</if>" +
+            "<if test ='courseId !=null'> " +
+            "     and o.course_id = #{courseId} " +
+            "</if>" +
+            "<if test ='videoId !=null'> " +
+            "     and o.video_id = #{videoId} " +
+            "</if>" +
+            "GROUP BY o.video_id," +
+            "<if test= 'sendType != 1 '> " +
+            " o.qw_user_id," +
+            "</if>\n" +
+            "<if test= 'sendType == 1 '> " +
+            " o.company_user_id," +
+            "</if>\n" +
+            "DATE(o.create_time)\n" +
+            "ORDER BY o.video_id ,DATE(o.create_time) " +
+            ") t ) t1 \n"+
+            "</script>"})
+    FsCourseWatchLogStatisticsListVO getTotalDataAddItem(FsCourseWatchLogStatisticsListParam param);
     @Select({"<script> " +
             "SELECT COUNT(*) FROM (" +
             "    SELECT 1 " +

+ 5 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java

@@ -45,6 +45,11 @@ public class FsCoursePlaySourceConfigCreateParam {
 
     @ApiModelProperty("所属公司")
     private Long companyId;
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
 
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;

+ 6 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java

@@ -43,6 +43,12 @@ public class FsCoursePlaySourceConfigEditParam {
     @ApiModelProperty("所属公司")
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
     private Long createDeptId;

+ 8 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java

@@ -88,6 +88,14 @@ public interface IFsCourseWatchLogService extends IService<FsCourseWatchLog> {
     void testFinishMsg();
 
     List<FsCourseWatchLogStatisticsListVO> selectFsCourseWatchLogStatisticsListVO(FsCourseWatchLogStatisticsListParam param);
+
+    /**
+     * 新增企微看课统计汇总行查询
+     * @param param
+     * @return
+     */
+    FsCourseWatchLogStatisticsListVO getTotalDataAddItem(FsCourseWatchLogStatisticsListParam param);
+
     List<FsCourseWatchLogStatisticsListByCompanyVO> selectFsCourseWatchLogStatisticsListByCompanyVO(FsCourseWatchLogStatisticsListParam param);
 
     void scheduleBatchUpdateToDatabase();

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

@@ -102,7 +102,7 @@ public interface IFsUserCoursePeriodService
 
     List<Long> selectFsUserCoursePeriodListByPeriodId(List<Long> periodIds,Long companyId);
 
-    int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod);
+    int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod,String s);
 
     List<SysDictData> selectFsUserCoursePeriodListLabel(FsUserCoursePeriod fsUserCoursePeriod);
 }

+ 23 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -59,6 +59,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -764,6 +766,27 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         return fsCourseWatchLogMapper.selectFsCourseWatchLogStatisticsListVO(param);
     }
 
+
+    /**
+     * 新增企微看课统计汇总行查询
+     * @param param
+     * @return
+     */
+    public FsCourseWatchLogStatisticsListVO getTotalDataAddItem(FsCourseWatchLogStatisticsListParam param){
+        FsCourseWatchLogStatisticsListVO addItem =  fsCourseWatchLogMapper.getTotalDataAddItem(param);
+        if(null != addItem && null != addItem.getOnLineNum() && 0 != addItem.getOnLineNum() && null != addItem.getSendNumber()){
+            addItem.setOnLineRate(new BigDecimal(addItem.getOnLineNum())
+                    .multiply(new BigDecimal(100))
+                    .divide(new BigDecimal(addItem.getSendNumber()),2,BigDecimal.ROUND_HALF_UP)
+                     + "%");
+
+            addItem.setFinishedRate(new BigDecimal(addItem.getType2())
+                    .multiply(new BigDecimal(100))
+                    .divide(new BigDecimal(addItem.getSendNumber()),2,BigDecimal.ROUND_HALF_UP) + "%");
+        }
+        return addItem;
+    }
+
     @Override
     public List<FsCourseWatchLogStatisticsListByCompanyVO> selectFsCourseWatchLogStatisticsListByCompanyVO(FsCourseWatchLogStatisticsListParam param) {
         return fsCourseWatchLogMapper.selectFsCourseWatchLogStatisticsListByCompanyVO(param);

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

@@ -313,7 +313,30 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     }
 
     @Override
-    public int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod) {
+    public int editIsNeedRegisterMember(FsUserCoursePeriod fsUserCoursePeriod,String companyId) {
+        String currentValue = fsUserCoursePeriod.getIsNeedRegisterMember();
+
+        if (currentValue.equals("0")) {
+            // 移除指定的 companyId
+            String updatedValue = Arrays.stream(currentValue.split(","))
+                    .map(String::trim)
+                    .filter(id -> !id.equals(companyId))
+                    .collect(Collectors.joining(","));
+            fsUserCoursePeriod.setIsNeedRegisterMember(updatedValue);
+        } else {
+            // 添加 companyId,并过滤掉 "0"
+            String updatedValue = Arrays.stream(currentValue.split(","))
+                    .map(String::trim)
+                    .filter(id -> !id.equals("0")) // 清除 "0"
+                    .collect(Collectors.collectingAndThen(
+                            Collectors.toCollection(LinkedHashSet::new),
+                            set -> {
+                                set.add(companyId);
+                                return String.join(",", set);
+                            }
+                    ));
+            fsUserCoursePeriod.setIsNeedRegisterMember(updatedValue);
+        }
         return fsUserCoursePeriodMapper.updateFsUserCoursePeriod(fsUserCoursePeriod);
     }
 

+ 97 - 95
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -503,7 +503,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
         //用户不存在唤起重新授权
         if (fsUser==null){
-            return R.error(504,"未授权");
+            return R.error(401,"未授权");
         }
 
         if (fsUser.getStatus()==0){
@@ -546,10 +546,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
 
 
-        //服务号授权的,缺mpOpenId的重新登录 linkType = 4为app看课 不需要mp
-        if (param.getLinkType() != 4 && config.getMiniAppAuthType()==2 && StringUtil.strIsNullOrEmpty(fsUser.getMpOpenId())){
-            return R.error(401,"授权后可继续!");
-        }
+//        //服务号授权的,缺mpOpenId的重新登录 linkType = 4为app看课 不需要mp
+//        if (param.getLinkType() != 4 && config.getMiniAppAuthType()==2 && StringUtil.strIsNullOrEmpty(fsUser.getMpOpenId())){
+//            return R.error(401,"授权后可继续!");
+//        }
 
         boolean oneCompanyCourse = config.isOneCompanyCourse();
         if(oneCompanyCourse && fsUser.getQwExtId() != null){
@@ -604,26 +604,70 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if(qwGroupChatUsers == null || qwGroupChatUsers.isEmpty()){
             return R.error("群参数异常");
         }
-        QwExternalContact qwExternalContact =
-                qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+        //群聊寻找用户新逻辑
+        QwExternalContact qwExternalContact = null;
+        if( null != param.getUserId() && null == qwExternalContact){
+            try {
+                qwExternalContact =  qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
                         .eq("user_id", qwGroupChat.getOwner())
                         .eq("fs_user_id", param.getUserId())
                         .eq("corp_id", param.getCorpId())
                         .eq("status",0));
-        if(null == qwExternalContact){
-            try{
-                //修改成通过昵称匹配
-                qwExternalContact =
-                        qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
-                                .eq("user_id", qwGroupChat.getOwner())
-                                .eq("name", user.getNickName())
-                                .eq("corp_id", param.getCorpId())
-                                .eq("status",0));
-            } catch(Exception e){
-                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),e);
+            } catch (Exception e){
+                log.error("群聊用户id匹配异常,参数user_id:{},fs_user_id:{},corp_id:{}",qwGroupChat.getOwner(),param.getUserId(),param.getCorpId(),e);
+            }
+        }
+        //找当前群中的用户匹配
+        if(StringUtils.isNotBlank(param.getChatId()) && null == qwExternalContact){
+            List<QwExternalContact> groupChatUserByChatIdAndUserName = qwExternalContactMapper.getGroupChatUserByChatIdAndUserName(qwGroupChat.getOwner(), user.getNickName(), param.getCorpId(), param.getChatId());
+            log.info("群聊用户查询结果,参数user_id:{},name:{},corp_id:{},chatId:{},groupChatUserByChatIdAndUserName:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),param.getChatId(),groupChatUserByChatIdAndUserName);
+            //没找到用户 || 找到的用户数量大于1 使用userid查询匹配
+            if(null == groupChatUserByChatIdAndUserName || groupChatUserByChatIdAndUserName.isEmpty() || groupChatUserByChatIdAndUserName.size() > 1){
+                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{},chatId:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),param.getChatId());
+            } else {
+                qwExternalContact =  groupChatUserByChatIdAndUserName.get(0);
             }
-
         }
+//        QwExternalContact qwExternalContact =  qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+//                            .eq("user_id", qwGroupChat.getOwner())
+//                            .eq("fs_user_id", param.getUserId())
+//                            .eq("corp_id", param.getCorpId())
+//                            .eq("status",0));
+//
+//        if(null == qwExternalContact){
+//            try{
+//                //修改成通过昵称匹配
+//                qwExternalContact =
+//                        qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+//                                .eq("user_id", qwGroupChat.getOwner())
+//                                .eq("name", user.getNickName())
+//                                .eq("corp_id", param.getCorpId())
+//                                .eq("status",0));
+//            } catch(Exception e){
+//                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),e);
+//            }
+//
+//        }
+//        QwExternalContact qwExternalContact =
+//                qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+//                        .eq("user_id", qwGroupChat.getOwner())
+//                        .eq("fs_user_id", param.getUserId())
+//                        .eq("corp_id", param.getCorpId())
+//                        .eq("status",0));
+//        if(null == qwExternalContact){
+//            try{
+//                //修改成通过昵称匹配
+//                qwExternalContact =
+//                        qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+//                                .eq("user_id", qwGroupChat.getOwner())
+//                                .eq("name", user.getNickName())
+//                                .eq("corp_id", param.getCorpId())
+//                                .eq("status",0));
+//            } catch(Exception e){
+//                log.error("群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{}",qwGroupChat.getOwner(),user.getNickName(),param.getCorpId(),e);
+//            }
+//
+//        }
         if(qwExternalContact==null){
             return addCustomerService(param.getQwUserId(),msg);
         }
@@ -723,82 +767,36 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 return R.error(567,"群聊通用链接").put("qwExternalId", contact.getId());
             }
         }
+        if ("今正科技".equals(cloudHostProper.getCompanyName())) {
+            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){
+                    param.setUserId(user.getUserId());
+                    createWatchLog(param);
+                }else {
+                    if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
+                        log.setUserId(param.getUserId());
+                    }
+                    log.setUpdateTime(new Date());
+                    courseWatchLogMapper.updateFsCourseWatchLog(log);
+                }
+                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>";
 
         return addCustomerService(param.getQwUserId(),msg);
 
-//        QwGroupChatDetailsResult result = qwApiService.groupChatDetails(courseLink.getChatId(), param.getCorpId());
-//        if(result.getErrCode() != 0){
-//            log.info("企微接口请求失败,请联系管理员:" +result.getErrMsg());
-//            return R.error("不是此群成员");
-//        }
-//        List<QwGroupChatDetailsResult.Member> collect = result.getGroupChat().getMemberList().stream().filter(e -> e.getType() == 2).collect(Collectors.toList());
-//        if(collect.isEmpty()){
-//            logger.info("群聊里面为空弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId());
-//            return addCustomerService(param.getQwUserId(),msg);
-//        }
-//        Optional<QwGroupChatDetailsResult.Member> optional = collect.stream().filter(e -> e.getName().equals(user.getNickName()) || e.getName().equals(param.getNickName())).findFirst();
-//        if(!optional.isPresent()){
-//            logger.info("昵称未匹配上弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId());
-//
-//            return addCustomerService(param.getQwUserId(),msg);
-//        }
-//        QwGroupChatDetailsResult.Member member = optional.get();
-//        QwExternalContact qwExternalContact = qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>().eq("user_id", result.getGroupChat().getOwner()).eq("external_user_id", member.getUserId()));
-//        if(qwExternalContact==null){
-//            logger.info("外部联系人为空弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId()+":"+member.getUserId()+param.getNickName());
-//            return addCustomerService(param.getQwUserId(),msg);
-//        }
-//        Long qwExternalId = qwExternalContact.getId();
-//        log.info("外部联系人数据:{}", qwExternalContact);
-////        addCompanyCompanyFsUser(param);
-//        FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(qwExternalId, param.getVideoId(),param.getQwUserId());
-//        if (log==null ){
-//            logger.info("看课记录为空弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId()+qwExternalId+":"+param.getVideoId()+":"+param.getQwUserId());
-//            return addCustomerService(param.getQwUserId(),msg);
-//        }
-//        //判断外部联系人有没有绑定userId
-//        if (qwExternalContact.getFsUserId()!=null){
-//            //有客户有小程序id  但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
-//            if (!qwExternalContact.getFsUserId().equals(param.getUserId())) {
-//                logger.info("小程序id不一致空弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId());
-//                return addCustomerService(param.getQwUserId(),msg);
-//            }
-//            List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());
-//            //匹配客户公司id
-//            if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
-//                logger.info("未匹配上公司空弹二维码:"+param.getCorpId()+":"+param.getQwUserId()+":"+param.getChatId()+":"+param.getUserId());
-//                return addCustomerService(param.getQwUserId(),msg);
-//            }
-//
-//            //看课记录中userId为0绑定userId
-//            if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
-//                log.setUserId(param.getUserId());
-//            }
-//
-//            log.setUpdateTime(new Date());
-//            courseWatchLogMapper.updateFsCourseWatchLog(log);
-//
-//            iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId,param.getUserId());
-//        }else {
-//            //没绑定fsUser直接绑定fsUser
-//            QwExternalContact contact = new QwExternalContact();
-//            contact.setId(qwExternalId);
-//            contact.setFsUserId(param.getUserId());
-//            qwExternalContactMapper.updateQwExternalContact(contact);
-//            FsUser fsUser = new FsUser();
-//            fsUser.setUserId(user.getUserId());
-//            fsUser.setIsAddQw(1);
-//            fsUserMapper.updateFsUser(fsUser);
-//            //绑定上之后 更新观看记录
-//            //看课记录中userId为0绑定userId
-//            log.setUserId(param.getUserId());
-//            log.setUpdateTime(new Date());
-//            courseWatchLogMapper.updateFsCourseWatchLog(log);
-//        }
-//
-//        return R.error(567,"群聊通用链接").put("qwExternalId", qwExternalContact.getId());
+
     }
 
     private void createWatchLog(FsUserCourseVideoAddKfUParam param) {
@@ -974,7 +972,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             qwAddContactWayParam.setType(1);
             qwAddContactWayParam.setScene(2);
             qwAddContactWayParam.setUser(users);
-            qwAddContactWayParam.setSkip_verify(true);
+            qwAddContactWayParam.setSkip_verify(false);
             QwAddContactWayResult qwAddContactWayResult = qwApiService.addContactWay(qwAddContactWayParam, qwUser.getCorpId());
             if (qwAddContactWayResult.getErrcode() == 0) {
                 qwUser.setContactWay(qwAddContactWayResult.getQr_code());
@@ -2184,11 +2182,15 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 if((companyUser.getIsAllowedAllRegister() !=null && companyUser.getIsAllowedAllRegister() != 1)){
                     return ResponseResult.fail(504,"当前销售禁止绑定会员,请联系销售!");
                 }
+                // 使用 Stream API 检查是否包含 companyId
+                // 修正类型转换问题
                 if (companyUser.getIsNeedRegisterMember() == null || companyUser.getIsNeedRegisterMember() == 1
-                        ||(ObjectUtils.isNotEmpty(fsUserCoursePeriod)
-                        &&ObjectUtils.isNotEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())
-                        &&fsUserCoursePeriod.getIsNeedRegisterMember().equals(1))){
-                    return ResponseResult.fail(504,"请联系销售发送邀请链接成为会员!");
+                        || (ObjectUtils.isNotEmpty(fsUserCoursePeriod)
+                        && ObjectUtils.isNotEmpty(fsUserCoursePeriod.getIsNeedRegisterMember())
+                        && Arrays.stream(fsUserCoursePeriod.getIsNeedRegisterMember().split(","))
+                        .map(String::trim)
+                        .anyMatch(id -> id.equals(String.valueOf(company.getCompanyId()))))) {
+                    return ResponseResult.fail(504, "请联系销售发送邀请链接成为会员!");
                 }
                 int defaultStatus = (company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1;
                 userCompanyUser = userCompanyUserService.bindRelationship(param.getUserId(), courseProject, companyUser.getCompanyId(), companyUser.getUserId(), defaultStatus);

+ 6 - 0
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -42,6 +42,12 @@ public class FsCoursePlaySourceConfigVO {
     @ApiModelProperty("所属公司")
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
     @ApiModelProperty("创建时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;

+ 1 - 1
fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java

@@ -46,7 +46,7 @@ public class uniPush2ServiceImpl implements uniPush2Service {
     public void pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe,String linkImageUrl, String link, Long companyUserId,Long fsUserId) throws JsonProcessingException {
 
         if (companyUserId!=null&&fsUserId!=null && fsUserId!=0){
-            openIMService.sendCourse(fsUserId,companyUserId,link,linkDescribe,linkImageUrl,cropId);
+            openIMService.sendCourse(fsUserId,companyUserId,link,linkTile,linkImageUrl,cropId);
         }
 
     }

+ 42 - 0
fs-service/src/main/java/com/fs/his/domain/DoctorMsg.java

@@ -0,0 +1,42 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 医生消息对象 doctor_msg
+ *
+ * @author fs
+ * @date 2025-11-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DoctorMsg extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 类型:1医生开方 2药师处方审核 3信息采集建议 */
+    @Excel(name = "类型:1医生开方 2药师处方审核 3信息采集建议")
+    private Integer type;
+
+    /** 标题 */
+    @Excel(name = "标题")
+    private String title;
+
+    /** 内容 */
+    @Excel(name = "内容")
+    private String content;
+
+    /** 0未读 1已读 */
+    @Excel(name = "0未读 1已读")
+    private Integer isRead;
+
+    /** 医生id */
+    @Excel(name = "医生id")
+    private Long doctorId;
+
+
+}

+ 47 - 0
fs-service/src/main/java/com/fs/his/domain/FsDoctorConfirm.java

@@ -0,0 +1,47 @@
+package com.fs.his.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 【请填写功能名称】对象 fs_doctor_confirm
+ *
+ * @author fs
+ * @date 2025-10-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsDoctorConfirm extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 用户信息采集id */
+    @Excel(name = "用户信息采集id")
+    private Long collectionId;
+
+    /** 开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date startTime;
+
+    /** 结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date doctorEndTime;
+
+    /** 医生id */
+    @Excel(name = "医生id")
+    private Long doctorId;
+
+    /** 确认秒数 */
+    @Excel(name = "确认秒数")
+    private Long confirmSecond;
+
+
+}

+ 10 - 0
fs-service/src/main/java/com/fs/his/domain/FsInquiryOrder.java

@@ -145,6 +145,16 @@ public class FsInquiryOrder extends BaseEntity
 
     private Long triageUserId;
 
+    private Integer isUserInformation;
+
+    public Integer getIsUserInformation() {
+        return isUserInformation;
+    }
+
+    public void setIsUserInformation(Integer isUserInformation) {
+        this.isUserInformation = isUserInformation;
+    }
+
     public Long getTriageUserId() {
         return triageUserId;
     }

+ 28 - 0
fs-service/src/main/java/com/fs/his/domain/FsQuestionAndAnswer.java

@@ -0,0 +1,28 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 问答对象 fs_question_and_answer
+ *
+ * @author fs
+ * @date 2025-09-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsQuestionAndAnswer extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    private String questionName;
+
+    /** 问答数据 */
+    @Excel(name = "问答数据")
+    private String jsonInfo;
+
+
+}

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

@@ -265,5 +265,6 @@ public class FsStoreOrder extends BaseEntity
     private Integer source;
     private BigDecimal billPrice;
     private String erpPhone;
+    private Integer doctorType2Confirm;
 
 }

+ 15 - 0
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -96,6 +96,15 @@ public class FsUser extends BaseEntity
     private Long companyId;
     private Long companyUserId;
     private String companyUserName;
+
+    /** 公司用户ID,逗号拼接*/
+    @TableField(exist = false)
+    private String companyUserIdMulti;
+
+    /** 公司用户ID,用于查询*/
+    @TableField(exist = false)
+    private String[] companyUserIds;
+
     @JsonFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "推线日期", width = 30, dateFormat = "yyyy-MM-dd")
     private Date registerDate;
@@ -209,6 +218,12 @@ public class FsUser extends BaseEntity
     @TableField(exist = false)
     private String nickname;
 
+    /**
+     * 昵称-精确查询
+     * **/
+    @TableField(exist = false)
+    private String nicknameExact;
+
     public String getNickname() {
         return nickname;
     }

+ 105 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserInformationCollection.java

@@ -0,0 +1,105 @@
+package com.fs.his.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 用户信息采集对象 fs_user_information_collection
+ *
+ * @author fs
+ * @date 2025-10-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserInformationCollection extends BaseEntity{
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 问答id */
+    @Excel(name = "问答id")
+    private Long questionId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 信息采集json数据 */
+    @Excel(name = "信息采集json数据")
+    private String jsonInfo;
+
+    /** 用户确认状态 0-未确认 1-已确认 */
+    @Excel(name = "用户确认状态 0-未确认 1-已确认")
+    private Integer userConfirm;
+
+    /** 医生确认状态 0-未确认 2-已确认 */
+    @Excel(name = "医生确认状态 0-未确认 2-已确认")
+    private Integer doctorConfirm;
+
+    // 医生id
+    private Long doctorId;
+
+    //销售id
+    private Long companyUserId;
+
+    //套餐包id
+    private Long packageId;
+
+    //支付类型 0-全款 1-物流代收
+    private Integer payType;
+
+    //代收金额
+    private BigDecimal amount;
+
+    //用户补充说明
+    private String userAdvice;
+
+    //医生建议
+    private String doctorAdvice;
+
+    //医生签名
+    private String doctorSign;
+
+    //是否关联套餐包 0-不关联 1-关联
+    private Integer isPackage;
+
+    //套餐包订单号
+    private String packageOrderCode;
+
+    //用户第二次确认状态
+    private Integer userConfirm2;
+
+    //确认状态 1第一次确认 2第二次确认
+    private Integer status;
+
+    //医生确认时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date doctorConfirmTime;
+
+    //用户性别 0女 1男
+    private Integer sex;
+    //用户姓名
+    private String userName;
+    //用户电话后四位
+    private String userPhoneFour;
+
+    //是否过敏
+    private String allergy;
+    //备注
+    private String remark;
+
+    private Long patientId;
+    private String patientName;
+
+    private Long companyId;
+    private Long doctorType2Id;
+    private Integer doctorType2Confirm;
+    private String doctorType2Sign;
+
+}

+ 71 - 0
fs-service/src/main/java/com/fs/his/domain/FsUserInformationCollectionSchedule.java

@@ -0,0 +1,71 @@
+package com.fs.his.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 用户信息采集进度对象 fs_user_information_collection_schedule
+ *
+ * @author fs
+ * @date 2025-11-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsUserInformationCollectionSchedule extends BaseEntity{
+
+    /** 主键 */
+    private Long id;
+
+    /** 用户信息采集表id */
+    private Long collectionId;
+
+    /** 用户id */
+    private Long userId;
+
+    /** 客户姓名 */
+    private String userName;
+
+    /** 医生id */
+    private Long doctorId;
+
+    /** 约诊医生 */
+    private String doctorName;
+
+    /** 套餐包Id */
+    private Long packageId;
+
+    /** 挂载商品名称 */
+    private String packageName;
+
+    /** 当前流程节点:(1:待用户第一次确认、2:待开方、3:待药师审核、4:待建议、5:待用户二次确认、6:完成);其中带疗法模式有1,2,3,5,6;无疗法模式只有1,4,5,6 */
+    private Integer currentStep;
+
+    /** 整体任务状态:1-进行中,2-已完成,3-已中止 */
+    private Integer status;
+
+    /** 创建时间 */
+    private Date createTime;
+
+    /** 完成时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "完成时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date completedTime;
+
+    /** 中止时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "中止时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date terminatedTime;
+
+    /** 中止操作人id */
+    private Long terminatedBy;
+
+    /** 订单号 */
+    private String orderCode;
+
+
+}

+ 103 - 0
fs-service/src/main/java/com/fs/his/dto/FsUserInformationCollectionDTO.java

@@ -0,0 +1,103 @@
+package com.fs.his.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class FsUserInformationCollectionDTO {
+    /** $column.columnComment */
+    private Long id;
+
+    /** 问答id */
+    @Excel(name = "问答id")
+    private Long questionId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 信息采集json数据 */
+    @Excel(name = "信息采集json数据")
+    private String jsonInfo;
+
+    /** 用户确认状态 0-未确认 1-已确认 */
+    @Excel(name = "用户确认状态 0-未确认 1-已确认")
+    private Integer userConfirm;
+
+    /** 医生确认状态 0-未确认 2-已确认 */
+    @Excel(name = "医生确认状态 0-未确认 2-已确认")
+    private Integer doctorConfirm;
+
+    // 医生id
+    private Long doctorId;
+
+    //销售id
+    private Long companyUserId;
+
+    //套餐包id
+    private Long packageId;
+
+    //支付类型 0-全款 1-物流代收
+    private Integer payType;
+
+    //代收金额
+    private BigDecimal amount;
+
+    //用户补充说明
+    private String userAdvice;
+
+    //医生建议
+    private String doctorAdvice;
+
+    //是否关联套餐包 0-不关联 1-关联
+    private Integer isPackage;
+
+    //套餐包订单号
+    private String packageOrderCode;
+
+    //用户第二次确认状态
+    private Integer userConfirm2;
+
+    //确认状态 1第一次确认 2第二次确认
+    private Integer status;
+
+    //医生确认时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date doctorConfirmTime;
+
+    //用户性别 0女 1男
+    private Integer sex;
+    //用户姓名
+    private String userName;
+    //用户电话后四位
+    private String userPhoneFour;
+
+    //是否过敏
+    private String allergy;
+    //备注
+    private String remark;
+
+    private Long patientId;
+
+    private String patientName;
+
+    private String companyUserName;
+
+    private String doctorName;
+
+    private String packageName;
+
+    private String questionJson;
+
+    private String doctorSign;
+
+    private String doctorType2Name;
+    private Long doctorType2Id;
+    private Integer doctorType2Confirm;
+    private String doctorType2Sign;
+
+}

+ 3 - 1
fs-service/src/main/java/com/fs/his/dto/PayloadDTO.java

@@ -1,5 +1,6 @@
 package com.fs.his.dto;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -12,6 +13,7 @@ public class PayloadDTO implements Serializable {
     private String description;
 
     @Data
+    @JsonInclude(JsonInclude.Include.NON_NULL)
     public static class Extension implements Serializable{
         private String title;
         private String patientName;
@@ -33,7 +35,7 @@ public class PayloadDTO implements Serializable {
         private Long companyId;
         private Long companyUserId;
         private Long doctorId;
-
+        private Long userInformationId;
     }
 
 }

+ 79 - 0
fs-service/src/main/java/com/fs/his/enums/PrescriptionTaskStepEnum.java

@@ -0,0 +1,79 @@
+package com.fs.his.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.Getter;
+
+/**
+ * 用户信息采集任务流程步骤枚举
+ *
+ * 1 - 待用户第一次确认
+ * 2 - 待开方
+ * 3 - 待药师审核
+ * 4 - 待建议
+ * 5 - 待用户二次确认
+ */
+@Getter
+public enum PrescriptionTaskStepEnum {
+
+    WAITING_FIRST_CONFIRM(1, "待用户第一次确认"),
+    WAITING_PRESCRIBE(2, "待开方"),
+    WAITING_PHARMACIST_REVIEW(3, "待药师审核"),
+    WAITING_SUGGESTION(4, "待建议"),
+    WAITING_SECOND_CONFIRM(5, "待用户二次确认"),
+    WAITING_COMPLETED(6, "完成");
+
+    /** 步骤码(存入数据库的值) */
+    private final Integer code;
+
+    /** 步骤描述 */
+    private final String desc;
+
+    PrescriptionTaskStepEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    /**
+     * 根据 code 获取枚举(用于从数据库值转为枚举)
+     *
+     * @param code 步骤码
+     * @return 对应的枚举,若无匹配则返回 null
+     */
+    public static PrescriptionTaskStepEnum fromCode(Integer code) {
+        if (code == null) {
+            return null;
+        }
+        for (PrescriptionTaskStepEnum step : values()) {
+            if (step.code.equals(code)) {
+                return step;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Jackson 反序列化时使用(支持 JSON 中直接传数字如 1 -> WAITING_FIRST_CONFIRM)
+     */
+    @JsonCreator
+    public static PrescriptionTaskStepEnum fromJsonValue(Object value) {
+        if (value instanceof Number) {
+            return fromCode(((Number) value).intValue());
+        } else if (value instanceof String) {
+            try {
+                return fromCode(Integer.parseInt((String) value));
+            } catch (NumberFormatException ignored) {
+                // ignore
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Jackson 序列化时输出 code 而不是 name(如输出 1 而不是 "WAITING_FIRST_CONFIRM")
+     */
+    @JsonValue
+    public Integer getCode() {
+        return this.code;
+    }
+}

+ 75 - 0
fs-service/src/main/java/com/fs/his/mapper/DoctorMsgMapper.java

@@ -0,0 +1,75 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.DoctorMsg;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+/**
+ * 医生消息Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-04
+ */
+public interface DoctorMsgMapper extends BaseMapper<DoctorMsg>{
+    /**
+     * 查询医生消息
+     *
+     * @param id 医生消息主键
+     * @return 医生消息
+     */
+    DoctorMsg selectDoctorMsgById(Long id);
+
+    /**
+     * 查询医生消息列表
+     *
+     * @param doctorMsg 医生消息
+     * @return 医生消息集合
+     */
+    List<DoctorMsg> selectDoctorMsgList(DoctorMsg doctorMsg);
+
+    /**
+     * 新增医生消息
+     *
+     * @param doctorMsg 医生消息
+     * @return 结果
+     */
+    int insertDoctorMsg(DoctorMsg doctorMsg);
+
+    /**
+     * 修改医生消息
+     *
+     * @param doctorMsg 医生消息
+     * @return 结果
+     */
+    int updateDoctorMsg(DoctorMsg doctorMsg);
+
+    /**
+     * 删除医生消息
+     *
+     * @param id 医生消息主键
+     * @return 结果
+     */
+    int deleteDoctorMsgById(Long id);
+
+    /**
+     * 批量删除医生消息
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteDoctorMsgByIds(Long[] ids);
+
+    //获取医生未读消息总数
+    @Select("select IFNULL(count( 0),0) from doctor_msg where doctor_id = #{doctorId} and is_read = 0 ")
+    Long selectDoctorMsgCountsByDoctorId(Long doctorId);
+
+    @Select("select IFNULL(count( type),0) from doctor_msg where doctor_id = #{doctorId} and is_read = 0 and type = #{type}")
+    Long selectDoctorMsgCountsByDoctorIdAndType(@Param("doctorId") Long doctorId, @Param("type") int type);
+
+    @Update("update  doctor_msg set is_read=1 where doctor_id = #{doctorId} ")
+    int setAllRead(Long doctorId);
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/mapper/FsDoctorConfirmMapper.java

@@ -0,0 +1,62 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsDoctorConfirm;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author fs
+ * @date 2025-10-18
+ */
+public interface FsDoctorConfirmMapper extends BaseMapper<FsDoctorConfirm>{
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    FsDoctorConfirm selectFsDoctorConfirmById(Long id);
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    List<FsDoctorConfirm> selectFsDoctorConfirmList(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    int insertFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    int updateFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 删除【请填写功能名称】
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 结果
+     */
+    int deleteFsDoctorConfirmById(Long id);
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsDoctorConfirmByIds(Long[] ids);
+}

+ 67 - 0
fs-service/src/main/java/com/fs/his/mapper/FsQuestionAndAnswerMapper.java

@@ -0,0 +1,67 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsQuestionAndAnswer;
+import com.fs.his.vo.OptionsVO;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * 问答Mapper接口
+ *
+ * @author fs
+ * @date 2025-09-29
+ */
+public interface FsQuestionAndAnswerMapper extends BaseMapper<FsQuestionAndAnswer>{
+    /**
+     * 查询问答
+     *
+     * @param id 问答主键
+     * @return 问答
+     */
+    FsQuestionAndAnswer selectFsQuestionAndAnswerById(Long id);
+
+    /**
+     * 查询问答列表
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 问答集合
+     */
+    List<FsQuestionAndAnswer> selectFsQuestionAndAnswerList(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 新增问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    int insertFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 修改问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    int updateFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 删除问答
+     *
+     * @param id 问答主键
+     * @return 结果
+     */
+    int deleteFsQuestionAndAnswerById(Long id);
+
+    /**
+     * 批量删除问答
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsQuestionAndAnswerByIds(Long[] ids);
+
+    @Select("select id dictValue,question_name dictLabel from fs_question_and_answer  ")
+    List<OptionsVO> selectAllQuestionOptions();
+}

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

@@ -375,7 +375,7 @@ public interface FsStoreOrderMapper
             "LEFT JOIN company c on c.company_id =so.company_id " +
             "LEFT JOIN company_user cu on cu.user_id=so.company_user_id " +
             "LEFT JOIN fs_doctor fd on so.follow_doctor_id =fd.doctor_id " +
-            "LEFT JOIN fs_patient pat ON pat.patient_id=p.patient_id  WHERE so.is_del=0  and order_id= #{orderId}")
+            "LEFT JOIN fs_patient pat ON pat.patient_id=p.patient_id  WHERE so.is_del=0  and so.order_id= #{orderId}")
     FsStoreOrderVO selectFsStoreOrderByOrderIdVO(@Param("orderId") Long orderId);
 
     @Update("update fs_store_order set status=-3 where order_id=#{orderId}")

+ 101 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionMapper.java

@@ -0,0 +1,101 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserInformationCollection;
+import com.fs.his.dto.FsUserInformationCollectionDTO;
+import com.fs.his.param.FsUserInformationCollectionListDParam;
+import com.fs.his.param.UserInformationDoctorType2Param;
+import com.fs.his.vo.FsUserInformationCollectionListDVO;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * 用户信息采集Mapper接口
+ *
+ * @author fs
+ * @date 2025-10-14
+ */
+public interface FsUserInformationCollectionMapper extends BaseMapper<FsUserInformationCollection>{
+    /**
+     * 查询用户信息采集
+     *
+     * @param id 用户信息采集主键
+     * @return 用户信息采集
+     */
+    FsUserInformationCollection selectFsUserInformationCollectionById(Long id);
+
+    FsUserInformationCollection selectFsUserInformationCollectionByUserId(Long userId);
+
+    /**
+     * 查询用户信息采集列表
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 用户信息采集集合
+     */
+    List<FsUserInformationCollection> selectFsUserInformationCollectionList(FsUserInformationCollection fsUserInformationCollection);
+
+    /**
+     * 新增用户信息采集
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 结果
+     */
+    int insertFsUserInformationCollection(FsUserInformationCollection fsUserInformationCollection);
+
+    /**
+     * 修改用户信息采集
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 结果
+     */
+    int updateFsUserInformationCollection(FsUserInformationCollection fsUserInformationCollection);
+
+    @Select("UPDATE fs_user_information_collection SET package_order_code = NULL WHERE id = #{id}")
+    void collectionOderCodeNULL(@Param("id") Long id);
+    /**
+     * 删除用户信息采集
+     *
+     * @param id 用户信息采集主键
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionById(Long id);
+
+    /**
+     * 批量删除用户信息采集
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionByIds(Long[] ids);
+
+    FsUserInformationCollection selectByUserId(Long userId);
+    FsUserInformationCollection selectByOrderCode(String orderCode);
+
+    @Select({"<script> " +
+            " SELECT uic.*,u.nickname userName FROM fs_user_information_collection uic LEFT JOIN fs_user u ON uic.user_id = u.user_id " +
+            "WHERE doctor_id = #{maps.doctorId} and is_package = 0  and user_confirm = 1 " +
+            "<if test='maps.doctorConfirm != null' > and uic.doctor_confirm = #{maps.doctorConfirm}  </if>" +
+            "<if test='maps.userConfirm != null' > and uic.user_confirm = #{maps.userConfirm}  </if>" +
+            "<if test='maps.userName != null ' > and u.nickname like concat('%',#{maps.userName},'%')</if>" +
+            "ORDER BY create_time desc" +
+            "</script>"})
+    List<FsUserInformationCollectionListDVO> selectFsUserInformationCollectionListDVO(@Param("maps") FsUserInformationCollectionListDParam param);
+
+    /**
+     * 查询需要自动退款订单(用户支付超过24小时,未第二次确认的订单号)
+     */
+    @Select("SELECT id,package_order_code FROM fs_user_information_collection uic LEFT JOIN fs_package_order po ON uic.package_order_code = po.order_sn  WHERE uic.doctor_confirm_time <= DATE_SUB(NOW(), INTERVAL 24 HOUR) and  uic.package_order_code IS NOT NULL   AND  uic.user_confirm2 = 0 AND po.is_pay = 1")
+    List<FsUserInformationCollection> selectAutoRefundOrderCode();
+
+    /**
+     * 查询需要自动确认订单(医生确认超过2小时,未第二次确认的信息采集)
+     */
+    @Select("SELECT * FROM fs_user_information_collection WHERE is_package = 0 AND user_confirm = 1 AND doctor_confirm = 1 AND user_confirm2 = 0 AND doctor_confirm_time <= DATE_SUB(NOW(), INTERVAL 2 HOUR)")
+    List<FsUserInformationCollection> selectAutoConfirm();
+
+    FsUserInformationCollectionDTO selectFsUserInformationCollectionDTOById(Long id);
+
+    List<FsUserInformationCollection>selectFsUserInformationCollectionByDoctorType2(@Param("maps") UserInformationDoctorType2Param userInformationDoctorType2Param);
+}

+ 69 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionScheduleMapper.java

@@ -0,0 +1,69 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsUserInformationCollectionSchedule;
+
+import java.util.List;
+
+/**
+ * 用户信息采集进度Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-18
+ */
+public interface FsUserInformationCollectionScheduleMapper extends BaseMapper<FsUserInformationCollectionSchedule>{
+    /**
+     * 查询用户信息采集进度
+     *
+     * @param id 用户信息采集进度主键
+     * @return 用户信息采集进度
+     */
+    FsUserInformationCollectionSchedule selectFsUserInformationCollectionScheduleById(Long id);
+
+    /**
+     * 查询用户信息采集进度列表
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度集合
+     */
+    List<FsUserInformationCollectionSchedule> selectFsUserInformationCollectionScheduleList(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 对于每条用户信息采集记录,只获取其最新的任务流程
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度集合
+     */
+    List<FsUserInformationCollectionSchedule> getUserRecordLatestTaskProcess(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+    /**
+     * 新增用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    int insertFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 修改用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    int updateFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 删除用户信息采集进度
+     *
+     * @param id 用户信息采集进度主键
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionScheduleById(Long id);
+
+    /**
+     * 批量删除用户信息采集进度
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionScheduleByIds(Long[] ids);
+}

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

@@ -33,6 +33,8 @@ import org.apache.ibatis.annotations.*;
  */
 public interface FsUserMapper
 {
+    @Select("select * from fs_user where phone=#{phone}")
+    List<FsUser> selectFsUsersByPhoneLimitOne(String phone);
     /**
      * 查询用户
      *
@@ -465,4 +467,6 @@ public interface FsUserMapper
      */
     @Update("update fs_user set order_count = order_count + 1, total_amount = IFNULL(total_amount, 0) + #{amount} where user_id = #{userId}")
     void updateUserOrderCountAndAmount(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
+
+    List<FsUser> selectFsUserListByPhone(String phone);
 }

+ 18 - 0
fs-service/src/main/java/com/fs/his/param/CollectionInfoConfirmParam.java

@@ -0,0 +1,18 @@
+package com.fs.his.param;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class CollectionInfoConfirmParam {
+    @NotNull(message = "信息id不能位空")
+    private Long id;
+
+    private Long userId;
+
+    //用户建议
+    private String userAdvice;
+
+    private Long patientId;
+}

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

@@ -48,5 +48,6 @@ public class FsInquiryOrderCreateParam implements Serializable {
     private Long companyId;
     private Long companyUserId;
     private Integer source;//订单来源 1:小程序 2:app  3:H5
+    private Integer isUserInformation = 1;
 
 }

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

@@ -22,5 +22,6 @@ public class FsInquiryOrderListPDParam  extends BaseParam implements Serializabl
     Long userId;
     private String eTime;
     private String sTime;
+    private Integer isUserInformation = 0;
 
 }

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

@@ -21,6 +21,8 @@ public class FsPackageOrderCreateParam implements Serializable {
     private Integer source;//订单来源 1:小程序 2:app  3:H5
     private String createPackageOrderKey;
     private Integer payType;
+    private Integer isUserInformation = 0;
+    private Long userInformationId;
 
 
 

+ 16 - 0
fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionListDParam.java

@@ -0,0 +1,16 @@
+package com.fs.his.param;
+
+import com.fs.hisStore.param.BaseParam;
+import lombok.Data;
+
+@Data
+public class FsUserInformationCollectionListDParam extends BaseParam {
+    private String userName;
+
+    private Long doctorId;
+
+    //医生确认状态 0未确认 1已确认
+    private Integer doctorConfirm;
+
+    private Integer userConfirm;
+}

+ 52 - 0
fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionParam.java

@@ -0,0 +1,52 @@
+package com.fs.his.param;
+
+import com.fs.his.vo.AnswerVO;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class FsUserInformationCollectionParam {
+
+    private Long id;
+
+    private Long questionId;
+
+    private List<AnswerVO> answers;
+
+    private Long userId;
+
+    //销售id
+    private Long companyUserId;
+
+    //是否关联套餐包 0-不关联 1-关联
+    private Integer isPackage;
+
+    //套餐包id
+    private Long packageId;
+
+    //支付类型 0-全款 1-物流代收
+    private Integer payType;
+
+    //代收金额
+    private BigDecimal amount;
+
+    //用户性别 0女 1男
+    private Integer sex;
+    //用户姓名
+    private String userName;
+    //用户电话后四位
+    private String userPhoneFour;
+
+    //是否过敏
+    private String allergy;
+    //备注
+    private String remark;
+
+    private Long patientId;
+
+    private String doctorSign;
+
+    private String packageOrderCode;
+}

+ 13 - 0
fs-service/src/main/java/com/fs/his/param/UserInformationDoctorType2Param.java

@@ -0,0 +1,13 @@
+package com.fs.his.param;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class UserInformationDoctorType2Param extends BaseParam implements Serializable {
+    private Integer doctorType2Confirm;
+    private String patientName;
+    private String packageOrderCode;
+    private Long doctorType2Id;
+}

+ 63 - 0
fs-service/src/main/java/com/fs/his/service/IFsDoctorConfirmService.java

@@ -0,0 +1,63 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsDoctorConfirm;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author fs
+ * @date 2025-10-18
+ */
+public interface IFsDoctorConfirmService extends IService<FsDoctorConfirm>{
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    FsDoctorConfirm selectFsDoctorConfirmById(Long id);
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    List<FsDoctorConfirm> selectFsDoctorConfirmList(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    int insertFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    int updateFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm);
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param ids 需要删除的【请填写功能名称】主键集合
+     * @return 结果
+     */
+    int deleteFsDoctorConfirmByIds(Long[] ids);
+
+    /**
+     * 删除【请填写功能名称】信息
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 结果
+     */
+    int deleteFsDoctorConfirmById(Long id);
+}

+ 66 - 0
fs-service/src/main/java/com/fs/his/service/IFsQuestionAndAnswerService.java

@@ -0,0 +1,66 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsQuestionAndAnswer;
+import com.fs.his.vo.FsQuestionAndAnswerVO;
+import com.fs.his.vo.OptionsVO;
+
+import java.util.List;
+
+/**
+ * 问答Service接口
+ *
+ * @author fs
+ * @date 2025-09-29
+ */
+public interface IFsQuestionAndAnswerService extends IService<FsQuestionAndAnswer>{
+    /**
+     * 查询问答
+     *
+     * @param id 问答主键
+     * @return 问答
+     */
+    FsQuestionAndAnswerVO selectFsQuestionAndAnswerById(Long id);
+
+    /**
+     * 查询问答列表
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 问答集合
+     */
+    List<FsQuestionAndAnswer> selectFsQuestionAndAnswerList(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 新增问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    int insertFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 修改问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    int updateFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer);
+
+    /**
+     * 批量删除问答
+     *
+     * @param ids 需要删除的问答主键集合
+     * @return 结果
+     */
+    int deleteFsQuestionAndAnswerByIds(Long[] ids);
+
+    /**
+     * 删除问答信息
+     *
+     * @param id 问答主键
+     * @return 结果
+     */
+    int deleteFsQuestionAndAnswerById(Long id);
+
+    List<OptionsVO> selectAllQuestionOptions();
+}

+ 70 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionScheduleService.java

@@ -0,0 +1,70 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsUserInformationCollectionSchedule;
+
+import java.util.List;
+
+/**
+ * 用户信息采集进度Service接口
+ *
+ * @author fs
+ * @date 2025-11-18
+ */
+public interface IFsUserInformationCollectionScheduleService extends IService<FsUserInformationCollectionSchedule>{
+    /**
+     * 查询用户信息采集进度
+     *
+     * @param id 用户信息采集进度主键
+     * @return 用户信息采集进度
+     */
+    FsUserInformationCollectionSchedule selectFsUserInformationCollectionScheduleById(Long id);
+
+    /**
+     * 查询用户信息采集进度列表
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度集合
+     */
+    List<FsUserInformationCollectionSchedule> getUserRecordLatestTaskProcess(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 查询用户信息采集进度列表
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度集合
+     */
+    List<FsUserInformationCollectionSchedule> selectFsUserInformationCollectionScheduleList(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 新增用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    int insertFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 修改用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    int updateFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule);
+
+    /**
+     * 批量删除用户信息采集进度
+     *
+     * @param ids 需要删除的用户信息采集进度主键集合
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionScheduleByIds(Long[] ids);
+
+    /**
+     * 删除用户信息采集进度信息
+     *
+     * @param id 用户信息采集进度主键
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionScheduleById(Long id);
+}

+ 114 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionService.java

@@ -0,0 +1,114 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsUserInformationCollection;
+import com.fs.his.dto.FsUserInformationCollectionDTO;
+import com.fs.his.param.CollectionInfoConfirmParam;
+import com.fs.his.param.FsUserInformationCollectionListDParam;
+import com.fs.his.param.FsUserInformationCollectionParam;
+import com.fs.his.param.UserInformationDoctorType2Param;
+import com.fs.his.vo.FsUserInfoCollectionUVO;
+import com.fs.his.vo.FsUserInformationCollectionAndPatientVO;
+import com.fs.his.vo.FsUserInformationCollectionListDVO;
+import com.fs.his.vo.FsUserInformationCollectionVO;
+
+import java.util.List;
+
+/**
+ * 用户信息采集Service接口
+ *
+ * @author fs
+ * @date 2025-10-14
+ */
+public interface IFsUserInformationCollectionService extends IService<FsUserInformationCollection>{
+    /**
+     * 查询用户信息采集
+     *
+     * @param id 用户信息采集主键
+     * @return 用户信息采集
+     */
+    FsUserInformationCollection selectFsUserInformationCollectionById(Long id);
+
+
+
+    /**
+     * 查询用户信息采集列表
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 用户信息采集集合
+     */
+    List<FsUserInformationCollection> selectFsUserInformationCollectionList(FsUserInformationCollection fsUserInformationCollection);
+
+    List<FsUserInformationCollection> selectFsUserInformationCollectionByDoctorType2(UserInformationDoctorType2Param userInformationDoctorType2Param);
+
+    /**
+     * 新增用户信息采集
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 结果
+     */
+    Long insertFsUserInformationCollection(FsUserInformationCollectionParam fsUserInformationCollection);
+
+    /**
+     * 修改用户信息采集
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 结果
+     */
+    Long update(FsUserInformationCollectionParam fsUserInformationCollection);
+
+    /**
+     * 修改用户信息采集
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 结果
+     */
+    Long updateFsUserInformationCollection(FsUserInformationCollectionParam fsUserInformationCollection);
+
+    /**
+     * 批量删除用户信息采集
+     *
+     * @param ids 需要删除的用户信息采集主键集合
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionByIds(Long[] ids);
+
+    /**
+     * 删除用户信息采集信息
+     *
+     * @param id 用户信息采集主键
+     * @return 结果
+     */
+    int deleteFsUserInformationCollectionById(Long id);
+
+
+    FsUserInformationCollectionVO getInfo(FsUserInformationCollection fsUserInformationCollection);
+
+    /**
+     * 查询医生端用户信息采集列表(只查询未关联套餐包的信息采集)
+     * @param param
+     * @return
+     */
+    List<FsUserInformationCollectionListDVO> selectFsUserInformationCollectionListDVO(FsUserInformationCollectionListDParam param);
+
+    FsUserInformationCollectionVO detail(Long id);
+
+    R getWxaCodePackageOrderUnLimit(Long collectionId);
+
+    R doctorConfirm(FsUserInformationCollection collection);
+    R doctorType2Confirm(FsUserInformationCollection collection);
+
+    FsUserInfoCollectionUVO info(Long id, Long userId);
+
+    R userConfirm(CollectionInfoConfirmParam param);
+
+    //自动退款
+    void autoRefund(FsUserInformationCollection collection);
+
+    FsUserInformationCollectionVO getCollectionByUserId(Long userId);
+
+    FsUserInformationCollectionDTO selectFsUserInformationCollectionDTOById(Long id);
+
+    int updatePackageOrderCode(FsUserInformationCollection fsUserInformationCollection);
+}

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

@@ -228,4 +228,6 @@ public interface IFsUserService
     void increaseIntegral(List<Long> longs, Long integral);
 
     HisFsUserVO getHisUserIntegralWithLogs(FsUser fsUser);
+
+    List<FsUser> selectFsUserListByPhone(String phone);
 }

+ 95 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsDoctorConfirmServiceImpl.java

@@ -0,0 +1,95 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsDoctorConfirm;
+import com.fs.his.mapper.FsDoctorConfirmMapper;
+import com.fs.his.service.IFsDoctorConfirmService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author fs
+ * @date 2025-10-18
+ */
+@Service
+public class FsDoctorConfirmServiceImpl extends ServiceImpl<FsDoctorConfirmMapper, FsDoctorConfirm> implements IFsDoctorConfirmService {
+
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public FsDoctorConfirm selectFsDoctorConfirmById(Long id)
+    {
+        return baseMapper.selectFsDoctorConfirmById(id);
+    }
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public List<FsDoctorConfirm> selectFsDoctorConfirmList(FsDoctorConfirm fsDoctorConfirm)
+    {
+        return baseMapper.selectFsDoctorConfirmList(fsDoctorConfirm);
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int insertFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm)
+    {
+        fsDoctorConfirm.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsDoctorConfirm(fsDoctorConfirm);
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsDoctorConfirm 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int updateFsDoctorConfirm(FsDoctorConfirm fsDoctorConfirm)
+    {
+        fsDoctorConfirm.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsDoctorConfirm(fsDoctorConfirm);
+    }
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param ids 需要删除的【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsDoctorConfirmByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsDoctorConfirmByIds(ids);
+    }
+
+    /**
+     * 删除【请填写功能名称】信息
+     *
+     * @param id 【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsDoctorConfirmById(Long id)
+    {
+        return baseMapper.deleteFsDoctorConfirmById(id);
+    }
+}

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java

@@ -1084,6 +1084,8 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         return R.ok("抢单成功");
     }
 
+
+
     @Override
     @Transactional
     public R receiveOrder(FsInquiryOrderReceiveParam param) throws JsonProcessingException {
@@ -1125,6 +1127,10 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
 
             }
         }
+        //是用户信息采集的订单发送用户信息给医生
+//        if (order.getIsUserInformation()==1){
+//            sendUserInformation(order.getUserId(),order.getDoctorId());
+//        }
         MsgDTO msgDTO=new MsgDTO();
         MsgCustomDTO customDTO=new MsgCustomDTO();
         customDTO.setType("startInquiry");

+ 11 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -168,6 +168,9 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
     @Autowired
     private CloudHostProper cloudHostProper;
 
+    @Autowired
+    private IFsUserInformationCollectionService fsUserInformationCollectionService;
+
     /**
      * 查询套餐订单
      *
@@ -606,7 +609,9 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         c.setTime(order.getStartTime());
         c.add(Calendar.DAY_OF_MONTH, fsPackage.getCycle());
         order.setFinishTime(c.getTime());
-        order.setFormJson(param.getFormJson());
+        if (param.getIsUserInformation() != 1){
+            order.setFormJson(param.getFormJson());
+        }
         order.setPackageJson(JSONUtil.toJsonStr(fsPackage));
         order.setCreateTime(new Date());
         if(patient!=null){
@@ -618,6 +623,11 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         order.setCycle(fsPackage.getCycle());
         order.setCostDiscountMoney(fsPackage.getTotalCostPrice().subtract(fsPackage.getTotalPrice()));
         if(fsPackageOrderMapper.insertFsPackageOrder(order)>0){
+            FsUserInformationCollection fsUserInformationCollection = fsUserInformationCollectionService.selectFsUserInformationCollectionById(param.getUserInformationId());
+            if (fsUserInformationCollection != null) {
+                fsUserInformationCollection.setPackageOrderCode(order.getOrderSn());
+                fsUserInformationCollectionService.updatePackageOrderCode(fsUserInformationCollection);
+            }
             String redisKey = String.valueOf(StrUtil.format("{}{}", FsConstants.REDIS_PACKAGE_ORDER_UNPAY, order.getOrderId()));
             redisCache.setCacheObject(redisKey,order.getOrderId(),30, TimeUnit.MINUTES);
             return R.ok().put("order",order);

+ 113 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsQuestionAndAnswerServiceImpl.java

@@ -0,0 +1,113 @@
+package com.fs.his.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsQuestionAndAnswer;
+import com.fs.his.mapper.FsQuestionAndAnswerMapper;
+import com.fs.his.service.IFsQuestionAndAnswerService;
+import com.fs.his.vo.AnswerVO;
+import com.fs.his.vo.FsQuestionAndAnswerVO;
+import com.fs.his.vo.OptionsVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 问答Service业务层处理
+ *
+ * @author fs
+ * @date 2025-09-29
+ */
+@Service
+public class FsQuestionAndAnswerServiceImpl extends ServiceImpl<FsQuestionAndAnswerMapper, FsQuestionAndAnswer> implements IFsQuestionAndAnswerService {
+
+
+    @Autowired
+    private FsQuestionAndAnswerMapper fsQuestionAndAnswerMapper;
+    /**
+     * 查询问答
+     *
+     * @param id 问答主键
+     * @return 问答
+     */
+    @Override
+    public FsQuestionAndAnswerVO selectFsQuestionAndAnswerById(Long id)
+    {
+        FsQuestionAndAnswer fsQuestionAndAnswer = baseMapper.selectFsQuestionAndAnswerById(id);
+        FsQuestionAndAnswerVO vo = new FsQuestionAndAnswerVO();
+        vo.setQuestionName(fsQuestionAndAnswer.getQuestionName());
+        List<AnswerVO> answerVOS = JSON.parseArray(fsQuestionAndAnswer.getJsonInfo(), AnswerVO.class);
+        vo.setAnswers(answerVOS);
+        vo.setId(fsQuestionAndAnswer.getId());
+        return vo;
+    }
+
+    /**
+     * 查询问答列表
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 问答
+     */
+    @Override
+    public List<FsQuestionAndAnswer> selectFsQuestionAndAnswerList(FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        return baseMapper.selectFsQuestionAndAnswerList(fsQuestionAndAnswer);
+    }
+
+    /**
+     * 新增问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    @Override
+    public int insertFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        fsQuestionAndAnswer.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsQuestionAndAnswer(fsQuestionAndAnswer);
+    }
+
+    /**
+     * 修改问答
+     *
+     * @param fsQuestionAndAnswer 问答
+     * @return 结果
+     */
+    @Override
+    public int updateFsQuestionAndAnswer(FsQuestionAndAnswer fsQuestionAndAnswer)
+    {
+        fsQuestionAndAnswer.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsQuestionAndAnswer(fsQuestionAndAnswer);
+    }
+
+    /**
+     * 批量删除问答
+     *
+     * @param ids 需要删除的问答主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsQuestionAndAnswerByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsQuestionAndAnswerByIds(ids);
+    }
+
+    /**
+     * 删除问答信息
+     *
+     * @param id 问答主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsQuestionAndAnswerById(Long id)
+    {
+        return baseMapper.deleteFsQuestionAndAnswerById(id);
+    }
+
+    @Override
+    public List<OptionsVO> selectAllQuestionOptions() {
+        return fsQuestionAndAnswerMapper.selectAllQuestionOptions();
+    }
+}

+ 105 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionScheduleServiceImpl.java

@@ -0,0 +1,105 @@
+package com.fs.his.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsUserInformationCollectionSchedule;
+import com.fs.his.mapper.FsUserInformationCollectionScheduleMapper;
+import com.fs.his.service.IFsUserInformationCollectionScheduleService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 用户信息采集进度Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-18
+ */
+@Service
+public class FsUserInformationCollectionScheduleServiceImpl extends ServiceImpl<FsUserInformationCollectionScheduleMapper, FsUserInformationCollectionSchedule> implements IFsUserInformationCollectionScheduleService {
+
+    /**
+     * 查询用户信息采集进度
+     *
+     * @param id 用户信息采集进度主键
+     * @return 用户信息采集进度
+     */
+    @Override
+    public FsUserInformationCollectionSchedule selectFsUserInformationCollectionScheduleById(Long id)
+    {
+        return baseMapper.selectFsUserInformationCollectionScheduleById(id);
+    }
+
+    /**
+     * 对于每条用户信息采集记录,只获取其最新的任务流程
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度
+     */
+    @Override
+    public List<FsUserInformationCollectionSchedule> getUserRecordLatestTaskProcess(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        return baseMapper.getUserRecordLatestTaskProcess(fsUserInformationCollectionSchedule);
+    }
+
+    /**
+     * 查询用户信息采集进度列表
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 用户信息采集进度
+     */
+    @Override
+    public List<FsUserInformationCollectionSchedule> selectFsUserInformationCollectionScheduleList(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        return baseMapper.getUserRecordLatestTaskProcess(fsUserInformationCollectionSchedule);
+    }
+
+    /**
+     * 新增用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    @Override
+    public int insertFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        fsUserInformationCollectionSchedule.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsUserInformationCollectionSchedule(fsUserInformationCollectionSchedule);
+    }
+
+    /**
+     * 修改用户信息采集进度
+     *
+     * @param fsUserInformationCollectionSchedule 用户信息采集进度
+     * @return 结果
+     */
+    @Override
+    public int updateFsUserInformationCollectionSchedule(FsUserInformationCollectionSchedule fsUserInformationCollectionSchedule)
+    {
+        return baseMapper.updateFsUserInformationCollectionSchedule(fsUserInformationCollectionSchedule);
+    }
+
+    /**
+     * 批量删除用户信息采集进度
+     *
+     * @param ids 需要删除的用户信息采集进度主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserInformationCollectionScheduleByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsUserInformationCollectionScheduleByIds(ids);
+    }
+
+    /**
+     * 删除用户信息采集进度信息
+     *
+     * @param id 用户信息采集进度主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserInformationCollectionScheduleById(Long id)
+    {
+        return baseMapper.deleteFsUserInformationCollectionScheduleById(id);
+    }
+}

+ 1011 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java

@@ -0,0 +1,1011 @@
+package com.fs.his.service.impl;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+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 com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.company.service.ICompanyService;
+import com.fs.core.config.WxMaConfiguration;
+import com.fs.core.config.WxPayProperties;
+import com.fs.core.utils.OrderCodeUtils;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.*;
+import com.fs.his.dto.FsUserInformationCollectionDTO;
+import com.fs.his.enums.FsStoreOrderStatusEnum;
+import com.fs.his.mapper.*;
+import com.fs.his.param.*;
+import com.fs.his.service.*;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.his.vo.*;
+import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentDelaytransConfirmrefundRequest;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
+import com.fs.huifuPay.service.HuiFuService;
+import com.fs.im.service.OpenIMService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.fs.system.oss.CloudStorageService;
+import com.fs.system.oss.OSSFactory;
+import com.fs.system.service.ISysConfigService;
+import com.fs.tzBankPay.TzBankService.TzBankService;
+import com.fs.tzBankPay.doman.RefundParam;
+import com.fs.tzBankPay.doman.RefundResult;
+import com.fs.tzBankPay.doman.TzBankResult;
+import com.fs.ybPay.dto.RefundDTO;
+import com.fs.ybPay.service.IPayService;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import me.chanjar.weixin.common.error.WxErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 用户信息采集Service业务层处理
+ *
+ * @author fs
+ * @date 2025-10-14
+ */
+@Service
+public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserInformationCollectionMapper, FsUserInformationCollection> implements IFsUserInformationCollectionService {
+    Logger logger= LoggerFactory.getLogger(getClass());
+
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    SysConfigMapper sysConfigMapper;
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
+
+    @Autowired
+    private WxPayService wxPayService;
+
+    @Autowired
+    IPayService payService;
+
+    @Autowired
+    private TzBankService tzBankService;
+
+    @Autowired
+    private HuiFuService huiFuService;
+
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
+
+    @Autowired
+    private FsDoctorMapper doctorMapper;
+
+    @Autowired
+    private IFsDoctorService iFsDoctorService;
+
+    @Autowired
+    private IFsQuestionAndAnswerService questionAndAnswerService;
+
+    @Autowired
+    private FsUserInformationCollectionMapper fsUserInformationCollectionMapper;
+
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private IFsDoctorConfirmService doctorConfirmService;
+
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    private FsPackageMapper packageMapper;
+
+    @Autowired
+    private IFsStoreOrderService storeOrderService;
+
+    @Autowired
+    private FsPackageOrderMapper packageOrderMapper;
+
+    @Autowired
+    private FsPrescribeMapper fsPrescribeMapper;
+
+    @Autowired
+    private IFsPrescribeService prescribeService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private FsStorePaymentMapper fsStorePaymentMapper;
+
+    @Autowired
+    private FsStoreOrderLogsMapper fsStoreOrderLogsMapper;
+    @Autowired
+    private DoctorMsgMapper doctorMsgMapper;
+    @Autowired
+    private IFsInquiryOrderService fsInquiryOrderService;
+    @Autowired
+    private OpenIMService openIMService;
+    /**
+     * 查询用户信息采集
+     *
+     * @param id 用户信息采集主键
+     * @return 用户信息采集
+     */
+    @Override
+    public FsUserInformationCollection selectFsUserInformationCollectionById(Long id)
+    {
+        return baseMapper.selectFsUserInformationCollectionById(id);
+    }
+
+    /**
+     * 查询用户信息采集列表
+     *
+     * @param fsUserInformationCollection 用户信息采集
+     * @return 用户信息采集
+     */
+    @Override
+    public List<FsUserInformationCollection> selectFsUserInformationCollectionList(FsUserInformationCollection fsUserInformationCollection)
+    {
+        return baseMapper.selectFsUserInformationCollectionList(fsUserInformationCollection);
+    }
+
+    @Override
+    public List<FsUserInformationCollection> selectFsUserInformationCollectionByDoctorType2(UserInformationDoctorType2Param userInformationDoctorType2Param) {
+        return fsUserInformationCollectionMapper.selectFsUserInformationCollectionByDoctorType2(userInformationDoctorType2Param);
+
+    }
+
+    /**
+     * 新增用户信息采集
+     *
+     * @param param 用户信息采集
+     * @return 结果
+     */
+    @Override
+    public Long insertFsUserInformationCollection(FsUserInformationCollectionParam param)
+    {
+
+        FsUserInformationCollection fsUserInformationCollection = getFsUserInformationCollection(param);
+        fsUserInformationCollection.setCreateTime(DateUtils.getNowDate());
+        baseMapper.insertFsUserInformationCollection(fsUserInformationCollection);
+        return fsUserInformationCollection.getId();
+    }
+
+    /**
+     * 修改用户信息采集
+     *
+     * @param param 用户信息采集
+     * @return 结果
+     */
+    @Override
+    public Long update(FsUserInformationCollectionParam param)
+    {
+        if (param.getId() == null || param.getId() < 1) {
+            throw new CustomException("参数错误");
+        }
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(param.getId());
+        if (collection == null) {
+            throw new CustomException("没有用户采集信息");
+        }
+        if (collection.getUserConfirm() == 1 && collection.getUserConfirm2() == 0) {
+            throw new CustomException("确认中,暂无法修改");
+        }
+        FsUserInformationCollection fsUserInformationCollection = getFsUserInformationCollection(param);
+        fsUserInformationCollection.setUpdateTime(DateUtils.getNowDate());
+        baseMapper.updateFsUserInformationCollection(fsUserInformationCollection);
+        return fsUserInformationCollection.getId();
+    }
+
+    /**
+     * 修改用户信息采集
+     *
+     * @param param 用户信息采集
+     * @return 结果
+     */
+    @Override
+    public Long updateFsUserInformationCollection(FsUserInformationCollectionParam param)
+    {
+        if (param.getId() == null || param.getId() < 1) {
+            throw new CustomException("参数错误");
+        }
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(param.getId());
+        if (collection == null) {
+            throw new CustomException("没有用户采集信息");
+        }
+        if (collection.getUserConfirm() == 1 && collection.getUserConfirm2() == 0) {
+            throw new CustomException("确认中,暂无法修改");
+        }
+        //清空订单号
+        fsUserInformationCollectionMapper.collectionOderCodeNULL(param.getId());
+        FsUserInformationCollection fsUserInformationCollection = getFsUserInformationCollection(param);
+        fsUserInformationCollection.setUserConfirm2(0);
+        fsUserInformationCollection.setUserConfirm(0);
+        fsUserInformationCollection.setDoctorConfirm(0);
+        fsUserInformationCollection.setStatus(1);
+        fsUserInformationCollection.setUpdateTime(DateUtils.getNowDate());
+        baseMapper.updateFsUserInformationCollection(fsUserInformationCollection);
+        return fsUserInformationCollection.getId();
+    }
+
+    /**
+     * 批量删除用户信息采集
+     *
+     * @param ids 需要删除的用户信息采集主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserInformationCollectionByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsUserInformationCollectionByIds(ids);
+    }
+
+    /**
+     * 删除用户信息采集信息
+     *
+     * @param id 用户信息采集主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsUserInformationCollectionById(Long id)
+    {
+        return baseMapper.deleteFsUserInformationCollectionById(id);
+    }
+
+    @Override
+    public FsUserInformationCollectionVO getInfo(FsUserInformationCollection map) {
+        FsUserInformationCollectionVO vo = new FsUserInformationCollectionVO();
+        Long userId = map.getUserId();
+        Long questionId = map.getQuestionId();
+//        FsUserInformationCollection fsUserInformationCollection = baseMapper.selectByUserId(userId);
+        FsUserInformationCollection fsUserInformationCollection = null;
+        if (map.getId() != null){
+            fsUserInformationCollection = baseMapper.selectFsUserInformationCollectionById(map.getId());
+        }
+        if (fsUserInformationCollection != null) {
+            //组装返回数据
+            vo.setQuestionId(fsUserInformationCollection.getQuestionId());
+            vo.setId(fsUserInformationCollection.getId());
+            vo.setAmount(fsUserInformationCollection.getAmount());
+            vo.setPackageId(fsUserInformationCollection.getPackageId());
+            vo.setPayType(fsUserInformationCollection.getPayType());
+            vo.setIsPackage(fsUserInformationCollection.getIsPackage());
+            vo.setSex(fsUserInformationCollection.getSex());
+            vo.setUserPhoneFour(fsUserInformationCollection.getUserPhoneFour());
+            vo.setUserName(fsUserInformationCollection.getUserName());
+            vo.setRemark(fsUserInformationCollection.getRemark());
+            vo.setAllergy(fsUserInformationCollection.getAllergy());
+            if (map.getQuestionId() == null) {
+                FsQuestionAndAnswerVO questionAndAnswerVO = questionAndAnswerService.selectFsQuestionAndAnswerById(fsUserInformationCollection.getQuestionId());
+                List<AnswerVO> answerVOS = JSON.parseArray(fsUserInformationCollection.getJsonInfo(), AnswerVO.class);
+                List<AnswerVO> collect = getAnswerVOs(answerVOS, questionAndAnswerVO.getAnswers());
+                vo.setAnswers(collect);
+            } else {
+                vo.setAnswers(JSON.parseArray(fsUserInformationCollection.getJsonInfo(), AnswerVO.class));
+            }
+        }
+        if (questionId != null) {
+            vo.setQuestionId(questionId);
+            //问答数据
+            FsQuestionAndAnswerVO questionAndAnswerVO = questionAndAnswerService.selectFsQuestionAndAnswerById(questionId);
+            if (questionAndAnswerVO != null) {
+                questionAndAnswerVO.getAnswers().forEach(answerVO -> {
+                    answerVO.setFlag(false);
+                });
+                if (fsUserInformationCollection != null) {
+                    vo.getAnswers().addAll(questionAndAnswerVO.getAnswers());
+                    vo.setAnswers(getAnswerVOs(vo.getAnswers(),questionAndAnswerVO.getAnswers()));
+                } else {
+                    //返回问答
+                    vo.setAnswers(questionAndAnswerVO.getAnswers());
+                }
+            }
+        }
+        if (ObjectUtil.isNotEmpty(vo.getAnswers())){
+            vo.getAnswers().forEach(answerVO -> {
+                if (answerVO.getSort() == null) {
+                    if (answerVO.getTitle().contains("糖尿病")) {
+                        answerVO.setSort(1);
+                    } else if (answerVO.getTitle().contains("心脑血管")) {
+                        answerVO.setSort(2);
+                    } else if (answerVO.getTitle().contains("风湿骨病")) {
+                        answerVO.setSort(3);
+                    } else if (answerVO.getTitle().contains("肝胆")) {
+                        answerVO.setSort(4);
+                    } else if (answerVO.getTitle().contains("其他")) {
+                        answerVO.setSort(5);
+                    } else if (answerVO.getTitle().contains("特殊")) {
+                        answerVO.setSort(6);
+                    }
+                }
+                if(answerVO.getFlag() == null) {
+                    answerVO.setFlag(false);
+                }
+                if (answerVO.getValue() == null) {
+                    answerVO.setValue(new ArrayList<>());
+                }
+            });
+            //有值且为true排前面
+//            List<AnswerVO> collect = vo.getAnswers().stream()
+//                    .sorted(Comparator.comparing(AnswerVO::getValue, Comparator.nullsFirst(Integer::compareTo)).reversed()).collect(Collectors.toList())
+//                    .stream()
+//                    .sorted((a,b)-> Boolean.compare(b.getFlag(),a.getFlag())).collect(Collectors.toList());
+            //List<AnswerVO> collect = vo.getAnswers().stream()
+            //        .sorted(Comparator.comparing(AnswerVO::getValue, Comparator.nullsFirst(List::indexOf)).reversed()).collect(Collectors.toList())
+            //        .stream()
+            //        .sorted((a,b)-> Boolean.compare(b.getFlag(),a.getFlag())).collect(Collectors.toList());
+            List<AnswerVO> collect = vo.getAnswers().stream()
+                    .sorted(Comparator.comparing(AnswerVO::getSort)).collect(Collectors.toList());
+
+            vo.setAnswers(collect);
+        }
+        return vo;
+    }
+
+    @Override
+    public List<FsUserInformationCollectionListDVO> selectFsUserInformationCollectionListDVO(FsUserInformationCollectionListDParam param) {
+        return fsUserInformationCollectionMapper.selectFsUserInformationCollectionListDVO(param);
+    }
+
+    @Override
+    public FsUserInformationCollectionVO detail(Long id) {
+        FsUserInformationCollectionVO vo = new FsUserInformationCollectionVO();
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(id);
+        if (collection != null) {
+            vo.setAllergy(collection.getAllergy());
+            vo.setRemark(collection.getRemark());
+            vo.setAnswers(JSON.parseArray(collection.getJsonInfo(), AnswerVO.class));
+            List<AnswerVO> answers = vo.getAnswers();
+            if (!CollectionUtils.isEmpty(answers)){
+                List<AnswerVO> collect = answers
+                        .stream()
+                        .filter(answerVO -> !answerVO.getValue().isEmpty())
+                        .collect(Collectors.toList());
+                if (!CollectionUtils.isEmpty(collect)) {
+                    collect.forEach(answerVO -> {
+                        List<Integer> value = answerVO.getValue();
+                        List<AnswerVO.Options> options = answerVO.getOptions();
+                        List<AnswerVO.Options> filterOptions = Lists.newArrayList();
+                        for (AnswerVO.Options option : options) {
+                            if (value.contains(option.getValue())) {
+                                filterOptions.add(option);
+                            }
+                        }
+                        answerVO.setOptions(filterOptions);
+                    });
+                }
+                vo.setAnswers(collect);
+            }
+        }
+        return vo;
+    }
+
+    @Override
+    public R getWxaCodePackageOrderUnLimit(Long collectionId) {
+        logger.info("生成用户信息采集二维码");
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+
+        final WxMaService wxMaService = WxMaConfiguration.getMaService(sysConfig.getAppid());
+
+        String scene="collectionId="+ collectionId ;
+        byte[] file;
+        try {
+            file = wxMaService.getQrcodeService().createWxaCodeUnlimitBytes(
+                    scene,
+                    "pages_order/confirmUserinfo",
+                    true,
+                    "release",//release trial
+                    430,
+                    true,
+                    null,
+                    false);
+
+            // 上传图片到存储桶
+            String suffix = ".png";
+            CloudStorageService storage = OSSFactory.build();
+            String url;
+            try {
+                url = storage.uploadSuffix(file, suffix);
+            }  catch (Exception e) {
+                // 记录错误日志
+                logger.error("生成图片失败:{}",e.getMessage(),e);
+                return R.error("生成图片失败");
+            }
+            // 返回成功信息
+            return R.ok().put("url",url);
+
+        } catch (WxErrorException e) {
+            logger.error(e.getMessage(), e);
+            return R.error("微信接口调用失败: " + e.getMessage());
+        }
+    }
+
+    @Override
+    @Transactional
+    public R doctorConfirm(FsUserInformationCollection collection) {
+        FsUserInformationCollection fsUserInformationCollection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(collection.getId());
+        if (fsUserInformationCollection == null) {
+            return R.error("没有用户采集信息");
+        }
+        if (fsUserInformationCollection.getUserConfirm() == 0){
+            return R.error("用户未确认");
+        }
+        if (fsUserInformationCollection.getDoctorConfirm() == 1){
+            return R.error("医生已确认");
+        }
+        List<AnswerVO> answerVOS = null;
+        //医生确认确认状态为true(用于封档)
+        if (StringUtils.isNotEmpty(fsUserInformationCollection.getJsonInfo()) ){
+            answerVOS = JSONArray.parseArray(fsUserInformationCollection.getJsonInfo(), AnswerVO.class);
+            answerVOS.forEach(answerVO -> {
+                answerVO.setFlag(true);
+            });
+        }
+        FsUserInformationCollection map = new FsUserInformationCollection();
+        map.setId(collection.getId());
+        map.setDoctorAdvice(collection.getDoctorAdvice());
+        map.setDoctorConfirm(1);
+        //医生确认时间
+        map.setDoctorConfirmTime(DateUtils.getNowDate());
+        //写入医生签名
+        FsDoctor fsDoctor = doctorMapper.selectFsDoctorByDoctorId(fsUserInformationCollection.getDoctorId());
+        map.setDoctorSign(fsDoctor.getSignUrl());
+        map.setDoctorAdvice(collection.getDoctorAdvice());
+        if (answerVOS != null && !answerVOS.isEmpty()) {
+            map.setJsonInfo(JSON.toJSONString(answerVOS));
+        }
+//        if (fsUserInformationCollection.getIsPackage() == 1) {
+//            //插入生成处方签定时任务数据
+//            if(fsUserInformationCollection.getPackageOrderCode() != null) {
+//                //套餐包订单
+//                FsPackageOrder fsPackageOrder = packageOrderMapper.selectByOderCode(fsUserInformationCollection.getPackageOrderCode());
+//                if (fsPackageOrder != null && fsPackageOrder.getIsPay() == 1) {
+//                    //套餐包信息
+//                    FsPackage fsPackage = JSON.parseObject(fsPackageOrder.getPackageJson(), FsPackage.class);
+//
+//                    //套餐包为药品生成处方信息
+//                    if(fsPackage != null && (fsPackage.getProductType() == 1 || fsPackage.getProductType() == 2 || fsPackage.getProductType() == 3)) {
+//                        FsStoreOrder fsStoreOrder = storeOrderService.selectFsStoreOrderByOrderCode(fsUserInformationCollection.getPackageOrderCode());
+//                        if (fsStoreOrder != null && fsStoreOrder.getIsPay() == 1 ) {
+//                            if (fsStoreOrder.getPrescribeId() != null) {
+////                                FsPrescribeParam fsPrescribeParam = new FsPrescribeParam();
+////                                fsPrescribeParam.setPrescribeId(fsStoreOrder.getPrescribeId());
+////                                prescribeService.confirmPrescribe(fsPrescribeParam);
+//                                prescribeService.collectionPrescribe(fsStoreOrder.getPrescribeId());
+//                            }
+//                        } else {
+//                            throw new CustomException("生成处方信息中......");
+//                        }
+//                    }
+//                }
+//            }
+//        } else {
+//            //没有关联套餐包医生确认清空所有状态
+//            map.setUserConfirm2(1);
+//        }
+
+        if (fsUserInformationCollectionMapper.updateFsUserInformationCollection(map) > 0) {
+
+            //更新医生确认信息
+//            FsDoctorConfirm doctorConfirm = redisCache.getCacheObject("doctorConfirm:" + collection.getId());
+//            if(doctorConfirm == null) {
+//                return R.error("没有医生确认信息");
+//            }
+//            doctorConfirm.setDoctorEndTime(DateUtils.getNowDate());
+//            Long seconds = DateUtil.between(doctorConfirm.getStartTime(), doctorConfirm.getDoctorEndTime(), DateUnit.SECOND);
+//            doctorConfirm.setConfirmSecond(seconds);
+//            doctorConfirmService.updateFsDoctorConfirm(doctorConfirm);
+//            redisCache.deleteObject("doctorConfirm:" + collection.getId());
+
+            openIMService.doctorSendMsgToUser(collection.getUserId(),collection.getDoctorId());
+            return R.ok();
+        }
+        return R.error("医生确认失败");
+    }
+
+    @Override
+    @Transactional
+    public R doctorType2Confirm(FsUserInformationCollection collection) {
+        FsUserInformationCollection fsUserInformationCollection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(collection.getId());
+        if (fsUserInformationCollection == null) {
+            return R.error("没有用户采集信息");
+        }
+        if (fsUserInformationCollection.getUserConfirm() == 0){
+            return R.error("用户未确认");
+        }
+        if (fsUserInformationCollection.getDoctorType2Confirm() == 1){
+            return R.error("药师已确认");
+        }
+        if (fsUserInformationCollection.getDoctorConfirm() != 1) {
+            return R.error("医生未签字无法确认");
+        }
+        if(StringUtils.isEmpty(fsUserInformationCollection.getPackageOrderCode())){
+            return R.error("用户未下单,无需确认");
+        }
+        List<AnswerVO> answerVOS = null;
+        //医生确认确认状态为true(用于封档)
+        if (StringUtils.isNotEmpty(fsUserInformationCollection.getJsonInfo()) ){
+            answerVOS = JSONArray.parseArray(fsUserInformationCollection.getJsonInfo(), AnswerVO.class);
+            answerVOS.forEach(answerVO -> {
+                answerVO.setFlag(true);
+            });
+        }
+        FsUserInformationCollection map = new FsUserInformationCollection();
+        map.setId(collection.getId());
+        map.setDoctorType2Confirm(1);
+        //医生确认时间
+        map.setDoctorConfirmTime(DateUtils.getNowDate());
+        //写入药师签名
+        FsDoctor fsDoctor = doctorMapper.selectFsDoctorByDoctorId(fsUserInformationCollection.getDoctorType2Id());
+        map.setDoctorType2Sign(fsDoctor.getSignUrl());
+        map.setDoctorAdvice(collection.getDoctorAdvice());
+        if (answerVOS != null && !answerVOS.isEmpty()) {
+            map.setJsonInfo(JSON.toJSONString(answerVOS));
+        }
+//
+
+        if (fsUserInformationCollectionMapper.updateFsUserInformationCollection(map) > 0) {
+            FsPackageOrder fsPackageOrder = packageOrderMapper.selectFsPackageOrderByOrderSn(collection.getPackageOrderCode());
+            if(fsPackageOrder.getStoreOrderId()==null||fsPackageOrder.getStoreOrderId()==0){
+                return R.error("用户未支付,无需确认");
+            }
+            FsStoreOrder fsStoreOrder = storeOrderService.selectFsStoreOrderByOrderId(fsPackageOrder.getStoreOrderId());
+            fsStoreOrder.setDoctorType2Confirm(1);
+            storeOrderService.updateFsStoreOrder(fsStoreOrder);
+            return R.ok();
+        }
+        return R.error("药师确认失败");
+    }
+
+    @Override
+    public FsUserInfoCollectionUVO info(Long id, Long userId) {
+        FsUserInfoCollectionUVO vo = new FsUserInfoCollectionUVO();
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(id);
+
+        if (collection != null) {
+
+//            if (!Objects.equals(collection.getUserId(), userId)) {
+//                return vo;
+//            }
+            if (collection.getIsPackage() == 1) {
+                vo.setPackageId(collection.getPackageId());
+                vo.setPayType(collection.getPayType());
+                vo.setAmount(collection.getAmount());
+                FsPackage fsPackage = new FsPackage();
+                FsPackage fsPackage1 = packageMapper.selectFsPackageByPackageId(collection.getPackageId());
+                if (fsPackage1 != null) {
+                    fsPackage = fsPackage1;
+                }
+                vo.setFsPackage(fsPackage);
+                CompanyUser companyUser = companyUserMapper.selectCompanyUserById(collection.getCompanyUserId());
+                if (companyUser == null) {
+                    throw new CustomException("销售不存在");
+                }
+                vo.setCompanyUserId(collection.getCompanyUserId());
+                vo.setCompanyId(companyUser.getCompanyId());
+                vo.setPackageOrderCode(collection.getPackageOrderCode());
+                FsPackageOrder fsPackageOrder = packageOrderMapper.selectFsPackageOrderByOrderSn(collection.getPackageOrderCode());
+                if(fsPackageOrder!=null) {
+                    vo.setOrderStatus(fsPackageOrder.getIsPay());
+                    vo.setOrderId(fsPackageOrder.getOrderId());
+                    vo.setPatientJson(fsPackageOrder.getPatientJson());
+                    if((fsPackage.getProductType() == 1 || fsPackage.getProductType() == 2 || fsPackage.getProductType() == 3) && fsPackageOrder.getIsPay() == 1) {
+                        //套餐包为药品且已支付的查询处方订单拿到处方签
+                        FsStoreOrder fsStoreOrder = storeOrderService.selectFsStoreOrderByOrderCode(collection.getPackageOrderCode());
+                        if (fsStoreOrder != null) {
+                            Long prescribeId = fsStoreOrder.getPrescribeId();
+                            FsPrescribe fsPrescribe = fsPrescribeMapper.selectFsPrescribeByPrescribeId(prescribeId);
+                            if (fsPrescribe != null) {
+                                vo.setPrescribeImgUrl(fsPrescribe.getPrescribeImgUrl());
+                                vo.setPrescribeStatus(fsPrescribe.getStatus());
+                            }
+                        } else {
+                            throw new CustomException("没有处方订单");
+                        }
+                    }
+                }
+            }
+            vo.setIsPackage(collection.getIsPackage());
+            vo.setId(collection.getId());
+            vo.setAnswers(JSON.parseArray(collection.getJsonInfo(), AnswerVO.class));
+            vo.setStatus(collection.getStatus());
+            vo.setUserConfirm(collection.getUserConfirm());
+            vo.setUserConfirm2(collection.getUserConfirm2());
+            vo.setDoctorConfirm(collection.getDoctorConfirm());
+            vo.setUserAdvice(collection.getUserAdvice());
+            vo.setDoctorAdvice(collection.getDoctorAdvice());
+            vo.setDoctor(doctorMapper.selectFsDoctorByDoctorId(collection.getDoctorId()));
+            vo.setAllergy(collection.getAllergy());
+            vo.setRemark(collection.getRemark());
+            vo.setSex(collection.getSex());
+            vo.setUserPhoneFour(collection.getUserPhoneFour());
+            vo.setUserName(collection.getUserName());
+        }
+        return vo;
+    }
+
+    @Override
+    @Transactional
+    public R userConfirm(CollectionInfoConfirmParam param) {
+
+        if (param.getId() == null) {
+            return R.error("参数错误");
+        }
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionById(param.getId());
+        if (collection == null) {
+            return R.error("没有用户采集信息");
+        }
+        if (collection.getStatus() == 1 ){
+            if (collection.getUserConfirm() == 1){
+                return R.error("用户已确认");
+            }
+        }
+        if (!Objects.equals(collection.getUserId(), param.getUserId())) {
+            return R.error("用户信息不匹配,无法确认");
+        }
+        FsUserInformationCollection map = new FsUserInformationCollection();
+        map.setId(param.getId());
+        map.setUserConfirm(1);
+        map.setUserAdvice(param.getUserAdvice());
+        if (param.getPatientId() == null|| param.getPatientId() == 0) {
+            return R.error("请提交就诊人信息");
+        }
+        map.setPatientId(param.getPatientId());
+        if (collection.getStatus() == 1) {
+
+            openIMService.sendUserInformation(collection.getUserId(),collection.getDoctorId(),collection.getId());
+            //用户确认后创建一个问诊订单,待医生接单
+//            FsInquiryOrderCreateParam fsInquiryOrderCreateParam = new FsInquiryOrderCreateParam();
+//            fsInquiryOrderCreateParam.setIsUserInformation(1);
+//            fsInquiryOrderCreateParam.setUserId(collection.getUserId());
+//            fsInquiryOrderCreateParam.setPatientId(collection.getPatientId());
+//            fsInquiryOrderCreateParam.setOrderType(1);
+//            fsInquiryOrderCreateParam.setInquiryType(1);
+//            fsInquiryOrderCreateParam.setIsVisit("1");
+//            fsInquiryOrderCreateParam.setInquirySubType(3);
+//            fsInquiryOrderService.createOrder(fsInquiryOrderCreateParam);
+//            //用户第一次确认添加医生消息
+//            DoctorMsg msg = new DoctorMsg();
+//            String name = collection.getUserName() != null ? collection.getUserName() : "-";
+//            //没套餐包的添加医生信息采集建议消息
+//            msg.setTitle("用户采集信息建议");
+//            msg.setType(3);
+//            msg.setContent("患者:" + name + "的信息采集,前往建议");
+//            msg.setDoctorId(collection.getDoctorId());
+//            msg.setCreateTime(DateUtils.getNowDate());
+//            //插入医生消息
+//            doctorMsgMapper.insertDoctorMsg(msg);
+//            //第一次确认
+            map.setStatus(2);
+            baseMapper.updateFsUserInformationCollection(map);
+        }
+//        if (fsUserInformationCollectionMapper.updateFsUserInformationCollection(map) > 0) {
+//            //存入医生确认统计时间数据
+//            FsDoctorConfirm doctorConfirm = new FsDoctorConfirm();
+//            doctorConfirm.setCollectionId(collection.getId());
+//            doctorConfirm.setDoctorId(collection.getDoctorId());
+//            doctorConfirm.setStartTime(DateUtils.getNowDate());
+//            doctorConfirmService.insertFsDoctorConfirm(doctorConfirm);
+//            //医生确认时间存入缓存 医生确认后删除
+//            redisCache.setCacheObject("doctorConfirm:" + collection.getId(), doctorConfirm);
+//            return R.ok();
+//        }
+        return R.ok();
+    }
+
+
+    @Override
+    @Transactional
+    public void autoRefund(FsUserInformationCollection collection) {
+
+        //清空订单号
+        fsUserInformationCollectionMapper.collectionOderCodeNULL(collection.getId());
+
+        //更新采集信息状态
+        FsUserInformationCollection map = new FsUserInformationCollection();
+        map.setId(collection.getId());
+        map.setUserConfirm2(0);
+        map.setStatus(1);
+        map.setUserConfirm(0);
+        map.setDoctorConfirm(0);
+        //更新用户信息采集状态
+        fsUserInformationCollectionMapper.updateFsUserInformationCollection(map);
+
+        //退款操作
+        FsStoreOrder fsStoreOrder = storeOrderService.selectFsStoreOrderByOrderCode(collection.getPackageOrderCode());
+        if (fsStoreOrder == null) {
+            throw new CustomException("没有处方订单");
+        }
+
+        //更新处方单信息
+        FsStoreOrder mapStoreOrder = new FsStoreOrder();
+        mapStoreOrder.setOrderId(fsStoreOrder.getOrderId());
+        mapStoreOrder.setStatus(-2);
+        mapStoreOrder.setRefundTime(DateUtils.getNowDate());
+        storeOrderService.updateFsStoreOrder(mapStoreOrder);
+
+        //订单日志
+        FsStoreOrderLogs Logs = new FsStoreOrderLogs();
+        Logs.setChangeMessage(FsStoreOrderStatusEnum.REFUND_STATUS_2.getDesc());
+        Logs.setOrderId(fsStoreOrder.getOrderId());
+        Logs.setChangeTime(new DateTime());
+        Logs.setChangeType(FsStoreOrderStatusEnum.REFUND_STATUS_2.getValue().toString());
+        fsStoreOrderLogsMapper.insertFsStoreOrderLogs(Logs);
+
+        String orderType = "store";
+        Long orderId = fsStoreOrder.getOrderId();
+        if (fsStoreOrder.getPackageOrderId() != null) {
+            orderType = "package";
+
+            FsPackageOrder fsPackageOrder = packageOrderMapper.selectFsPackageOrderByOrderSn(collection.getPackageOrderCode());
+            if (fsPackageOrder == null) {
+                throw new CustomException("没有套餐订单");
+            }
+            orderId = fsStoreOrder.getPackageOrderId();
+
+            //更新套餐单信息
+            FsPackageOrder mapPackageOrder = new FsPackageOrder();
+            mapPackageOrder.setOrderId(fsPackageOrder.getOrderId());
+            mapPackageOrder.setStatus(-2);
+            mapPackageOrder.setRefundStatus(2);
+            packageOrderMapper.updateFsPackageOrder(fsPackageOrder);
+        }
+
+        if (fsStoreOrder.getCompanyId() != null) {
+            companyService.refundCompanyMoney(fsStoreOrder);
+        }
+
+        //获取支付明细
+        List<FsStorePayment> payments = fsStorePaymentMapper.selectFsStorePaymentByPay(2, fsStoreOrder.getOrderId());
+        if (fsStoreOrder.getPackageOrderId() != null) {
+
+            payments = fsStorePaymentMapper.selectFsStorePaymentByPay(3, fsStoreOrder.getPackageOrderId());
+        }
+
+        if (payments != null && !payments.isEmpty()) {
+            FsStorePayment payment = payments.get(0);
+            String json = configService.selectConfigByKey("his.pay");
+            if (payment.getPayMode().equals("wx")) {
+                WxPayConfig payConfig = new WxPayConfig();
+                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
+                FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
+                payConfig.setAppId(fsPayConfig.getAppId());
+                payConfig.setMchId(fsPayConfig.getWxMchId());
+                payConfig.setMchKey(fsPayConfig.getWxMchKey());
+                payConfig.setKeyPath(wxPayProperties.getKeyPath());
+                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                wxPayService.setConfig(payConfig);
+                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                refundRequest.setOutTradeNo(orderType + "-" + payment.getPayCode());
+                refundRequest.setOutRefundNo(orderType + "-" + payment.getPayCode());
+                refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                try {
+                    WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                    WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                    if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                        FsStorePayment paymentMap = new FsStorePayment();
+                        paymentMap.setPaymentId(payment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(payment.getPayMoney());
+                        fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+                    } else {
+                        throw new CustomException("退款请求失败" + refundQueryResult.getReturnMsg());
+                    }
+                } catch (WxPayException e) {
+                    throw new CustomException("退款请求失败" + e.getReturnMsg());
+                }
+            } else if (payment.getPayMode().equals("yb")) {
+                //易宝
+                RefundDTO refundDTO = new RefundDTO();
+                refundDTO.setRefundMoney(payment.getPayMoney().toString());
+                refundDTO.setLowRefundNo(orderType + "-" + payment.getPayCode());
+                refundDTO.setUpOrderId(payment.getTradeNo());
+                com.fs.ybPay.domain.RefundResult result = payService.refund(refundDTO);
+                logger.info("订单退款返回结果:退款订单id:" + orderId + result);
+                if (result.getState().equals("5")) {
+                    FsStorePayment paymentMap = new FsStorePayment();
+                    paymentMap.setPaymentId(payment.getPaymentId());
+                    paymentMap.setStatus(-1);
+                    paymentMap.setRefundTime(DateUtils.getNowDate());
+                    paymentMap.setRefundMoney(payment.getPayMoney());
+                    fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+                } else {
+                    throw new CustomException("退款请求失败" + result.getMessage());
+                }
+            } else if (payment.getPayMode().equals("tz")) {
+                RefundParam tzBankResult = new RefundParam();
+                // 使用set方法为对象的字段赋值
+                //商户原支付订单号
+                tzBankResult.setOldPayOutOrderNo(orderType + payment.getPayCode());
+                // 商户退款订单号 对接平台系统里自己生成的退款订单号
+                tzBankResult.setRefundOrderNo(orderType + payment.getPayCode());
+                // 交易发送时间 yyyyMMddHHmmss
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+                tzBankResult.setTrxSendTime(sdf.format(new Date()));
+                // 退款金额
+                tzBankResult.setRefundOrdTransAmt(payment.getPayMoney().doubleValue());
+                TzBankResult<RefundResult> result = tzBankService.refund(tzBankResult);
+                logger.info("订单退款返回结果:退款订单id:" + orderId + result);
+                if (result.getBody().getRefundOrdStatus().equals("90") || result.getBody().getRefundOrdStatus().equals("60")) {
+                    FsStorePayment paymentMap = new FsStorePayment();
+                    paymentMap.setPaymentId(payment.getPaymentId());
+                    paymentMap.setStatus(-1);
+                    paymentMap.setRefundTime(DateUtils.getNowDate());
+                    paymentMap.setRefundMoney(payment.getPayMoney());
+                    fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+                } else {
+                    throw new CustomException("退款请求失败" + result.getRetMsg());
+                }
+            } else if (payment.getPayMode().equals("hf")) {
+                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 todo
+//                    HuifuConfirmrefundResult result = huiFuService.confirmRefund(confirmRefundRequest, null);
+//                    if (result.getResp_code().equals("00000000") && (result.getTrans_stat().equals("S") || result.getTrans_stat().equals("P"))) {
+//                        refund(payment, orderType, orderId);
+//                    } else {
+//                        throw new CustomException("交易确认退款请求失败" + result.getResp_desc());
+//                    }
+                } else {
+                    refund(payment, orderType, orderId);
+                }
+            }
+        } else {
+            throw new CustomException("未找的支付明细");
+        }
+
+
+    }
+    private void refund(FsStorePayment payment, String orderType, Long orderId) {
+        V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+        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_req_seq_id", orderType + "-" + payment.getPayCode());
+        request.setExtendInfo(extendInfoMap);
+        HuiFuRefundResult refund = huiFuService.refund(request);
+        logger.info("订单退款返回结果:退款订单id:" + orderId + refund);
+        if ((refund.getResp_code().equals("00000000") || refund.getResp_code().equals("00000100")) && (refund.getTrans_stat().equals("S") || refund.getTrans_stat().equals("P"))) {
+            FsStorePayment paymentMap = new FsStorePayment();
+            paymentMap.setPaymentId(payment.getPaymentId());
+            paymentMap.setStatus(-1);
+            paymentMap.setRefundTime(DateUtils.getNowDate());
+            paymentMap.setRefundMoney(payment.getPayMoney());
+            fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+        } else {
+            throw new CustomException("退款请求失败" + refund.getResp_desc());
+        }
+    }
+    @Override
+    public FsUserInformationCollectionVO getCollectionByUserId(Long userId) {
+        FsUserInformationCollectionVO vo = new FsUserInformationCollectionVO();
+        FsUserInformationCollection collection = fsUserInformationCollectionMapper.selectFsUserInformationCollectionByUserId(userId);
+        if (collection != null) {
+            vo.setAnswers(JSON.parseArray(collection.getJsonInfo(), AnswerVO.class));
+            //医生建议
+            if (collection.getDoctorAdvice() != null){
+                vo.setDoctorAdvice(collection.getDoctorAdvice());
+            }
+        }
+        return vo;
+    }
+
+    @Override
+    public FsUserInformationCollectionDTO selectFsUserInformationCollectionDTOById(Long id) {
+        return fsUserInformationCollectionMapper.selectFsUserInformationCollectionDTOById(id);
+    }
+
+    @Override
+    public int updatePackageOrderCode(FsUserInformationCollection fsUserInformationCollection) {
+        return fsUserInformationCollectionMapper.updateFsUserInformationCollection(fsUserInformationCollection);
+    }
+
+    private List<AnswerVO> getAnswerVOs(List<AnswerVO> target,List<AnswerVO> source) {
+        target.addAll(source);
+        return target.stream()
+                .collect(Collectors.groupingBy(AnswerVO::getTitle))
+                .values().stream()
+                .map(group -> group.stream().reduce((a, b) -> a).orElse(null))
+                .collect(Collectors.toList());
+    }
+
+    private FsUserInformationCollection getFsUserInformationCollection(FsUserInformationCollectionParam param) {
+        FsUserInformationCollection fsUserInformationCollection = new FsUserInformationCollection();
+        if (!CollectionUtils.isEmpty(param.getAnswers())) {
+            param.getAnswers().forEach(answer -> {
+                if (answer.getFlag() == null) {
+                    answer.setFlag(false);
+                }
+            });
+        }
+        fsUserInformationCollection.setJsonInfo(JSON.toJSONString(param.getAnswers()));
+        fsUserInformationCollection.setUserId(param.getUserId());
+        fsUserInformationCollection.setCompanyUserId(param.getCompanyUserId());
+        fsUserInformationCollection.setQuestionId(param.getQuestionId());
+        fsUserInformationCollection.setId(param.getId());
+        fsUserInformationCollection.setPackageId(param.getPackageId());
+        fsUserInformationCollection.setPayType(param.getPayType());
+        fsUserInformationCollection.setAmount(param.getAmount());
+        fsUserInformationCollection.setIsPackage(param.getIsPackage());
+        fsUserInformationCollection.setUserName(param.getUserName());
+        fsUserInformationCollection.setUserPhoneFour(param.getUserPhoneFour());
+        fsUserInformationCollection.setSex(param.getSex());
+        fsUserInformationCollection.setAllergy(param.getAllergy());
+        fsUserInformationCollection.setRemark(param.getRemark());
+        fsUserInformationCollection.setPatientId(param.getPatientId());
+        fsUserInformationCollection.setDoctorSign(param.getDoctorSign());
+        //获取医生信息
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
+        if (companyUser == null) {
+            throw new CustomException("销售不存在");
+        }
+        Long doctorId = null;
+        if (companyUser.getDoctorId() != null) {
+            FsDoctor doctor = doctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
+            if (doctor != null) {
+                doctorId = doctor.getDoctorId();
+            }
+        } else {
+            //随机获取医生id
+            doctorId = iFsDoctorService.selectFsDoctorDoctorByPackage();
+        }
+        doctorId = 324l;
+        fsUserInformationCollection.setDoctorId(doctorId);
+
+        return fsUserInformationCollection;
+    }
+
+    public static void main(String[] args) {
+//        String str1 = "[{\"options\":[{\"flag\":false,\"name\":\"通天\",\"value\":0},{\"flag\":false,\"name\":\"哈哈\",\"value\":1}],\"title\":\"测试标题1\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"呼呼\",\"value\":0},{\"flag\":false,\"name\":\"嘻嘻\",\"value\":1}],\"title\":\"测试标题2\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"胸痛\",\"value\":0},{\"flag\":false,\"name\":\"胸闷\",\"value\":1},{\"flag\":false,\"name\":\"头晕\",\"value\":2},{\"flag\":false,\"name\":\"肢体麻木\",\"value\":3},{\"flag\":false,\"name\":\"无\",\"value\":4}],\"title\":\"您目前是否有心脑血管相关症状,如胸痛、胸闷、头晕、肢体麻木等?\",\"value\":1}]";
+//        String str2 = "[{\"options\":[{\"flag\":true,\"name\":\"胸痛\",\"value\":0},{\"flag\":true,\"name\":\"胸闷\",\"value\":1},{\"flag\":true,\"name\":\"头晕\",\"value\":2},{\"flag\":true,\"name\":\"肢体麻木\",\"value\":3},{\"flag\":true,\"name\":\"无\",\"value\":4}],\"title\":\"您目前是否有心脑血管相关症状,如胸痛、胸闷、头晕、肢体麻木等?\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"胃疼\",\"value\":0},{\"flag\":false,\"name\":\"反酸\",\"value\":1},{\"flag\":false,\"name\":\"恶心\",\"value\":2},{\"flag\":false,\"name\":\"呕吐\",\"value\":3},{\"flag\":false,\"name\":\"黑便\",\"value\":4},{\"flag\":false,\"name\":\"无\",\"value\":5}],\"title\":\"您近期是否出现胃部不适症状,如胃痛、反酸、恶心、呕吐或黑便?\",\"value\":1}]";
+//        List<AnswerVO> vo1 = null;
+//        List<AnswerVO> vo2 = JSON.parseArray(str2, AnswerVO.class);
+//        System.out.println(vo1);
+//        System.out.println(vo2);
+//        vo2.addAll(vo1);
+//        Map<String, List<AnswerVO>> collect = vo2.stream()
+//                .collect(Collectors.groupingBy(AnswerVO::getTitle));
+//        List<AnswerVO> collect1 = vo2.stream()
+//                .collect(Collectors.groupingBy(AnswerVO::getTitle))
+//                .values().stream()
+//                .map(group -> group.stream().reduce((a, b) -> a).orElse(null)).collect(Collectors.toList());
+//        System.out.println(JSON.toJSONString(collect));
+//        System.out.println(JSON.toJSONString(collect1));
+        boolean contains = "是否有糖尿病相关疾病?".contains("糖尿病");
+    }
+}

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

@@ -1561,4 +1561,9 @@ public class FsUserServiceImpl implements IFsUserService {
         return new HisFsUserVO();
     }
 
+    @Override
+    public List<FsUser> selectFsUserListByPhone(String phone) {
+        return fsUserMapper.selectFsUserListByPhone(phone);
+    }
+
 }

+ 20 - 0
fs-service/src/main/java/com/fs/his/utils/PhoneUtil.java

@@ -77,4 +77,24 @@ public class PhoneUtil {
 
         return text;
     }
+    /**
+     * 用于查询 使用老的数据加密
+     * @param text
+     * @return
+     */
+    private static String OLD_KEY = "2c8d1a7f4e9b3c6ae6d5c4b3a291f8c9";
+    public static String encryptPhoneOldKey(String text) {
+        String encryptedText=null;
+        try {
+            SecretKeySpec secretKey = new SecretKeySpec(OLD_KEY.getBytes(), "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            // Encryption
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
+            encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return encryptedText;
+    }
 }

+ 32 - 0
fs-service/src/main/java/com/fs/his/vo/AnswerVO.java

@@ -0,0 +1,32 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class AnswerVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String title;
+
+    private List<Options> options;
+
+    //已选择数据(多选)
+    private List<Integer> value;
+
+    //排序
+    private Integer sort;
+    //private Integer value;
+
+
+    //是否医生已确认
+    private Boolean flag;
+
+   @Data
+    public static class Options implements Serializable{
+        private String name;
+        private Integer value;
+    }
+}

+ 15 - 0
fs-service/src/main/java/com/fs/his/vo/FsQuestionAndAnswerVO.java

@@ -0,0 +1,15 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FsQuestionAndAnswerVO {
+
+    private Long id;
+
+    private String questionName;
+
+    private List<AnswerVO> answers;
+}

+ 79 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserInfoCollectionUVO.java

@@ -0,0 +1,79 @@
+package com.fs.his.vo;
+
+import com.fs.his.domain.FsDoctor;
+import com.fs.his.domain.FsPackage;
+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;
+
+    //是否过敏
+    private String allergy;
+    //备注
+    private String remark;
+
+    //用户性别 0女 1男
+    private Integer sex;
+    //用户姓名
+    private String userName;
+    //用户电话后四位
+    private String userPhoneFour;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionAndPatientVO.java

@@ -0,0 +1,18 @@
+package com.fs.his.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.his.domain.FsPatient;
+import com.fs.his.domain.FsUserInformationCollection;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class FsUserInformationCollectionAndPatientVO extends FsUserInformationCollection {
+    private FsPatient patientInfo; //病人信息
+
+
+}

+ 23 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionListDVO.java

@@ -0,0 +1,23 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+@Data
+public class FsUserInformationCollectionListDVO {
+
+    private Long id;
+
+    //用户信息
+    private String userName;
+
+    //医生确认状态 0未确认 1已确认
+    private Integer doctorConfirm;
+
+
+    private Integer userConfirm;
+
+    //用户补充说明
+    private String userAdvice;
+
+    private String doctorAdvice;
+}

+ 47 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionVO.java

@@ -0,0 +1,47 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class FsUserInformationCollectionVO {
+
+    private Long id;
+
+    private Long questionId;
+
+    //套餐包id
+    private Long packageId;
+
+    //支付类型 0-全款 1-物流代收
+    private Integer payType;
+
+    //代收金额
+    private BigDecimal amount;
+
+    private List<AnswerVO> answers;
+
+    //是否关联套餐包 0-不关联 1-关联
+    private Integer isPackage;
+
+    //用户性别 0女 1男
+    private Integer sex;
+    //用户姓名
+    private String userName;
+    //用户电话后四位
+    private String userPhoneFour;
+
+    //是否过敏
+    private String allergy;
+
+    //备注
+    private String remark;
+
+    //医生建议
+    private String doctorAdvice;
+
+    private Long patientId;
+
+}

+ 19 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreProductScrm.java

@@ -1,9 +1,11 @@
 package com.fs.hisStore.domain;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
@@ -320,4 +322,21 @@ public class FsStoreProductScrm extends BaseEntity
     private String returnAddress;
 
 
+    /** 原产地 */
+    @Excel(name = "原产地")
+    private String originPlace;
+
+    /** 净含量 */
+    @Excel(name = "净含量")
+    private String netContent;
+
+    /** 有效日期 */
+    @Excel(name = "有效日期")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date shelfLife;
+
+    /** 国产或进口 */
+    @Excel(name = "国产或进口")
+    private String domesticImported;
+
 }

+ 10 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java

@@ -215,6 +215,16 @@ public class FsUserScrm extends BaseEntity
     private String companyName;
     private String rank;
     private String react;
+    /** 绑定的公司用户ID */
+    private Long bindCompanyUserId;
+
+    public Long getBindCompanyUserId() {
+        return bindCompanyUserId;
+    }
+
+    public void setBindCompanyUserId(Long bindCompanyUserId) {
+        this.bindCompanyUserId = bindCompanyUserId;
+    }
 
     /**
      * 项目ID

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است